aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-helper-vpn-windows.c
diff options
context:
space:
mode:
authorChristian Fuchs <christian.fuchs@cfuchs.net>2013-01-10 09:39:20 +0000
committerChristian Fuchs <christian.fuchs@cfuchs.net>2013-01-10 09:39:20 +0000
commit4216ae8f09c0b6ec6d46e09cba6cb680df63bf14 (patch)
tree8ab2fb248e020a34263a8d3be27067ab49540437 /src/vpn/gnunet-helper-vpn-windows.c
parent9ad019b1441ccace9176e9d11f8bb6413422e8ab (diff)
downloadgnunet-4216ae8f09c0b6ec6d46e09cba6cb680df63bf14.tar.gz
gnunet-4216ae8f09c0b6ec6d46e09cba6cb680df63bf14.zip
In Windows, pipes, files and the console have to be accessed
differently(in contrast to *nix). overlapping does not exist for console handles, and different functions are required to read/write/poll stdin/out. - THus, we can now detect the type of handle we got as stdin/stdout from our calling process. - Did a bit of refactoring. next: add logics to use the proper access mode depending on our handletype.
Diffstat (limited to 'src/vpn/gnunet-helper-vpn-windows.c')
-rw-r--r--src/vpn/gnunet-helper-vpn-windows.c180
1 files changed, 92 insertions, 88 deletions
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c
index 516ba5d0e..08aad624a 100644
--- a/src/vpn/gnunet-helper-vpn-windows.c
+++ b/src/vpn/gnunet-helper-vpn-windows.c
@@ -140,17 +140,18 @@ static char device_guid[256];
140/* Overlapped IO Begins here (warning: nasty!) */ 140/* Overlapped IO Begins here (warning: nasty!) */
141 141
142/** 142/**
143 * A overlapped-IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling 143 * A IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling
144 */ 144 */
145struct overlapped_facility 145struct io_facility
146{ 146{
147 int iostate; 147 DWORD handle_type;
148 BOOL status; // BOOL is winbool, NOT boolean! 148 HANDLE handle;
149 BOOL path_open; 149
150 DWORD flags; 150 BOOL path_open; // BOOL is winbool, NOT boolean!
151 151 int facility_state;
152 BOOL status;
153
152 OVERLAPPED overlapped; 154 OVERLAPPED overlapped;
153
154 DWORD buffer_size; 155 DWORD buffer_size;
155 unsigned char buffer[MAX_SIZE]; 156 unsigned char buffer[MAX_SIZE];
156}; 157};
@@ -700,62 +701,62 @@ tun_up (HANDLE handle)
700} 701}
701 702
702static boolean 703static boolean
703attempt_std_in (HANDLE stdin_handle, 704attempt_std_in (struct io_facility * std_in,
704 struct overlapped_facility * std_in, 705 struct io_facility * tap_write)
705 struct overlapped_facility * tap_write)
706{ 706{
707 707
708 // We could use PeekConsoleInput() or WaitForSingleObject() 708 // We could use PeekConsoleInput() or WaitForSingleObject()
709 // however, the interwebs states that WaitForSingleObject with filehandles 709 // however, the interwebs states that WaitForSingleObject with filehandles
710 // might misbehave on some windows (unspecified which ones!). 710 // might misbehave on some windows (unspecified which ones!).
711 // unfortunately, peekconsoleinput () just waits for KEYPRESS-event, which would never happen on a pipe or a file 711 // unfortunately, peekconsoleinput () just waits for KEYPRESS-event, which would never happen on a pipe or a file
712 712
713 // See: 713 // See:
714 // http://www.cplusplus.com/forum/windows/28837/ 714 // http://www.cplusplus.com/forum/windows/28837/
715 // http://stackoverflow.com/questions/4551644/using-overlapped-io-for-console-input 715 // http://stackoverflow.com/questions/4551644/using-overlapped-io-for-console-input
716 // http://cygwin.com/ml/cygwin/2012-05/msg00322.html 716 // http://cygwin.com/ml/cygwin/2012-05/msg00322.html
717 717
718 // possible soltion? 718 // possible soltion?
719 // http://stackoverflow.com/questions/3661106/overlapped-readfileex-on-child-process-redirected-stdout-never-fires 719 // http://stackoverflow.com/questions/3661106/overlapped-readfileex-on-child-process-redirected-stdout-never-fires
720 720
721 // we may read from STDIN, and no job was active 721 // we may read from STDIN, and no job was active
722 if (IOSTATE_READY == std_in->iostate){ 722 if (IOSTATE_READY == std_in->facility_state)
723 723 {
724
724 } 725 }
725 // we must complete a previous read from stdin, before doing more work 726 // we must complete a previous read from stdin, before doing more work
726 else if (IOSTATE_QUEUED == std_in->iostate ){ 727 else if (IOSTATE_QUEUED == std_in->facility_state)
728 {
727 // there is some data to be read from STDIN! 729 // there is some data to be read from STDIN!
728/* if (PeekConsoleInput(stdin_handle, 730 /* if (PeekConsoleInput(stdin_handle,
729 &std_in->buffer[MAX_SIZE], 731 &std_in->buffer[MAX_SIZE],
730 MAX_SIZE, 732 MAX_SIZE,
731 &std_in->buffer_size)){ 733 &std_in->buffer_size)){
732 734
733 735
734 736
735 }*/ 737 }*/
736 // else { // nothing to do, try again next time } 738 // else { // nothing to do, try again next time }
737 } 739 }
738 740
739 return TRUE; 741 return TRUE;
740} 742}
741 743
742static boolean 744static boolean
743attempt_tap_read (HANDLE tap_handle, 745attempt_tap_read (struct io_facility * tap_read,
744 struct overlapped_facility * tap_read, 746 struct io_facility * std_out)
745 struct overlapped_facility * std_out)
746{ 747{
747 748
748 if (IOSTATE_READY == tap_read->iostate) 749 if (IOSTATE_READY == tap_read->facility_state)
749 { 750 {
750 if (!ResetEvent (tap_read->overlapped.hEvent)) 751 if (!ResetEvent (tap_read->overlapped.hEvent))
751 { 752 {
752 return FALSE; 753 return FALSE;
753 } 754 }
754 tap_read->status = ReadFile (tap_handle, 755 tap_read->status = ReadFile (tap_read->handle,
755 &tap_read->buffer[MAX_SIZE], 756 &tap_read->buffer[MAX_SIZE],
756 MAX_SIZE, 757 MAX_SIZE,
757 &tap_read->buffer_size, 758 &tap_read->buffer_size,
758 &tap_read->overlapped); 759 &tap_read->overlapped);
759 760
760 /* Check how the task is handled */ 761 /* Check how the task is handled */
761 if (tap_read->status) 762 if (tap_read->status)
@@ -767,17 +768,17 @@ attempt_tap_read (HANDLE tap_handle,
767 768
768 /* we successfully read something from the TAP and now need to 769 /* we successfully read something from the TAP and now need to
769 * send it our via STDOUT. Is that possible at the moment? */ 770 * send it our via STDOUT. Is that possible at the moment? */
770 if (IOSTATE_READY == std_out->iostate && 0 < tap_read->buffer_size) 771 if (IOSTATE_READY == std_out->facility_state && 0 < tap_read->buffer_size)
771 { /* hand over this buffers content */ 772 { /* hand over this buffers content */
772 memcpy (std_out->buffer, 773 memcpy (std_out->buffer,
773 tap_read->buffer, 774 tap_read->buffer,
774 MAX_SIZE); 775 MAX_SIZE);
775 std_out->buffer_size = tap_read->buffer_size; 776 std_out->buffer_size = tap_read->buffer_size;
776 std_out->iostate = IOSTATE_READY; 777 std_out->facility_state = IOSTATE_READY;
777 } 778 }
778 else if (0 < tap_read->buffer_size) 779 else if (0 < tap_read->buffer_size)
779 { /* If we have have read our buffer, wait for our write-partner*/ 780 { /* If we have have read our buffer, wait for our write-partner*/
780 tap_read->iostate = IOSTATE_WAITING; 781 tap_read->facility_state = IOSTATE_WAITING;
781 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? 782 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
782 } 783 }
783 } 784 }
@@ -786,23 +787,23 @@ attempt_tap_read (HANDLE tap_handle,
786 int err = GetLastError (); 787 int err = GetLastError ();
787 if (ERROR_IO_PENDING == err) 788 if (ERROR_IO_PENDING == err)
788 { /* operation queued */ 789 { /* operation queued */
789 tap_read->iostate = IOSTATE_QUEUED; 790 tap_read->facility_state = IOSTATE_QUEUED;
790 } 791 }
791 else 792 else
792 { /* error occurred, let the rest of the elements finish */ 793 { /* error occurred, let the rest of the elements finish */
793 tap_read->path_open = FALSE; 794 tap_read->path_open = FALSE;
794 tap_read->iostate = IOSTATE_FAILED; 795 tap_read->facility_state = IOSTATE_FAILED;
795 } 796 }
796 } 797 }
797 } 798 }
798 // We are queued and should check if the read has finished 799 // We are queued and should check if the read has finished
799 else if (IOSTATE_QUEUED == tap_read->iostate ) 800 else if (IOSTATE_QUEUED == tap_read->facility_state)
800 { 801 {
801 // there was an operation going on already, check if that has completed now. 802 // there was an operation going on already, check if that has completed now.
802 tap_read->status = GetOverlappedResult (tap_handle, 803 tap_read->status = GetOverlappedResult (tap_read->handle,
803 &tap_read->overlapped, 804 &tap_read->overlapped,
804 &tap_read->buffer_size, 805 &tap_read->buffer_size,
805 FALSE); 806 FALSE);
806 if (tap_read->status) 807 if (tap_read->status)
807 {/* successful return for a queued operation */ 808 {/* successful return for a queued operation */
808 if (!ResetEvent (tap_read->overlapped.hEvent)) 809 if (!ResetEvent (tap_read->overlapped.hEvent))
@@ -810,28 +811,28 @@ attempt_tap_read (HANDLE tap_handle,
810 811
811 /* we successfully read something from the TAP and now need to 812 /* we successfully read something from the TAP and now need to
812 * send it our via STDOUT. Is that possible at the moment? */ 813 * send it our via STDOUT. Is that possible at the moment? */
813 if (IOSTATE_READY == std_out->iostate && 0 < tap_read->buffer_size ) 814 if (IOSTATE_READY == std_out->facility_state && 0 < tap_read->buffer_size)
814 { /* hand over this buffers content */ 815 { /* hand over this buffers content */
815 memcpy (std_out->buffer, 816 memcpy (std_out->buffer,
816 tap_read->buffer, 817 tap_read->buffer,
817 MAX_SIZE); 818 MAX_SIZE);
818 std_out->buffer_size = tap_read->buffer_size; 819 std_out->buffer_size = tap_read->buffer_size;
819 std_out->iostate = IOSTATE_READY; 820 std_out->facility_state = IOSTATE_READY;
820 tap_read->iostate = IOSTATE_READY; 821 tap_read->facility_state = IOSTATE_READY;
821 } 822 }
822 else if (0 < tap_read->buffer_size) 823 else if (0 < tap_read->buffer_size)
823 { /* If we have have read our buffer, wait for our write-partner*/ 824 { /* If we have have read our buffer, wait for our write-partner*/
824 tap_read->iostate = IOSTATE_WAITING; 825 tap_read->facility_state = IOSTATE_WAITING;
825 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? 826 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
826 } 827 }
827 } 828 }
828 else 829 else
829 { /* operation still pending/queued or failed? */ 830 { /* operation still pending/queued or failed? */
830 int err = GetLastError (); 831 int err = GetLastError ();
831 if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err ) 832 if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err)
832 { /* error occurred, let the rest of the elements finish */ 833 { /* error occurred, let the rest of the elements finish */
833 tap_read->path_open = FALSE; 834 tap_read->path_open = FALSE;
834 tap_read->iostate = IOSTATE_FAILED; 835 tap_read->facility_state = IOSTATE_FAILED;
835 } 836 }
836 } 837 }
837 } 838 }
@@ -839,17 +840,15 @@ attempt_tap_read (HANDLE tap_handle,
839} 840}
840 841
841static boolean 842static boolean
842attempt_tap_write (HANDLE tap_handle, 843attempt_tap_write (struct io_facility * tap_write,
843 struct overlapped_facility * tap_write, 844 struct io_facility * std_in)
844 struct overlapped_facility * std_in)
845{ 845{
846 return TRUE; 846 return TRUE;
847} 847}
848 848
849static boolean 849static boolean
850attempt_std_out (HANDLE stdout_handle, 850attempt_std_out (struct io_facility * std_out,
851 struct overlapped_facility * std_out, 851 struct io_facility * tap_read)
852 struct overlapped_facility * tap_read)
853{ 852{
854 return TRUE; 853 return TRUE;
855} 854}
@@ -863,14 +862,16 @@ attempt_std_out (HANDLE stdout_handle,
863 * @return true on success, else false 862 * @return true on success, else false
864 */ 863 */
865static boolean 864static boolean
866initialize_overlapped_facility (struct overlapped_facility * elem, 865initialize_io_facility (struct io_facility * elem,
867 BOOL initial_state, 866 BOOL initial_state,
868 BOOL signaled) 867 BOOL signaled)
869{ 868{
870 869
871 elem->path_open = TRUE; 870 elem->path_open = TRUE;
872 elem->status = initial_state; 871 elem->status = initial_state;
873 elem->iostate = 0; 872 elem->handle_type = 0;
873 elem->handle = INVALID_HANDLE_VALUE;
874 elem->facility_state = 0;
874 elem->buffer_size = 0; 875 elem->buffer_size = 0;
875 elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL); 876 elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL);
876 if (NULL == elem->overlapped.hEvent) 877 if (NULL == elem->overlapped.hEvent)
@@ -888,17 +889,13 @@ static void
888run (HANDLE tap_handle) 889run (HANDLE tap_handle)
889{ 890{
890 /* IO-Facility for reading from our virtual interface */ 891 /* IO-Facility for reading from our virtual interface */
891 struct overlapped_facility tap_read; 892 struct io_facility tap_read;
892 /* IO-Facility for writing to our virtual interface */ 893 /* IO-Facility for writing to our virtual interface */
893 struct overlapped_facility tap_write; 894 struct io_facility tap_write;
894 /* IO-Facility for reading from stdin */ 895 /* IO-Facility for reading from stdin */
895 struct overlapped_facility std_in; 896 struct io_facility std_in;
896 /* IO-Facility for writing to stdout */ 897 /* IO-Facility for writing to stdout */
897 struct overlapped_facility std_out; 898 struct io_facility std_out;
898
899 /* Handles for STDIN and STDOUT */
900 HANDLE stdin_handle = INVALID_HANDLE_VALUE;
901 HANDLE stdout_handle = INVALID_HANDLE_VALUE;
902 899
903 /* tun up: */ 900 /* tun up: */
904 /* we do this HERE and not beforehand (in init_tun()), in contrast to openvpn 901 /* we do this HERE and not beforehand (in init_tun()), in contrast to openvpn
@@ -911,22 +908,29 @@ run (HANDLE tap_handle)
911 goto teardown; 908 goto teardown;
912 909
913 /* Initialize our overlapped IO structures*/ 910 /* Initialize our overlapped IO structures*/
914 if (!(initialize_overlapped_facility (&tap_read, TRUE, FALSE) 911 if (!(initialize_io_facility (&tap_read, TRUE, FALSE)
915 && initialize_overlapped_facility (&tap_write, FALSE, TRUE) 912 && initialize_io_facility (&tap_write, FALSE, TRUE)
916 && initialize_overlapped_facility (&std_in, TRUE, FALSE) 913 && initialize_io_facility (&std_in, TRUE, FALSE)
917 && initialize_overlapped_facility (&std_out, FALSE, TRUE))) 914 && initialize_io_facility (&std_out, FALSE, TRUE)))
918 goto teardown; 915 goto teardown;
919 916
920 stdin_handle = GetStdHandle ( STD_INPUT_HANDLE ); 917 /* Handles for STDIN and STDOUT */
921 918 std_in.handle = GetStdHandle (STD_INPUT_HANDLE);
922 if (stdin_handle == INVALID_HANDLE_VALUE) 919 std_out.handle = GetStdHandle (STD_OUTPUT_HANDLE);
923 fprintf (stderr, "CreateFile failed for stdin\n"); 920 tap_read.handle = tap_handle;
921 tap_write.handle = tap_handle;
922
923 /*
924 * Find out the types of our handles.
925 * This part is a problem, because in windows we need to handle files,
926 * pipes and the console differently.
927 */
928 std_in.handle_type = GetFileType (std_in.handle);
929 std_out.handle_type = GetFileType (std_out.handle);
930 /* the tap handle is always a file, but we still set this for consistency */
931 tap_read.handle_type = FILE_TYPE_DISK;
932 tap_write.handle_type = FILE_TYPE_DISK;
924 933
925 stdin_handle = GetStdHandle ( STD_OUTPUT_HANDLE );
926
927 if (stdin_handle == INVALID_HANDLE_VALUE)
928 fprintf (stderr, "CreateFile failed for stdout\n");
929
930 //openvpn 934 //openvpn
931 // Set Device to Subnet-Mode? 935 // Set Device to Subnet-Mode?
932 // do we really need tun.c:2925 ? 936 // do we really need tun.c:2925 ?
@@ -946,26 +950,26 @@ run (HANDLE tap_handle)
946 { 950 {
947 /* perform READ from stdin if possible */ 951 /* perform READ from stdin if possible */
948 if ((std_in.path_open && tap_write.path_open) 952 if ((std_in.path_open && tap_write.path_open)
949 || IOSTATE_QUEUED == std_in.iostate) 953 || IOSTATE_QUEUED == std_in.facility_state)
950 if (!attempt_std_in (stdin_handle, &std_in, &tap_write)) 954 if (!attempt_std_in (&std_in, &tap_write))
951 break; 955 break;
952 956
953 /* perform READ from tap if possible */ 957 /* perform READ from tap if possible */
954 if ((tap_read.path_open && std_out.path_open) 958 if ((tap_read.path_open && std_out.path_open)
955 || IOSTATE_QUEUED == tap_read.iostate ) 959 || IOSTATE_QUEUED == tap_read.facility_state)
956 if (!attempt_tap_read (tap_handle, &tap_read, &std_out)) 960 if (!attempt_tap_read (&tap_read, &std_out))
957 break; 961 break;
958 962
959 /* perform WRITE to tap if possible */ 963 /* perform WRITE to tap if possible */
960 if ( IOSTATE_READY == tap_write.iostate && tap_write.path_open ) 964 if (IOSTATE_READY == tap_write.facility_state && tap_write.path_open)
961 if (!attempt_tap_write (tap_handle, &tap_write, &std_in)) 965 if (!attempt_tap_write (&tap_write, &std_in))
962 break; 966 break;
963 967
964 /* perform WRITE to STDOUT if possible */ 968 /* perform WRITE to STDOUT if possible */
965 if ( IOSTATE_READY == std_out.iostate && std_out.path_open) 969 if (IOSTATE_READY == std_out.facility_state && std_out.path_open)
966 if (!attempt_std_out (stdout_handle, &std_out, &tap_read)) 970 if (!attempt_std_out (&std_out, &tap_read))
967 break; 971 break;
968 972
969 // check if any path is blocked 973 // check if any path is blocked
970 } 974 }
971teardown: 975teardown: