diff options
-rw-r--r-- | ipc.c | 32 | ||||
-rw-r--r-- | ipc.h | 2 | ||||
-rw-r--r-- | irc.c | 79 | ||||
-rw-r--r-- | irc.h | 5 | ||||
-rw-r--r-- | root_commands.c | 3 |
5 files changed, 91 insertions, 30 deletions
@@ -332,27 +332,10 @@ static void ipc_child_cmd_takeover( irc_t *irc, char **cmd ) strcmp( irc->user->nick, cmd[2] ) == 0 && strcmp( irc->password, cmd[3] ) == 0 ) { - GSList *l; - - /* TODO: Move this all into irc_switch_fd() or so and - irc_sync() */ - b_event_remove( irc->r_watch_source_id ); - closesocket( irc->fd ); - irc->fd = ipc_child_recv_fd; - irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc ); - ipc_child_recv_fd = -1; - - irc_write( irc, ":%s!%s@%s MODE %s :+%s", irc->user->nick, - irc->user->user, irc->user->host, irc->user->nick, - irc->umode ); - - for( l = irc->channels; l; l = l->next ) - { - irc_channel_t *ic = l->data; - if( ic->flags & IRC_CHANNEL_JOINED ) - irc_send_join( ic, irc->user ); - } + irc_switch_fd( irc, ipc_child_recv_fd ); + irc_sync( irc ); irc_usermsg( irc, "You've successfully taken over your old session" ); + ipc_child_recv_fd = -1; ipc_to_master_str( "TAKEOVER DONE\r\n" ); } @@ -376,7 +359,6 @@ static void ipc_child_cmd_takeover( irc_t *irc, char **cmd ) static void ipc_child_cmd_takeover_yes( void *data ) { irc_t *irc = data; - GSList *l; /* Master->New connection */ ipc_to_master_str( "TAKEOVER AUTH %s :%s\r\n", @@ -391,13 +373,7 @@ static void ipc_child_cmd_takeover_yes( void *data ) irc->status &= ~USTATUS_IDENTIFIED; irc_umode_set( irc, "-R", 1 ); - for( l = irc->channels; l; l = l->next ) - irc_channel_del_user( l->data, irc->user, IRC_CDU_KICK, - "Switching to old session" ); - - irc_write( irc, ":%s!%s@%s MODE %s :-%s", irc->user->nick, - irc->user->user, irc->user->host, irc->user->nick, - irc->umode ); + irc_desync( irc ); } static void ipc_child_cmd_takeover_no( void *data ) @@ -54,6 +54,8 @@ void ipc_master_free_all(); void ipc_child_disable(); +gboolean ipc_child_identify( irc_t *irc ); + void ipc_to_master( char **cmd ); void ipc_to_master_str( char *format, ... ) G_GNUC_PRINTF( 1, 2 ); void ipc_to_children( char **cmd ); @@ -618,6 +618,85 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) return; } +/* Flush sendbuffer if you can. If it fails, fail silently and let some + I/O event handler clean up. */ +void irc_flush( irc_t *irc ) +{ + ssize_t n; + size_t len; + + if( irc->sendbuffer == NULL ) + return; + + len = strlen( irc->sendbuffer ); + if( ( n = send( irc->fd, irc->sendbuffer, len, 0 ) ) == len ) + { + g_free( irc->sendbuffer ); + irc->sendbuffer = NULL; + + b_event_remove( irc->w_watch_source_id ); + irc->w_watch_source_id = 0; + } + else if( n > 0 ) + { + char *s = g_strdup( irc->sendbuffer + n ); + g_free( irc->sendbuffer ); + irc->sendbuffer = s; + } + /* Otherwise something went wrong and we don't currently care + what the error was. We may or may not succeed later, we + were just trying to flush the buffer immediately. */ +} + +/* Meant for takeover functionality. Transfer an IRC connection to a different + socket. */ +void irc_switch_fd( irc_t *irc, int fd ) +{ + irc_write( irc, "ERROR :Transferring session to a new connection" ); + irc_flush( irc ); /* Write it now or forget about it forever. */ + + if( irc->sendbuffer ) + { + b_event_remove( irc->w_watch_source_id ); + g_free( irc->sendbuffer ); + irc->sendbuffer = irc->w_watch_source_id = 0; + } + + b_event_remove( irc->r_watch_source_id ); + closesocket( irc->fd ); + irc->fd = fd; + irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc ); +} + +void irc_sync( irc_t *irc ) +{ + GSList *l; + + irc_write( irc, ":%s!%s@%s MODE %s :+%s", irc->user->nick, + irc->user->user, irc->user->host, irc->user->nick, + irc->umode ); + + for( l = irc->channels; l; l = l->next ) + { + irc_channel_t *ic = l->data; + if( ic->flags & IRC_CHANNEL_JOINED ) + irc_send_join( ic, irc->user ); + } +} + +void irc_desync( irc_t *irc ) +{ + GSList *l; + + for( l = irc->channels; l; l = l->next ) + irc_channel_del_user( l->data, irc->user, IRC_CDU_KICK, + "Switching to old session" ); + + irc_write( irc, ":%s!%s@%s MODE %s :-%s", irc->user->nick, + irc->user->user, irc->user->host, irc->user->nick, + irc->umode ); +} + int irc_check_login( irc_t *irc ) { if( irc->user->user && irc->user->nick ) @@ -229,6 +229,11 @@ void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); void irc_vawrite( irc_t *irc, char *format, va_list params ); +void irc_flush( irc_t *irc ); +void irc_switch_fd( irc_t *irc, int fd ); +void irc_sync( irc_t *irc ); +void irc_desync( irc_t *irc ); + int irc_check_login( irc_t *irc ); void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); diff --git a/root_commands.c b/root_commands.c index cf448e8d..6fa4fd54 100644 --- a/root_commands.c +++ b/root_commands.c @@ -27,8 +27,7 @@ #include "commands.h" #include "bitlbee.h" #include "help.h" - -#include <string.h> +#include "ipc.h" void root_command_string( irc_t *irc, char *command ) { |