Changes in / [fa30fa5:2c2df7d]


Ignore:
Files:
1 added
1 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • dcc.c

    rfa30fa5 r2c2df7d  
    2828#include <poll.h>
    2929#include <netinet/tcp.h>
    30 #include <regex.h>
    3130
    3231/*
     
    6160unsigned int receivedchunks=0, receiveddata=0;
    6261
     62/*
     63 * If using DCC SEND AHEAD this value will be set before the first transfer starts.
     64 * Not that in this case it degenerates to the maximum message size to send() and
     65 * has nothing to do with packets.
     66 */
     67#ifdef DCC_SEND_AHEAD
     68int max_packet_size = DCC_PACKET_SIZE;
     69#else
    6370int max_packet_size = 0;
     71#endif
    6472
    6573static void dcc_finish( file_transfer_t *file );
     
    6876gboolean dcc_listen( dcc_file_transfer_t *df, struct sockaddr_storage **saddr_ptr );
    6977int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr );
    70 gboolean dccs_recv_start( file_transfer_t *ft );
    71 gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond);
    72 gboolean dccs_recv_write_request( file_transfer_t *ft );
    7378
    7479/* As defined in ft.h */
     
    9499
    95100/* As defined in ft.h */
    96 gboolean imcb_file_recv_start( file_transfer_t *ft )
    97 {
    98         return dccs_recv_start( ft );
    99 }
    100 
    101 dcc_file_transfer_t *dcc_alloc_transfer( char *file_name, size_t file_size, struct im_connection *ic )
    102 {
    103         file_transfer_t *file = g_new0( file_transfer_t, 1 );
    104         dcc_file_transfer_t *df = file->priv = g_new0( dcc_file_transfer_t, 1);
     101gboolean imcb_file_write( file_transfer_t *file, gpointer data, size_t data_size )
     102{
     103        return dccs_send_write( file, data, data_size );
     104}
     105
     106/* This is where the sending magic starts... */
     107file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size )
     108{
     109        file_transfer_t *file;
     110        dcc_file_transfer_t *df;
     111        struct sockaddr_storage **saddr;
     112
     113        if( file_size > global.conf->max_filetransfer_size )
     114                return NULL;
     115       
     116        /* alloc stuff */
     117        file = g_new0( file_transfer_t, 1 );
     118        file->priv = df = g_new0( dcc_file_transfer_t, 1);
    105119        file->file_size = file_size;
    106120        file->file_name = g_strdup( file_name );
     
    109123        df->ft = file;
    110124       
    111         return df;
    112 }
    113 
    114 /* This is where the sending magic starts... */
    115 file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size )
    116 {
    117         file_transfer_t *file;
    118         dcc_file_transfer_t *df;
    119         struct sockaddr_storage *saddr;
    120 
    121         if( file_size > global.conf->max_filetransfer_size )
     125        /* listen and request */
     126        if( !dcc_listen( df, saddr ) ||
     127            !dccs_send_request( df, user_nick, *saddr ) )
    122128                return NULL;
    123        
    124         df = dcc_alloc_transfer( file_name, file_size, ic );
    125         file = df->ft;
    126         file->write = dccs_send_write;
    127         file->sending = TRUE;
    128 
    129         /* listen and request */
    130         if( !dcc_listen( df, &saddr ) ||
    131             !dccs_send_request( df, user_nick, saddr ) )
    132                 return NULL;
    133 
    134         g_free( saddr );
     129
     130        g_free( *saddr );
    135131
    136132        /* watch */
     
    182178                struct sockaddr_in *saddr_ipv4 = ( struct sockaddr_in *) saddr;
    183179
     180                /*
     181                 * this is so ridiculous. We're supposed to convert the address to
     182                 * host byte order!!! Let's exclude anyone running big endian just
     183                 * for the fun of it...
     184                 */
    184185                sprintf( ipaddr, "%d",
    185                          ntohl( saddr_ipv4->sin_addr.s_addr ) );
     186                         htonl( saddr_ipv4->sin_addr.s_addr ) );
    186187                port = saddr_ipv4->sin_port;
    187188        } else
     
    208209
    209210        g_free( cmd );
     211
     212        /* message is sortof redundant cause the users client probably informs him about that. remove? */
     213        imcb_log( df->ic, "Transferring file %s: Chose local address %s for DCC connection", df->ft->file_name, ipaddr );
    210214
    211215        return TRUE;
     
    257261
    258262/*
    259  * Checks poll(), same for receiving and sending
    260  */
    261 gboolean dcc_poll( dcc_file_transfer_t *df, int fd, short *revents )
    262 {
     263 * After setup, the transfer itself is handled entirely by this function.
     264 * There are basically four things to handle: connect, receive, send, and error.
     265 */
     266gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond )
     267{
     268        dcc_file_transfer_t *df = data;
     269        file_transfer_t *file = df->ft;
    263270        struct pollfd pfd = { .fd = fd, .events = POLLHUP|POLLERR|POLLIN|POLLOUT };
    264 
    265         ASSERTSOCKOP( poll( &pfd, 1, 0 ), "poll()" )
    266 
    267         if( pfd.revents & POLLERR )
     271        short revents;
     272       
     273        if ( poll( &pfd, 1, 0 ) == -1 )
     274        {
     275                imcb_log( df->ic, "poll() failed, weird!" );
     276                revents = 0;
     277        };
     278
     279        revents = pfd.revents;
     280
     281        if( revents & POLLERR )
    268282        {
    269283                int sockerror;
     
    276290        }
    277291       
    278         if( pfd.revents & POLLHUP )
     292        if( revents & POLLHUP )
    279293                return dcc_abort( df, "Remote end closed connection" );
    280294       
    281         *revents = pfd.revents;
    282 
    283         return TRUE;
    284 }
    285 
    286 /*
    287  * fills max_packet_size with twice the TCP maximum segment size
    288  */
    289 gboolean  dcc_check_maxseg( dcc_file_transfer_t *df, int fd )
    290 {
    291         /*
    292          * use twice the maximum segment size as a maximum for calls to send().
    293          */
    294         if( max_packet_size == 0 )
    295         {
    296                 unsigned int mpslen = sizeof( max_packet_size );
    297                 if( getsockopt( fd, IPPROTO_TCP, TCP_MAXSEG, &max_packet_size, &mpslen ) )
    298                         return dcc_abort( df, "getsockopt() failed" );
    299                 max_packet_size *= 2;
    300         }
    301         return TRUE;
    302 }
    303 
    304 /*
    305  * After setup, the transfer itself is handled entirely by this function.
    306  * There are basically four things to handle: connect, receive, send, and error.
    307  */
    308 gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond )
    309 {
    310         dcc_file_transfer_t *df = data;
    311         file_transfer_t *file = df->ft;
    312         short revents;
    313        
    314         if( !dcc_poll( df, fd, &revents) )
    315                 return FALSE;
    316 
    317295        if( ( revents & POLLIN ) &&
    318296            ( file->status & FT_STATUS_LISTENING ) )
     
    327305                closesocket( fd );
    328306                fd = df->fd;
    329                 file->status = FT_STATUS_TRANSFERRING;
     307                file->status = FT_STATUS_TRANSFERING;
    330308                sock_make_nonblocking( fd );
    331309
    332                 if ( !dcc_check_maxseg( df, fd ) )
    333                         return FALSE;
    334 
     310#ifdef DCC_SEND_AHEAD
     311                /*
     312                 * use twice the maximum segment size as a maximum for calls to send().
     313                 */
     314                if( max_packet_size == 0 )
     315                {
     316                        unsigned int mpslen = sizeof( max_packet_size );
     317                        if( getsockopt( fd, IPPROTO_TCP, TCP_MAXSEG, &max_packet_size, &mpslen ) )
     318                                return dcc_abort( df, "getsockopt() failed" );
     319                        max_packet_size *= 2;
     320                }
     321#endif
    335322                /* IM protocol callback */
     323
    336324                if( file->accept )
    337325                        file->accept( file );
    338 
    339326                /* reschedule for reading on new fd */
    340327                df->watch_in = b_input_add( fd, GAIM_INPUT_READ, dccs_send_proto, df );
     
    380367                }
    381368       
     369#ifndef DCC_SEND_AHEAD
     370                /* reschedule writer if neccessary */
     371                if( file->bytes_transferred >= df->bytes_sent &&
     372                    df->watch_out == 0 &&
     373                    df->queued_bytes > 0 ) {
     374                        df->watch_out = b_input_add( fd, GAIM_INPUT_WRITE, dcc_send_proto, df );
     375                }
     376#endif
    382377                return TRUE;
    383378        }
    384379
    385         return TRUE;
    386 }
    387 
    388 gboolean dccs_recv_start( file_transfer_t *ft )
    389 {
    390         dcc_file_transfer_t *df = ft->priv;
    391         struct sockaddr_storage *saddr = &df->saddr;
    392         int fd;
    393         socklen_t sa_len = saddr->ss_family == AF_INET ?
    394                 sizeof( struct sockaddr_in ) : sizeof( struct sockaddr_in6 );
    395        
    396         if( !ft->write )
    397                 return dcc_abort( df, "Protocol didn't register write()" );
    398        
    399         ASSERTSOCKOP( fd = df->fd = socket( saddr->ss_family, SOCK_STREAM, 0 ) , "Opening Socket" );
    400 
    401         sock_make_nonblocking( fd );
    402 
    403         if( ( connect( fd, (struct sockaddr *)saddr, sa_len ) == -1 ) &&
    404             ( errno != EINPROGRESS ) )
    405                 return dcc_abort( df, "Connecting" );
    406 
    407         ft->status = FT_STATUS_CONNECTING;
    408 
    409         /* watch */
    410         df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_recv_proto, df );
    411         ft->write_request = dccs_recv_write_request;
    412 
    413         return TRUE;
    414 }
    415 
    416 gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond)
    417 {
    418         dcc_file_transfer_t *df = data;
    419         file_transfer_t *ft = df->ft;
    420         short revents;
    421 
    422         if( !dcc_poll( df, fd, &revents ) )
    423                 return FALSE;
    424        
    425         if( ( revents & POLLOUT ) &&
    426             ( ft->status & FT_STATUS_CONNECTING ) )
    427         {
    428                 ft->status = FT_STATUS_TRANSFERRING;
    429                 if ( !dcc_check_maxseg( df, fd ) )
     380        if( revents & POLLOUT )
     381        {
     382                struct dcc_buffer *dccb;
     383                int ret;
     384                char *msg;
     385
     386                if( df->queued_bytes == 0 )
     387                {
     388                        /* shouldn't happen */
     389                        imcb_log( df->ic, "WARNING: DCC SEND: write called with empty queue" );
     390
     391                        df->watch_out = 0;
    430392                        return FALSE;
    431 
    432                 //df->watch_in = b_input_add( df->fd, GAIM_INPUT_READ, dccs_recv_proto, df );
     393                }
     394
     395                /* start where we left off */
     396                if( !( df->queued_buffers ) ||
     397                    !( dccb = df->queued_buffers->data ) )
     398                        return dcc_abort( df, "BUG in DCC SEND: queued data but no buffers" );
     399
     400                msg = dccb->b + df->buffer_pos;
     401
     402                int msgsize = MIN(
     403#ifndef DCC_SEND_AHEAD
     404                                  file->bytes_transferred + MAX_PACKET_SIZE - df->bytes_sent,
     405#else
     406                                  max_packet_size,
     407#endif
     408                                  dccb->len - df->buffer_pos );
     409
     410                if ( msgsize == 0 )
     411                {
     412                        df->watch_out = 0;
     413                        return FALSE;
     414                }
     415
     416                ASSERTSOCKOP( ret = send( fd, msg, msgsize, 0 ), "Sending data" );
     417
     418                if( ret == 0 )
     419                        return dcc_abort( df, "Remote end closed connection" );
     420
     421                df->bytes_sent += ret;
     422                df->queued_bytes -= ret;
     423                df->buffer_pos += ret;
     424
     425                if( df->buffer_pos == dccb->len )
     426                {
     427                        df->buffer_pos = 0;
     428                        df->queued_buffers = g_slist_remove( df->queued_buffers, dccb );
     429                        g_free( dccb->b );
     430                        g_free( dccb );
     431                }
     432
     433                if( ( df->queued_bytes < DCC_QUEUE_THRESHOLD_LOW ) && file->out_of_data )
     434                        file->out_of_data( file );
     435       
     436                if( df->queued_bytes > 0 )
     437                {
     438                        /* Who knows how long the event loop cycle will take,
     439                         * let's just try to send some more now. */
     440#ifndef DCC_SEND_AHEAD
     441                        if( df->bytes_sent < ( file->bytes_transferred + max_packet_size ) )
     442#endif
     443                                return dccs_send_proto( df, fd, cond );
     444                }
    433445
    434446                df->watch_out = 0;
     
    436448        }
    437449
    438         if( revents & POLLIN )
    439         {
    440                 int ret, done;
    441 
    442                 ASSERTSOCKOP( ret = recv( fd, ft->buffer, sizeof( ft->buffer ), 0 ), "Receiving" );
    443 
    444                 if( ret == 0 )
    445                         return dcc_abort( df, "Remote end closed connection" );
    446 
    447                 df->bytes_sent += ret;
    448 
    449                 done = df->bytes_sent >= ft->file_size;
    450 
    451                 if( ( ( df->bytes_sent - ft->bytes_transferred ) > DCC_PACKET_SIZE ) ||
    452                     done )
    453                 {
    454                         int ack, ackret;
    455                         ack = htonl( ft->bytes_transferred = df->bytes_sent );
    456 
    457                         ASSERTSOCKOP( ackret = send( fd, &ack, 4, 0 ), "Sending DCC ACK" );
    458                        
    459                         if ( ackret != 4 )
    460                                 return dcc_abort( df, "Error sending DCC ACK, sent %d instead of 4 bytes", ackret );
    461                 }
    462                
    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 
    471                         df->watch_in = 0;
    472                         return FALSE;
    473                 }
    474 
    475                 df->watch_in = 0;
    476                 return FALSE;
    477         }
     450        /* Send buffer full, come back later */
    478451
    479452        return TRUE;
    480453}
    481454
    482 gboolean dccs_recv_write_request( file_transfer_t *ft )
    483 {
    484         dcc_file_transfer_t *df = ft->priv;
    485 
    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 
    494 gboolean 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;
    501 }
    502 
    503455/*
    504  * Incoming data.
     456 * Incoming data. Note that the buffer MUST NOT be freed by the caller!
     457 * We don't copy the buffer but put it in our queue.
    505458 *
    506  */
    507 gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_len )
     459 * */
     460gboolean dccs_send_write( file_transfer_t *file, gpointer data, unsigned int data_size )
    508461{
    509462        dcc_file_transfer_t *df = file->priv;
    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;
     463        struct dcc_buffer *dccb = g_new0( struct dcc_buffer, 1 );
     464
     465        receivedchunks++; receiveddata += data_size;
     466
     467        dccb->b = data;
     468        dccb->len = data_size;
     469
     470        df->queued_buffers = g_slist_append( df->queued_buffers, dccb );
     471
     472        df->queued_bytes += data_size;
     473
     474        if( ( file->status & FT_STATUS_TRANSFERING ) &&
     475#ifndef DCC_SEND_AHEAD
     476            ( file->bytes_transferred >= df->bytes_sent ) &&
     477#endif
     478            ( df->watch_out == 0 ) &&
     479            ( df->queued_bytes > 0 ) )
     480        {
     481                df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_send_proto, df );
     482        }
     483       
     484        return df->queued_bytes > DCC_QUEUE_THRESHOLD_HIGH;
    532485}
    533486
     
    550503                b_event_remove( df->watch_out );
    551504       
     505        if( df->queued_buffers )
     506        {
     507                struct dcc_buffer *dccb;
     508                GSList *gslist = df->queued_buffers;
     509
     510                for( ; gslist ; gslist = g_slist_next( gslist ) )
     511                {
     512                        dccb = gslist->data;
     513                        g_free( dccb->b );
     514                        g_free( dccb );
     515                }
     516                g_slist_free( df->queued_buffers );
     517        }
     518
    552519        df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file );
    553520       
     
    566533        dcc_close( file );
    567534}
    568 
    569 /*
    570  * DCC SEND <filename> <IP> <port> <filesize>
    571  *
    572  * filename can be in "" or not. If it is, " can probably be escaped...
    573  * IP can be an unsigned int (IPV4) or something else (IPV6)
    574  *
    575  */
    576 file_transfer_t *dcc_request( struct im_connection *ic, char *line )
    577 {
    578         char *pattern = "SEND"
    579                 " (([^\"][^ ]*)|\"([^\"]|\\\")*\")"
    580                 " (([0-9]*)|([^ ]*))"
    581                 " ([0-9]*)"
    582                 " ([0-9]*)\001";
    583         regmatch_t pmatch[9];
    584         regex_t re;
    585         file_transfer_t *ft;
    586         dcc_file_transfer_t *df;
    587 
    588         if( regcomp( &re, pattern, REG_EXTENDED ) )
    589                 return NULL;
    590         if( regexec( &re, line, 9, pmatch, 0 ) )
    591                 return NULL;
    592 
    593         if( ( pmatch[1].rm_so > 0 ) &&
    594             ( pmatch[4].rm_so > 0 ) &&
    595             ( pmatch[7].rm_so > 0 ) &&
    596             ( pmatch[8].rm_so > 0 ) )
    597         {
    598                 char *input = g_strdup( line );
    599                 char *filename, *host, *port;
    600                 size_t filesize;
    601                 struct addrinfo hints, *rp;
    602 
    603                 /* "filename" or filename */
    604                 if ( pmatch[2].rm_so > 0 )
    605                 {
    606                         input[pmatch[2].rm_eo] = '\0';
    607                         filename = input + pmatch[2].rm_so;
    608                 } else
    609                 {
    610                         input[pmatch[3].rm_eo] = '\0';
    611                         filename = input + pmatch[3].rm_so;
    612                 }
    613                        
    614                 input[pmatch[4].rm_eo] = '\0';
    615 
    616                 /* number means ipv4, something else means ipv6 */
    617                 if ( pmatch[5].rm_so > 0 )
    618                 {
    619                         struct in_addr ipaddr = { htonl( atoi( input + pmatch[5].rm_so ) ) };
    620                         host = inet_ntoa( ipaddr );
    621                 } else
    622                 {
    623                         /* Contains non-numbers, hopefully an IPV6 address */
    624                         host = input + pmatch[6].rm_so;
    625                 }
    626 
    627                 input[pmatch[7].rm_eo] = '\0';
    628                 input[pmatch[8].rm_eo] = '\0';
    629 
    630                 port = input + pmatch[7].rm_so;
    631                 filesize = atoll( input + pmatch[8].rm_so );
    632 
    633                 memset( &hints, 0, sizeof ( struct addrinfo ) );
    634                 if ( getaddrinfo( host, port, &hints, &rp ) )
    635                 {
    636                         g_free( input );
    637                         return NULL;
    638                 }
    639 
    640                 df = dcc_alloc_transfer( filename, filesize, ic );
    641                 ft = df->ft;
    642                 ft->sending = TRUE;
    643                 memcpy( &df->saddr, rp->ai_addr, rp->ai_addrlen );
    644 
    645                 freeaddrinfo( rp );
    646                 g_free( input );
    647 
    648                 df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, ft );
    649 
    650                 return ft;
    651         }
    652 
    653         return NULL;
    654 }
    655 
  • dcc.h

    rfa30fa5 r2c2df7d  
    4444#define _DCC_H
    4545
    46 /* Send an ACK after receiving this amount of data */
     46/* don't wait for acknowledgments */
     47#define DCC_SEND_AHEAD
     48
     49/* This multiplier specifies how many bytes we
     50 * can go ahead within one event loop cycle. Notice that all in all,
     51 * we can easily be more ahead if the event loop shoots often enough.
     52 * (or the receiver processes slow enough)
     53 *
     54 * Setting this value too high will cause send buffer overflows.
     55 */
     56#define DCC_SEND_AHEAD_MUL 10
     57
     58/*
     59 * queue thresholds for the out of data and overflow conditions
     60 */
     61#define DCC_QUEUE_THRESHOLD_LOW 2048
     62#define DCC_QUEUE_THRESHOLD_HIGH 65536
     63
     64/* only used in non-ahead mode */
    4765#define DCC_PACKET_SIZE 1024
     66
     67/* stores buffers handed over by IM protocols */
     68struct dcc_buffer {
     69        char *b;
     70        int len;
     71};
    4872
    4973typedef struct dcc_file_transfer {
     
    6589       
    6690        /*
     91         * The total number of queued bytes. The following equality should always hold:
     92         *
     93         *      queued_bytes = sum(queued_buffers.len) - buffer_pos
     94         */
     95        unsigned int queued_bytes;
     96
     97        /*
     98         * A list of dcc_buffer structures.
     99         * These are provided by the protocols directly so that no copying is neccessary.
     100         */
     101        GSList *queued_buffers;
     102       
     103        /*
     104         * current position within the first buffer.
     105         * Is non-null if the whole buffer couldn't be sent at once.
     106         */
     107        int buffer_pos;
     108
     109        /*
    67110         * The total amount of bytes that have been sent to the irc client.
    68111         */
    69112        size_t bytes_sent;
    70113       
    71         /* imc's handle */
     114        /* imcb's handle */
    72115        file_transfer_t *ft;
    73 
    74         /* if we're receiving, this is the sender's socket address */
    75         struct sockaddr_storage saddr;
    76116
    77117} dcc_file_transfer_t;
     
    81121void dcc_canceled( file_transfer_t *file, char *reason );
    82122
    83 gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_size );
     123gboolean dccs_send_write( file_transfer_t *file, gpointer data, unsigned int data_size );
    84124
    85 file_transfer_t *dcc_request( struct im_connection *ic, char *line );
    86125#endif
  • doc/user-guide/commands.xml

    rfa30fa5 r2c2df7d  
    861861
    862862        </bitlbee-command>
    863        
    864         <bitlbee-command name="transfers">
    865                 <short-description>Monitor, cancel, or reject file transfers</short-description>
    866                 <syntax>transfers [&lt;cancel&gt; id | &lt;reject&gt;]</syntax>
    867                
    868                 <description>
    869                         <para>
    870                                 Without parameters the currently pending file transfers and their status will be listed. Available actions are <emphasis>cancel</emphasis> and <emphasis>reject</emphasis>. See <emphasis>help transfers &lt;action&gt;</emphasis> for more information.
    871                         </para>
    872 
    873                         <ircexample>
    874                                 <ircline nick="ulim">transfers</ircline>
    875                         </ircexample>
    876                 </description>
    877                
    878                 <bitlbee-command name="cancel">
    879                         <short-description>Cancels the file transfer with the given id</short-description>
    880                         <syntax>transfers &lt;cancel&gt; id</syntax>
    881 
    882                         <description>
    883                                 <para>Cancels the file transfer with the given id</para>
    884                         </description>
    885 
    886                         <ircexample>
    887                                 <ircline nick="ulim">transfers cancel 1</ircline>
    888                                 <ircline nick="root">Canceling file transfer for test</ircline>
    889                         </ircexample>
    890                 </bitlbee-command>
    891 
    892                 <bitlbee-command name="reject">
    893                         <short-description>Rejects all incoming transfers</short-description>
    894                         <syntax>transfers &lt;reject&gt;</syntax>
    895 
    896                         <description>
    897                                 <para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is neccessary. Or is it?</para>
    898                         </description>
    899 
    900                         <ircexample>
    901                                 <ircline nick="ulim">transfers reject</ircline>
    902                         </ircexample>
    903                 </bitlbee-command>
    904         </bitlbee-command>
    905        
    906863</chapter>
  • irc.c

    rfa30fa5 r2c2df7d  
    2828#include "crypting.h"
    2929#include "ipc.h"
    30 #include "dcc.h"
    31 
    32 #include <regex.h>
    33 #include <netinet/in.h>
    3430
    3531static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
     
    985981                        return( 1 );
    986982                }
    987                 else if( g_strncasecmp( s + 1, "DCC", 3 ) == 0 )
    988                 {
    989                         if( u && u->ic && u->ic->acc->prpl->transfer_request )
    990                         {
    991                                 file_transfer_t *ft = dcc_request( u->ic, s + 5 );
    992                                 if ( ft )
    993                                         u->ic->acc->prpl->transfer_request( u->ic, ft, u->handle );
    994                         }
    995                         return( 1 );
    996                 }               
    997983                else
    998984                {
    999                         irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" );
     985                        irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
    1000986                        return( 0 );
    1001987                }
  • protocols/ft.h

    rfa30fa5 r2c2df7d  
    2727#define _FT_H
    2828
    29 /*
    30  * One buffer is needed for each transfer. The receiver stores a message
    31  * in it and gives it to the sender. The sender will stall the receiver
    32  * till the buffer has been sent out.
    33  */
    34 #define FT_BUFFER_SIZE 2048
    35 
    3629typedef enum {
    3730        FT_STATUS_LISTENING     = 1,
    38         FT_STATUS_TRANSFERRING  = 2,
     31        FT_STATUS_TRANSFERING   = 2,
    3932        FT_STATUS_FINISHED      = 4,
    40         FT_STATUS_CANCELED      = 8,
    41         FT_STATUS_CONNECTING    = 16
     33        FT_STATUS_CANCELED      = 8
    4234} file_status_t;
    4335
     
    6961 */
    7062typedef struct file_transfer {
    71 
    72         /* Are we sending something? */
    73         int sending;
    74 
    7563        /*
    7664         * The current status of this file transfer.
     
    138126       
    139127        /*
    140          * called by the sending side to indicate that it is writable.
    141          * The callee should check if data is available and call the
    142          * function(as seen below) if that is the case.
     128         * If set, called when the transfer queue is running empty and
     129         * more data can be added.
    143130         */
    144         gboolean (*write_request) ( struct file_transfer *file );
    145 
    146         /*
    147          * When sending files, protocols register this function to receive data.
    148          * This should only be called once after write_request is called. The caller
    149          * should not read more data until write_request is called again. This technique
    150          * avoids buffering.
    151          */
    152         gboolean (*write) (struct file_transfer *file, char *buffer, unsigned int len );
    153 
    154         /* The send buffer associated with this transfer.
    155          * Since receivers always wait for a write_request call one is enough.
    156          */
    157         char buffer[FT_BUFFER_SIZE];
     131        void (*out_of_data) ( struct file_transfer *file );
    158132
    159133} file_transfer_t;
     
    170144void imcb_file_canceled( file_transfer_t *file, char *reason );
    171145
    172 gboolean imcb_file_recv_start( file_transfer_t *ft );
     146/*
     147 * The given buffer is queued for transfer and MUST NOT be freed by the caller.
     148 * When the method returns false the caller should not invoke this method again
     149 * until out_of_data has been called.
     150 */
     151gboolean imcb_file_write( file_transfer_t *file, gpointer data, size_t data_size );
     152
    173153#endif
  • protocols/jabber/Makefile

    rfa30fa5 r2c2df7d  
    1010
    1111# [SH] Program variables
    12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o si.o s5bytestream.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o si.o stream.o
    1313
    1414CFLAGS += -Wall
  • protocols/jabber/iq.c

    rfa30fa5 r2c2df7d  
    168168                {
    169169                        /* Bytestream Request (stage 2 of file transfer) */
    170                         return jabber_bs_recv_request( ic, node, c );
     170                        return jabber_bs_request( ic, node, c );
    171171                } else
    172172                {
  • protocols/jabber/jabber.c

    rfa30fa5 r2c2df7d  
    502502        ret->send_typing = jabber_send_typing;
    503503        ret->handle_cmp = g_strcasecmp;
    504         ret->transfer_request = jabber_si_transfer_request;
    505504
    506505        register_protocol( ret );
  • protocols/jabber/jabber.h

    rfa30fa5 r2c2df7d  
    146146
    147147        size_t bytesread, byteswritten;
     148        int receiver_overflow;
    148149        int fd;
    149         struct sockaddr_storage saddr;
    150150};
    151151
     
    201201
    202202/* si.c */
    203 int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
    204 void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
    205 void jabber_si_free_transfer( file_transfer_t *ft);
    206 
    207 /* s5bytestream.c */
    208 int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
    209 gboolean jabber_bs_send_start( struct jabber_transfer *tf );
    210 gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
     203int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode);
     204
     205/* stream.c */
     206int jabber_bs_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
    211207
    212208/* message.c */
  • protocols/jabber/jabber_util.c

    rfa30fa5 r2c2df7d  
    265265        new = g_new( char, len + 1 );
    266266        for( i = 0; i < len; i ++ )
    267         {
    268                 /* don't normalize the resource */
    269                 if( orig[i] == '/' )
    270                         break;
    271267                new[i] = tolower( orig[i] );
    272         }
    273         for( ; i < len; i ++ )
    274                 new[i] = orig[i];
    275268       
    276269        new[i] = 0;
  • protocols/jabber/si.c

    rfa30fa5 r2c2df7d  
    2626
    2727void jabber_si_answer_request( file_transfer_t *ft );
    28 int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf );
    29 
    30 /* file_transfer free() callback */
     28
     29/* imcb callback */
    3130void jabber_si_free_transfer( file_transfer_t *ft)
    3231{
     
    5150}
    5251
    53 /* file_transfer finished() callback */
     52/* imcb callback */
    5453void jabber_si_finished( file_transfer_t *ft )
    5554{
     
    5958}
    6059
    61 /* file_transfer canceled() callback */
     60/* imcb callback */
    6261void jabber_si_canceled( file_transfer_t *ft, char *reason )
    6362{
     
    7776        xt_free_node( reply );
    7877
    79 }
    80 
    81 void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who )
    82 {
    83         struct jabber_transfer *tf;
    84         struct jabber_data *jd = ic->proto_data;
    85 
    86         imcb_log( ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who );
    87 
    88         tf = g_new0( struct jabber_transfer, 1 );
    89 
    90         tf->ic = ic;
    91         tf->ft = ft;
    92         tf->ft->data = tf;
    93         tf->ft->free = jabber_si_free_transfer;
    94         tf->ft->finished = jabber_si_finished;
    95         ft->write = jabber_bs_send_write;
    96 
    97         jd->filetransfers = g_slist_prepend( jd->filetransfers, tf );
    98 
    99         jabber_si_send_request( ic, who, tf );
    100 
    101         imcb_file_recv_start( ft );
    10278}
    10379
     
    160136                                break;
    161137                        }
    162 
    163                 if ( !requestok )
    164                         imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid);
    165138        }
    166139       
     
    187160
    188161                *s = '/';
    189         }
     162        } else
     163                imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid);
    190164
    191165        if ( !requestok )
     
    224198
    225199/*
    226  * imc called the accept callback which probably means that the user accepted this file transfer.
     200 * imcb called the accept callback which probably means that the user accepted this file transfer.
    227201 * We send our response to the initiator.
    228202 * In the next step, the initiator will send us a request for the given stream type.
     
    271245        xt_free_node( reply );
    272246}
    273 
    274 static xt_status jabber_si_handle_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
    275 {
    276         struct xt_node *c, *d;
    277         char *ini_jid, *tgt_jid, *iq_id;
    278         GSList *tflist;
    279         struct jabber_transfer *tf=NULL;
    280         struct jabber_data *jd = ic->proto_data;
    281 
    282         if( !( tgt_jid = xt_find_attr( node, "from" ) ) ||
    283             !( ini_jid = xt_find_attr( node, "to" ) ) )
    284         {
    285                 imcb_log( ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid );
    286                 return XT_HANDLED;
    287         }
    288        
    289         /* All this means we expect something like this: ( I think )
    290          * <iq from=... to=... id=...>
    291          *      <si xmlns=si>
    292          *      [       <file xmlns=ft/>    ] <-- not neccessary
    293          *              <feature xmlns=feature>
    294          *                      <x xmlns=xdata type=submit>
    295          *                              <field var=stream-method>
    296          *                                      <value>
    297          */
    298         if( !( tgt_jid = xt_find_attr( node, "from" ) ) ||
    299             !( ini_jid = xt_find_attr( node, "to" ) ) ||
    300             !( iq_id   = xt_find_attr( node, "id" ) ) ||
    301             !( c = xt_find_node( node->children, "si" ) ) ||
    302             !( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_SI ) == 0 ) ||
    303 /*          !( d = xt_find_node( c->children, "file" ) ) ||
    304             !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FILETRANSFER ) == 0 ) || */
    305             !( d = xt_find_node( c->children, "feature" ) ) ||
    306             !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FEATURE ) == 0 ) ||
    307             !( d = xt_find_node( d->children, "x" ) ) ||
    308             !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_XDATA ) == 0 ) ||
    309             !( strcmp( xt_find_attr( d, "type" ), "submit" ) == 0 ) ||
    310             !( d = xt_find_node( d->children, "field" ) ) ||
    311             !( strcmp( xt_find_attr( d, "var" ), "stream-method" ) == 0 ) ||
    312             !( d = xt_find_node( d->children, "value" ) ) )
    313         {
    314                 imcb_log( ic, "WARNING: Received incomplete Stream Initiation response" );
    315                 return XT_HANDLED;
    316         }
    317 
    318         if( !( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) ) {
    319                 /* since we should only have advertised what we can do and the peer should
    320                  * only have chosen what we offered, this should never happen */
    321                 imcb_log( ic, "WARNING: Received invalid Stream Initiation response, method %s", d->text );
    322                        
    323                 return XT_HANDLED;
    324         }
    325        
    326         /* Let's see if we can find out what this bytestream should be for... */
    327 
    328         for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) )
    329         {
    330                 struct jabber_transfer *tft = tflist->data;
    331                 if( ( strcmp( tft->iq_id, iq_id ) == 0 ) )
    332                 {
    333                         tf = tft;
    334                         break;
    335                 }
    336         }
    337 
    338         if (!tf)
    339         {
    340                 imcb_log( ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid );
    341                 return XT_HANDLED;
    342         }
    343 
    344         tf->ini_jid = g_strdup( ini_jid );
    345         tf->tgt_jid = g_strdup( tgt_jid );
    346 
    347         imcb_log( ic, "File %s: %s accepted the transfer!", tf->ft->file_name, tgt_jid );
    348 
    349         jabber_bs_send_start( tf );
    350 
    351         return XT_HANDLED;
    352 }
    353 
    354 int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf )
    355 {
    356         struct xt_node *node, *sinode;
    357         struct jabber_buddy *bud;
    358 
    359         /* who knows how many bits the future holds :) */
    360         char filesizestr[ 1 + ( int ) ( 0.301029995663981198f * sizeof( size_t ) * 8 ) ];
    361 
    362         const char *methods[] =
    363         {       
    364                 XMLNS_BYTESTREAMS,
    365                 //XMLNS_IBB,
    366                 NULL
    367         };
    368         const char **m;
    369         char *s;
    370 
    371         /* Maybe we should hash this? */
    372         tf->sid = g_strdup_printf( "BitlBeeJabberSID%d", tf->ft->local_id );
    373        
    374         if( ( s = strchr( who, '=' ) ) && jabber_chat_by_name( ic, s + 1 ) )
    375                 bud = jabber_buddy_by_ext_jid( ic, who, 0 );
    376         else
    377                 bud = jabber_buddy_by_jid( ic, who, 0 );
    378 
    379         /* start with the SI tag */
    380         sinode = xt_new_node( "si", NULL, NULL );
    381         xt_add_attr( sinode, "xmlns", XMLNS_SI );
    382         xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER );
    383         xt_add_attr( sinode, "id", tf->sid );
    384 
    385 /*      if( mimetype )
    386                 xt_add_attr( node, "mime-type", mimetype ); */
    387 
    388         /* now the file tag */
    389 /*      if( desc )
    390                 node = xt_new_node( "desc", descr, NULL ); */
    391         node = xt_new_node( "range", NULL, NULL );
    392 
    393         sprintf( filesizestr, "%zd", tf->ft->file_size );
    394         node = xt_new_node( "file", NULL, node );
    395         xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER );
    396         xt_add_attr( node, "name", tf->ft->file_name );
    397         xt_add_attr( node, "size", filesizestr );
    398 /*      if (hash)
    399                 xt_add_attr( node, "hash", hash );
    400         if (date)
    401                 xt_add_attr( node, "date", date ); */
    402 
    403         xt_add_child( sinode, node );
    404 
    405         /* and finally the feature tag */
    406         node = xt_new_node( "field", NULL, NULL );
    407         xt_add_attr( node, "var", "stream-method" );
    408         xt_add_attr( node, "type", "list-single" );
    409 
    410         for ( m = methods ; *m ; m ++ )
    411                 xt_add_child( node, xt_new_node( "option", NULL, xt_new_node( "value", (char *)*m, NULL ) ) );
    412 
    413         node = xt_new_node( "x", NULL, node );
    414         xt_add_attr( node, "xmlns", XMLNS_XDATA );
    415         xt_add_attr( node, "type", "form" );
    416 
    417         node = xt_new_node( "feature", NULL, node );
    418         xt_add_attr( node, "xmlns", XMLNS_FEATURE );
    419 
    420         xt_add_child( sinode, node );
    421 
    422         /* and we are there... */
    423         node = jabber_make_packet( "iq", "set", bud ? bud->full_jid : who, sinode );
    424         jabber_cache_add( ic, node, jabber_si_handle_response );
    425         tf->iq_id = g_strdup( xt_find_attr( node, "id" ) );
    426        
    427         return jabber_write_packet( ic, node );
    428 }
  • protocols/nogaim.h

    rfa30fa5 r2c2df7d  
    229229         * - Most protocols will just want to set this to g_strcasecmp().*/
    230230        int (* handle_cmp) (const char *who1, const char *who2);
    231 
    232         /* Incoming transfer request */
    233         void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle );
    234231};
    235232
Note: See TracChangeset for help on using the changeset viewer.