distSOCKET/safesend.c
///////////////////////////////////////////////////////////////////////////////
// Filename: safesend.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: implements "safe" sendto()/recvfrom() functions
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date     Time     Name      Description   
// -------- -------- --------  ------------------------------------------------
// 96/03/19 20:04:26 muellerg: created
//
// possible improvements:
//
// use better timeout algorithm (e.g. TCPs). Not done to keep code simpler
///////////////////////////////////////////////////////////////////////////////
// Feature test switches ///////////////////////////// Feature test switches //
    /* NONE */
// System headers /////////////////////////////////////////// System headers //
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#ifndef sun
#include <strings.h>
#endif
// Local headers ///////////////////////////////////////////// Local headers //
#include "../common.h"
// Macros /////////////////////////////////////////////////////////// Macros //
    /* NONE */
// File scope objects /////////////////////////////////// File scope objects //
struct recinfo;                     // defined later
const int MAXKEEPSTATE = 1000;      // remember the last MAXKEEPSTATE sequence
                                    // numbers sent to the process
const int MAXKEEP = 100;            // maximum number of "false" reads
static recinfo *data = NULL;        // information from "false" read
static int actnumber = 0;           // number of allocated slots
static int firstdata = 0;           // number of first data slot to look in
static int nextdata = 0;            // number of next slot to use
static unsigned long sequencenumber;// is initialized in initialize() to a
                                    // random number. Sequence numbers are
                                    // used for all outgoing messages
static int MAXRETRY = 10;           // how often to retry a message
static int TIMEOUT = 10;            // timeout in seconds
static int MAXBUFFER = 16384;       // maximum size of messages, some bytes
                                    // needed for own message header 
static bool initialized = false;    // initialize data only once
static unsigned long crc_32_tab[256];// CRC-32 table
// External variables, functions, and classes ///////////// External objects //
    /* NONE */
// Signal catching functions ///////////////////// Signal catching functions //
    /* NONE */
// Structures, unions, and class definitions /////////////////// Definitions //
enum messagetype {SEND, ACK};       // type of message
// format of all messages sent and received by the safe functions
struct newmessage
{
    unsigned long sequencenumber;// sequence number for this message
    messagetype type;            // type of message (only for safety)
    unsigned long CRC;           // checksum
    char data[0];                // actual data starts here
};