diff options
author | ulim <a.sporto+bee@gmail.com> | 2008-05-06 02:20:11 +0200 |
---|---|---|
committer | ulim <a.sporto+bee@gmail.com> | 2008-05-06 02:20:11 +0200 |
commit | d56ee38d444fb9a4bc0fbf7f699eaf675e019591 (patch) | |
tree | e01b72d9906e40d627c1dceb8d7956463cef8607 | |
parent | 29c1456dcadec0d239ffc9d88ea06695b66c435c (diff) |
timeout of transfers after 120 seconds of no progress (bytes received/sent).
-rw-r--r-- | dcc.c | 31 | ||||
-rw-r--r-- | dcc.h | 8 | ||||
-rw-r--r-- | protocols/jabber/si.c | 3 |
3 files changed, 39 insertions, 3 deletions
@@ -84,6 +84,7 @@ int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct soc gboolean dccs_recv_start( file_transfer_t *ft ); gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond); gboolean dccs_recv_write_request( file_transfer_t *ft ); +gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond ); /* As defined in ft.h */ file_transfer_t *imcb_file_send_start( struct im_connection *ic, char *handle, char *file_name, size_t file_size ) @@ -151,6 +152,8 @@ file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, cha df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, file ); + df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df ); + return file; } @@ -167,8 +170,8 @@ gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... ) if( file->canceled ) file->canceled( file, msg ); - else - imcb_log( df->ic, "DCC transfer aborted: %s", msg ); + + imcb_log( df->ic, "File %s: DCC transfer aborted: %s", file->file_name, msg ); g_free( msg ); @@ -177,6 +180,25 @@ gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... ) return FALSE; } +gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond ) +{ + struct dcc_file_transfer *df = data; + + if( df->ft->bytes_transferred == df->progress_bytes_last ) + { + /* no progress. cancel */ + if( df->bytes_sent == 0 ) + return dcc_abort( df, "Couldnt establish transfer within %d seconds", DCC_MAX_STALL ); + else + return dcc_abort( df, "Transfer stalled for %d seconds at %d kb", DCC_MAX_STALL, df->ft->bytes_transferred / 1024 ); + + } + + df->progress_bytes_last = df->ft->bytes_transferred; + + return TRUE; +} + /* used extensively for socket operations */ #define ASSERTSOCKOP(op, msg) \ if( (op) == -1 ) \ @@ -434,6 +456,8 @@ gboolean dccs_recv_start( file_transfer_t *ft ) df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_recv_proto, df ); ft->write_request = dccs_recv_write_request; + df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df ); + return TRUE; } @@ -573,6 +597,9 @@ static void dcc_close( file_transfer_t *file ) if( df->watch_out ) b_event_remove( df->watch_out ); + if( df->progress_timeout ) + b_event_remove( df->progress_timeout ); + df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file ); g_free( df ); @@ -46,6 +46,10 @@ /* Send an ACK after receiving this amount of data */ #define DCC_PACKET_SIZE 1024 +/* Time in seconds that a DCC transfer can be stalled before being aborted. + * By handling this here individual protocols don't have to think about this. */ +#define DCC_MAX_STALL 120 + typedef struct dcc_file_transfer { struct im_connection *ic; @@ -63,6 +67,10 @@ typedef struct dcc_file_transfer { gint watch_in; /* readable */ gint watch_out; /* writable */ + /* the progress watcher cancels any file transfer if nothing happens within DCC_MAX_STALL */ + gint progress_timeout; + size_t progress_bytes_last; + /* * The total amount of bytes that have been sent to the irc client. */ diff --git a/protocols/jabber/si.c b/protocols/jabber/si.c index aab71c8b..d47cf7a4 100644 --- a/protocols/jabber/si.c +++ b/protocols/jabber/si.c @@ -54,8 +54,9 @@ void jabber_si_free_transfer( file_transfer_t *ft) void jabber_si_finished( file_transfer_t *ft ) { struct jabber_transfer *tf = ft->data; + time_t diff = time( NULL ) - ft->started; - imcb_log( tf->ic, "File %s transferred successfully!" , ft->file_name ); + imcb_log( tf->ic, "File %s transferred successfully at %d kb/s!" , ft->file_name, (int) ( ft->bytes_transferred / 1024 / diff ) ); } /* file_transfer canceled() callback */ |