inc/rudp.h

Go to the documentation of this file.
00001 /* rudp - (semi) reliable UDP communication.  This adds an
00002  * acknowledgement and resend layer on top of UDP. 
00003  *
00004  * UDP is a packet based rather than stream based internet communication 
00005  * protocol. Messages sent by UDP are checked for integrety by the UDP layer, 
00006  * and discarded if transmission errors are detected.  However packets are
00007  * not necessarily received in the same order that they are sent,
00008  * and packets may be duplicated or lost.  
00009  
00010  * Using rudp packets are only very rarely lost, and the sender is 
00011  * notified if they are.  After rudp there are still duplicate
00012  * packets that may arrive out of order.  Aside from the duplicates
00013  * the packets are in order though.
00014  *
00015  * For many, perhaps most applications, TCP/IP is a saner choice
00016  * than UDP or rudp.  If the communication channel is between just 
00017  * two computers you can pretty much just treat TCP/IP as a fairly
00018  * reliable pipe.   However if the communication involves many
00019  * computers sometimes UDP can be a better choice.  It is possible to
00020  * do broadcast and multicast with UDP but not with TCP/IP.  Also
00021  * for systems like parasol, where a server may be making and breaking
00022  * connections rapidly to thousands of computers, TCP paradoxically
00023  * can end up less reliable than UDP.  Though TCP is relatively 
00024  * robust when a connection is made,  it can relatively easily fail
00025  * to make a connection in the first place, and spend quite a long
00026  * time figuring out that the connection can't be made.  Moreover at
00027  * the end of each connection TCP goes into a 'TIMED_WAIT' state,  which
00028  * prevents another connection from coming onto the same port for a
00029  * time that can be as long as 255 seconds.  Since there are only
00030  * about 15000 available ports,  this limits TCP/IP to 60 connections
00031  * per second in some cases.  Generally the system does not handle
00032  * running out of ports gracefully, and this did occur with the 
00033  * TCP/IP based version of Parasol.
00034  *
00035  * This module puts a thin layer around UDP to make it a little bit more
00036  * reliable.  Currently the interface is geared towards Parasol rather
00037  * than broadcast type applications.  This module will try to send
00038  * a message a limited number of times before giving up.  It puts
00039  * a small header containing a message ID and timestamp on each message.   
00040  * This header is echoed back in acknowledgment by the reciever. This
00041  * echo lets the sender know if it needs to resend the message, and
00042  * lets it know how long a message takes to get to the destination and
00043  * back.  It uses this round trip time information to figure out how
00044  * long to wait between resends. 
00045  *
00046  * Much of this code is based on the 'Adding Reliability to a UDP Application
00047  * section in volume I, chapter 20, section 5, of _UNIX Network Programming_
00048  * by W. Richard Stevens. */
00049 
00050 #ifndef RUDP_H
00051 #define RUDP_H
00052 
00053 #ifndef INTERNET_H
00054 #include "internet.h"
00055 #endif
00056 
00057 struct rudp
00058 /* A UDP socket and a little bit of stuff to help keep track
00059  * of how often we should resend unacknowledged messages. */
00060     {
00061     int socket;         /* The associated UDP socket. */
00062     int rttLast;        /* Last round trip time (RTT) for a message/ack in microseconds. */
00063     int rttAve;         /* Approximate average of recent RTTs. */
00064     int rttVary;        /* Approximate variation of recent RTTs. */
00065     int timeOut;        /* Ideal timeout for next receive. */
00066     int receiveCount;   /* Number of packets attempted to receive. */
00067     int sendCount;      /* Number of packets attempted to send. */
00068     int resendCount;    /* Number of resends. */
00069     int failCount;      /* Number of failures. */
00070     bits32 lastId;      /* Id number of last message sent. */
00071     int maxRetries;     /* Maximum number of retries per message. */
00072     };
00073 
00074 enum rudpType
00075     {
00076     rudpAck = 199,      /* Acknowledge message. */
00077     rudpData = 200,     /* Message with some data. */
00078     };
00079 
00080 struct rudpHeader
00081 /* The header to a rudp message.  */
00082     {
00083     bits32 id;          /* Message id.  Returned with ack. */
00084     bits32 sendSec;     /* Time sent in seconds.  Returned with ack. */
00085     bits32 sendMicro;   /* Time sent microseconds. Returned with ack. */
00086     bits8 type;         /* One of rudpType above. */
00087     bits8 reserved1;    /* Reserved, always zero for now. */
00088     bits8 reserved2;    /* Reserved, always zero for now. */
00089     bits8 reserved3;    /* Reserved, always zero for now. */
00090     };
00091 
00092 typedef bits32 rudpHost;  /* The IP address (in host order) of another computer. */
00093 
00094 #define udpEthMaxSize 1444
00095     /* Max data size that will fit into a single ethernet packet after UDP and IP
00096      * headers.  Things are faster & more reliable if you stay below this */
00097 
00098 #define rudpMaxSize (udpEthMaxSize - sizeof(struct rudpHeader)  )
00099 
00100 struct rudp *rudpNew(int socket);
00101 /* Wrap a rudp around a socket. Call rudpFree when done, or
00102  * rudpClose if you also want to close(socket). */
00103 
00104 void rudpFree(struct rudp **pRu);
00105 /* Free up rudp.  Note this does *not* close the associated socket. */
00106 
00107 struct rudp *rudpOpen();
00108 /* Open up an unbound rudp.   This is suitable for
00109  * writing to and for reading responses.  However 
00110  * you'll want to rudpOpenBound if you want to listen for
00111  * incoming messages.   Call rudpClose() when done 
00112  * with this one.  Warns and returns NULL if there is
00113  * a problem. */
00114 
00115 struct rudp *rudpMustOpen();
00116 /* Open up unbound rudp.  Warn and die if there is a problem. */
00117 
00118 struct rudp *rudpOpenBound(struct sockaddr_in *sai);
00119 /* Open up a rudp socket bound to a particular port and address.
00120  * Use this rather than rudpOpen if you want to wait for
00121  * messages at a specific address in a server or the like. */
00122 
00123 struct rudp *rudpMustOpenBound(struct sockaddr_in *sai);
00124 /* Open up a rudp socket bound to a particular port and address
00125  * or die trying. */
00126 
00127 void rudpClose(struct rudp **pRu);
00128 /* Close socket and free memory. */
00129 
00130 int rudpSend(struct rudp *ru, struct sockaddr_in *sai, void *message, int size);
00131 /* Send message of given size to port at host via rudp.  Prints a warning and
00132  * sets errno and returns -1 if there's a problem. */
00133 
00134 int rudpReceive(struct rudp *ru, void *messageBuf, int bufSize);
00135 /* Read message into buffer of given size.  Returns actual size read on
00136  * success. On failure prints a warning, sets errno, and returns -1. */
00137 
00138 int rudpReceiveFrom(struct rudp *ru, void *messageBuf, int bufSize, 
00139         struct sockaddr_in *retFrom);
00140 /* Read message into buffer of given size.  Returns actual size read on
00141  * success. On failure prints a warning, sets errno, and returns -1. 
00142  * Also returns ip address of message source. */
00143 
00144 int rudpReceiveTimeOut(struct rudp *ru, void *messageBuf, int bufSize, 
00145         struct sockaddr_in *retFrom, int timeOut);
00146 /* Like rudpReceive from above, but with a timeOut (in microseconds)
00147  * parameter.  If timeOut is zero then it will wait forever. */
00148 
00149 void rudpPrintStatus(struct rudp *ru);
00150 /* Print out status info. */
00151 
00152 void rudpTest();
00153 /* Test out rudp stuff. */
00154 
00155 #endif /* RUDP_H */

Generated on Tue Dec 25 18:39:29 2007 for blat by  doxygen 1.5.2