Changes in / [2c2df7d:fa30fa5]


Ignore:
Files:
1 added
1 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • dcc.c

    r2c2df7d rfa30fa5  
    2828#include <poll.h>
    2929#include <netinet/tcp.h>
     30#include <regex.h>
    3031
    3132/*
     
    6061unsigned int receivedchunks=0, receiveddata=0;
    6162
    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
    68 int max_packet_size = DCC_PACKET_SIZE;
    69 #else
    7063int max_packet_size = 0;
    71 #endif
    7264
    7365static void dcc_finish( file_transfer_t *file );
     
    7668gboolean dcc_listen( dcc_file_transfer_t *df, struct sockaddr_storage **saddr_ptr );
    7769int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr );
     70gboolean dccs_recv_start( file_transfer_t *ft );
     71gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond);
     72gboolean dccs_recv_write_request( file_transfer_t *ft );
    7873
    7974/* As defined in ft.h */
     
    9994
    10095/* As defined in ft.h */
    101 gboolean 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... */
    107 file_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);
     96gboolean imcb_file_recv_start( file_transfer_t *ft )
     97{
     98        return dccs_recv_start( ft );
     99}
     100
     101dcc_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);
    119105        file->file_size = file_size;
    120106        file->file_name = g_strdup( file_name );
     
    123109        df->ft = file;
    124110       
     111        return df;
     112}
     113
     114/* This is where the sending magic starts... */
     115file_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 )
     122                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
    125129        /* listen and request */
    126         if( !dcc_listen( df, saddr ) ||
    127             !dccs_send_request( df, user_nick, *saddr ) )
     130        if( !dcc_listen( df, &saddr ) ||
     131            !dccs_send_request( df, user_nick, saddr ) )
    128132                return NULL;
    129133
    130         g_free( *saddr );
     134        g_free( saddr );
    131135
    132136        /* watch */
     
    178182                struct sockaddr_in *saddr_ipv4 = ( struct sockaddr_in *) saddr;
    179183
    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                  */
    185184                sprintf( ipaddr, "%d",
    186                          htonl( saddr_ipv4->sin_addr.s_addr ) );
     185                         ntohl( saddr_ipv4->sin_addr.s_addr ) );
    187186                port = saddr_ipv4->sin_port;
    188187        } else
     
    209208
    210209        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 );
    214210
    215211        return TRUE;
     
    261257
    262258/*
     259 * Checks poll(), same for receiving and sending
     260 */
     261gboolean dcc_poll( dcc_file_transfer_t *df, int fd, short *revents )
     262{
     263        struct pollfd pfd = { .fd = fd, .events = POLLHUP|POLLERR|POLLIN|POLLOUT };
     264
     265        ASSERTSOCKOP( poll( &pfd, 1, 0 ), "poll()" )
     266
     267        if( pfd.revents & POLLERR )
     268        {
     269                int sockerror;
     270                socklen_t errlen = sizeof( sockerror );
     271
     272                if ( getsockopt( fd, SOL_SOCKET, SO_ERROR, &sockerror, &errlen ) )
     273                        return dcc_abort( df, "getsockopt() failed, unknown socket error (weird!)" );
     274
     275                return dcc_abort( df, "Socket error: %s", strerror( sockerror ) );
     276        }
     277       
     278        if( pfd.revents & POLLHUP )
     279                return dcc_abort( df, "Remote end closed connection" );
     280       
     281        *revents = pfd.revents;
     282
     283        return TRUE;
     284}
     285
     286/*
     287 * fills max_packet_size with twice the TCP maximum segment size
     288 */
     289gboolean  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/*
    263305 * After setup, the transfer itself is handled entirely by this function.
    264306 * There are basically four things to handle: connect, receive, send, and error.
     
    268310        dcc_file_transfer_t *df = data;
    269311        file_transfer_t *file = df->ft;
    270         struct pollfd pfd = { .fd = fd, .events = POLLHUP|POLLERR|POLLIN|POLLOUT };
    271312        short revents;
    272313       
    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 )
    282         {
    283                 int sockerror;
    284                 socklen_t errlen = sizeof( sockerror );
    285 
    286                 if ( getsockopt( fd, SOL_SOCKET, SO_ERROR, &sockerror, &errlen ) )
    287                         return dcc_abort( df, "getsockopt() failed, unknown socket error (weird!)" );
    288 
    289                 return dcc_abort( df, "Socket error: %s", strerror( sockerror ) );
    290         }
    291        
    292         if( revents & POLLHUP )
    293                 return dcc_abort( df, "Remote end closed connection" );
    294        
     314        if( !dcc_poll( df, fd, &revents) )
     315                return FALSE;
     316
    295317        if( ( revents & POLLIN ) &&
    296318            ( file->status & FT_STATUS_LISTENING ) )
     
    305327                closesocket( fd );
    306328                fd = df->fd;
    307                 file->status = FT_STATUS_TRANSFERING;
     329                file->status = FT_STATUS_TRANSFERRING;
    308330                sock_make_nonblocking( fd );
    309331
    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
     332                if ( !dcc_check_maxseg( df, fd ) )
     333                        return FALSE;
     334
    322335                /* IM protocol callback */
    323 
    324336                if( file->accept )
    325337                        file->accept( file );
     338
    326339                /* reschedule for reading on new fd */
    327340                df->watch_in = b_input_add( fd, GAIM_INPUT_READ, dccs_send_proto, df );
     
    367380                }
    368381       
    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 );
     382                return TRUE;
     383        }
     384
     385        return TRUE;
     386}
     387
     388gboolean 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
     416gboolean 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 ) )
     430                        return FALSE;
     431
     432                //df->watch_in = b_input_add( df->fd, GAIM_INPUT_READ, dccs_recv_proto, df );
     433
     434                df->watch_out = 0;
     435                return FALSE;
     436        }
     437
     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 );
    375461                }
    376 #endif
    377                 return TRUE;
    378         }
    379 
    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;
     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;
    392472                        return FALSE;
    393473                }
    394474
    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                 }
    445 
    446                 df->watch_out = 0;
     475                df->watch_in = 0;
    447476                return FALSE;
    448477        }
    449478
    450         /* Send buffer full, come back later */
    451 
    452         return TRUE;
     479        return TRUE;
     480}
     481
     482gboolean 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
     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;
    453501}
    454502
    455503/*
    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.
     504 * Incoming data.
    458505 *
    459  * */
    460 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 )
    461508{
    462509        dcc_file_transfer_t *df = file->priv;
    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;
     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;
    485532}
    486533
     
    503550                b_event_remove( df->watch_out );
    504551       
    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 
    519552        df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file );
    520553       
     
    533566        dcc_close( file );
    534567}
     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 */
     576file_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

    r2c2df7d rfa30fa5  
    4444#define _DCC_H
    4545
    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 */
     46/* Send an ACK after receiving this amount of data */
    6547#define DCC_PACKET_SIZE 1024
    66 
    67 /* stores buffers handed over by IM protocols */
    68 struct dcc_buffer {
    69         char *b;
    70         int len;
    71 };
    7248
    7349typedef struct dcc_file_transfer {
     
    8965       
    9066        /*
    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         /*
    11067         * The total amount of bytes that have been sent to the irc client.
    11168         */
    11269        size_t bytes_sent;
    11370       
    114         /* imcb's handle */
     71        /* imc's handle */
    11572        file_transfer_t *ft;
     73
     74        /* if we're receiving, this is the sender's socket address */
     75        struct sockaddr_storage saddr;
    11676
    11777} dcc_file_transfer_t;
     
    12181void dcc_canceled( file_transfer_t *file, char *reason );
    12282
    123 gboolean dccs_send_write( file_transfer_t *file, gpointer data, unsigned int data_size );
     83gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_size );
    12484
     85file_transfer_t *dcc_request( struct im_connection *ic, char *line );
    12586#endif
  • doc/user-guide/commands.xml

    r2c2df7d rfa30fa5  
    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       
    863906</chapter>
  • irc.c

    r2c2df7d rfa30fa5  
    2828#include "crypting.h"
    2929#include "ipc.h"
     30#include "dcc.h"
     31
     32#include <regex.h>
     33#include <netinet/in.h>
    3034
    3135static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
     
    981985                        return( 1 );
    982986                }
     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                }               
    983997                else
    984998                {
    985                         irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
     999                        irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" );
    9861000                        return( 0 );
    9871001                }
  • protocols/ft.h

    r2c2df7d rfa30fa5  
    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
    2936typedef enum {
    3037        FT_STATUS_LISTENING     = 1,
    31         FT_STATUS_TRANSFERING   = 2,
     38        FT_STATUS_TRANSFERRING  = 2,
    3239        FT_STATUS_FINISHED      = 4,
    33         FT_STATUS_CANCELED      = 8
     40        FT_STATUS_CANCELED      = 8,
     41        FT_STATUS_CONNECTING    = 16
    3442} file_status_t;
    3543
     
    6169 */
    6270typedef struct file_transfer {
     71
     72        /* Are we sending something? */
     73        int sending;
     74
    6375        /*
    6476         * The current status of this file transfer.
     
    126138       
    127139        /*
    128          * If set, called when the transfer queue is running empty and
    129          * more data can be added.
     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.
    130143         */
    131         void (*out_of_data) ( struct file_transfer *file );
     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];
    132158
    133159} file_transfer_t;
     
    144170void imcb_file_canceled( file_transfer_t *file, char *reason );
    145171
    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  */
    151 gboolean imcb_file_write( file_transfer_t *file, gpointer data, size_t data_size );
    152 
     172gboolean imcb_file_recv_start( file_transfer_t *ft );
    153173#endif
  • protocols/jabber/Makefile

    r2c2df7d rfa30fa5  
    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 stream.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o si.o s5bytestream.o
    1313
    1414CFLAGS += -Wall
  • protocols/jabber/iq.c

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

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

    r2c2df7d rfa30fa5  
    146146
    147147        size_t bytesread, byteswritten;
    148         int receiver_overflow;
    149148        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 
    205 /* stream.c */
    206 int jabber_bs_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
     203int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
     204void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     205void jabber_si_free_transfer( file_transfer_t *ft);
     206
     207/* s5bytestream.c */
     208int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
     209gboolean jabber_bs_send_start( struct jabber_transfer *tf );
     210gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
    207211
    208212/* message.c */
  • protocols/jabber/jabber_util.c

    r2c2df7d rfa30fa5  
    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;
    267271                new[i] = tolower( orig[i] );
     272        }
     273        for( ; i < len; i ++ )
     274                new[i] = orig[i];
    268275       
    269276        new[i] = 0;
  • protocols/jabber/si.c

    r2c2df7d rfa30fa5  
    2626
    2727void jabber_si_answer_request( file_transfer_t *ft );
    28 
    29 /* imcb callback */
     28int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf );
     29
     30/* file_transfer free() callback */
    3031void jabber_si_free_transfer( file_transfer_t *ft)
    3132{
     
    5051}
    5152
    52 /* imcb callback */
     53/* file_transfer finished() callback */
    5354void jabber_si_finished( file_transfer_t *ft )
    5455{
     
    5859}
    5960
    60 /* imcb callback */
     61/* file_transfer canceled() callback */
    6162void jabber_si_canceled( file_transfer_t *ft, char *reason )
    6263{
     
    7677        xt_free_node( reply );
    7778
     79}
     80
     81void 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 );
    78102}
    79103
     
    136160                                break;
    137161                        }
     162
     163                if ( !requestok )
     164                        imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid);
    138165        }
    139166       
     
    160187
    161188                *s = '/';
    162         } else
    163                 imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid);
     189        }
    164190
    165191        if ( !requestok )
     
    198224
    199225/*
    200  * imcb called the accept callback which probably means that the user accepted this file transfer.
     226 * imc called the accept callback which probably means that the user accepted this file transfer.
    201227 * We send our response to the initiator.
    202228 * In the next step, the initiator will send us a request for the given stream type.
     
    245271        xt_free_node( reply );
    246272}
     273
     274static 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
     354int 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

    r2c2df7d rfa30fa5  
    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 );
    231234};
    232235
Note: See TracChangeset for help on using the changeset viewer.