diff options
Diffstat (limited to 'protocols/msn')
-rw-r--r-- | protocols/msn/invitation.c | 12 | ||||
-rw-r--r-- | protocols/msn/msn.c | 32 | ||||
-rw-r--r-- | protocols/msn/msn.h | 9 | ||||
-rw-r--r-- | protocols/msn/msn_util.c | 16 | ||||
-rw-r--r-- | protocols/msn/ns.c | 79 | ||||
-rw-r--r-- | protocols/msn/sb.c | 93 |
6 files changed, 164 insertions, 77 deletions
diff --git a/protocols/msn/invitation.c b/protocols/msn/invitation.c index d2b2a5c8..9f8b9a6e 100644 --- a/protocols/msn/invitation.c +++ b/protocols/msn/invitation.c @@ -208,7 +208,7 @@ gboolean msn_ftps_connected( gpointer data, gint fd, b_input_condition cond ) fd = msn_file->fd; sock_make_nonblocking( fd ); - msn_file->r_event_id = b_input_add( fd, GAIM_INPUT_READ, msn_ftp_read, file ); + msn_file->r_event_id = b_input_add( fd, B_EV_IO_READ, msn_ftp_read, file ); return FALSE; } @@ -229,7 +229,7 @@ void msn_invitations_accept( msn_filetransfer_t *msn_file, struct msn_switchboar return; } - msn_file->r_event_id = b_input_add( msn_file->fd, GAIM_INPUT_READ, msn_ftps_connected, file ); + msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file ); g_snprintf( buf, sizeof( buf ), "IP-Address: %s\r\n" @@ -317,7 +317,7 @@ gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond ) return FALSE; sock_make_nonblocking( msn_file->fd ); - msn_file->r_event_id = b_input_add( msn_file->fd, GAIM_INPUT_READ, msn_ftp_read, file ); + msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file ); return FALSE; } @@ -414,7 +414,7 @@ gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len ) if( ( msn_file->sbufpos < MSNFTP_PSIZE ) && ( msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size ) ) { if( !msn_file->w_event_id ) - msn_file->w_event_id = b_input_add( msn_file->fd, GAIM_INPUT_WRITE, msn_ftp_send, file ); + msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); return TRUE; } @@ -451,7 +451,7 @@ gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len ) } else { /* we might already be listening if this is data from an overflow */ if( !msn_file->w_event_id ) - msn_file->w_event_id = b_input_add( msn_file->fd, GAIM_INPUT_WRITE, msn_ftp_send, file ); + msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); } return TRUE; @@ -616,7 +616,7 @@ gboolean msn_ftpr_write_request( file_transfer_t *file ) } msn_file->r_event_id = - b_input_add( msn_file->fd, GAIM_INPUT_READ, msn_ftp_read, file ); + b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file ); return TRUE; } diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 3a8b8f7b..0d67cc17 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -30,16 +30,14 @@ int msn_chat_id; GSList *msn_connections; GSList *msn_switchboards; -static char *msn_set_display_name( set_t *set, char *value ); +static char *set_eval_display_name( set_t *set, char *value ); static void msn_init( account_t *acc ) { - set_t *s; - - s = set_add( &acc->set, "display_name", NULL, msn_set_display_name, acc ); - s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; - - s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); + set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); + set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc ); + set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); + set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc ); } static void msn_login( account_t *acc ) @@ -170,7 +168,7 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) static void msn_set_my_name( struct im_connection *ic, char *info ) { - msn_set_display_name( set_find( &ic->acc->set, "display_name" ), info ); + msn_set_display_name( ic, info ); } static void msn_get_info(struct im_connection *ic, char *who) @@ -286,18 +284,14 @@ static int msn_send_typing( struct im_connection *ic, char *who, int typing ) return( 1 ); } -static char *msn_set_display_name( set_t *set, char *value ) +static char *set_eval_display_name( set_t *set, char *value ) { account_t *acc = set->data; struct im_connection *ic = acc->ic; - struct msn_data *md; - char buf[1024], *fn; - /* Double-check. */ + /* Allow any name if we're offline. */ if( ic == NULL ) - return NULL; - - md = ic->proto_data; + return value; if( strlen( value ) > 129 ) { @@ -305,16 +299,10 @@ static char *msn_set_display_name( set_t *set, char *value ) return NULL; } - fn = msn_http_encode( value ); - - g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn ); - msn_write( ic, buf, strlen( buf ) ); - g_free( fn ); - /* Returning NULL would be better, because the server still has to confirm the name change. However, it looks a bit confusing to the user. */ - return value; + return msn_set_display_name( ic, value ) ? value : NULL; } void msn_initmodule() diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 50f273ad..f3cb8635 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -30,6 +30,7 @@ */ #define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r" #define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r" +#define SB_KEEPALIVE_MESSAGE "\r\r\rDONT HANG UP ON ME!\r\r\r" #ifdef DEBUG_MSN #define debug( text... ) imcb_log( ic, text ); @@ -53,6 +54,10 @@ "TypingUser: %s\r\n" \ "\r\n\r\n" +#define SB_KEEPALIVE_HEADERS "MIME-Version: 1.0\r\n" \ + "Content-Type: text/x-ping\r\n" \ + "\r\n\r\n" + #define PROFILE_URL "http://members.msn.com/" struct msn_data @@ -83,6 +88,7 @@ struct msn_switchboard int fd; gint inp; struct msn_handler_data *handler; + gint keepalive; int trId; int ready; @@ -161,6 +167,7 @@ char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); char *msn_http_encode( const char *input ); void msn_msgq_purge( struct im_connection *ic, GSList **list ); +gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); @@ -179,6 +186,8 @@ struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb ); void msn_sb_destroy( struct msn_switchboard *sb ); gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ); int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ); +void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ); +void msn_sb_stop_keepalives( struct msn_switchboard *sb ); /* invitation.c */ void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 668a8b8a..9c9d2720 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -37,10 +37,10 @@ int msn_write( struct im_connection *ic, char *s, int len ) { imcb_error( ic, "Short write() to main server" ); imc_logout( ic, TRUE ); - return( 0 ); + return 0; } - return( 1 ); + return 1; } int msn_logged_in( struct im_connection *ic ) @@ -376,3 +376,15 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ) imcb_log( ic, "%s", ret->str ); g_string_free( ret, TRUE ); } + +gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ) +{ + char *fn = msn_http_encode( rawname ); + struct msn_data *md = ic->proto_data; + char buf[1024]; + + g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn ); + g_free( fn ); + + return msn_write( ic, buf, strlen( buf ) ) != 0; +} diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index d78d753a..2b0600a3 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -34,6 +34,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); static void msn_auth_got_passport_token( struct msn_auth_data *mad ); +static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { @@ -74,7 +75,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId ); if( msn_write( ic, s, strlen( s ) ) ) { - ic->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, ic ); + ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); imcb_log( ic, "Connected to server, waiting for reply" ); } @@ -230,25 +231,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 ) { - set_t *s; - if( num_parts == 7 ) - { - http_decode( cmd[4] ); - - strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); - ic->displayname[sizeof(ic->displayname)-1] = 0; - - if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) - { - g_free( s->value ); - s->value = g_strdup( cmd[4] ); - } - } + msn_ns_got_display_name( ic, cmd[4] ); else - { imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); - } imcb_log( ic, "Authenticated, getting buddy list" ); @@ -435,8 +421,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "FLN" ) == 0 ) { - if( cmd[1] ) - imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); + if( cmd[1] == NULL ) + return 1; + + imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); + + msn_sb_start_keepalives( msn_sb_by_handle( ic, cmd[1] ), TRUE ); } else if( strcmp( cmd[0], "NLN" ) == 0 ) { @@ -462,6 +452,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | ( st != msn_away_state_list ? OPT_AWAY : 0 ), st->name, NULL ); + + msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) ); } else if( strcmp( cmd[0], "RNG" ) == 0 ) { @@ -566,6 +558,9 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imc_logout( ic, allow_reconnect ); return( 0 ); } +#if 0 + /* Discard this one completely for now since I don't care about the ack + and since MSN servers can apparently screw up the formatting. */ else if( strcmp( cmd[0], "REA" ) == 0 ) { if( num_parts != 5 ) @@ -596,6 +591,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imcb_rename_buddy( ic, cmd[3], cmd[4] ); } } +#endif else if( strcmp( cmd[0], "IPG" ) == 0 ) { imcb_error( ic, "Received IPG command, we don't handle them yet." ); @@ -745,3 +741,48 @@ static void msn_auth_got_passport_token( struct msn_auth_data *mad ) imc_logout( ic, TRUE ); } } + +static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ) +{ + set_t *s; + + if( ( s = set_find( &ic->acc->set, "display_name" ) ) == NULL ) + return FALSE; /* Shouldn't happen.. */ + + http_decode( name ); + + if( s->value && strcmp( s->value, name ) == 0 ) + { + return TRUE; + /* The names match, nothing to worry about. */ + } + else if( s->value != NULL && + ( strcmp( name, ic->acc->user ) == 0 || + set_getbool( &ic->acc->set, "local_display_name" ) ) ) + { + /* The server thinks our display name is our e-mail address + which is probably wrong, or the user *wants* us to do this: + Always use the locally set display_name. */ + return msn_set_display_name( ic, s->value ); + } + else + { + if( s->value && *s->value ) + imcb_log( ic, "BitlBee thinks your display name is `%s' but " + "the MSN server says it's `%s'. Using the MSN " + "server's name. Set local_display_name to true " + "to use the local name.", s->value, name ); + + if( g_utf8_validate( name, -1, NULL ) ) + { + g_free( s->value ); + s->value = g_strdup( name ); + } + else + { + imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); + } + + return TRUE; + } +} diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index c3302e57..1614f69f 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -179,6 +179,11 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) buf = g_strdup( text ); i = strlen( buf ); } + else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 ) + { + buf = g_strdup( SB_KEEPALIVE_HEADERS ); + i = strlen( buf ); + } else { buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 ); @@ -255,6 +260,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" ); msn_msgq_purge( ic, &sb->msgq ); + msn_sb_stop_keepalives( sb ); if( sb->key ) g_free( sb->key ); if( sb->who ) g_free( sb->who ); @@ -314,7 +320,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session ); if( msn_sb_write( sb, buf, strlen( buf ) ) ) - sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb ); + sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb ); else debug( "Error %d while connecting to switchboard server", 2 ); @@ -327,9 +333,13 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c struct im_connection *ic = sb->ic; struct msn_data *md = ic->proto_data; - if( msn_handler( sb->handler ) == -1 ) + if( msn_handler( sb->handler ) != -1 ) + return TRUE; + + if( sb->msgq != NULL ) { time_t now = time( NULL ); + char buf[1024]; if( now - md->first_sb_failure > 600 ) { @@ -346,37 +356,28 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c imcb_log( ic, "Warning: Many switchboard failures on MSN connection. " "There might be problems delivering your messages." ); - if( sb->msgq != NULL ) + if( md->msgq == NULL ) { - char buf[1024]; - - if( md->msgq == NULL ) - { - md->msgq = sb->msgq; - } - else - { - GSList *l; - - for( l = md->msgq; l->next; l = l->next ); - l->next = sb->msgq; - } - sb->msgq = NULL; + md->msgq = sb->msgq; + } + else + { + GSList *l; - debug( "Moved queued messages back to the main queue, creating a new switchboard to retry." ); - g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); - if( !msn_write( ic, buf, strlen( buf ) ) ) - return FALSE; + for( l = md->msgq; l->next; l = l->next ); + l->next = sb->msgq; } + sb->msgq = NULL; - msn_sb_destroy( sb ); - - return FALSE; - } - else - { - return TRUE; + debug( "Moved queued messages back to the main queue, " + "creating a new switchboard to retry." ); + g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); + if( !msn_write( ic, buf, strlen( buf ) ) ) + return FALSE; } + + msn_sb_destroy( sb ); + return FALSE; } static int msn_sb_command( gpointer data, char **cmd, int num_parts ) @@ -476,6 +477,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } sb->ready = 1; + + msn_sb_start_keepalives( sb, FALSE ); } else if( strcmp( cmd[0], "CAL" ) == 0 ) { @@ -525,6 +528,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) sb->msgq = g_slist_remove( sb->msgq, m ); } + msn_sb_start_keepalives( sb, FALSE ); + return( st ); } else if( sb->who ) @@ -586,6 +591,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( sb->who ) { + msn_sb_stop_keepalives( sb ); + /* This is a single-person chat, and the other person is leaving. */ g_free( sb->who ); sb->who = NULL; @@ -748,3 +755,33 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int return( 1 ); } + +static gboolean msn_sb_keepalive( gpointer data, gint source, b_input_condition cond ) +{ + struct msn_switchboard *sb = data; + return sb->ready && msn_sb_sendmessage( sb, SB_KEEPALIVE_MESSAGE ); +} + +void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ) +{ + struct buddy *b; + + if( sb && sb->who && sb->keepalive == 0 && + ( b = imcb_find_buddy( sb->ic, sb->who ) ) && !b->present && + set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) ) + { + if( initial ) + msn_sb_keepalive( sb, 0, 0 ); + + sb->keepalive = b_timeout_add( 20000, msn_sb_keepalive, sb ); + } +} + +void msn_sb_stop_keepalives( struct msn_switchboard *sb ) +{ + if( sb && sb->keepalive > 0 ) + { + b_event_remove( sb->keepalive ); + sb->keepalive = 0; + } +} |