gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r25741 - gnunet/src/vpn


From: gnunet
Subject: [GNUnet-SVN] r25741 - gnunet/src/vpn
Date: Thu, 10 Jan 2013 12:54:16 +0100

Author: cfuchs
Date: 2013-01-10 12:54:16 +0100 (Thu, 10 Jan 2013)
New Revision: 25741

Modified:
   gnunet/src/vpn/gnunet-helper-vpn-windows.c
Log:
as discussed, vpn-helper-windows will only function if stdin/stdout are 
handed down as pipes.

helper will reopen stdin and stdout in overlapped mode. ReOpenFile 
requires WinXPSP2 or Win2003SP1.




Modified: gnunet/src/vpn/gnunet-helper-vpn-windows.c
===================================================================
--- gnunet/src/vpn/gnunet-helper-vpn-windows.c  2013-01-10 10:49:42 UTC (rev 
25740)
+++ gnunet/src/vpn/gnunet-helper-vpn-windows.c  2013-01-10 11:54:16 UTC (rev 
25741)
@@ -144,13 +144,12 @@
  */
 struct io_facility
 {
-  DWORD handle_type;
   HANDLE handle;
-  
+
   BOOL path_open; // BOOL is winbool, NOT boolean!
   int facility_state;
   BOOL status;
-  
+
   OVERLAPPED overlapped;
   DWORD buffer_size;
   unsigned char buffer[MAX_SIZE];
@@ -164,7 +163,8 @@
 #define IOSTATE_QUEUED           1 /* overlapped I/O has been queued */
 #define IOSTATE_WAITING          3 /* overlapped I/O has finished, but is 
waiting for it's write-partner */
 
-#if WINVER < 0x0600
+// ReOpenFile is only available as of XP SP2 and 2003 SP1
+WINBASEAPI HANDLE WINAPI ReOpenFile (HANDLE, DWORD, DWORD, DWORD);
 
 /**
  * inet_pton() wrapper for WSAStringToAddress()
@@ -203,7 +203,6 @@
     }
   return 0;
 }
-#endif
 
 /**
  * Wrapper for executing a shellcommand in windows.
@@ -705,39 +704,96 @@
                 struct io_facility * tap_write)
 {
 
-  // We could use PeekConsoleInput() or WaitForSingleObject()
-  // however, the interwebs states that WaitForSingleObject with filehandles 
-  // might misbehave on some windows (unspecified which ones!).
-  // unfortunately, peekconsoleinput () just waits for KEYPRESS-event, which 
would never happen on a pipe or a file
-
-  // See:
-  // http://www.cplusplus.com/forum/windows/28837/
-  // 
http://stackoverflow.com/questions/4551644/using-overlapped-io-for-console-input
-  // http://cygwin.com/ml/cygwin/2012-05/msg00322.html
-
-  // possible soltion?
-  // 
http://stackoverflow.com/questions/3661106/overlapped-readfileex-on-child-process-redirected-stdout-never-fires
-
-  // we may read from STDIN, and no job was active
   if (IOSTATE_READY == std_in->facility_state)
     {
+      if (!ResetEvent (std_in->overlapped.hEvent))
+        {
+          return FALSE;
+        }
+/*      std_in->status = ReadFile (std_in->handle,
+                                 &std_in->buffer[MAX_SIZE],
+                                 MAX_SIZE,
+                                 &std_in->buffer_size,
+                                 &std_in->overlapped);
+*/
+      /* Check how the task is handled */
+      if (std_in->status)
+        {/* async event processed immediately*/
 
+          /* reset event manually*/
+          if (!SetEvent (std_in->overlapped.hEvent))
+            return FALSE;
+
+          /* we successfully read something from the TAP and now need to
+           * send it our via STDOUT. Is that possible at the moment? */
+          if (IOSTATE_READY == tap_write->facility_state && 0 < 
std_in->buffer_size)
+            { /* hand over this buffers content */
+              memcpy (tap_write->buffer,
+                      std_in->buffer,
+                      MAX_SIZE);
+              tap_write->buffer_size = std_in->buffer_size;
+              tap_write->facility_state = IOSTATE_READY;
+            }
+          else if (0 < std_in->buffer_size)
+            { /* If we have have read our buffer, wait for our write-partner*/
+              std_in->facility_state = IOSTATE_WAITING;
+              // TODO: shall we attempt to fill our buffer or should we wait 
for our write-partner to finish?
+            }
+        }
+      else /* operation was either queued or failed*/
+        {
+          int err = GetLastError ();
+          if (ERROR_IO_PENDING == err)
+            { /* operation queued */
+              std_in->facility_state = IOSTATE_QUEUED;
+            }
+          else
+            { /* error occurred, let the rest of the elements finish */
+              std_in->path_open = FALSE;
+              std_in->facility_state = IOSTATE_FAILED;
+            }
+        }
     }
-    // we must complete a previous read from stdin, before doing more work
+    // We are queued and should check if the read has finished
   else if (IOSTATE_QUEUED == std_in->facility_state)
     {
-      // there is some data to be read from STDIN! 
-      /*      if (PeekConsoleInput(stdin_handle,
-                                 &std_in->buffer[MAX_SIZE],
-                                 MAX_SIZE,
-                                 &std_in->buffer_size)){
-          
-          
-          
-              }*/
-      // else { // nothing to do, try again next time }
+      // there was an operation going on already, check if that has completed 
now.
+      std_in->status = GetOverlappedResult (std_in->handle,
+                                            &std_in->overlapped,
+                                            &std_in->buffer_size,
+                                            FALSE);
+      if (std_in->status)
+        {/* successful return for a queued operation */
+          if (!ResetEvent (std_in->overlapped.hEvent))
+            return FALSE;
+
+          /* we successfully read something from the TAP and now need to
+           * send it our via STDOUT. Is that possible at the moment? */
+          if (IOSTATE_READY == tap_write->facility_state && 0 < 
std_in->buffer_size)
+            { /* hand over this buffers content */
+              memcpy (tap_write->buffer,
+                      std_in->buffer,
+                      MAX_SIZE);
+              tap_write->buffer_size = std_in->buffer_size;
+              tap_write->facility_state = IOSTATE_READY;
+              std_in->facility_state = IOSTATE_READY;
+            }
+          else if (0 < std_in->buffer_size)
+            { /* If we have have read our buffer, wait for our write-partner*/
+              std_in->facility_state = IOSTATE_WAITING;
+              // TODO: shall we attempt to fill our buffer or should we wait 
for our write-partner to finish?
+            }
+        }
+      else
+        { /* operation still pending/queued or failed? */
+          int err = GetLastError ();
+          if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err)
+            { /* error occurred, let the rest of the elements finish */
+              std_in->path_open = FALSE;
+              std_in->facility_state = IOSTATE_FAILED;
+            }
+        }
     }
-
   return TRUE;
 }
 
@@ -863,13 +919,12 @@
  */
 static boolean
 initialize_io_facility (struct io_facility * elem,
-                                BOOL initial_state,
-                                BOOL signaled)
+                        BOOL initial_state,
+                        BOOL signaled)
 {
 
   elem->path_open = TRUE;
   elem->status = initial_state;
-  elem->handle_type = 0;
   elem->handle = INVALID_HANDLE_VALUE;
   elem->facility_state = 0;
   elem->buffer_size = 0;
@@ -897,6 +952,9 @@
   /* IO-Facility for writing to stdout */
   struct io_facility std_out;
 
+  HANDLE parent_std_in_handle = GetStdHandle (STD_INPUT_HANDLE);
+  HANDLE parent_std_out_handle = GetStdHandle (STD_OUTPUT_HANDLE);
+
   /* tun up: */
   /* we do this HERE and not beforehand (in init_tun()), in contrast to openvpn
    * to remove the need to flush the arp cache, handle DHCP and wrong IPs.
@@ -915,8 +973,6 @@
     goto teardown;
 
   /* Handles for STDIN and STDOUT */
-  std_in.handle = GetStdHandle (STD_INPUT_HANDLE);
-  std_out.handle = GetStdHandle (STD_OUTPUT_HANDLE);
   tap_read.handle = tap_handle;
   tap_write.handle = tap_handle;
 
@@ -925,12 +981,35 @@
    * This part is a problem, because in windows we need to handle files, 
    * pipes and the console differently.
    */
-  std_in.handle_type = GetFileType (std_in.handle);
-  std_out.handle_type = GetFileType (std_out.handle);
-  /* the tap handle is always a file, but we still set this for consistency */
-  tap_read.handle_type = FILE_TYPE_DISK;
-  tap_write.handle_type = FILE_TYPE_DISK;
+  if (FILE_TYPE_PIPE != GetFileType (parent_std_in_handle) ||
+      FILE_TYPE_PIPE != GetFileType (parent_std_out_handle))
+    {
+      fprintf (stderr, "Fatal: stdin/stdout must be pipes!\n");
+      goto teardown;
+    }
 
+  std_in.handle = ReOpenFile (parent_std_in_handle,
+                              GENERIC_READ,
+                              FILE_SHARE_WRITE | FILE_SHARE_READ,
+                              FILE_FLAG_OVERLAPPED);
+
+  if (INVALID_HANDLE_VALUE == std_in.handle)
+    {
+      fprintf (stderr, "Fatal: Could not reopen stdin for in overlapped 
mode!\n");
+      goto teardown;
+    }
+
+  std_out.handle = ReOpenFile (parent_std_out_handle,
+                               GENERIC_WRITE,
+                               FILE_SHARE_READ,
+                               FILE_FLAG_OVERLAPPED);
+
+  if (INVALID_HANDLE_VALUE == std_out.handle)
+    {
+      fprintf (stderr, "Fatal: Could not reopen stdout for in overlapped 
mode!\n");
+      goto teardown;
+    }
+
   //openvpn  
   // Set Device to Subnet-Mode? 
   // do we really need tun.c:2925 ?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]