Changeset 7c0a497 for protocols


Ignore:
Timestamp:
2005-12-17T20:56:50Z (19 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
a03a9f3
Parents:
b5a22e3 (diff), ad8b8a3 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Moved HTTP-stuff (right now only for passport) into a separate module. This
all works 100% asynchronous and non-blocking, so almost all I/O in BitlBee
should be completely non-blocking now!

Right now support for other modules than GnuTLS is probably broken, I'll fix
it later.

Location:
protocols
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • protocols/Makefile

    rb5a22e3 r7c0a497  
    1010
    1111# [SH] Program variables
    12 objects = md5.o nogaim.o proxy.o sha.o util.o $(SSL_CLIENT)
     12objects = http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) util.o
    1313
    1414# [SH] The next two lines should contain the directory name (in $(subdirs))
  • protocols/msn/ns.c

    rb5a22e3 r7c0a497  
    208208                {
    209209                        /* Time for some Passport black magic... */
    210                         if( !passport_get_id( gc, gc->username, gc->password, cmd[4], msn_auth_got_passport_id ) )
     210                        if( !passport_get_id( msn_auth_got_passport_id, gc, gc->username, gc->password, cmd[4] ) )
    211211                        {
    212212                                hide_login_progress_error( gc, "Error while contacting Passport server" );
  • protocols/msn/passport.c

    rb5a22e3 r7c0a497  
    2020 */
    2121
    22 #include "ssl_client.h"
     22#include "http_client.h"
    2323#include "passport.h"
    2424#include "msn.h"
     
    3131static char *prd_cached = NULL;
    3232
    33 static char *passport_create_header( char *reply, char *email, char *pwd );
     33static int passport_get_id_real( gpointer func, gpointer data, char *header );
     34static void passport_get_id_ready( struct http_request *req );
     35
    3436static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header );
    35 static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond );
    36 static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url );
    37 static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond );
     37static void passport_retrieve_dalogin_ready( struct http_request *req );
     38
     39static char *passport_create_header( char *cookie, char *email, char *pwd );
    3840static void destroy_reply( struct passport_reply *rep );
    3941
    40 
    41 int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func )
     42int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie )
    4243{
    4344        char *header = passport_create_header( cookie, username, password );
    4445       
    45         if( prd_cached )
    46         {
    47                 int st;
    48                
    49                 st = passport_get_id_from( data, func, header, prd_cached );
    50                 g_free( header );
    51                 return( st );
    52         }
     46        if( prd_cached == NULL )
     47                return passport_retrieve_dalogin( func, data, header );
    5348        else
    54         {
    55                 return( passport_retrieve_dalogin( data, func, header ) );
    56         }
    57 }
    58 
    59 
    60 static char *passport_create_header( char *reply, char *email, char *pwd )
    61 {
    62         char *buffer = g_new0( char, 2048 );
    63         char *currenttoken;
    64         char *email_enc, *pwd_enc;
    65        
    66         email_enc = g_new0( char, strlen( email ) * 3 + 1 );
    67         strcpy( email_enc, email );
    68         http_encode( email_enc );
    69        
    70         pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 );
    71         strcpy( pwd_enc, pwd );
    72         http_encode( pwd_enc );
    73        
    74         currenttoken = strstr( reply, "lc=" );
    75         if( currenttoken == NULL )
    76                 return( NULL );
    77        
    78         g_snprintf( buffer, 2048,
    79                     "Authorization: Passport1.4 OrgVerb=GET,"
    80                     "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom,"
    81                     "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc,
    82                     currenttoken );
    83        
    84         g_free( email_enc );
    85         g_free( pwd_enc );
    86        
    87         return( buffer );
    88 }
    89 
    90 
    91 static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header )
    92 {
    93         struct passport_reply *rep = g_new0( struct passport_reply, 1 );
    94         void *ssl;
    95        
     49                return passport_get_id_real( func, data, header );
     50}
     51
     52static int passport_get_id_real( gpointer func, gpointer data, char *header )
     53{
     54        struct passport_reply *rep;
     55        char *server, *dummy, *reqs;
     56        struct http_request *req;
     57       
     58        rep = g_new0( struct passport_reply, 1 );
    9659        rep->data = data;
    9760        rep->func = func;
    98         rep->header = header;
    99        
    100         ssl = ssl_connect( "nexus.passport.com", 443, passport_retrieve_dalogin_connected, rep );
    101        
    102         if( !ssl )
    103                 destroy_reply( rep );
    104        
    105         return( ssl != NULL );
    106 }
    107 
    108 #define PPR_BUFFERSIZE 2048
    109 #define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n"
    110 static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond )
    111 {
    112         int ret;
    113         char buffer[PPR_BUFFERSIZE+1];
    114         struct passport_reply *rep = data;
     61       
     62        server = g_strdup( prd_cached );
     63        dummy = strchr( server, '/' );
     64       
     65        if( dummy == NULL )
     66        {
     67                destroy_reply( rep );
     68                return( 0 );
     69        }
     70       
     71        reqs = g_malloc( strlen( header ) + strlen( dummy ) + 128 );
     72        sprintf( reqs, "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header );
     73       
     74        *dummy = 0;
     75        req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep );
     76       
     77        g_free( server );
     78        g_free( reqs );
     79       
     80        if( req == NULL )
     81                destroy_reply( rep );
     82       
     83        return( req != NULL );
     84}
     85
     86static void passport_get_id_ready( struct http_request *req )
     87{
     88        struct passport_reply *rep = req->data;
    11589       
    11690        if( !g_slist_find( msn_connections, rep->data ) )
    11791        {
    118                 if( ssl ) ssl_disconnect( ssl );
    11992                destroy_reply( rep );
    12093                return;
    12194        }
    12295       
    123         if( !ssl )
    124         {
    125                 rep->func( rep );
    126                 destroy_reply( rep );
    127                 return;
    128         }
    129        
    130         ssl_write( ssl, PPR_REQUEST, strlen( PPR_REQUEST ) );
    131        
    132         if( ( ret = ssl_read( ssl, buffer, PPR_BUFFERSIZE ) ) <= 0 )
    133         {
    134                 goto failure;
    135         }
    136 
    137         {
    138                 char *dalogin = strstr( buffer, "DALogin=" );
    139                 char *urlend;
     96        if( req->status_code == 200 )
     97        {
     98                char *dummy;
    14099               
    141                 if( !dalogin )
    142                         goto failure;
    143                
    144                 dalogin += strlen( "DALogin=" );
    145                 urlend = strchr( dalogin, ',' );
    146                 if( urlend )
    147                         *urlend = 0;
    148                
    149                 /* strip the http(s):// part from the url */
    150                 urlend = strstr( urlend, "://" );
    151                 if( urlend )
    152                         dalogin = urlend + strlen( "://" );
    153                
    154                 if( prd_cached == NULL )
    155                         prd_cached = g_strdup( dalogin );
    156         }
    157        
    158         if( passport_get_id_from( rep->data, rep->func, rep->header, prd_cached ) )
    159         {
    160                 ssl_disconnect( ssl );
    161                 destroy_reply( rep );
    162                 return;
    163         }
    164        
    165 failure:       
    166         ssl_disconnect( ssl );
    167         rep->func( rep );
    168         destroy_reply( rep );
    169 }
    170 
    171 
    172 static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url )
    173 {
    174         struct passport_reply *rep = g_new0( struct passport_reply, 1 );
    175         char server[512], *dummy;
    176         void *ssl;
    177        
    178         rep->data = data;
    179         rep->func = func;
    180         rep->redirects = 4;
    181        
    182         strncpy( server, url, 512 );
    183         dummy = strchr( server, '/' );
    184         if( dummy )
    185                 *dummy = 0;
    186        
    187         ssl = ssl_connect( server, 443, passport_get_id_connected, rep );
    188        
    189         if( ssl )
    190         {
    191                 rep->header = g_strdup( header_i );
    192                 rep->url = g_strdup( url );
    193         }
    194         else
    195         {
    196                 destroy_reply( rep );
    197         }
    198        
    199         return( ssl != NULL );
    200 }
    201 
    202 #define PPG_BUFFERSIZE 4096
    203 static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond )
    204 {
    205         struct passport_reply *rep = data;
    206         char server[512], buffer[PPG_BUFFERSIZE+1], *dummy;
    207         int ret;
    208        
    209         if( !g_slist_find( msn_connections, rep->data ) )
    210         {
    211                 if( ssl ) ssl_disconnect( ssl );
    212                 destroy_reply( rep );
    213                 return;
    214         }
    215        
    216         if( !ssl )
    217         {
    218                 rep->func( rep );
    219                 destroy_reply( rep );
    220                 return;
    221         }
    222        
    223         memset( buffer, 0, PPG_BUFFERSIZE + 1 );
    224        
    225         strncpy( server, rep->url, 512 );
    226         dummy = strchr( server, '/' );
    227         if( dummy == NULL )
    228                 goto end;
    229        
    230         g_snprintf( buffer, PPG_BUFFERSIZE - 1, "GET %s HTTP/1.0\r\n"
    231                     "%s\r\n\r\n", dummy, rep->header );
    232        
    233         ssl_write( ssl, buffer, strlen( buffer ) );
    234         memset( buffer, 0, PPG_BUFFERSIZE + 1 );
    235        
    236         {
    237                 char *buffer2 = buffer;
    238                
    239                 while( ( ( ret = ssl_read( ssl, buffer2, 512 ) ) > 0 ) &&
    240                        ( buffer + PPG_BUFFERSIZE - buffer2 - ret - 512 >= 0 ) )
    241                 {
    242                         buffer2 += ret;
    243                 }
    244         }
    245        
    246         if( *buffer == 0 )
    247                 goto end;
    248        
    249         if( ( dummy = strstr( buffer, "Location:" ) ) )
    250         {
    251                 char *urlend;
    252                
    253                 rep->redirects --;
    254                 if( rep->redirects == 0 )
    255                         goto end;
    256                
    257                 dummy += strlen( "Location:" );
    258                 while( isspace( *dummy ) ) dummy ++;
    259                 urlend = dummy;
    260                 while( !isspace( *urlend ) ) urlend ++;
    261                 *urlend = 0;
    262                 if( ( urlend = strstr( dummy, "://" ) ) )
    263                         dummy = urlend + strlen( "://" );
    264                
    265                 g_free( rep->url );
    266                 rep->url = g_strdup( dummy );
    267                
    268                 strncpy( server, dummy, sizeof( server ) - 1 );
    269                 dummy = strchr( server, '/' );
    270                 if( dummy ) *dummy = 0;
    271                
    272                 ssl_disconnect( ssl );
    273                
    274                 if( ssl_connect( server, 443, passport_get_id_connected, rep ) )
    275                 {
    276                         return;
    277                 }
    278                 else
    279                 {
    280                         rep->func( rep );
    281                         destroy_reply( rep );
    282                         return;
    283                 }
    284         }
    285         else if( strstr( buffer, "200 OK" ) )
    286         {
    287                 if( ( dummy = strstr( buffer, "from-PP='" ) ) )
     100                if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) )
    288101                {
    289102                        char *responseend;
     
    298111        }
    299112       
    300 end:
    301         ssl_disconnect( ssl );
    302113        rep->func( rep );
    303114        destroy_reply( rep );
    304115}
    305116
     117static char *passport_create_header( char *cookie, char *email, char *pwd )
     118{
     119        char *buffer = g_new0( char, 2048 );
     120        char *currenttoken;
     121        char *email_enc, *pwd_enc;
     122       
     123        email_enc = g_new0( char, strlen( email ) * 3 + 1 );
     124        strcpy( email_enc, email );
     125        http_encode( email_enc );
     126       
     127        pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 );
     128        strcpy( pwd_enc, pwd );
     129        http_encode( pwd_enc );
     130       
     131        currenttoken = strstr( cookie, "lc=" );
     132        if( currenttoken == NULL )
     133                return( NULL );
     134       
     135        g_snprintf( buffer, 2048,
     136                    "Authorization: Passport1.4 OrgVerb=GET,"
     137                    "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom,"
     138                    "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc,
     139                    currenttoken );
     140       
     141        g_free( email_enc );
     142        g_free( pwd_enc );
     143       
     144        return( buffer );
     145}
     146
     147#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n"
     148static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header )
     149{
     150        struct passport_reply *rep = g_new0( struct passport_reply, 1 );
     151        struct http_request *req;
     152       
     153        rep->data = data;
     154        rep->func = func;
     155        rep->header = header;
     156       
     157        req = http_dorequest( "nexus.passport.com", 443, 1, PPR_REQUEST, passport_retrieve_dalogin_ready, rep );
     158       
     159        if( !req )
     160                destroy_reply( rep );
     161       
     162        return( req != NULL );
     163}
     164
     165static void passport_retrieve_dalogin_ready( struct http_request *req )
     166{
     167        struct passport_reply *rep = req->data;
     168        char *dalogin;
     169        char *urlend;
     170       
     171        if( !g_slist_find( msn_connections, rep->data ) )
     172        {
     173                destroy_reply( rep );
     174                return;
     175        }
     176       
     177        dalogin = strstr( req->reply_headers, "DALogin=" );     
     178       
     179        if( !dalogin )
     180                goto failure;
     181       
     182        dalogin += strlen( "DALogin=" );
     183        urlend = strchr( dalogin, ',' );
     184        if( urlend )
     185                *urlend = 0;
     186       
     187        /* strip the http(s):// part from the url */
     188        urlend = strstr( urlend, "://" );
     189        if( urlend )
     190                dalogin = urlend + strlen( "://" );
     191       
     192        if( prd_cached == NULL )
     193                prd_cached = g_strdup( dalogin );
     194       
     195        if( passport_get_id_real( rep->func, rep->data, rep->header ) )
     196        {
     197                destroy_reply( rep );
     198                return;
     199        }
     200       
     201failure:       
     202        rep->func( rep );
     203        destroy_reply( rep );
     204}
    306205
    307206static void destroy_reply( struct passport_reply *rep )
    308207{
    309         if( rep->result ) g_free( rep->result );
    310         if( rep->url ) g_free( rep->url );
    311         if( rep->header ) g_free( rep->header );
    312         if( rep ) g_free( rep );
    313 }
     208        g_free( rep->result );
     209        g_free( rep->header );
     210        g_free( rep );
     211}
  • protocols/msn/passport.h

    rb5a22e3 r7c0a497  
    3535struct passport_reply
    3636{
     37        void (*func)( struct passport_reply * );
    3738        void *data;
    3839        char *result;
    39         void (*func)( struct passport_reply * );
    40         char *url;
    4140        char *header;
    42         int redirects;
    4341};
    4442
    45 int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func );
     43int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie );
    4644
    4745#endif /* __PASSPORT_H__ */
  • protocols/proxy.c

    rb5a22e3 r7c0a497  
    106106        if (condition & GAIM_WRITE_COND)
    107107                gaim_cond |= GAIM_INPUT_WRITE;
    108 //      if (condition & GAIM_ERR_COND)
    109 //              fprintf( stderr, "ERROR! fd=%d\n", g_io_channel_unix_get_fd( source ) );
    110108
    111109        closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond);
  • protocols/ssl_bogus.c

    rb5a22e3 r7c0a497  
    2828int ssl_errno;
    2929
    30 void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
     30void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
    3131{
    3232        return( NULL );
  • protocols/ssl_client.h

    rb5a22e3 r7c0a497  
    3333extern int ssl_errno;
    3434
    35 typedef void (*SslInputFunction)(gpointer, void*, GaimInputCondition);
     35typedef void (*ssl_input_function)(gpointer, void*, GaimInputCondition);
    3636
    37 G_MODULE_EXPORT void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data );
     37G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data );
    3838G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len );
    3939G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len );
    4040G_MODULE_EXPORT void ssl_disconnect( void *conn_ );
    4141G_MODULE_EXPORT int ssl_getfd( void *conn );
     42G_MODULE_EXPORT GaimInputCondition ssl_getdirection( void *conn );
  • protocols/ssl_gnutls.c

    rb5a22e3 r7c0a497  
    3838struct scd
    3939{
    40         SslInputFunction func;
     40        ssl_input_function func;
    4141        gpointer data;
    4242        int fd;
     
    5151
    5252
    53 void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
     53void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
    5454{
    5555        struct scd *conn = g_new0( struct scd, 1 );
     
    117117                if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
    118118                {
    119                         conn->inpa = gaim_input_add( conn->fd,
    120                                                      gnutls_record_get_direction( conn->session ) ?
    121                                                          GAIM_INPUT_WRITE : GAIM_INPUT_READ,
     119                        conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ),
    122120                                                     ssl_handshake, data );
    123121                }
     
    145143int ssl_read( void *conn, char *buf, int len )
    146144{
     145        int st;
     146       
    147147        if( !((struct scd*)conn)->established )
    148148        {
     
    151151        }
    152152       
    153         return( gnutls_record_recv( ((struct scd*)conn)->session, buf, len ) );
    154        
     153        st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len );
     154       
     155        ssl_errno = SSL_OK;
     156        if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
     157                ssl_errno = SSL_AGAIN;
     158       
     159        return st;
    155160}
    156161
    157162int ssl_write( void *conn, const char *buf, int len )
    158163{
     164        int st;
     165       
    159166        if( !((struct scd*)conn)->established )
    160167        {
     
    163170        }
    164171       
    165         return( gnutls_record_send( ((struct scd*)conn)->session, buf, len ) );
     172        st = gnutls_record_send( ((struct scd*)conn)->session, buf, len );
     173       
     174        ssl_errno = SSL_OK;
     175        if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
     176                ssl_errno = SSL_AGAIN;
     177       
     178        return st;
    166179}
    167180
     
    184197        return( ((struct scd*)conn)->fd );
    185198}
     199
     200GaimInputCondition ssl_getdirection( void *conn )
     201{
     202        return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ?
     203                GAIM_INPUT_WRITE : GAIM_INPUT_READ );
     204}
  • protocols/ssl_nss.c

    rb5a22e3 r7c0a497  
    4545struct scd
    4646{
    47         SslInputFunction func;
     47        ssl_input_function func;
    4848        gpointer data;
    4949        int fd;
     
    9191
    9292
    93 void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
     93void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
    9494{
    9595        struct scd *conn = g_new0( struct scd, 1 );
  • protocols/ssl_openssl.c

    rb5a22e3 r7c0a497  
    4141struct scd
    4242{
    43         SslInputFunction func;
     43        ssl_input_function func;
    4444        gpointer data;
    4545        int fd;
     
    5454
    5555
    56 void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
     56void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
    5757{
    5858        struct scd *conn = g_new0( struct scd, 1 );
Note: See TracChangeset for help on using the changeset viewer.