diff options
author | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-01-10 09:39:20 +0000 |
---|---|---|
committer | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-01-10 09:39:20 +0000 |
commit | 4216ae8f09c0b6ec6d46e09cba6cb680df63bf14 (patch) | |
tree | 8ab2fb248e020a34263a8d3be27067ab49540437 /src/vpn/gnunet-helper-vpn-windows.c | |
parent | 9ad019b1441ccace9176e9d11f8bb6413422e8ab (diff) | |
download | gnunet-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.c | 180 |
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 | */ |
145 | struct overlapped_facility | 145 | struct 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 | ||
702 | static boolean | 703 | static boolean |
703 | attempt_std_in (HANDLE stdin_handle, | 704 | attempt_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 | ||
742 | static boolean | 744 | static boolean |
743 | attempt_tap_read (HANDLE tap_handle, | 745 | attempt_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 | ||
841 | static boolean | 842 | static boolean |
842 | attempt_tap_write (HANDLE tap_handle, | 843 | attempt_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 | ||
849 | static boolean | 849 | static boolean |
850 | attempt_std_out (HANDLE stdout_handle, | 850 | attempt_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 | */ |
865 | static boolean | 864 | static boolean |
866 | initialize_overlapped_facility (struct overlapped_facility * elem, | 865 | initialize_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 | |||
888 | run (HANDLE tap_handle) | 889 | run (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 | } |
971 | teardown: | 975 | teardown: |