diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-07-11 01:29:19 +0100 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-07-11 01:29:19 +0100 |
commit | e92c4f4f63ca0ba9ac6f959f7ff894ad2fc72a04 (patch) | |
tree | c9aff24a9af5f9b8757f9174647d2e4db5a54829 | |
parent | f1c2b21af3a51796b747ca4dbc2cdec9611efc5d (diff) |
Takeover stuff now works in daemon mode as well.
-rw-r--r-- | ipc.c | 73 | ||||
-rw-r--r-- | root_commands.c | 23 |
2 files changed, 90 insertions, 6 deletions
@@ -171,6 +171,11 @@ void ipc_master_cmd_takeover( irc_t *data, char **cmd ) struct bitlbee_child *child = (void*) data; char *fwd = NULL; + /* Normal daemon mode doesn't keep these and has simplified code for + takeovers. */ + if( child == NULL ) + return; + if( child->to_child == NULL || g_slist_find( child_list, child->to_child ) == NULL ) return ipc_master_takeover_fail( child, FALSE ); @@ -358,22 +363,58 @@ static void ipc_child_cmd_takeover( irc_t *irc, char **cmd ) static void ipc_child_cmd_takeover_yes( void *data ) { - irc_t *irc = data; + irc_t *irc = data, *old = NULL; + char *to_auth[] = { "TAKEOVER", "AUTH", irc->user->nick, irc->password, NULL }; /* Master->New connection */ ipc_to_master_str( "TAKEOVER AUTH %s :%s\r\n", irc->user->nick, irc->password ); + if( global.conf->runmode == RUNMODE_DAEMON ) + { + GSList *l; + + for( l = irc_connection_list; l; l = l->next ) + { + old = l->data; + + if( irc != old && + irc->user->nick && old->user->nick && + irc->password && old->password && + strcmp( irc->user->nick, old->user->nick ) == 0 && + strcmp( irc->password, old->password ) == 0 ) + break; + } + if( l == NULL ) + { + to_auth[1] = "FAIL"; + ipc_child_cmd_takeover( irc, to_auth ); + return; + } + } + /* Drop credentials, we'll shut down soon and shouldn't overwrite any settings. */ irc_usermsg( irc, "Trying to take over existing session" ); + irc_desync( irc ); + + if( old ) + { + ipc_child_recv_fd = dup( irc->fd ); + ipc_child_cmd_takeover( old, to_auth ); + } + /* TODO: irc_setpass() should do all of this. */ irc_setpass( irc, NULL ); irc->status &= ~USTATUS_IDENTIFIED; irc_umode_set( irc, "-R", 1 ); - irc_desync( irc ); + if( old ) + { + irc->status |= USTATUS_SHUTDOWN; + irc_abort( irc, FALSE, NULL ); + } } static void ipc_child_cmd_takeover_no( void *data ) @@ -405,6 +446,30 @@ gboolean ipc_child_identify( irc_t *irc ) return TRUE; } + else if( global.conf->runmode == RUNMODE_DAEMON ) + { + GSList *l; + irc_t *old; + char *to_init[] = { "TAKEOVER", "INIT", NULL }; + + for( l = irc_connection_list; l; l = l->next ) + { + old = l->data; + + if( irc != old && + irc->user->nick && old->user->nick && + irc->password && old->password && + strcmp( irc->user->nick, old->user->nick ) == 0 && + strcmp( irc->password, old->password ) == 0 ) + break; + } + if( l == NULL ) + return FALSE; + + ipc_child_cmd_takeover( irc, to_init ); + + return TRUE; + } else return FALSE; } @@ -508,10 +573,14 @@ static char *ipc_readline( int fd, int *recv_fd ) close( *recv_fd ); *recv_fd = *(int*) CMSG_DATA( cmsg ); + /* fprintf( stderr, "pid %d received fd %d\n", (int) getpid(), *recv_fd ); + */ } + /* fprintf( stderr, "pid %d received: %s", (int) getpid(), buf ); + */ return g_strndup( buf, size - 2 ); } diff --git a/root_commands.c b/root_commands.c index 6fa4fd54..4aeb1470 100644 --- a/root_commands.c +++ b/root_commands.c @@ -154,16 +154,31 @@ static void cmd_identify( irc_t *irc, char **cmd ) irc_setpass( irc, password ); irc->status |= USTATUS_IDENTIFIED; irc_umode_set( irc, "+R", 1 ); - irc_channel_auto_joins( irc, NULL ); - if( ipc_child_identify( irc ) ) + /* The following code is a bit hairy now. With takeover + support, we shouldn't immediately auto_connect in case + we're going to offer taking over an existing session. + Do it in 200ms since that should give the parent process + enough time to come back to us. */ + if( load ) { - if( load && set_getbool( &irc->b->set, "auto_connect" ) ) + irc_channel_auto_joins( irc, NULL ); + if( set_getbool( &irc->b->set, "auto_connect" ) ) irc->login_source_id = b_timeout_add( 200, cmd_identify_finish, irc ); } - else if( load && set_getbool( &irc->b->set, "auto_connect" ) ) + + /* If ipc_child_identify() returns FALSE, it means we're + already sure that there's no takeover target (only + possible in 1-process daemon mode). Start auto_connect + immediately. */ + if( !ipc_child_identify( irc ) && load && + set_getbool( &irc->b->set, "auto_connect" ) ) + { + b_event_remove( irc->login_source_id ); + irc->login_source_id = -1; cmd_identify_finish( irc, 0, 0 ); + } break; case STORAGE_OTHER_ERROR: |