[Telepathy-commits] [telepathy-gabble/master] Support streams opened by the remote host

Marco Barisione marco at barisione.org
Tue Jan 6 08:41:20 PST 2009


---
 src/bytestream-socks5.c |  105 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/src/bytestream-socks5.c b/src/bytestream-socks5.c
index 8087a3d..57ed6b6 100644
--- a/src/bytestream-socks5.c
+++ b/src/bytestream-socks5.c
@@ -80,9 +80,11 @@ enum
 enum _Socks5State
 {
   SOCKS5_STATE_INVALID,
-  SOCKS5_STATE_AUTH,
+  SOCKS5_STATE_AUTH_REQUEST_SENT,
   SOCKS5_STATE_CONNECT_REQUESTED,
   SOCKS5_STATE_CONNECTED,
+  SOCKS5_STATE_AWAITING_AUTH_REQUEST,
+  SOCKS5_STATE_AWAITING_COMMAND,
 };
 
 typedef enum _Socks5State Socks5State;
@@ -433,7 +435,7 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
 
   switch (priv->socks5_state)
     {
-      case SOCKS5_STATE_AUTH:
+      case SOCKS5_STATE_AUTH_REQUEST_SENT:
         if (string->len < 2)
           return 0;
 
@@ -472,6 +474,39 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
 
         return 2;
 
+      case SOCKS5_STATE_AWAITING_AUTH_REQUEST:
+        if (string->len < 3)
+          return 0;
+
+        /* FIXME: handle errors */
+        g_assert (string->str[0] == SOCKS5_VERSION &&
+            string->str[1] == 1 &&
+            string->str[2] == SOCKS5_AUTH_NONE);
+
+        msg[0] = SOCKS5_VERSION;
+        msg[1] = SOCKS5_AUTH_NONE;
+
+        socks5_schedule_write (self, msg, 2);
+
+        priv->socks5_state = SOCKS5_STATE_AWAITING_COMMAND;
+
+        return 3;
+
+      case SOCKS5_STATE_AWAITING_COMMAND:
+        if (string->len < 47)
+          return 0;
+
+        /* FIXME: check the values */
+
+        msg[0] = SOCKS5_VERSION;
+        msg[1] = SOCKS5_STATUS_OK; // XXX rinominare OK?
+
+        socks5_schedule_write (self, msg, 2);
+
+        priv->socks5_state = SOCKS5_STATE_CONNECTED;
+
+        return 47;
+
       case SOCKS5_STATE_CONNECTED:
         g_signal_emit (G_OBJECT (self), signals[DATA_RECEIVED], 0, priv->peer_handle, string);
 
@@ -626,8 +661,6 @@ socks5_connect (gpointer data)
   g_assert (priv->read_buffer == NULL);
   priv->read_buffer = g_string_sized_new (4096);
 
-  priv->socks5_state = SOCKS5_STATE_AUTH;
-
   msg[0] = SOCKS5_VERSION;
   /* Number of auth methods we are offering */
   msg[1] = 1;
@@ -635,6 +668,8 @@ socks5_connect (gpointer data)
 
   socks5_schedule_write (self, msg, 3);
 
+  priv->socks5_state = SOCKS5_STATE_AUTH_REQUEST_SENT;
+
   return FALSE;
 }
 
@@ -912,6 +947,47 @@ socks5_init_reply_cb (GabbleConnection *conn,
   return LM_HANDLER_RESULT_REMOVE_MESSAGE;
 }
 
+static gboolean
+socks5_listen_cb (GIOChannel *source,
+                  GIOCondition condition,
+                  gpointer data)
+{
+  GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (data);
+  GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self);
+  gint fd;
+  struct sockaddr_in addr;
+  guint addr_len = sizeof (addr);
+  int flags;
+
+  fd = accept (g_io_channel_unix_get_fd (source), (struct sockaddr *) &addr,
+      &addr_len);
+
+  /* Set non-blocking */
+  flags = fcntl (fd, F_GETFL, 0);
+  fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+
+  priv->io_channel = g_io_channel_unix_new (fd);
+
+  g_io_channel_set_encoding (priv->io_channel, NULL, NULL);
+  g_io_channel_set_buffered (priv->io_channel, FALSE);
+  g_io_channel_set_close_on_unref (priv->io_channel, TRUE);
+
+  priv->read_watch = g_io_add_watch(priv->io_channel, G_IO_IN,
+      socks5_channel_readable_cb, self);
+  priv->error_watch = g_io_add_watch(priv->io_channel, G_IO_HUP | G_IO_ERR,
+      socks5_channel_error_cb, self);
+
+  g_assert (priv->write_buffer == NULL);
+  priv->write_buffer = g_string_new ("");
+
+  g_assert (priv->read_buffer == NULL);
+  priv->read_buffer = g_string_sized_new (4096);
+
+  priv->socks5_state = SOCKS5_STATE_AWAITING_AUTH_REQUEST;
+
+  return FALSE;
+}
+
 /*
  * gabble_bytestream_socks5_initiate
  *
@@ -922,8 +998,10 @@ gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
 {
   GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface);
   GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self);
+  struct sockaddr_in addr;
+  gint fd;
+  GIOChannel *channel;
   LmMessage *msg;
-  //gchar *block_size;
 
   if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_INITIATING)
     {
@@ -932,6 +1010,21 @@ gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
       return FALSE;
     }
 
+  fd = socket (AF_INET, SOCK_STREAM, 0);
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = INADDR_ANY;
+  addr.sin_port = htons (5087);
+
+  /* FIXME: check the return values */
+  bind (fd, (struct sockaddr *)&addr, sizeof (addr));
+  listen (fd, 5);
+  channel = g_io_channel_unix_new (fd);
+
+  g_io_channel_set_close_on_unref (channel, TRUE);
+
+  /* FIXME handle errors */
+  priv->read_watch = g_io_add_watch (channel, G_IO_IN, socks5_listen_cb, self);
+
   /* FIXME: send a real address and port. */
   msg = lm_message_build (priv->peer_jid, LM_MESSAGE_TYPE_IQ,
       '@', "type", "set",
@@ -942,7 +1035,7 @@ gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
         '(', "streamhost", "",
           '@', "jid", priv->peer_jid,
           '@', "host", "127.0.0.1",
-          '@', "port", "5086",
+          '@', "port", "5087",
         ')',
       ')', NULL);
 
-- 
1.5.6.5




More information about the Telepathy-commits mailing list