]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
ps.c debug code
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sat, 18 Feb 2006 16:35:21 +0000 (16:35 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sat, 18 Feb 2006 16:35:21 +0000 (16:35 +0000)
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@902 e7ae566f-a301-0410-adde-c780ea21d3b5

errlevel.h
ps.c

index 426a4ac8007ed6ec909964b573b518c64be4a3e9..20de9fd98fc5c2df4795690033d1f7291c9009e3 100644 (file)
 #define D_ALIGN_DEBUG        LOGLEV(7, 70, M_DEBUG)  /* show verbose struct alignment info */
 #define D_PACKET_TRUNC_DEBUG LOGLEV(7, 70, M_DEBUG)  /* PACKET_TRUNCATION_CHECK verbose */
 #define D_PING               LOGLEV(7, 70, M_DEBUG)  /* PING send/receive messages */
-#define D_PS_PROXY_DEBUG     LOGLEV(7, 70, M_DEBUG)  /* port share proxy debug */
+#define D_PS_PROXY_DEBUG     LOGLEV(4, 70, M_DEBUG)  /* JYFIXME port share proxy debug */
 
 #define D_HANDSHAKE_VERBOSE  LOGLEV(8, 70, M_DEBUG)  /* show detailed description of each handshake */
 #define D_TLS_DEBUG_MED      LOGLEV(8, 70, M_DEBUG)  /* limited info from tls_session routines */
diff --git a/ps.c b/ps.c
index 5b15b90c10f5a4c3d27fe16ab3e2c5263616e674..b9be9b55e8e33bc01803b82b807c2395b3600192 100644 (file)
--- a/ps.c
+++ b/ps.c
@@ -238,6 +238,19 @@ pc_list_len (struct proxy_connection *pc)
   return count;
 }
 
+static void
+proxy_entry_close_sd (struct proxy_connection *pc, struct event_set *es)
+{
+  if (pc->defined && socket_defined (pc->sd))
+    {
+      dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: delete sd=%d", pc->sd);
+      if (es)
+       event_del (es, pc->sd);
+      openvpn_close_socket (pc->sd);
+      pc->sd = SOCKET_UNDEFINED;
+    }
+}
+
 /*
  * Mark a proxy entry and its counterpart for close.
  */
@@ -247,18 +260,10 @@ proxy_entry_mark_for_close (struct proxy_connection *pc, struct event_set *es)
   if (pc->defined)
     {
       struct proxy_connection *cp = pc->counterpart;
-      dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: delete sd=%d", pc->sd);
-      if (socket_defined (pc->sd))
-       {
-         if (es)
-           event_del (es, pc->sd);
-         openvpn_close_socket (pc->sd);
-         pc->sd = SOCKET_UNDEFINED;
-       }
+      proxy_entry_close_sd (pc, es);
       free_buf (&pc->buf);
       pc->buffer_initial = false;
       pc->rwflags = 0;
-      pc->counterpart = NULL;
       pc->defined = false;
       if (cp && cp->defined && cp->counterpart == pc)
        proxy_entry_mark_for_close (cp, es);
@@ -327,7 +332,7 @@ sock_addr_set (struct openvpn_sockaddr *osaddr,
 static inline void
 proxy_connection_io_requeue (struct proxy_connection *pc, const int rwflags_new, struct event_set *es)
 {
-  if (pc->rwflags != rwflags_new)
+  if (socket_defined (pc->sd) && pc->rwflags != rwflags_new)
     {
       event_ctl (es, pc->sd, rwflags_new, (void*)pc);
       pc->rwflags = rwflags_new;
@@ -489,67 +494,120 @@ control_message_from_parent (const socket_descriptor_t sd_control,
   return ret;
 }
 
-/* proxy_connection_io_xfer return values */
+/*
+ * Return values for proxy_connection_io functions
+ */
+
+#define IOSTAT_UNDEF            0
+#define IOSTAT_EAGAIN_ON_READ   1 /* recv returned EAGAIN */
+#define IOSTAT_EAGAIN_ON_WRITE  2 /* send returned EAGAIN */
+#define IOSTAT_READ_ERROR       3 /* the other end of our read socket (pc) was closed */
+#define IOSTAT_WRITE_ERROR      4 /* the other end of our write socket (pc->counterpart) was closed */
+#define IOSTAT_BOTH_CLOSED      5 /* both sockets are closed, preventing action */
+#define IOSTAT_HALF_CLOSED_1    6 /* one socket is closed, preventing action */
+#define IOSTAT_HALF_CLOSED_2    7 /* one socket is closed, preventing action */
+#define IOSTAT_GOOD             8 /* nothing to report */
+#define IOSTAT_ASYMFLUSH        9 /* pc socket is closed, flushed send data to pc->counterpart socket */
+
+static int
+proxy_connection_io_recv (struct proxy_connection *pc)
+{
+  /* recv data from socket */
+  ssize_t status = recv (pc->sd, BPTR(&pc->buf), BCAP(&pc->buf), MSG_NOSIGNAL);
+  if (status == -1)
+    {
+      return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
+    }
+  else
+    {
+      if (!status)
+       return IOSTAT_READ_ERROR;
+      pc->buf.len = status;
+    }
+  return IOSTAT_GOOD;
+}
+
+static int
+proxy_connection_io_send (struct proxy_connection *pc)
+{
+  if ((get_random() % 4096) == 0) // JYFIXME
+    {
+      /* send data to counterpart socket */
+      ssize_t status = send (pc->counterpart->sd, BPTR(&pc->buf), BLEN(&pc->buf), MSG_NOSIGNAL);
+      if (status == -1)
+       {
+         const int e = errno;
+         return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_WRITE_ERROR;
+       }
+      else
+       {
+         if (status != pc->buf.len)
+           return IOSTAT_WRITE_ERROR;
+         pc->buf.len = 0;
+       }
 
-#define IOSTAT_EAGAIN_ON_READ   0
-#define IOSTAT_EAGAIN_ON_WRITE  1
-#define IOSTAT_ERROR            2
+      /* realloc send buffer after initial send */
+      if (pc->buffer_initial)
+       {
+         free_buf (&pc->buf);
+         pc->buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
+         pc->buffer_initial = false;
+       }
+      return IOSTAT_GOOD;
+    }
+  return IOSTAT_EAGAIN_ON_WRITE;
+}
 
 /*
  * Forward data from pc to pc->counterpart.
- * Return values:
- *
- * IOSTAT_EAGAIN_ON_READ -- recv returned EAGAIN
- * IOSTAT_EAGAIN_ON_WRITE -- send return EAGAIN
- * IOSTAT_ERROR -- the other end of one of our sockets was closed
  */
+
 static int
 proxy_connection_io_xfer (struct proxy_connection *pc)
 {
-  while (true)
+  const bool sd_defined = (pc->defined && socket_defined (pc->sd));
+  const bool sd_counterpart_defined = (pc->counterpart->defined && socket_defined (pc->counterpart->sd));
+
+  if (sd_defined && sd_counterpart_defined)
     {
-      if (!BLEN (&pc->buf))
+      while (true)
        {
-         /* recv data from socket */
-         ssize_t status = recv (pc->sd, BPTR(&pc->buf), BCAP(&pc->buf), MSG_NOSIGNAL);
-         if (status == -1)
+         if (!BLEN (&pc->buf))
            {
-             return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_ERROR;
+             const int status = proxy_connection_io_recv (pc);
+             if (status != IOSTAT_GOOD)
+               return status;
            }
-         else
+
+         if (BLEN (&pc->buf))
            {
-             if (!status)
-               return IOSTAT_ERROR;
-             pc->buf.len = status;
+             const int status = proxy_connection_io_send (pc);
+             if (status != IOSTAT_GOOD)
+               return status;
            }
        }
-
+    }
+  else if (!sd_defined && sd_counterpart_defined)
+    {
       if (BLEN (&pc->buf))
        {
-         /* send data to counterpart socket */
-         ssize_t status = send (pc->counterpart->sd, BPTR(&pc->buf), BLEN(&pc->buf), MSG_NOSIGNAL);
-         if (status == -1)
-           {
-             const int e = errno;
-             return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_ERROR;
-           }
-         else
-           {
-             if (status != pc->buf.len)
-               return IOSTAT_ERROR;
-             pc->buf.len = 0;
-           }
-
-         /* successful send */
-         if (pc->buffer_initial)
-           {
-             free_buf (&pc->buf);
-             pc->buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
-             pc->buffer_initial = false;
-           }
+         /*
+          * One side of the connection has been closed, but the other side is open
+          * and still has pending output which must be sent before closure.
+          */
+         const int status = proxy_connection_io_send (pc);
+         dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: asymmetric flush on sd=%d status=%d",
+               pc->counterpart->sd, status);
+         return (status == IOSTAT_EAGAIN_ON_WRITE) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_ASYMFLUSH;
        }
+      else
+       return IOSTAT_HALF_CLOSED_1;
+    }
+  else if (sd_defined && !sd_counterpart_defined)
+    {
+      return IOSTAT_HALF_CLOSED_2;
     }
-  return IOSTAT_ERROR;
+  return IOSTAT_BOTH_CLOSED;
 }
 
 /*
@@ -560,16 +618,45 @@ proxy_connection_io_status (const int status, int *rwflags_pc, int *rwflags_cp)
 {
   switch (status)
     {
-       case IOSTAT_EAGAIN_ON_READ:
-         *rwflags_pc |= EVENT_READ;
-         *rwflags_cp &= ~EVENT_WRITE;
-         return true;
-       case IOSTAT_EAGAIN_ON_WRITE:
-         *rwflags_pc &= ~EVENT_READ;
-         *rwflags_cp |= EVENT_WRITE;
-         return true;
-       default:
-         return false;
+    case IOSTAT_EAGAIN_ON_READ:
+      *rwflags_pc |= EVENT_READ;
+      *rwflags_cp &= ~EVENT_WRITE;
+      return true;
+    case IOSTAT_EAGAIN_ON_WRITE:
+      *rwflags_pc &= ~EVENT_READ;
+      *rwflags_cp |= EVENT_WRITE;
+      return true;
+    default:
+      return false;
+    }
+}
+
+static void
+proxy_connection_close (struct proxy_connection *pc, struct event_set *es)
+{
+  if (BLEN (&pc->buf) && pc->counterpart && socket_defined (pc->counterpart->sd))
+    proxy_entry_close_sd (pc, es);          /* close one side of the connection (pc) */
+  else
+    proxy_entry_mark_for_close (pc, es);    /* close both sides of the connection */
+}
+
+static void
+proxy_connection_exception (struct proxy_connection *pc, const int status, struct event_set *es)
+{
+  dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: proxy_connection_exception, status=%d", status);
+  switch (status)
+    {
+    case IOSTAT_READ_ERROR:
+      proxy_connection_close (pc, es);
+      break;
+    case IOSTAT_WRITE_ERROR:
+      proxy_connection_close (pc->counterpart, es);
+      break;
+    case IOSTAT_ASYMFLUSH:
+      proxy_entry_mark_for_close (pc, es); /* close both sides of the connection */
+      break;
+    default:
+      break;
     }
 }
 
@@ -577,36 +664,29 @@ proxy_connection_io_status (const int status, int *rwflags_pc, int *rwflags_cp)
  * Dispatch function for forwarding data between the two socket fds involved
  * in the proxied connection.
  */
-static bool
+static void
 proxy_connection_io_dispatch (struct proxy_connection *pc,
                              const int rwflags,
                              struct event_set *es)
 {
   struct proxy_connection *cp = pc->counterpart;
-  int status;
   int rwflags_pc = pc->rwflags;
   int rwflags_cp = cp->rwflags;
 
   if (rwflags & EVENT_READ)
     {
-      status = proxy_connection_io_xfer (pc);
+      const int status = proxy_connection_io_xfer (pc);
       if (!proxy_connection_io_status (status, &rwflags_pc, &rwflags_cp))
-       goto bad;
+       proxy_connection_exception (pc, status, es);
     }
   if (rwflags & EVENT_WRITE)
     {
-      status = proxy_connection_io_xfer (cp);
+      const int status = proxy_connection_io_xfer (cp);
       if (!proxy_connection_io_status (status, &rwflags_cp, &rwflags_pc))
-       goto bad;
+       proxy_connection_exception (pc, status, es);
     }
   proxy_connection_io_requeue (pc, rwflags_pc, es);
   proxy_connection_io_requeue (cp, rwflags_cp, es);
-
-  return true;
-
- bad:
-  proxy_entry_mark_for_close (pc, es);
-  return false;
 }
 
 /*