cpw.malu.xmpp.jingle_ft: 16079fdc: Can now connect socks5 bytestreams in bo...
malu at pidgin.im
malu at pidgin.im
Sat Apr 4 06:30:44 EDT 2009
-----------------------------------------------------------------
Revision: 16079fdc89df0572a9d5a3181a8e22b35603497b
Ancestor: f19687878c8a00e4120c5612d76fb1cf6dae5bfd
Author: malu at pidgin.im
Date: 2009-04-04T10:19:38
Branch: im.pidgin.cpw.malu.xmpp.jingle_ft
URL: http://d.pidgin.im/viewmtn/revision/info/16079fdc89df0572a9d5a3181a8e22b35603497b
Modified files:
libpurple/protocols/jabber/jingle/file-transfer.c
libpurple/protocols/jabber/jingle/s5b.c
ChangeLog:
Can now connect socks5 bytestreams in both directions.
Still doesn't set up the file transfer on it though...
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/jingle/file-transfer.c d24475bec9bb750cd139846098e54e7f43c84dd3
+++ libpurple/protocols/jabber/jingle/file-transfer.c e860803fd3dc0a58553a646c003c69366777305a
@@ -676,7 +676,14 @@ jingle_file_transfer_handle_action_inter
JingleTransport *transport = jingle_transport_parse(
xmlnode_get_child(xmlcontent, "transport"));
- /* do stuff... */
+ /* if there is a <streamhost-used/>, signal local S5B transport
+ to stop connections attempts */
+ /* if we are the receiver and sent a <streamhost-used/> to the
+ initiator, we should give up our own listening streamhost to
+ avoid ending up with two parallell streams */
+ /* also when receiving a <streamhost-used/> we need to check if
+ that is not one of our local streamhosts, in which case it is
+ a proxy, and we should connect to that */
/* we should check for "stream-host" error (in the case of S5B) and
offer a transport-replace with IBB */
============================================================
--- libpurple/protocols/jabber/jingle/s5b.c 04cfaa7c4b43ba81053a72ce6b3c584195f47396
+++ libpurple/protocols/jabber/jingle/s5b.c 075b05fb1064814c2ecefe6b2f515ea16267c5ca
@@ -120,6 +120,9 @@ struct _JingleS5BPrivate {
PurpleNetworkListenData *listen_data;
PurpleProxyInfo *ppi;
int watcher;
+ char *rxqueue;
+ size_t rxlen;
+ gsize rxmaxlen;
GList *remote_streamhosts;
GList *local_streamhosts;
GList *remaining_streamhosts; /* pointer to untested remote SHs */
@@ -193,13 +196,6 @@ jingle_s5b_init (JingleS5B *s5b)
{
s5b->priv = JINGLE_S5B_GET_PRIVATE(s5b);
memset(s5b->priv, 0, sizeof(s5b->priv));
- s5b->priv->local_streamhosts = NULL;
- s5b->priv->remote_streamhosts = NULL;
- s5b->priv->fd = 0;
- s5b->priv->local_fd = 0;
- s5b->priv->remote_fd = 0;
- s5b->priv->sid = NULL;
- s5b->priv->ppi = NULL;
}
static void
@@ -354,6 +350,303 @@ static void
} JingleS5BConnectData;
static void
+jingle_s5b_send_read_again_resp_cb(gpointer data, gint source,
+ PurpleInputCondition cond)
+{
+ JingleS5B *s5b = ((JingleS5BConnectData *) data)->s5b;
+ int len;
+
+ purple_debug_info("jingle-s5b", "in jingle_s5b_send_read_again_cb\n");
+ len = write(source, s5b->priv->rxqueue + s5b->priv->rxlen,
+ s5b->priv->rxmaxlen - s5b->priv->rxlen);
+ if (len < 0 && errno == EAGAIN)
+ return;
+ else if (len < 0) {
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ g_free(s5b->priv->rxqueue);
+ s5b->priv->rxqueue = NULL;
+ close(source);
+ /* TODO: signal to the content that an error has occurred */
+ return;
+ }
+ s5b->priv->rxlen += len;
+
+ if (s5b->priv->rxlen < s5b->priv->rxmaxlen)
+ return;
+
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ g_free(s5b->priv->rxqueue);
+ s5b->priv->rxqueue = NULL;
+
+ /* Before actually starting sending the file, we need to wait until the
+ * recipient sends the IQ result with <streamhost-used/>
+ */
+ purple_debug_info("jingle-s5b", "SOCKS5 connection negotiation completed. "
+ "Waiting for IQ result to start file transfer.\n");
+
+ g_free(data);
+}
+
+static void
+jingle_s5b_send_read_again_cb(gpointer data, gint source,
+ PurpleInputCondition cond)
+{
+ JingleS5B *s5b = ((JingleS5BConnectData *) data)->s5b;
+ JingleSession *session = ((JingleS5BConnectData *) data)->session;
+ const gchar *who = jingle_session_get_remote_jid(session);
+ JabberID *dstjid = jabber_id_new(who);
+ JabberStream *js = jingle_session_get_js(session);
+ char buffer[256];
+ int len;
+ char *dstaddr, *hash;
+ const char *host;
+
+ purple_debug_info("jingle-s5b",
+ "in jingle_s5b_send_read_again_cb\n");
+
+ if(s5b->priv->rxlen < 5) {
+ purple_debug_info("jingle-s5b", "reading the first 5 bytes\n");
+ len = read(source, buffer, 5 - s5b->priv->rxlen);
+ if(len < 0 && errno == EAGAIN)
+ return;
+ else if(len <= 0) {
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ close(source);
+ /* TODO: signal the content that an error occured */
+ return;
+ }
+ s5b->priv->rxqueue =
+ g_realloc(s5b->priv->rxqueue, len + s5b->priv->rxlen);
+ memcpy(s5b->priv->rxqueue + s5b->priv->rxlen, buffer, len);
+ s5b->priv->rxlen += len;
+ return;
+ } else if(s5b->priv->rxqueue[0] != 0x05 || s5b->priv->rxqueue[1] != 0x01 ||
+ s5b->priv->rxqueue[3] != 0x03) {
+ purple_debug_info("jingle-s5b", "invalid socks5 stuff\n");
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ close(source);
+ /* TODO: signal the content that an error occured */
+ return;
+ } else if(s5b->priv->rxlen - 5 < s5b->priv->rxqueue[4] + 2) {
+ purple_debug_info("jingle-s5b", "reading umpteen more bytes\n");
+ len = read(source, buffer,
+ s5b->priv->rxqueue[4] + 5 + 2 - s5b->priv->rxlen);
+ if(len < 0 && errno == EAGAIN)
+ return;
+ else if(len <= 0) {
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ close(source);
+ /* TODO: signal the content that an error occured */
+ return;
+ }
+ s5b->priv->rxqueue =
+ g_realloc(s5b->priv->rxqueue, len + s5b->priv->rxlen);
+ memcpy(s5b->priv->rxqueue + s5b->priv->rxlen, buffer, len);
+ s5b->priv->rxlen += len;
+ }
+
+ if(s5b->priv->rxlen - 5 < s5b->priv->rxqueue[4] + 2)
+ return;
+
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+
+ if(jingle_session_is_initiator(session))
+ dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", s5b->priv->sid,
+ js->user->node, js->user->domain, js->user->resource,
+ dstjid->node, dstjid->domain, dstjid->resource);
+ else
+ dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", s5b->priv->sid,
+ dstjid->node, dstjid->domain, dstjid->resource,
+ js->user->node, js->user->domain, js->user->resource);
+
+ g_free(dstjid);
+
+ /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
+ hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr));
+ purple_debug_info("jingle-s5b", "dstaddr: %s\n", dstaddr);
+ purple_debug_info("jingle-s5b", "expecting to receive hash %s\n", hash);
+
+ if(s5b->priv->rxqueue[4] != 40 || strncmp(hash, s5b->priv->rxqueue+5, 40) ||
+ s5b->priv->rxqueue[45] != 0x00 || s5b->priv->rxqueue[46] != 0x00) {
+ purple_debug_error("jingle-s5b",
+ "someone connected with the wrong info!\n");
+ close(source);
+ /* TODO: signal the content that an error occured */
+ g_free(hash);
+ g_free(dstaddr);
+ return;
+ }
+
+ g_free(hash);
+ g_free(dstaddr);
+
+ g_free(s5b->priv->rxqueue);
+ host = purple_network_get_my_ip(js->fd);
+
+ s5b->priv->rxmaxlen = 5 + strlen(host) + 2;
+ s5b->priv->rxqueue = g_malloc(s5b->priv->rxmaxlen);
+ s5b->priv->rxlen = 0;
+
+ s5b->priv->rxqueue[0] = 0x05;
+ s5b->priv->rxqueue[1] = 0x00;
+ s5b->priv->rxqueue[2] = 0x00;
+ s5b->priv->rxqueue[3] = 0x03;
+ s5b->priv->rxqueue[4] = strlen(host);
+ memcpy(s5b->priv->rxqueue + 5, host, strlen(host));
+ s5b->priv->rxqueue[5+strlen(host)] = 0x00;
+ s5b->priv->rxqueue[6+strlen(host)] = 0x00;
+
+ s5b->priv->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
+ jingle_s5b_send_read_again_resp_cb, data);
+ jingle_s5b_send_read_again_resp_cb(data, source,
+ PURPLE_INPUT_WRITE);
+}
+
+static void
+jingle_s5b_send_read_response_cb(gpointer data, gint source,
+ PurpleInputCondition cond)
+{
+ JingleS5B *s5b = ((JingleS5BConnectData *) data)->s5b;
+ int len;
+
+ purple_debug_info("jingle-s5b", "in jingle_s5b_send_read_response_cb\n");
+
+ len = write(source, s5b->priv->rxqueue + s5b->priv->rxlen,
+ s5b->priv->rxmaxlen - s5b->priv->rxlen);
+ if (len < 0 && errno == EAGAIN)
+ return;
+ else if (len < 0) {
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ g_free(s5b->priv->rxqueue);
+ s5b->priv->rxqueue = NULL;
+ close(source);
+ /* TODO: signal to "surrounding" content that an error has occured */
+ return;
+ }
+ s5b->priv->rxlen += len;
+
+ if (s5b->priv->rxlen < s5b->priv->rxmaxlen)
+ return;
+
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+
+ if (s5b->priv->rxqueue[1] == 0x00) {
+ s5b->priv->watcher = purple_input_add(source, PURPLE_INPUT_READ,
+ jingle_s5b_send_read_again_cb, data);
+ g_free(s5b->priv->rxqueue);
+ s5b->priv->rxqueue = NULL;
+ } else {
+ close(source);
+ /* TODO: signal "surrounding" content that an error has occured */
+ }
+}
+
+static void
+jingle_s5b_send_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+{
+ JingleS5B *s5b = ((JingleS5BConnectData *) data)->s5b;
+ int i;
+ int len;
+ char buffer[256];
+
+ purple_debug_info("jingle-s5b", "in jingle_s5b_send_read_cb\n");
+
+ s5b->priv->local_fd = source;
+
+ if(s5b->priv->rxlen < 2) {
+ purple_debug_info("jingle-s5b", "reading those first two bytes\n");
+ len = read(source, buffer, 2 - s5b->priv->rxlen);
+ if(len < 0 && errno == EAGAIN)
+ return;
+ else if(len <= 0) {
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ close(source);
+ /* TODO: signal the "surrounding" content an error has occured */
+ return;
+ }
+ s5b->priv->rxqueue =
+ g_realloc(s5b->priv->rxqueue, len + s5b->priv->rxlen);
+ memcpy(s5b->priv->rxqueue + s5b->priv->rxlen, buffer, len);
+ s5b->priv->rxlen += len;
+ return;
+ } else if(s5b->priv->rxlen - 2 < s5b->priv->rxqueue[1]) {
+ purple_debug_info("jingle-s5b", "reading the next umpteen bytes\n");
+ len = read(source, buffer, s5b->priv->rxqueue[1] + 2 - s5b->priv->rxlen);
+ if(len < 0 && errno == EAGAIN)
+ return;
+ else if(len <= 0) {
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+ close(source);
+ /* TODO: signal the "surrounding" content an error has occured */
+ return;
+ }
+ s5b->priv->rxqueue =
+ g_realloc(s5b->priv->rxqueue, len + s5b->priv->rxlen);
+ memcpy(s5b->priv->rxqueue + s5b->priv->rxlen, buffer, len);
+ s5b->priv->rxlen += len;
+ }
+
+ if(s5b->priv->rxlen -2 < s5b->priv->rxqueue[1])
+ return;
+
+ purple_input_remove(s5b->priv->watcher);
+ s5b->priv->watcher = 0;
+
+ purple_debug_info("jingle-s5b", "checking to make sure we're socks FIVE\n");
+
+ if(s5b->priv->rxqueue[0] != 0x05) {
+ purple_debug_error("jingle-s5b", "it's not socks FIVE, giving up\n");
+ close(source);
+ /* TODO: signal to the "surrounding" content that an error has occured */
+ return;
+ }
+
+ purple_debug_info("jingle-s5b", "going to test %hhu different methods\n",
+ s5b->priv->rxqueue[1]);
+
+ for(i = 0; i < s5b->priv->rxqueue[1]; i++) {
+ purple_debug_info("jingle-s5b", "testing %hhu\n",
+ s5b->priv->rxqueue[i+2]);
+ if(s5b->priv->rxqueue[i+2] == 0x00) {
+ g_free(s5b->priv->rxqueue);
+ s5b->priv->rxlen = 0;
+ s5b->priv->rxmaxlen = 2;
+ s5b->priv->rxqueue = g_malloc(s5b->priv->rxmaxlen);
+ s5b->priv->rxqueue[0] = 0x05;
+ s5b->priv->rxqueue[1] = 0x00;
+ s5b->priv->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
+ jingle_s5b_send_read_response_cb, data);
+ jingle_s5b_send_read_response_cb(data, source, PURPLE_INPUT_WRITE);
+ s5b->priv->rxqueue = NULL;
+ s5b->priv->rxlen = 0;
+ return;
+ }
+ }
+
+ /* question to self: is this called if there was no methods given? */
+ g_free(s5b->priv->rxqueue);
+ s5b->priv->rxlen = 0;
+ s5b->priv->rxmaxlen = 2;
+ s5b->priv->rxqueue = g_malloc(s5b->priv->rxmaxlen);
+ s5b->priv->rxqueue[0] = 0x05;
+ s5b->priv->rxqueue[1] = 0xFF;
+ s5b->priv->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
+ jingle_s5b_send_read_response_cb, data);
+ jingle_s5b_send_read_response_cb(data,
+ source, PURPLE_INPUT_WRITE);
+}
+
+static void
jingle_s5b_send_connected_cb(gpointer data, gint source,
PurpleInputCondition cond)
{
@@ -381,10 +674,8 @@ jingle_s5b_send_connected_cb(gpointer da
fcntl(acceptfd, F_SETFD, FD_CLOEXEC);
#endif
- /*
s5b->priv->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ,
jingle_s5b_send_read_cb, data);
- */
}
static void
@@ -487,9 +778,16 @@ jingle_s5b_connect_cb(gpointer data, gin
jingle_s5b_connect_cb(gpointer data, gint source, const gchar *error_message)
{
JingleS5BConnectData *cd = (JingleS5BConnectData *) data;
+ JingleS5B *s5b = cd->s5b;
purple_debug_info("jingle-s5b", "Successful in connecting!\n");
+ s5b->priv->remote_fd = source;
+
+ /* should stop trying to connect */
+
+ /* should send transport-info with streamhost-used */
+
g_free(cd);
}
@@ -527,8 +825,10 @@ jingle_s5b_attempt_connect_internal(Jing
js->user->node, js->user->domain, js->user->resource);
/* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
+ purple_debug_info("jingle-s5b", "dstaddr: %s\n", dstaddr);
hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr));
-
+ purple_debug_info("jingle-s5b", "connecting with hash: %s\n", hash);
+
data = g_new0(JingleS5BConnectData, 1);
data->session = session;
data->s5b = s5b;
More information about the Commits
mailing list