/* --------------------------------------------------------------------------- $Id: net_ka.h,v 1.24 2007/05/02 13:32:22 cnepveu Exp $ --------------------------------------------------------------------------- Copyright (c) 2007 Hexago Inc. All rights reserved. LICENSE NOTICE: You may use and modify this source code only if you have executed a valid license agreement with Hexago Inc. granting you the right to do so, the said license agreement governing such use and modifications. Copyright or other intellectual property notices are not to be removed from the source code. --------------------------------------------------------------------------- */ /* This implements a keepalive algorythm. Should be able to get a ping socket for all the platforms, generate the ICMP6 raw data and process the actual ping based on internal values. Algo: Start from the maximum value suggested by the server. Need: 1. Major fuzz factor The major fuzz factor is applied to major increases or decreases of the timeout value. +/- 0% - 40%, initial +25% 2. Minor fuzz factor Thee minor fuzz factor is applied after we have reached the upper timeout value zone. +/- 0% - 5%, initial +3% 3. Initial timeout Fixed to 5 seconds 4. Maximal timeout Given by the server 5. Upper timeout value zone ( (Maximal timeout - 25%) - Maximal timeout ) (ie, 75% - 100% of 30 seconds). This is meant as a comfort zone in which we can apply small changes to the keep alive value - changes in the order of the minor fuzz factor. (from Teredo, section 6.7) a) Apply +(Major fuzz factor) to the timeout value until we reach the upper timeout value zone, then throttle to +/-(Minor fuzz factor) with an adjustment to stay in the upper timeout value zone. b) When we get no replies, apply -(Major fuzz factor) to the timeout value until initial timeout is reached. Forfeit if we get too many timeouts. If reply, go to a) So. Each time NetKeepaliveDo() is called, we check next_event and see if we have to let out a keepalive packet. If so we do, recompute major_fuzz, minor_fuzz, apply either +(major_fuzz) or +/-(minor_fuzz) to next_event and exit. Apply +(major_fuzz) if outside the comfort zone, +/-(minor_fuzz) otherwise. If we have an event ready and we havent got a read from the socket, we send the keepalive and recompute major_fuzz, minor_fuzz, apply -(major_fuzz) to next_event and exit. */ /* forward functions declarations */ int NetKeepaliveInit(char *src, char *dst, int maximal_keepalive, int family); /* return values : 0 - ok 1 - error */ void NetKeepaliveDestroy(); int NetKeepaliveV6V4Tunnel(char *src, char *dst, int maximal_keepalive); #ifdef V4V6_SUPPORT int NetKeepaliveV4V6Tunnel(char *src, char *dst, int maximal_keepalive, int lifetime); #endif /* V4V6_SUPPORT */ int NetKeepaliveDo(); /* return values : 0 - everything is OK 1 - warning - timeout 2 - fatal - too many timeouts */ void NetKeepaliveGotRead(); void NetKeepaliveGotWrite(); unsigned short in_cksum(unsigned short *addr, int len); /* Data */ struct NetKeepAlive { int init; /* is it initialized? */ char host[512]; /* host to send ping to */ SOCKET keepalive_fd; int family; struct sockaddr_in6 sa6_local; /* our ipv6 */ /* needed for cksum */ struct sockaddr_in6 sa6; /* ping6 destination */ struct sockaddr_in sa_local; /* ipv4 keepalive */ struct sockaddr_in sa; /* ping4 destination */ int still_up; // link is still up? int doit; // we had no write out, ping out to keepalive int count; // read counter in between cycles int got_read; // read flag int got_write; // write flag int pinged; // pinged flag int consecutive_timeout; /* number of consecutive timeouts */ int maximal_keepalive; /* the maximal wait factor */ double current_keepalive; float minor_fuzz; /* the minor fuzz factor */ float major_fuzz; /* the major fuzz factor */ #define KA_INITIAL_KEEPALIVE 5 // initial timeout value #define KA_MAXIMAL_CYCLES 5 // maximal number of consecutive keepalive // missed before declaring a timeout struct timeval next_event; /* take action at OR after this time */ };