aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/jabber/si.c
diff options
context:
space:
mode:
authorulim <a.sporto+bee@gmail.com>2008-05-10 12:09:19 +0200
committerulim <a.sporto+bee@gmail.com>2008-05-10 12:09:19 +0200
commitb5cfc2bdad8a68011bf9215c63293299e4e8dc5c (patch)
treece99a6fd138d9c16f94e32ea42d9d1602e59675a /protocols/jabber/si.c
parentb043ad5e69d91730145ea49305a1fab588c83a93 (diff)
some changes for sending.
* not only query but also respect peer's features (i.e. abort ft if an important feature is not advertised) * wait for proxy discovery to complete before starting the transfer (important for sending to people with auto accept)
Diffstat (limited to 'protocols/jabber/si.c')
-rw-r--r--protocols/jabber/si.c106
1 files changed, 96 insertions, 10 deletions
diff --git a/protocols/jabber/si.c b/protocols/jabber/si.c
index 6e62f684..3afa30ff 100644
--- a/protocols/jabber/si.c
+++ b/protocols/jabber/si.c
@@ -44,6 +44,9 @@ void jabber_si_free_transfer( file_transfer_t *ft)
tf->fd = 0;
}
+ if( tf->disco_timeout )
+ b_event_remove( tf->disco_timeout );
+
g_free( tf->ini_jid );
g_free( tf->tgt_jid );
g_free( tf->iq_id );
@@ -79,12 +82,90 @@ void jabber_si_canceled( file_transfer_t *ft, char *reason )
}
+int jabber_si_check_features( struct jabber_transfer *tf, GSList *features ) {
+ int foundft = FALSE, foundbt = FALSE, foundsi = FALSE;
+
+ while ( features )
+ {
+ if( !strcmp( features->data, XMLNS_FILETRANSFER ) )
+ foundft = TRUE;
+ if( !strcmp( features->data, XMLNS_BYTESTREAMS ) )
+ foundbt = TRUE;
+ if( !strcmp( features->data, XMLNS_SI ) )
+ foundsi = TRUE;
+
+ features = g_slist_next(features);
+ }
+
+ if( !foundft )
+ imcb_file_canceled( tf->ft, "Buddy's client doesn't feature file transfers" );
+ else if( !foundbt )
+ imcb_file_canceled( tf->ft, "Buddy's client doesn't feature byte streams (required)" );
+ else if( !foundsi )
+ imcb_file_canceled( tf->ft, "Buddy's client doesn't feature stream initiation (required)" );
+
+ return foundft && foundbt && foundsi;
+}
+
+void jabber_si_transfer_start( struct jabber_transfer *tf ) {
+
+ if( !jabber_si_check_features( tf, tf->bud->features ) )
+ return;
+
+ /* send the request to our buddy */
+ jabber_si_send_request( tf->ic, tf->bud->full_jid, tf );
+
+ /* and start the receive logic */
+ imcb_file_recv_start( tf->ft );
+
+}
+
+gboolean jabber_si_waitfor_disco( gpointer data, gint fd, b_input_condition cond )
+{
+ struct jabber_transfer *tf = data;
+ struct jabber_data *jd = tf->ic->proto_data;
+
+ tf->disco_timeout_fired++;
+
+ if( tf->bud->features && jd->have_streamhosts==1 ) {
+ jabber_si_transfer_start( tf );
+ tf->disco_timeout = 0;
+ return FALSE;
+ }
+
+ /* 8 seconds should be enough for server and buddy to respond */
+ if ( tf->disco_timeout_fired < 16 )
+ 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" );
+ else if( !tf->bud->features )
+ imcb_file_canceled( tf->ft, "Couldn't get buddy's features" );
+ else
+ imcb_file_canceled( tf->ft, "Couldn't get server's features" );
+
+ tf->disco_timeout = 0;
+ return FALSE;
+}
+
void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who )
{
struct jabber_transfer *tf;
struct jabber_data *jd = ic->proto_data;
- char *server = jd->server;
+ struct jabber_buddy *bud;
+ char *server = jd->server, *s;
+
+ if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) )
+ bud = jabber_buddy_by_ext_jid( ic, who, 0 );
+ else
+ bud = jabber_buddy_by_jid( ic, who, 0 );
+ if( bud == NULL )
+ {
+ imcb_file_canceled( tf->ft, "Couldn't find buddy (BUG?)" );
+ return;
+ }
+
imcb_log( ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who );
tf = g_new0( struct jabber_transfer, 1 );
@@ -94,22 +175,27 @@ void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft,
tf->ft->data = tf;
tf->ft->free = jabber_si_free_transfer;
tf->ft->finished = jabber_si_finished;
+ tf->bud = bud;
ft->write = jabber_bs_send_write;
jd->filetransfers = g_slist_prepend( jd->filetransfers, tf );
- /* query the buddy's features */
- jabber_iq_query_features( ic, who );
+ /* query buddy's features and server's streaming proxies if neccessary */
- /* query proxies from the server */
- if( !jd->have_streamhosts )
- jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS );
+ if( !tf->bud->features )
+ jabber_iq_query_features( ic, bud->full_jid );
- /* send the request to our buddy */
- jabber_si_send_request( ic, who, tf );
+ if( jd->have_streamhosts!=1 ) {
+ jd->have_streamhosts = 0;
+ jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS );
+ }
- /* and start the receive logic */
- imcb_file_recv_start( ft );
+ /* if we had to do a query, wait for the result.
+ * Otherwise fire away. */
+ if( !tf->bud->features || jd->have_streamhosts!=1 )
+ tf->disco_timeout = b_timeout_add( 500, jabber_si_waitfor_disco, tf );
+ else
+ jabber_si_transfer_start( tf );
}
/*