aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--protocols/jabber/jabber.c2
-rw-r--r--protocols/jabber/s5bytestream.c101
-rw-r--r--protocols/jabber/si.c22
3 files changed, 93 insertions, 32 deletions
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index 04d6f906..8b1d78db 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -61,6 +61,8 @@ static void jabber_init( account_t *acc )
s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );
s->flags |= ACC_SET_OFFLINE_ONLY;
+
+ s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc );
}
static void jabber_generate_id_hash( struct jabber_data *jd );
diff --git a/protocols/jabber/s5bytestream.c b/protocols/jabber/s5bytestream.c
index 809fbb22..c492491b 100644
--- a/protocols/jabber/s5bytestream.c
+++ b/protocols/jabber/s5bytestream.c
@@ -361,7 +361,7 @@ int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, stru
tf->streamhandle = bt;
tf->ft->free = jabber_bs_free_transfer;
- jabber_bs_recv_handshake( bt, 0, 0 );
+ jabber_bs_recv_handshake( bt, -1, 0 );
return XT_HANDLED;
}
@@ -380,7 +380,7 @@ gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition con
short revents;
int gret;
- if ( ( fd != 0 ) && !jabber_bs_poll( bt, fd, &revents ) )
+ if ( ( fd != -1 ) && !jabber_bs_poll( bt, fd, &revents ) )
return FALSE;
switch( bt->phase )
@@ -553,7 +553,7 @@ gboolean jabber_bs_recv_handshake_abort( struct bs_transfer *bt, char *error )
if( shlist && shlist->next )
{
bt->sh = shlist->next->data;
- return jabber_bs_recv_handshake( bt, 0, 0 );
+ return jabber_bs_recv_handshake( bt, -1, 0 );
}
@@ -619,7 +619,7 @@ gboolean jabber_bs_recv_read( gpointer data, gint fd, b_input_condition cond )
struct bs_transfer *bt = data;
struct jabber_transfer *tf = bt->tf;
- if( fd != 0 ) /* called via event thread */
+ if( fd != -1 ) /* called via event thread */
{
tf->watch_in = 0;
ASSERTSOCKOP( ret = recv( fd, tf->ft->buffer, sizeof( tf->ft->buffer ), 0 ) , "Receiving" );
@@ -665,7 +665,7 @@ gboolean jabber_bs_recv_write_request( file_transfer_t *ft )
return FALSE;
}
- jabber_bs_recv_read( tf->streamhandle, 0 , 0 );
+ jabber_bs_recv_read( tf->streamhandle, -1 , 0 );
return TRUE;
}
@@ -775,14 +775,16 @@ static xt_status jabber_bs_send_handle_reply(struct im_connection *ic, struct xt
{
/* using a proxy, abort listen */
- if ( tf->watch_in )
+ if( tf->watch_in )
{
b_event_remove( tf->watch_in );
tf->watch_in = 0;
}
- closesocket( tf->fd );
- tf->fd = 0;
+ if( tf->fd != -1 ) {
+ closesocket( tf->fd );
+ tf->fd = -1;
+ }
if ( bt->connect_timeout )
{
@@ -797,7 +799,7 @@ static xt_status jabber_bs_send_handle_reply(struct im_connection *ic, struct xt
if( strcmp( sh->jid, jid ) == 0 )
{
bt->sh = sh;
- jabber_bs_recv_handshake( bt, 0, 0 );
+ jabber_bs_recv_handshake( bt, -1, 0 );
return XT_HANDLED;
}
}
@@ -871,20 +873,80 @@ static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struc
return XT_HANDLED;
}
+jabber_streamhost_t *jabber_si_parse_proxy( struct im_connection *ic, char *proxy )
+{
+ char *host, *port, *jid;
+ jabber_streamhost_t *sh;
+
+ if( ( ( host = strchr( proxy, ',' ) ) == 0 ) ||
+ ( ( port = strchr( host+1, ',' ) ) == 0 ) ) {
+ imcb_log( ic, "Error parsing proxy setting: \"%s\" (ignored)", proxy );
+ return NULL;
+ }
+
+ jid = proxy;
+ *host++ = '\0';
+ *port++ = '\0';
+
+ sh = g_new0( jabber_streamhost_t, 1 );
+ sh->jid = g_strdup( jid );
+ sh->host = g_strdup( host );
+ strcpy( sh->port, port );
+
+ return sh;
+}
+
+void jabber_si_set_proxies( struct bs_transfer *bt )
+{
+ struct jabber_transfer *tf = bt->tf;
+ struct jabber_data *jd = tf->ic->proto_data;
+ char *proxysetting = g_strdup ( set_getstr( &tf->ic->acc->set, "proxy" ) );
+ char *proxy,*next;
+ char port[6];
+ char host[INET6_ADDRSTRLEN];
+ jabber_streamhost_t *sh, *sh2;
+ GSList *streamhosts = jd->streamhosts;
+
+ proxy = proxysetting;
+ while ( proxy && ( *proxy!='\0' ) ) {
+ if( ( next = strchr( proxy, ';' ) ) )
+ *next++ = '\0';
+
+ if( ( strcmp( proxy, "<local>" ) == 0 ) && jabber_bs_send_listen( bt, &tf->saddr, host, port ) ) {
+ sh = g_new0( jabber_streamhost_t, 1 );
+ sh->jid = g_strdup( tf->ini_jid );
+ sh->host = g_strdup( host );
+ strcpy( sh->port, port );
+ bt->streamhosts = g_slist_append( bt->streamhosts, sh );
+
+ bt->tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_send_handshake, bt );
+ bt->connect_timeout = b_timeout_add( JABBER_BS_LISTEN_TIMEOUT * 1000, jabber_bs_connect_timeout, bt );
+ } else if( strcmp( proxy, "<auto>" ) == 0 ) {
+ while ( streamhosts ) {
+ sh = g_new0( jabber_streamhost_t, 1 );
+ sh2 = streamhosts->data;
+ sh->jid = g_strdup( sh2->jid );
+ sh->host = g_strdup( sh2->host );
+ strcpy( sh->port, sh2->port );
+ bt->streamhosts = g_slist_append( bt->streamhosts, sh );
+ streamhosts = g_slist_next( streamhosts );
+ }
+ } else if( ( sh = jabber_si_parse_proxy( tf->ic, proxy ) ) )
+ bt->streamhosts = g_slist_append( bt->streamhosts, sh );
+ proxy = next;
+ }
+}
+
/*
* Starts a bytestream.
*/
gboolean jabber_bs_send_start( struct jabber_transfer *tf )
{
- char host[INET6_ADDRSTRLEN];
struct bs_transfer *bt;
sha1_state_t sha;
char hash_hex[41];
unsigned char hash[20];
int i,ret;
- struct jabber_data *jd = tf->ic->proto_data;
- jabber_streamhost_t sh;
- GSList *streamhosts = jd->streamhosts;
/* SHA1( SID + Initiator JID + Target JID ) is given to the streamhost which it will match against the initiator's value */
sha1_init( &sha );
@@ -904,18 +966,9 @@ gboolean jabber_bs_send_start( struct jabber_transfer *tf )
tf->ft->free = jabber_bs_free_transfer;
tf->ft->canceled = jabber_bs_canceled;
- if ( !jabber_bs_send_listen( bt, &tf->saddr, sh.host = host, sh.port ) )
- return FALSE;
-
- bt->tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_send_handshake, bt );
- bt->connect_timeout = b_timeout_add( JABBER_BS_LISTEN_TIMEOUT * 1000, jabber_bs_connect_timeout, bt );
-
- sh.jid = tf->ini_jid;
+ jabber_si_set_proxies( bt );
- /* temporarily add listen address to streamhosts, send the request and remove it */
- streamhosts = g_slist_prepend( streamhosts, &sh );
- ret = jabber_bs_send_request( tf, streamhosts);
- streamhosts = g_slist_remove( streamhosts, &sh );
+ ret = jabber_bs_send_request( tf, bt->streamhosts);
return ret;
}
diff --git a/protocols/jabber/si.c b/protocols/jabber/si.c
index 3afa30ff..e7cb2a17 100644
--- a/protocols/jabber/si.c
+++ b/protocols/jabber/si.c
@@ -38,10 +38,10 @@ void jabber_si_free_transfer( file_transfer_t *ft)
jd->filetransfers = g_slist_remove( jd->filetransfers, tf );
- if( tf->fd )
+ if( tf->fd != -1 )
{
close( tf->fd );
- tf->fd = 0;
+ tf->fd = -1;
}
if( tf->disco_timeout )
@@ -128,8 +128,8 @@ gboolean jabber_si_waitfor_disco( gpointer data, gint fd, b_input_condition cond
tf->disco_timeout_fired++;
if( tf->bud->features && jd->have_streamhosts==1 ) {
- jabber_si_transfer_start( tf );
tf->disco_timeout = 0;
+ jabber_si_transfer_start( tf );
return FALSE;
}
@@ -138,13 +138,14 @@ gboolean jabber_si_waitfor_disco( gpointer data, gint fd, b_input_condition cond
return TRUE;
if( !tf->bud->features && jd->have_streamhosts!=1 )
- imcb_file_canceled( tf->ft, "Couldn't get buddy's features or the server's" );
+ imcb_log( tf->ic, "Couldn't get buddy's features nor discover all services of the server" );
else if( !tf->bud->features )
- imcb_file_canceled( tf->ft, "Couldn't get buddy's features" );
+ imcb_log( tf->ic, "Couldn't get buddy's features" );
else
- imcb_file_canceled( tf->ft, "Couldn't get server's features" );
+ imcb_log( tf->ic, "Couldn't discover some of the server's services" );
tf->disco_timeout = 0;
+ jabber_si_transfer_start( tf );
return FALSE;
}
@@ -172,6 +173,7 @@ void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft,
tf->ic = ic;
tf->ft = ft;
+ tf->fd = -1;
tf->ft->data = tf;
tf->ft->free = jabber_si_free_transfer;
tf->ft->finished = jabber_si_finished;
@@ -185,10 +187,13 @@ void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft,
if( !tf->bud->features )
jabber_iq_query_features( ic, bud->full_jid );
- if( jd->have_streamhosts!=1 ) {
+ /* If <auto> is not set don't check for proxies */
+ if( ( jd->have_streamhosts!=1 ) && ( jd->streamhosts==NULL ) &&
+ ( strstr( set_getstr( &ic->acc->set, "proxy" ), "<auto>" ) != NULL ) ) {
jd->have_streamhosts = 0;
jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS );
- }
+ } else if ( jd->streamhosts!=NULL )
+ jd->have_streamhosts = 1;
/* if we had to do a query, wait for the result.
* Otherwise fire away. */
@@ -308,6 +313,7 @@ int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, st
tf->sid = g_strdup( sid );
tf->ic = ic;
tf->ft = ft;
+ tf->fd = -1;
tf->ft->data = tf;
tf->ft->accept = jabber_si_answer_request;
tf->ft->free = jabber_si_free_transfer;