diff options
author | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-01-03 16:11:02 +0000 |
---|---|---|
committer | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-01-03 16:11:02 +0000 |
commit | b53d7bfde8da84afaa7ee8888d15f1cc6cffd866 (patch) | |
tree | 054c60c339f25f78c92b99d500e19e6832081eab /src/vpn | |
parent | 213bc87131772ae2b808428a6e5ff65a1d963e24 (diff) | |
download | gnunet-b53d7bfde8da84afaa7ee8888d15f1cc6cffd866.tar.gz gnunet-b53d7bfde8da84afaa7ee8888d15f1cc6cffd866.zip |
There are now four states for the OI facilities:
* ready (to do work),
* queued (waiting for async-io to return),
* waiting (a read-facilities wait for its output partner to get process)
* failed (if a socket error occured)
added attempt_tap_read machine.
reworked run() for overlapped IO
Diffstat (limited to 'src/vpn')
-rw-r--r-- | src/vpn/gnunet-helper-vpn-windows.c | 193 |
1 files changed, 157 insertions, 36 deletions
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c index 39aa84d9d..98e82dad9 100644 --- a/src/vpn/gnunet-helper-vpn-windows.c +++ b/src/vpn/gnunet-helper-vpn-windows.c | |||
@@ -146,6 +146,7 @@ struct overlapped_facility | |||
146 | { | 146 | { |
147 | int iostate; | 147 | int iostate; |
148 | BOOL status; // BOOL is winbool, NOT boolean! | 148 | BOOL status; // BOOL is winbool, NOT boolean! |
149 | BOOL path_open; | ||
149 | DWORD flags; | 150 | DWORD flags; |
150 | 151 | ||
151 | OVERLAPPED overlapped; | 152 | OVERLAPPED overlapped; |
@@ -155,11 +156,12 @@ struct overlapped_facility | |||
155 | }; | 156 | }; |
156 | 157 | ||
157 | /** | 158 | /** |
158 | * Operlapped IO states for its objects | 159 | * Operlapped IO states for facility objects |
159 | */ | 160 | */ |
160 | #define IOSTATE_INITIAL 0 | 161 | #define IOSTATE_FAILED -1 /* overlapped I/O has failed, stop processing */ |
162 | #define IOSTATE_READY 0 /* overlapped I/O is ready for work */ | ||
161 | #define IOSTATE_QUEUED 1 /* overlapped I/O has been queued */ | 163 | #define IOSTATE_QUEUED 1 /* overlapped I/O has been queued */ |
162 | #define IOSTATE_IMMEDIATE_RETURN 2 /* I/O function returned immediately without queueing */ | 164 | #define IOSTATE_WAITING 3 /* overlapped I/O has finished, but is waiting for it's write-partner */ |
163 | 165 | ||
164 | #if WINVER < 0x0600 | 166 | #if WINVER < 0x0600 |
165 | 167 | ||
@@ -697,6 +699,127 @@ tun_up (HANDLE handle) | |||
697 | 699 | ||
698 | } | 700 | } |
699 | 701 | ||
702 | static boolean | ||
703 | attempt_std_in ( struct overlapped_facility * std_in, | ||
704 | struct overlapped_facility * tap_write) | ||
705 | { | ||
706 | return TRUE; | ||
707 | } | ||
708 | |||
709 | static boolean | ||
710 | attempt_tap_read (HANDLE tap_handle, | ||
711 | struct overlapped_facility * tap_read, | ||
712 | struct overlapped_facility * std_out) | ||
713 | { | ||
714 | |||
715 | if (IOSTATE_READY == tap_read->iostate) | ||
716 | { | ||
717 | if (!ResetEvent (tap_read->overlapped.hEvent)) | ||
718 | { | ||
719 | return FALSE; | ||
720 | } | ||
721 | tap_read->status = ReadFile (tap_handle, | ||
722 | &tap_read->buffer[MAX_SIZE], | ||
723 | MAX_SIZE, | ||
724 | &tap_read->buffer_size, | ||
725 | &tap_read->overlapped); | ||
726 | |||
727 | /* Check how the task is handled */ | ||
728 | if (tap_read->status) | ||
729 | {/* async event processed immediately*/ | ||
730 | |||
731 | /* reset event manually*/ | ||
732 | if (!SetEvent (tap_read->overlapped.hEvent)) | ||
733 | return FALSE; | ||
734 | |||
735 | /* we successfully read something from the TAP and now need to | ||
736 | * send it our via STDOUT. Is that possible at the moment? */ | ||
737 | if (IOSTATE_READY == std_out->iostate && 0 < tap_read->buffer_size) | ||
738 | { /* hand over this buffers content */ | ||
739 | memcpy (std_out->buffer, | ||
740 | tap_read->buffer, | ||
741 | MAX_SIZE); | ||
742 | std_out->buffer_size = tap_read->buffer_size; | ||
743 | std_out->iostate = IOSTATE_READY; | ||
744 | } | ||
745 | else if (0 < tap_read->buffer_size) | ||
746 | { /* If we have have read our buffer, wait for our write-partner*/ | ||
747 | tap_read->iostate = IOSTATE_WAITING; | ||
748 | // TODO: shall we attempt to fill our bufferm or should we wait for our write-partner to finish? | ||
749 | } | ||
750 | } | ||
751 | else /* operation was either queued or failed*/ | ||
752 | { | ||
753 | int err = GetLastError (); | ||
754 | if (ERROR_IO_PENDING == err) | ||
755 | { /* operation queued */ | ||
756 | tap_read->iostate = IOSTATE_QUEUED; | ||
757 | } | ||
758 | else | ||
759 | { /* error occurred, let the rest of the elements finish */ | ||
760 | tap_read->path_open = FALSE; | ||
761 | tap_read->iostate = IOSTATE_FAILED; | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | // We are queued and should check if the read has finished | ||
766 | else if (IOSTATE_QUEUED == tap_read->iostate ) | ||
767 | { | ||
768 | // there was an operation going on already, check if that has completed now. | ||
769 | tap_read->status = GetOverlappedResult (tap_handle, | ||
770 | &tap_read->overlapped, | ||
771 | &tap_read->buffer_size, | ||
772 | FALSE); | ||
773 | if (tap_read->status) | ||
774 | {/* successful return for a queued operation */ | ||
775 | if (!ResetEvent (tap_read->overlapped.hEvent)) | ||
776 | return FALSE; | ||
777 | |||
778 | /* we successfully read something from the TAP and now need to | ||
779 | * send it our via STDOUT. Is that possible at the moment? */ | ||
780 | if (IOSTATE_READY == std_out->iostate && 0 < tap_read->buffer_size ) | ||
781 | { /* hand over this buffers content */ | ||
782 | memcpy (std_out->buffer, | ||
783 | tap_read->buffer, | ||
784 | MAX_SIZE); | ||
785 | std_out->buffer_size = tap_read->buffer_size; | ||
786 | std_out->iostate = IOSTATE_READY; | ||
787 | tap_read->iostate = IOSTATE_READY; | ||
788 | } | ||
789 | else if (0 < tap_read->buffer_size) | ||
790 | { /* If we have have read our buffer, wait for our write-partner*/ | ||
791 | tap_read->iostate = IOSTATE_WAITING; | ||
792 | // TODO: shall we attempt to fill our bufferm or should we wait for our write-partner to finish? | ||
793 | } | ||
794 | } | ||
795 | else | ||
796 | { /* operation still pending/queued or failed? */ | ||
797 | int err = GetLastError (); | ||
798 | if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err ) | ||
799 | { /* error occurred, let the rest of the elements finish */ | ||
800 | tap_read->path_open = FALSE; | ||
801 | tap_read->iostate = IOSTATE_FAILED; | ||
802 | } | ||
803 | } | ||
804 | } | ||
805 | return TRUE; | ||
806 | } | ||
807 | |||
808 | static boolean | ||
809 | attempt_tap_write (HANDLE tap_handle, | ||
810 | struct overlapped_facility * tap_write, | ||
811 | struct overlapped_facility * std_in) | ||
812 | { | ||
813 | return TRUE; | ||
814 | } | ||
815 | |||
816 | static boolean | ||
817 | attempt_std_out ( struct overlapped_facility * std_out, | ||
818 | struct overlapped_facility * tap_read) | ||
819 | { | ||
820 | return TRUE; | ||
821 | } | ||
822 | |||
700 | /** | 823 | /** |
701 | * Initialize a overlapped structure | 824 | * Initialize a overlapped structure |
702 | * | 825 | * |
@@ -711,9 +834,10 @@ initialize_overlapped_facility (struct overlapped_facility * elem, | |||
711 | BOOL signaled) | 834 | BOOL signaled) |
712 | { | 835 | { |
713 | 836 | ||
837 | elem->path_open = TRUE; | ||
714 | elem->status = initial_state; | 838 | elem->status = initial_state; |
715 | elem->iostate = 0; | 839 | elem->iostate = 0; |
716 | elem->buffer_size = MAX_SIZE; | 840 | elem->buffer_size = 0; |
717 | elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL); | 841 | elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL); |
718 | if (NULL == elem->overlapped.hEvent) | 842 | if (NULL == elem->overlapped.hEvent) |
719 | return FALSE; | 843 | return FALSE; |
@@ -727,13 +851,8 @@ initialize_overlapped_facility (struct overlapped_facility * elem, | |||
727 | * @param fd_tun tunnel FD | 851 | * @param fd_tun tunnel FD |
728 | */ | 852 | */ |
729 | static void | 853 | static void |
730 | run (HANDLE handle) | 854 | run (HANDLE tap_handle) |
731 | { | 855 | { |
732 | /* read refers to reading from fd_tun, writing to stdout */ | ||
733 | int read_open = 1; | ||
734 | /* write refers to reading from stdin, writing to fd_tun */ | ||
735 | int write_open = 1; | ||
736 | |||
737 | /* IO-Facility for reading from our virtual interface */ | 856 | /* IO-Facility for reading from our virtual interface */ |
738 | struct overlapped_facility tap_read; | 857 | struct overlapped_facility tap_read; |
739 | /* IO-Facility for writing to our virtual interface */ | 858 | /* IO-Facility for writing to our virtual interface */ |
@@ -750,10 +869,7 @@ run (HANDLE handle) | |||
750 | * DHCP and such are all features we will never use in gnunet afaik. | 869 | * DHCP and such are all features we will never use in gnunet afaik. |
751 | * But for openvpn those are essential. | 870 | * But for openvpn those are essential. |
752 | */ | 871 | */ |
753 | if (!tun_up (handle)) | 872 | if (!tun_up (tap_handle)) |
754 | goto teardown; | ||
755 | |||
756 | if (!) | ||
757 | goto teardown; | 873 | goto teardown; |
758 | 874 | ||
759 | /* Initialize our overlapped IO structures*/ | 875 | /* Initialize our overlapped IO structures*/ |
@@ -776,29 +892,34 @@ run (HANDLE handle) | |||
776 | // tunnel_point_to_point | 892 | // tunnel_point_to_point |
777 | // openvpn.c:62 | 893 | // openvpn.c:62 |
778 | 894 | ||
779 | while ((1 == read_open) || (1 == write_open)) | 895 | while (std_in.path_open |
896 | || std_out.path_open | ||
897 | || tap_read.path_open | ||
898 | || tap_write.path_open) | ||
780 | { | 899 | { |
781 | 900 | /* perform READ from stdin if possible */ | |
782 | /* READ from stdin is possible */ | 901 | if ((std_in.path_open && tap_write.path_open) |
783 | if (std_in.status) | 902 | || IOSTATE_QUEUED == std_in.iostate) |
784 | { | 903 | if (!attempt_std_in (&std_in, &tap_write)) |
785 | 904 | break; | |
786 | } | 905 | |
787 | /* READ from tap is possible */ | 906 | /* perform READ from tap if possible */ |
788 | if (tap_read.status) | 907 | if ((tap_read.path_open && std_out.path_open) |
789 | { | 908 | || IOSTATE_QUEUED == tap_read.iostate ) |
790 | 909 | if (!attempt_tap_read (tap_handle, &tap_read, &std_out)) | |
791 | } | 910 | break; |
792 | /* WRITE to tap is possible */ | 911 | |
793 | if (tap_write.status) | 912 | /* perform WRITE to tap if possible */ |
794 | { | 913 | if ( IOSTATE_READY == tap_write.iostate && tap_write.path_open ) |
795 | 914 | if (!attempt_tap_write (tap_handle, &tap_write, &std_in)) | |
796 | } | 915 | break; |
797 | /* WRITE to STDOUT is possible */ | 916 | |
798 | if (std_out.status) | 917 | /* perform WRITE to STDOUT if possible */ |
799 | { | 918 | if ( IOSTATE_READY == std_out.iostate && std_out.path_open) |
800 | 919 | if (!attempt_std_out (&std_out, &tap_read)) | |
801 | } | 920 | break; |
921 | |||
922 | // check if any path is blocked | ||
802 | } | 923 | } |
803 | teardown: | 924 | teardown: |
804 | ; | 925 | ; |