diff options
author | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-01-10 12:36:06 +0000 |
---|---|---|
committer | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-01-10 12:36:06 +0000 |
commit | 763db022115084a225f62f8795a897c1512b8709 (patch) | |
tree | f274da38acbb6238535882bdff5723fda9368622 /src/vpn/gnunet-helper-vpn-windows.c | |
parent | 7c9dad282dc26d582da100d34a463d6aec13fbce (diff) | |
download | gnunet-763db022115084a225f62f8795a897c1512b8709.tar.gz gnunet-763db022115084a225f62f8795a897c1512b8709.zip |
consolidated read and write functions, as we can read from a named pipe
the same way as we can read from our TAP.
added high-level description of attempt_read
Diffstat (limited to 'src/vpn/gnunet-helper-vpn-windows.c')
-rw-r--r-- | src/vpn/gnunet-helper-vpn-windows.c | 241 |
1 files changed, 91 insertions, 150 deletions
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c index f7000e8fa..c67e654e2 100644 --- a/src/vpn/gnunet-helper-vpn-windows.c +++ b/src/vpn/gnunet-helper-vpn-windows.c | |||
@@ -678,7 +678,12 @@ init_tun () | |||
678 | 678 | ||
679 | return handle; | 679 | return handle; |
680 | } | 680 | } |
681 | 681 | /** | |
682 | * Brings a TAP device up and sets it to connected state. | ||
683 | * | ||
684 | * @param handle the handle to our TAP device | ||
685 | * @return True if the operation succeeded, else false | ||
686 | */ | ||
682 | static boolean | 687 | static boolean |
683 | tun_up (HANDLE handle) | 688 | tun_up (HANDLE handle) |
684 | { | 689 | { |
@@ -699,142 +704,69 @@ tun_up (HANDLE handle) | |||
699 | 704 | ||
700 | } | 705 | } |
701 | 706 | ||
707 | /** | ||
708 | * Attempts to read off an input facility (tap or named pipe) in overlapped mode. | ||
709 | * | ||
710 | * 1. | ||
711 | * If the input facility is in IOSTATE_READY, it will issue a new read operation to the | ||
712 | * input handle. Then it goes into IOSTATE_QUEUED state. | ||
713 | * In case the read succeeded instantly the input facility enters 3. | ||
714 | * | ||
715 | * 2. | ||
716 | * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already. | ||
717 | * If it has finished, go to state 3. | ||
718 | * If it has failed, set IOSTATE_FAILED | ||
719 | * | ||
720 | * 3. | ||
721 | * If the output facility is in state IOSTATE_READY, the read-buffer is copied to the output buffer. | ||
722 | * The input facility enters state IOSTATE_READY | ||
723 | * The output facility enters state IOSTATE_READY | ||
724 | * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING | ||
725 | * | ||
726 | * IOSTATE_WAITING is reset by the output facility, once it has completed. | ||
727 | * | ||
728 | * @param input_facility input named pipe or file to work with. | ||
729 | * @param output_facility output pipe or file to hand over data to. | ||
730 | * @return false if an event reset was impossible (OS error), else true | ||
731 | */ | ||
702 | static boolean | 732 | static boolean |
703 | attempt_std_in (struct io_facility * std_in, | 733 | attempt_read (struct io_facility * input_facility, |
704 | struct io_facility * tap_write) | 734 | struct io_facility * output_facility) |
705 | { | ||
706 | |||
707 | if (IOSTATE_READY == std_in->facility_state) | ||
708 | { | ||
709 | if (!ResetEvent (std_in->overlapped.hEvent)) | ||
710 | { | ||
711 | return FALSE; | ||
712 | } | ||
713 | /* std_in->status = ReadFile (std_in->handle, | ||
714 | &std_in->buffer[MAX_SIZE], | ||
715 | MAX_SIZE, | ||
716 | &std_in->buffer_size, | ||
717 | &std_in->overlapped); | ||
718 | */ | ||
719 | /* Check how the task is handled */ | ||
720 | if (std_in->status) | ||
721 | {/* async event processed immediately*/ | ||
722 | |||
723 | /* reset event manually*/ | ||
724 | if (!SetEvent (std_in->overlapped.hEvent)) | ||
725 | return FALSE; | ||
726 | |||
727 | /* we successfully read something from the TAP and now need to | ||
728 | * send it our via STDOUT. Is that possible at the moment? */ | ||
729 | if (IOSTATE_READY == tap_write->facility_state && 0 < std_in->buffer_size) | ||
730 | { /* hand over this buffers content */ | ||
731 | memcpy (tap_write->buffer, | ||
732 | std_in->buffer, | ||
733 | MAX_SIZE); | ||
734 | tap_write->buffer_size = std_in->buffer_size; | ||
735 | tap_write->facility_state = IOSTATE_READY; | ||
736 | } | ||
737 | else if (0 < std_in->buffer_size) | ||
738 | { /* If we have have read our buffer, wait for our write-partner*/ | ||
739 | std_in->facility_state = IOSTATE_WAITING; | ||
740 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? | ||
741 | } | ||
742 | } | ||
743 | else /* operation was either queued or failed*/ | ||
744 | { | ||
745 | int err = GetLastError (); | ||
746 | if (ERROR_IO_PENDING == err) | ||
747 | { /* operation queued */ | ||
748 | std_in->facility_state = IOSTATE_QUEUED; | ||
749 | } | ||
750 | else | ||
751 | { /* error occurred, let the rest of the elements finish */ | ||
752 | std_in->path_open = FALSE; | ||
753 | std_in->facility_state = IOSTATE_FAILED; | ||
754 | } | ||
755 | } | ||
756 | } | ||
757 | // We are queued and should check if the read has finished | ||
758 | else if (IOSTATE_QUEUED == std_in->facility_state) | ||
759 | { | ||
760 | // there was an operation going on already, check if that has completed now. | ||
761 | std_in->status = GetOverlappedResult (std_in->handle, | ||
762 | &std_in->overlapped, | ||
763 | &std_in->buffer_size, | ||
764 | FALSE); | ||
765 | if (std_in->status) | ||
766 | {/* successful return for a queued operation */ | ||
767 | if (!ResetEvent (std_in->overlapped.hEvent)) | ||
768 | return FALSE; | ||
769 | |||
770 | /* we successfully read something from the TAP and now need to | ||
771 | * send it our via STDOUT. Is that possible at the moment? */ | ||
772 | if (IOSTATE_READY == tap_write->facility_state && 0 < std_in->buffer_size) | ||
773 | { /* hand over this buffers content */ | ||
774 | memcpy (tap_write->buffer, | ||
775 | std_in->buffer, | ||
776 | MAX_SIZE); | ||
777 | tap_write->buffer_size = std_in->buffer_size; | ||
778 | tap_write->facility_state = IOSTATE_READY; | ||
779 | std_in->facility_state = IOSTATE_READY; | ||
780 | } | ||
781 | else if (0 < std_in->buffer_size) | ||
782 | { /* If we have have read our buffer, wait for our write-partner*/ | ||
783 | std_in->facility_state = IOSTATE_WAITING; | ||
784 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? | ||
785 | } | ||
786 | } | ||
787 | else | ||
788 | { /* operation still pending/queued or failed? */ | ||
789 | int err = GetLastError (); | ||
790 | if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err) | ||
791 | { /* error occurred, let the rest of the elements finish */ | ||
792 | std_in->path_open = FALSE; | ||
793 | std_in->facility_state = IOSTATE_FAILED; | ||
794 | } | ||
795 | } | ||
796 | } | ||
797 | return TRUE; | ||
798 | } | ||
799 | |||
800 | static boolean | ||
801 | attempt_tap_read (struct io_facility * tap_read, | ||
802 | struct io_facility * std_out) | ||
803 | { | 735 | { |
804 | 736 | ||
805 | if (IOSTATE_READY == tap_read->facility_state) | 737 | if (IOSTATE_READY == input_facility->facility_state) |
806 | { | 738 | { |
807 | if (!ResetEvent (tap_read->overlapped.hEvent)) | 739 | if (!ResetEvent (input_facility->overlapped.hEvent)) |
808 | { | 740 | { |
809 | return FALSE; | 741 | return FALSE; |
810 | } | 742 | } |
811 | tap_read->status = ReadFile (tap_read->handle, | 743 | input_facility->status = ReadFile (input_facility->handle, |
812 | &tap_read->buffer[MAX_SIZE], | 744 | &input_facility->buffer[MAX_SIZE], |
813 | MAX_SIZE, | 745 | MAX_SIZE, |
814 | &tap_read->buffer_size, | 746 | &input_facility->buffer_size, |
815 | &tap_read->overlapped); | 747 | &input_facility->overlapped); |
816 | 748 | ||
817 | /* Check how the task is handled */ | 749 | /* Check how the task is handled */ |
818 | if (tap_read->status) | 750 | if (input_facility->status) |
819 | {/* async event processed immediately*/ | 751 | {/* async event processed immediately*/ |
820 | 752 | ||
821 | /* reset event manually*/ | 753 | /* reset event manually*/ |
822 | if (!SetEvent (tap_read->overlapped.hEvent)) | 754 | if (!SetEvent (input_facility->overlapped.hEvent)) |
823 | return FALSE; | 755 | return FALSE; |
824 | 756 | ||
825 | /* we successfully read something from the TAP and now need to | 757 | /* we successfully read something from the TAP and now need to |
826 | * send it our via STDOUT. Is that possible at the moment? */ | 758 | * send it our via STDOUT. Is that possible at the moment? */ |
827 | if (IOSTATE_READY == std_out->facility_state && 0 < tap_read->buffer_size) | 759 | if (IOSTATE_READY == output_facility->facility_state && 0 < input_facility->buffer_size) |
828 | { /* hand over this buffers content */ | 760 | { /* hand over this buffers content */ |
829 | memcpy (std_out->buffer, | 761 | memcpy (output_facility->buffer, |
830 | tap_read->buffer, | 762 | input_facility->buffer, |
831 | MAX_SIZE); | 763 | MAX_SIZE); |
832 | std_out->buffer_size = tap_read->buffer_size; | 764 | output_facility->buffer_size = input_facility->buffer_size; |
833 | std_out->facility_state = IOSTATE_READY; | 765 | output_facility->facility_state = IOSTATE_READY; |
834 | } | 766 | } |
835 | else if (0 < tap_read->buffer_size) | 767 | else if (0 < input_facility->buffer_size) |
836 | { /* If we have have read our buffer, wait for our write-partner*/ | 768 | { /* If we have have read our buffer, wait for our write-partner*/ |
837 | tap_read->facility_state = IOSTATE_WAITING; | 769 | input_facility->facility_state = IOSTATE_WAITING; |
838 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? | 770 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? |
839 | } | 771 | } |
840 | } | 772 | } |
@@ -843,42 +775,42 @@ attempt_tap_read (struct io_facility * tap_read, | |||
843 | int err = GetLastError (); | 775 | int err = GetLastError (); |
844 | if (ERROR_IO_PENDING == err) | 776 | if (ERROR_IO_PENDING == err) |
845 | { /* operation queued */ | 777 | { /* operation queued */ |
846 | tap_read->facility_state = IOSTATE_QUEUED; | 778 | input_facility->facility_state = IOSTATE_QUEUED; |
847 | } | 779 | } |
848 | else | 780 | else |
849 | { /* error occurred, let the rest of the elements finish */ | 781 | { /* error occurred, let the rest of the elements finish */ |
850 | tap_read->path_open = FALSE; | 782 | input_facility->path_open = FALSE; |
851 | tap_read->facility_state = IOSTATE_FAILED; | 783 | input_facility->facility_state = IOSTATE_FAILED; |
852 | } | 784 | } |
853 | } | 785 | } |
854 | } | 786 | } |
855 | // We are queued and should check if the read has finished | 787 | // We are queued and should check if the read has finished |
856 | else if (IOSTATE_QUEUED == tap_read->facility_state) | 788 | else if (IOSTATE_QUEUED == input_facility->facility_state) |
857 | { | 789 | { |
858 | // there was an operation going on already, check if that has completed now. | 790 | // there was an operation going on already, check if that has completed now. |
859 | tap_read->status = GetOverlappedResult (tap_read->handle, | 791 | input_facility->status = GetOverlappedResult (input_facility->handle, |
860 | &tap_read->overlapped, | 792 | &input_facility->overlapped, |
861 | &tap_read->buffer_size, | 793 | &input_facility->buffer_size, |
862 | FALSE); | 794 | FALSE); |
863 | if (tap_read->status) | 795 | if (input_facility->status) |
864 | {/* successful return for a queued operation */ | 796 | {/* successful return for a queued operation */ |
865 | if (!ResetEvent (tap_read->overlapped.hEvent)) | 797 | if (!ResetEvent (input_facility->overlapped.hEvent)) |
866 | return FALSE; | 798 | return FALSE; |
867 | 799 | ||
868 | /* we successfully read something from the TAP and now need to | 800 | /* we successfully read something from the TAP and now need to |
869 | * send it our via STDOUT. Is that possible at the moment? */ | 801 | * send it our via STDOUT. Is that possible at the moment? */ |
870 | if (IOSTATE_READY == std_out->facility_state && 0 < tap_read->buffer_size) | 802 | if (IOSTATE_READY == output_facility->facility_state && 0 < input_facility->buffer_size) |
871 | { /* hand over this buffers content */ | 803 | { /* hand over this buffers content */ |
872 | memcpy (std_out->buffer, | 804 | memcpy (output_facility->buffer, |
873 | tap_read->buffer, | 805 | input_facility->buffer, |
874 | MAX_SIZE); | 806 | MAX_SIZE); |
875 | std_out->buffer_size = tap_read->buffer_size; | 807 | output_facility->buffer_size = input_facility->buffer_size; |
876 | std_out->facility_state = IOSTATE_READY; | 808 | output_facility->facility_state = IOSTATE_READY; |
877 | tap_read->facility_state = IOSTATE_READY; | 809 | input_facility->facility_state = IOSTATE_READY; |
878 | } | 810 | } |
879 | else if (0 < tap_read->buffer_size) | 811 | else if (0 < input_facility->buffer_size) |
880 | { /* If we have have read our buffer, wait for our write-partner*/ | 812 | { /* If we have have read our buffer, wait for our write-partner*/ |
881 | tap_read->facility_state = IOSTATE_WAITING; | 813 | input_facility->facility_state = IOSTATE_WAITING; |
882 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? | 814 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? |
883 | } | 815 | } |
884 | } | 816 | } |
@@ -887,25 +819,34 @@ attempt_tap_read (struct io_facility * tap_read, | |||
887 | int err = GetLastError (); | 819 | int err = GetLastError (); |
888 | if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err) | 820 | if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err) |
889 | { /* error occurred, let the rest of the elements finish */ | 821 | { /* error occurred, let the rest of the elements finish */ |
890 | tap_read->path_open = FALSE; | 822 | input_facility->path_open = FALSE; |
891 | tap_read->facility_state = IOSTATE_FAILED; | 823 | input_facility->facility_state = IOSTATE_FAILED; |
892 | } | 824 | } |
893 | } | 825 | } |
894 | } | 826 | } |
895 | return TRUE; | 827 | return TRUE; |
896 | } | 828 | } |
897 | 829 | ||
830 | /** | ||
831 | * Attempts to write to an output facility (tap or named pipe) in overlapped mode. | ||
832 | * | ||
833 | * TODO: high level description | ||
834 | * | ||
835 | * @param output_facility output pipe or file to hand over data to. | ||
836 | * @param input_facility input named pipe or file to work with. | ||
837 | * @return false if an event reset was impossible (OS error), else true | ||
838 | */ | ||
898 | static boolean | 839 | static boolean |
899 | attempt_tap_write (struct io_facility * tap_write, | 840 | attempt_write (struct io_facility * output_facility, |
900 | struct io_facility * std_in) | 841 | struct io_facility * input_facility) |
901 | { | 842 | { |
902 | return TRUE; | 843 | if (IOSTATE_READY == output_facility->facility_state && output_facility->buffer_size > 0 ){ |
903 | } | 844 | |
845 | } | ||
846 | else if (IOSTATE_QUEUED == output_facility->facility_state){ | ||
847 | |||
848 | } | ||
904 | 849 | ||
905 | static boolean | ||
906 | attempt_std_out (struct io_facility * std_out, | ||
907 | struct io_facility * tap_read) | ||
908 | { | ||
909 | return TRUE; | 850 | return TRUE; |
910 | } | 851 | } |
911 | 852 | ||
@@ -984,7 +925,7 @@ run (HANDLE tap_handle) | |||
984 | if (FILE_TYPE_PIPE != GetFileType (parent_std_in_handle) || | 925 | if (FILE_TYPE_PIPE != GetFileType (parent_std_in_handle) || |
985 | FILE_TYPE_PIPE != GetFileType (parent_std_out_handle)) | 926 | FILE_TYPE_PIPE != GetFileType (parent_std_out_handle)) |
986 | { | 927 | { |
987 | fprintf (stderr, "Fatal: stdin/stdout must be pipes!\n"); | 928 | fprintf (stderr, "Fatal: stdin/stdout must be named pipes!\n"); |
988 | goto teardown; | 929 | goto teardown; |
989 | } | 930 | } |
990 | 931 | ||
@@ -995,7 +936,7 @@ run (HANDLE tap_handle) | |||
995 | 936 | ||
996 | if (INVALID_HANDLE_VALUE == std_in.handle) | 937 | if (INVALID_HANDLE_VALUE == std_in.handle) |
997 | { | 938 | { |
998 | fprintf (stderr, "Fatal: Could not reopen stdin for in overlapped mode!\n"); | 939 | fprintf (stderr, "Fatal: Could not reopen stdin for in overlapped mode, has to be a named pipe!\n"); |
999 | goto teardown; | 940 | goto teardown; |
1000 | } | 941 | } |
1001 | 942 | ||
@@ -1006,7 +947,7 @@ run (HANDLE tap_handle) | |||
1006 | 947 | ||
1007 | if (INVALID_HANDLE_VALUE == std_out.handle) | 948 | if (INVALID_HANDLE_VALUE == std_out.handle) |
1008 | { | 949 | { |
1009 | fprintf (stderr, "Fatal: Could not reopen stdout for in overlapped mode!\n"); | 950 | fprintf (stderr, "Fatal: Could not reopen stdout for in overlapped mode, has to be a named pipe!\n"); |
1010 | goto teardown; | 951 | goto teardown; |
1011 | } | 952 | } |
1012 | 953 | ||
@@ -1030,23 +971,23 @@ run (HANDLE tap_handle) | |||
1030 | /* perform READ from stdin if possible */ | 971 | /* perform READ from stdin if possible */ |
1031 | if ((std_in.path_open && tap_write.path_open) | 972 | if ((std_in.path_open && tap_write.path_open) |
1032 | || IOSTATE_QUEUED == std_in.facility_state) | 973 | || IOSTATE_QUEUED == std_in.facility_state) |
1033 | if (!attempt_std_in (&std_in, &tap_write)) | 974 | if (!attempt_read (&std_in, &tap_write)) |
1034 | break; | 975 | break; |
1035 | 976 | ||
1036 | /* perform READ from tap if possible */ | 977 | /* perform READ from tap if possible */ |
1037 | if ((tap_read.path_open && std_out.path_open) | 978 | if ((tap_read.path_open && std_out.path_open) |
1038 | || IOSTATE_QUEUED == tap_read.facility_state) | 979 | || IOSTATE_QUEUED == tap_read.facility_state) |
1039 | if (!attempt_tap_read (&tap_read, &std_out)) | 980 | if (!attempt_read (&tap_read, &std_out)) |
1040 | break; | 981 | break; |
1041 | 982 | ||
1042 | /* perform WRITE to tap if possible */ | 983 | /* perform WRITE to tap if possible */ |
1043 | if (IOSTATE_READY == tap_write.facility_state && tap_write.path_open) | 984 | if (IOSTATE_READY == tap_write.facility_state && tap_write.path_open) |
1044 | if (!attempt_tap_write (&tap_write, &std_in)) | 985 | if (!attempt_write (&tap_write, &std_in)) |
1045 | break; | 986 | break; |
1046 | 987 | ||
1047 | /* perform WRITE to STDOUT if possible */ | 988 | /* perform WRITE to STDOUT if possible */ |
1048 | if (IOSTATE_READY == std_out.facility_state && std_out.path_open) | 989 | if (IOSTATE_READY == std_out.facility_state && std_out.path_open) |
1049 | if (!attempt_std_out (&std_out, &tap_read)) | 990 | if (!attempt_write (&std_out, &tap_read)) |
1050 | break; | 991 | break; |
1051 | 992 | ||
1052 | // check if any path is blocked | 993 | // check if any path is blocked |