[Telepathy-commits] [telepathy-gabble/master] Add more comments and make code clearer
Marco Barisione
marco at barisione.org
Tue Jan 6 08:41:30 PST 2009
---
src/bytestream-factory.c | 1 +
src/bytestream-socks5.c | 74 +++++++++++++++++++++++++++++++++++----------
2 files changed, 58 insertions(+), 17 deletions(-)
diff --git a/src/bytestream-factory.c b/src/bytestream-factory.c
index 36f5ba9..f6d71a3 100644
--- a/src/bytestream-factory.c
+++ b/src/bytestream-factory.c
@@ -117,6 +117,7 @@ struct _GabbleBytestreamFactoryPrivate
*
* BytestreamIdentifier -> GabbleBytestreamIBB */
GHashTable *ibb_bytestreams;
+ /* BytestreamIdentifier -> GabbleBytestreamSocks5 */
GHashTable *socks5_bytestreams;
/* MUC pseudo-IBB - data sent by groupchat messages, IQs not allowed.
diff --git a/src/bytestream-socks5.c b/src/bytestream-socks5.c
index 2e5b697..28a5838 100644
--- a/src/bytestream-socks5.c
+++ b/src/bytestream-socks5.c
@@ -108,6 +108,9 @@ typedef enum _Socks5State Socks5State;
#define SOCKS5_STATUS_OK 0x00
#define SOCKS5_AUTH_NONE 0x00
+#define SHA1_LENGTH 40
+#define SOCKS5_CONNECT_LENGTH (7 + SHA1_LENGTH)
+
struct _Streamhost
{
gchar *jid;
@@ -155,7 +158,11 @@ struct _GabbleBytestreamSocks5Private
GabbleBytestreamState bytestream_state;
gchar *peer_jid;
+ /* List of Streamhost */
GSList *streamhosts;
+
+ /* Connections to streamhosts are async, so we keep the IQ set message
+ * around */
LmMessage *msg_for_acknowledge_connection;
GIOChannel *io_channel;
@@ -510,6 +517,9 @@ socks5_error (GabbleBytestreamSocks5 *self)
priv->socks5_state = SOCKS5_STATE_ERROR;
+ /* If msg_for_acknowledge_connection is not NULL it means that we are
+ * trying to find a working streamhost, so we should try the next available
+ * one instead of just failing */
if (priv->msg_for_acknowledge_connection != NULL)
{
/* The attempt for connect to the streamhost failed... */
@@ -577,7 +587,7 @@ socks5_channel_writable_cb (GIOChannel *source,
if (status != G_IO_STATUS_NORMAL)
{
- DEBUG ("Error writing on the SOCSK5 bytestream");
+ DEBUG ("Error writing on the SOCKS5 bytestream");
socks5_error (self);
return FALSE;
@@ -601,14 +611,16 @@ socks5_schedule_write (GabbleBytestreamSocks5 *self,
socks5_channel_writable_cb, self);
}
+/* Process the received data and returns the number of bytes that have been
+ * used */
static gsize
socks5_handle_received_data (GabbleBytestreamSocks5 *self,
GString *string)
{
GabbleBytestreamSocks5Private *priv =
GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self);
- gchar msg[47] = {'\0'};
- guint authentication_methods;
+ gchar msg[SOCKS5_CONNECT_LENGTH];
+ guint auth_len;
guint i;
const gchar *from;
const gchar *to;
@@ -619,6 +631,8 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
switch (priv->socks5_state)
{
case SOCKS5_STATE_AUTH_REQUEST_SENT:
+ /* We sent an authorization request and we are awaiting for a
+ * response, the response is 2 bytes-long */
if (string->len < 2)
return 0;
@@ -631,6 +645,8 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
return string->len;
}
+ /* We have been authorized, let's send a CONNECT command */
+
from = lm_message_node_get_attribute (
priv->msg_for_acknowledge_connection->node, "from");
to = lm_message_node_get_attribute (
@@ -660,6 +676,8 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
return 2;
case SOCKS5_STATE_CONNECT_REQUESTED:
+ /* We sent an CONNECT request and we are awaiting for a response, the
+ * response is 2 bytes-long */
if (string->len < 2)
return 0;
@@ -674,6 +692,7 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
priv->socks5_state = SOCKS5_STATE_CONNECTED;
+ /* Acknowledge the connection */
iq_result = lm_iq_message_make_result (
priv->msg_for_acknowledge_connection);
if (NULL != iq_result)
@@ -696,6 +715,8 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
return 2;
case SOCKS5_STATE_AWAITING_AUTH_REQUEST:
+ /* A client connected to us and we are awaiting for the authorization
+ * request (at least 2 bytes) */
if (string->len < 2)
return 0;
@@ -707,21 +728,24 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
return string->len;
}
- authentication_methods = string->str[1];
- if (string->len < authentication_methods + 2)
+ /* The auth request string is SOCKS5_VERSION + # of methods + methods */
+ auth_len = string->str[1] + 2;
+ if (string->len < auth_len)
+ /* We are still receiving some auth method */
return 0;
- for (i = 0; i < authentication_methods; i++)
+ for (i = 2; i < auth_len; i++)
{
- if (string->str[i + 2] == SOCKS5_AUTH_NONE)
+ if (string->str[i] == SOCKS5_AUTH_NONE)
{
+ /* Authorize the connection */
msg[0] = SOCKS5_VERSION;
msg[1] = SOCKS5_AUTH_NONE;
socks5_schedule_write (self, msg, 2);
priv->socks5_state = SOCKS5_STATE_AWAITING_COMMAND;
- return authentication_methods + 2;
+ return auth_len;
}
}
@@ -729,26 +753,35 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
socks5_error (self);
- return authentication_methods + 2;
+ return auth_len;
case SOCKS5_STATE_AWAITING_COMMAND:
- if (string->len < 47)
+ /* The client has been authorized and we are waiting for a command,
+ * the only one supported by the SOCKS5 bytestreams XEP is
+ * CONNECT with:
+ * - ATYP = DOMAIN
+ * - PORT = 0
+ * - DOMAIN = SHA1(sid + initiator + target)
+ */
+ if (string->len < SOCKS5_CONNECT_LENGTH)
return 0;
if (string->str[0] != SOCKS5_VERSION ||
string->str[1] != SOCKS5_CMD_CONNECT ||
string->str[2] != SOCKS5_RESERVED ||
string->str[3] != SOCKS5_ATYP_DOMAIN ||
- string->str[4] != 40 ||
- string->str[45] != 0 ||
- string->str[46] != 0)
+ string->str[4] != SHA1_LENGTH ||
+ string->str[45] != 0 || /* first half of the port number */
+ string->str[46] != 0) /* second half of the port number */
{
- DEBUG ("Invalid SOCSK5 connect message");
+ DEBUG ("Invalid SOCKS5 connect message");
socks5_error (self);
return string->len;
}
+ /* FIXME: check the domain type */
+
msg[0] = SOCKS5_VERSION;
msg[1] = SOCKS5_STATUS_OK;
@@ -756,20 +789,22 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
priv->socks5_state = SOCKS5_STATE_CONNECTED;
- return 47;
+ return SOCKS5_CONNECT_LENGTH;
case SOCKS5_STATE_CONNECTED:
+ /* We are connected, everything we receive now is data */
g_signal_emit (G_OBJECT (self), signals[DATA_RECEIVED], 0,
priv->peer_handle, string);
return string->len;
case SOCKS5_STATE_ERROR:
- /* An error occurred and the channel will be close in an idle
+ /* An error occurred and the channel will be closed in an idle
* callback, so let's just throw away the data we receive */
return string->len;
case SOCKS5_STATE_INVALID:
+ DEBUG ("Invalid SOCKS5 state");
break;
}
@@ -908,7 +943,8 @@ socks5_connect (gpointer data)
msg[0] = SOCKS5_VERSION;
- /* Number of auth methods we are offering */
+ /* Number of auth methods we are offering, we support just
+ * SOCKS5_AUTH_NONE */
msg[1] = 1;
msg[2] = SOCKS5_AUTH_NONE;
@@ -1416,6 +1452,10 @@ gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
}
g_list_free (ips);
+ /* FIXME: for now we support only direct connections, we should also
+ * add support for external proxies to have more chances to make the
+ * bytestream work */
+
if (!_gabble_connection_send_with_reply (priv->conn, msg,
socks5_init_reply_cb, G_OBJECT (self), NULL, NULL))
{
--
1.5.6.5
More information about the Telepathy-commits
mailing list