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 )  { | 
