icqlib will notice if it's sent a SRV_GO_AWAY, but it won't notice if the connection is lost any other way, for
example by unplugging the network.
This is fixed by changing udp.c line 217 from
icq_UDPSockWriteDirect(icqlink, p); /* don't queue keep alive packets! */
to
icq_UDPSockWrite(icqlink, p); /* do queue keep alive packets! */
and deleting the icq_PacketDelete(p) that's not used with icq_UDPSockWrite().
This way, keepalive packets use the same timeout mechanism as all other UDP packets, and it will force a
disconnect after 90 seconds of failure.
Making this change exposed a bug in queue.c line 127: p was freed by icq_Disconnect() so can no longer be
used to refer to icqlink in the invoke_callback(). Here's some new code:
if (p->attempts > 6)
{
icq_Link *link;
link=p->icqlink;
icq_Disconnect(p->icqlink);
invoke_callback(link, icq_Disconnected)(link);
return;
}