/* Do not remove the headers from this file! see /USAGE for more info. */
/*
** reconnect.c -- provide reconnection logic for socket users
**
** 95-May-11. Deathblade. Created.
*/
/*
** The client should fill in this function with the reconnection callback.
** The function prototype is: void func(string key)
*/
nosave function reconn_func;
/*
** Store the retry time for each key as we try to reestablish contact.
** key -> ({ period, count }). If a key has an entry here, then we are
** attempting to establish contact.
*/
nosave private mapping retry_info = ([ ]);
#define MAX_RETRY_PERIOD 3600 /* one hour */
#define RETRY_PER_PERIOD 4 /* 4 retries at each time period */
private nomask void time_to_reconnect(string key)
{
/*
** If the connection was successful and the retry data was cleared,
** then just return.
*/
if ( !retry_info[key] )
return;
evaluate(reconn_func, key);
}
protected nomask void cancel_reconnection(string key)
{
map_delete(retry_info, key);
}
protected nomask void trigger_reconnect(string key)
{
int delay;
/*
** Attempt to reconnect to the target. If we are not in the process
** of retrying, then set up the retry with a 1-minute period and begin
** immediately.
**
** If we have been retrying and we've hit the max # retries for this
** time period, then double the time period and schedule a retry.
*/
if ( !retry_info[key] )
{
retry_info[key] = ({ 60, 0 });
delay = 0;
}
else if ( ++retry_info[key][1] == RETRY_PER_PERIOD )
{
delay = retry_info[key][0] * 2;
if ( delay > MAX_RETRY_PERIOD )
delay = MAX_RETRY_PERIOD;
retry_info[key] = ({ delay, 0 });
}
else
delay = retry_info[key][0];
call_out((: time_to_reconnect :), delay, key);
}
string stat_me()
{
return sprintf("\nRETRY INFO\n%O\n", retry_info);
}