diff options
-rw-r--r-- | account.c | 78 | ||||
-rw-r--r-- | doc/user-guide/commands.xml | 10 | ||||
-rw-r--r-- | irc.c | 2 | ||||
-rw-r--r-- | protocols/nogaim.c | 6 |
4 files changed, 72 insertions, 24 deletions
@@ -234,38 +234,82 @@ void account_off( irc_t *irc, account_t *a ) } } -char *set_eval_account_reconnect_delay( set_t *set, char *value ) +struct account_reconnect_delay { int start; char op; int step; + int max; +}; + +int account_reconnect_delay_parse( char *value, struct account_reconnect_delay *p ) +{ + memset( p, 0, sizeof( *p ) ); + /* A whole day seems like a sane "maximum maximum". */ + p->max = 86400; - if( sscanf( value, "%d%c%d", &start, &op, &step ) == 3 && - step > 0 && ( op == '+' || op == '*' ) ) - return value; - else - return set_eval_int( set, value ); + /* Format: /[0-9]+([*+][0-9]+(<[0-9+]))/ */ + while( *value && isdigit( *value ) ) + p->start = p->start * 10 + *value++ - '0'; + + /* Sure, call me evil for implementing my own fscanf here, but it's + dead simple and I'm immediately at the next part to parse. */ + + if( *value == 0 ) + /* If the string ends now, the delay is constant. */ + return 1; + else if( *value != '+' && *value != '*' ) + /* Otherwise allow either a + or a * */ + return 0; + + p->op = *value++; + + /* + or * the delay by this number every time. */ + while( *value && isdigit( *value ) ) + p->step = p->step * 10 + *value++ - '0'; + + if( *value == 0 ) + /* Use the default maximum (one day). */ + return 1; + else if( *value != '<' ) + return 0; + + p->max = 0; + value ++; + while( *value && isdigit( *value ) ) + p->max = p->max * 10 + *value++ - '0'; + + return p->max > 0; +} + +char *set_eval_account_reconnect_delay( set_t *set, char *value ) +{ + struct account_reconnect_delay p; + + return account_reconnect_delay_parse( value, &p ) ? value : NULL; } int account_reconnect_delay( account_t *a ) { char *setting = set_getstr( &a->irc->set, "auto_reconnect_delay" ); - int start, step; - char op; + struct account_reconnect_delay p; - if( sscanf( setting, "%d%c%d", &start, &op, &step ) == 3 && step > 0 ) + if( account_reconnect_delay_parse( setting, &p ) ) { if( a->auto_reconnect_delay == 0 ) - return a->auto_reconnect_delay = start; - else if( op == '+' ) - return a->auto_reconnect_delay += step; - else if( op == '*' ) - return a->auto_reconnect_delay *= step; + a->auto_reconnect_delay = p.start; + else if( p.op == '+' ) + a->auto_reconnect_delay += p.step; + else if( p.op == '*' ) + a->auto_reconnect_delay *= p.step; + + if( a->auto_reconnect_delay > p.max ) + a->auto_reconnect_delay = p.max; } - else if( sscanf( setting, "%d", &start ) == 1 ) + else { - return a->auto_reconnect_delay = start; + a->auto_reconnect_delay = 0; } - return 0; + return a->auto_reconnect_delay; } diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 6d77f8cd..cd16808e 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -320,12 +320,16 @@ </description> </bitlbee-setting> - <bitlbee-setting name="auto_reconnect_delay" type="integer" scope="global"> - <default>300</default> + <bitlbee-setting name="auto_reconnect_delay" type="string" scope="global"> + <default>5*3<900</default> <description> <para> - Tell BitlBee after how many seconds it should attempt to bring an IM-connection back up after a crash. It's not a good idea to set this value very low, it will cause too much useless traffic when an IM-server is down for a few hours. + Tell BitlBee after how many seconds it should attempt to bring a broken IM-connection back up. + </para> + + <para> + This can be one integer, for a constant delay. One can also set it to something like "10*10", which means wait for ten seconds on the first reconnect, multiply it by ten on every failure. Once successfully connected, this delay is re-set to the initial value. With < you can give a maximum delay. </para> <para> @@ -138,7 +138,7 @@ irc_t *irc_new( int fd ) set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc ); set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc ); - set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_account_reconnect_delay, irc ); + set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc ); set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index eb3fc2ad..b6f8d6e4 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -293,6 +293,7 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) irc_t *irc = ic->irc; user_t *t, *u; account_t *a; + int delay; /* Nested calls might happen sometimes, this is probably the best place to catch them. */ @@ -332,10 +333,9 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) /* Uhm... This is very sick. */ } else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) && - set_getbool( &a->set, "auto_reconnect" ) ) + set_getbool( &a->set, "auto_reconnect" ) && + ( delay = account_reconnect_delay( a ) ) > 0 ) { - int delay = account_reconnect_delay( a ); - imcb_log( ic, "Reconnecting in %d seconds..", delay ); a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a ); } |