Changeset dce3903 for dcc.c


Ignore:
Timestamp:
2007-12-04T00:48:57Z (16 years ago)
Author:
ulim <a.sporto+bee@…>
Branches:
master
Children:
8076ec0, fa30fa5
Parents:
2ff2076
Message:

Send and receive seems to work now! Also adopted the new buffering strategy,
only one buffer of 2k per transfer now.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • dcc.c

    r2ff2076 rdce3903  
    6161unsigned int receivedchunks=0, receiveddata=0;
    6262
    63 /*
    64  * If using DCC SEND AHEAD this value will be set before the first transfer starts.
    65  * Not that in this case it degenerates to the maximum message size to send() and
    66  * has nothing to do with packets.
    67  */
    68 #ifdef DCC_SEND_AHEAD
    69 int max_packet_size = DCC_PACKET_SIZE;
    70 #else
    7163int max_packet_size = 0;
    72 #endif
    7364
    7465static void dcc_finish( file_transfer_t *file );
     
    7970gboolean dccs_recv_start( file_transfer_t *ft );
    8071gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond);
    81 void dccs_recv_out_of_data( file_transfer_t *ft );
     72gboolean dccs_recv_write_request( file_transfer_t *ft );
    8273
    8374/* As defined in ft.h */
     
    10091
    10192        dcc_close( file );
    102 }
    103 
    104 /* As defined in ft.h */
    105 gboolean imcb_file_write( file_transfer_t *file, gpointer data, size_t data_size )
    106 {
    107         return dccs_send_write( file, data, data_size );
    10893}
    10994
     
    139124        df = dcc_alloc_transfer( file_name, file_size, ic );
    140125        file = df->ft;
     126        file->write = dccs_send_write;
     127        file->sending = TRUE;
    141128
    142129        /* listen and request */
     
    195182                struct sockaddr_in *saddr_ipv4 = ( struct sockaddr_in *) saddr;
    196183
    197                 /*
    198                  * this is so ridiculous. We're supposed to convert the address to
    199                  * host byte order!!! Let's exclude anyone running big endian just
    200                  * for the fun of it...
    201                  */
    202184                sprintf( ipaddr, "%d",
    203                          htonl( saddr_ipv4->sin_addr.s_addr ) );
     185                         ntohl( saddr_ipv4->sin_addr.s_addr ) );
    204186                port = saddr_ipv4->sin_port;
    205187        } else
     
    226208
    227209        g_free( cmd );
    228 
    229         /* message is sortof redundant cause the users client probably informs him about that. remove? */
    230         imcb_log( df->ic, "Transferring file %s: Chose local address %s for DCC connection", df->ft->file_name, ipaddr );
    231210
    232211        return TRUE;
     
    305284}
    306285
     286/*
     287 * fills max_packet_size with twice the TCP maximum segment size
     288 */
    307289gboolean  dcc_check_maxseg( dcc_file_transfer_t *df, int fd )
    308290{
    309 #ifdef DCC_SEND_AHEAD
    310291        /*
    311292         * use twice the maximum segment size as a maximum for calls to send().
     
    318299                max_packet_size *= 2;
    319300        }
    320 #endif
    321301        return TRUE;
    322302}
     
    354334
    355335                /* IM protocol callback */
    356 
    357336                if( file->accept )
    358337                        file->accept( file );
     338
    359339                /* reschedule for reading on new fd */
    360340                df->watch_in = b_input_add( fd, GAIM_INPUT_READ, dccs_send_proto, df );
     
    400380                }
    401381       
    402 #ifndef DCC_SEND_AHEAD
    403                 /* reschedule writer if neccessary */
    404                 if( file->bytes_transferred >= df->bytes_sent &&
    405                     df->watch_out == 0 &&
    406                     df->queued_bytes > 0 ) {
    407                         df->watch_out = b_input_add( fd, GAIM_INPUT_WRITE, dcc_send_proto, df );
    408                 }
    409 #endif
    410382                return TRUE;
    411383        }
    412 
    413         if( revents & POLLOUT )
    414         {
    415                 struct dcc_buffer *dccb;
    416                 int ret;
    417                 char *msg;
    418 
    419                 if( df->queued_bytes == 0 )
    420                 {
    421                         /* shouldn't happen */
    422                         imcb_log( df->ic, "WARNING: DCC SEND: write called with empty queue" );
    423 
    424                         df->watch_out = 0;
    425                         return FALSE;
    426                 }
    427 
    428                 /* start where we left off */
    429                 if( !( df->queued_buffers ) ||
    430                     !( dccb = df->queued_buffers->data ) )
    431                         return dcc_abort( df, "BUG in DCC SEND: queued data but no buffers" );
    432 
    433                 msg = dccb->b + df->buffer_pos;
    434 
    435                 int msgsize = MIN(
    436 #ifndef DCC_SEND_AHEAD
    437                                   file->bytes_transferred + MAX_PACKET_SIZE - df->bytes_sent,
    438 #else
    439                                   max_packet_size,
    440 #endif
    441                                   dccb->len - df->buffer_pos );
    442 
    443                 if ( msgsize == 0 )
    444                 {
    445                         df->watch_out = 0;
    446                         return FALSE;
    447                 }
    448 
    449                 ASSERTSOCKOP( ret = send( fd, msg, msgsize, 0 ), "Sending data" );
    450 
    451                 if( ret == 0 )
    452                         return dcc_abort( df, "Remote end closed connection" );
    453 
    454                 df->bytes_sent += ret;
    455                 df->queued_bytes -= ret;
    456                 df->buffer_pos += ret;
    457 
    458                 if( df->buffer_pos == dccb->len )
    459                 {
    460                         df->buffer_pos = 0;
    461                         df->queued_buffers = g_slist_remove( df->queued_buffers, dccb );
    462                         g_free( dccb->b );
    463                         g_free( dccb );
    464                 }
    465 
    466                 if( ( df->queued_bytes < DCC_QUEUE_THRESHOLD_LOW ) && file->out_of_data )
    467                         file->out_of_data( file );
    468        
    469                 if( df->queued_bytes > 0 )
    470                 {
    471                         /* Who knows how long the event loop cycle will take,
    472                          * let's just try to send some more now. */
    473 #ifndef DCC_SEND_AHEAD
    474                         if( df->bytes_sent < ( file->bytes_transferred + max_packet_size ) )
    475 #endif
    476                                 return dccs_send_proto( df, fd, cond );
    477                 }
    478 
    479                 df->watch_out = 0;
    480                 return FALSE;
    481         }
    482 
    483         /* Send buffer full, come back later */
    484384
    485385        return TRUE;
     
    509409        /* watch */
    510410        df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_recv_proto, df );
    511         ft->out_of_data = dccs_recv_out_of_data;
     411        ft->write_request = dccs_recv_write_request;
    512412
    513413        return TRUE;
     
    538438        if( revents & POLLIN )
    539439        {
    540                 char *buffer = g_malloc( 65536 );
    541440                int ret, done;
    542441
    543                 ASSERTSOCKOP( ret = recv( fd, buffer, 65536, 0 ), "Receiving" );
     442                ASSERTSOCKOP( ret = recv( fd, ft->buffer, sizeof( ft->buffer ), 0 ), "Receiving" );
    544443
    545444                if( ret == 0 )
    546445                        return dcc_abort( df, "Remote end closed connection" );
    547 
    548                 buffer = g_realloc( buffer, ret );
    549446
    550447                df->bytes_sent += ret;
     
    561458                       
    562459                        if ( ackret != 4 )
    563                                 return dcc_abort( df, "Error sending DCC ACK, sent %d instead of 4 bytes", ret );
     460                                return dcc_abort( df, "Error sending DCC ACK, sent %d instead of 4 bytes", ackret );
    564461                }
    565462               
    566                 if( !ft->write( df->ft, buffer, ret ) && !done )
    567                 {
     463                if( !ft->write( df->ft, ft->buffer, ret ) )
     464                        return FALSE;
     465
     466                if( done )
     467                {
     468                        closesocket( fd );
     469                        dcc_finish( ft );
     470
    568471                        df->watch_in = 0;
    569472                        return FALSE;
    570473                }
    571474
    572                 if( done )
    573                 {
    574                         closesocket( fd );
    575                         dcc_finish( ft );
    576 
    577                         df->watch_in = 0;
    578                         return FALSE;
    579                 }
    580 
    581                 return TRUE;
    582         }
    583 
    584         return TRUE;
    585 }
    586 
    587 void dccs_recv_out_of_data( file_transfer_t *ft )
     475                df->watch_in = 0;
     476                return FALSE;
     477        }
     478
     479        return TRUE;
     480}
     481
     482gboolean dccs_recv_write_request( file_transfer_t *ft )
    588483{
    589484        dcc_file_transfer_t *df = ft->priv;
    590485
    591         if( !df->watch_in )
    592                 df->watch_in = b_input_add( df->fd, GAIM_INPUT_READ, dccs_recv_proto, df );
     486        if( df->watch_in )
     487                return dcc_abort( df, "BUG: write_request() called while watching" );
     488
     489        df->watch_in = b_input_add( df->fd, GAIM_INPUT_READ, dccs_recv_proto, df );
     490
     491        return TRUE;
     492}
     493
     494gboolean dccs_send_can_write( gpointer data, gint fd, b_input_condition cond )
     495{
     496        struct dcc_file_transfer *df = data;
     497        df->watch_out = 0;
     498
     499        df->ft->write_request( df->ft );
     500        return FALSE;
    593501}
    594502
    595503/*
    596  * Incoming data. Note that the buffer MUST NOT be freed by the caller!
    597  * We don't copy the buffer but put it in our queue.
     504 * Incoming data.
    598505 *
    599  * */
    600 gboolean dccs_send_write( file_transfer_t *file, gpointer data, unsigned int data_size )
     506 */
     507gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_len )
    601508{
    602509        dcc_file_transfer_t *df = file->priv;
    603         struct dcc_buffer *dccb = g_new0( struct dcc_buffer, 1 );
    604 
    605         receivedchunks++; receiveddata += data_size;
    606 
    607         dccb->b = data;
    608         dccb->len = data_size;
    609 
    610         df->queued_buffers = g_slist_append( df->queued_buffers, dccb );
    611 
    612         df->queued_bytes += data_size;
    613 
    614         if( ( file->status & FT_STATUS_TRANSFERRING ) &&
    615 #ifndef DCC_SEND_AHEAD
    616             ( file->bytes_transferred >= df->bytes_sent ) &&
    617 #endif
    618             ( df->watch_out == 0 ) &&
    619             ( df->queued_bytes > 0 ) )
    620         {
    621                 df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_send_proto, df );
    622         }
    623        
    624         return df->queued_bytes > DCC_QUEUE_THRESHOLD_HIGH;
     510        int ret;
     511
     512        receivedchunks++; receiveddata += data_len;
     513
     514        if( df->watch_out )
     515                return dcc_abort( df, "BUG: write() called while watching" );
     516
     517        ASSERTSOCKOP( ret = send( df->fd, data, data_len, 0 ), "Sending data" );
     518
     519        if( ret == 0 )
     520                return dcc_abort( df, "Remote end closed connection" );
     521
     522        /* TODO: this should really not be fatal */
     523        if( ret < data_len )
     524                return dcc_abort( df, "send() sent %d instead of %d", ret, data_len );
     525
     526        df->bytes_sent += ret;
     527
     528        if( df->bytes_sent < df->ft->file_size )
     529                df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_send_can_write, df );
     530
     531        return TRUE;
    625532}
    626533
     
    643550                b_event_remove( df->watch_out );
    644551       
    645         if( df->queued_buffers )
    646         {
    647                 struct dcc_buffer *dccb;
    648                 GSList *gslist = df->queued_buffers;
    649 
    650                 for( ; gslist ; gslist = g_slist_next( gslist ) )
    651                 {
    652                         dccb = gslist->data;
    653                         g_free( dccb->b );
    654                         g_free( dccb );
    655                 }
    656                 g_slist_free( df->queued_buffers );
    657         }
    658 
    659552        df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file );
    660553       
Note: See TracChangeset for help on using the changeset viewer.