diff options
| author | ulim <a.sporto+bee@gmail.com> | 2008-07-22 14:37:49 +0200 | 
|---|---|---|
| committer | ulim <a.sporto+bee@gmail.com> | 2008-07-22 14:37:49 +0200 | 
| commit | 8a90001ab2cde971abc64b8d5e4174dc4c4b0ae2 (patch) | |
| tree | 5f4b8fe94f20258ac2e62560cae96390d9bf6539 | |
| parent | 9afeeface6363ea81c5f80a7274a691f18550a21 (diff) | |
Added an account setting 'proxy'.
Note that this is only used for sending. The default <local>;<auto> means let
the receiver try a direct connection first and then the proxy discovered from
the server (if any). If you know you're firewalled you can remove the <local>.
If you want to provide your own proxy try something like
"<local>;JID,HOST,PORT". E.g.
"<local>;proxy.somewhere.org,123.123.123.123,7777".
| -rw-r--r-- | protocols/jabber/jabber.c | 2 | ||||
| -rw-r--r-- | protocols/jabber/s5bytestream.c | 101 | ||||
| -rw-r--r-- | protocols/jabber/si.c | 22 | 
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; | 
