/*
---------------------------------------------------------------------------
 $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 */
};




syntax highlighted by Code2HTML, v. 0.9.1