#include // symbolic constants, sys svc protos #include // standard I/O library #include // utility function protos #include // error handling #include // char string functions #include // function prototypes like bzero, ... #include // gethostbyname #include // socket, bind, accept, connect, send, recv #include // socket address struct #include // same as sys/types.h, listen #include // prototypes like inet_ntoa #include // gettimeofday #include // getservbyport // --| prototypes |-- int xread(int, char *, int); // --| typedefs |-- typedef unsigned int socklen_t; // already defined in Solaris and Linux typedef struct hdr { u_char cntrl; // control information (DATA, ACK, EOT) u_char seqNum; // sequence number ushort length; // #bytes in payload char sndr[6]; // fake sender MAC address char rcvr[6]; // fake receiver MAC address } hdr_t; static const int BodySz = 20; typedef struct frame { hdr_t hdr; char body[BodySz]; } frame_t; typedef char bit; typedef int Bool; // --| constants |-- enum Boolean {NO=0, YES}; static const u_char DATA = 0x1; static const u_char ACK = 0x2; static const u_char EOT = 0x4; // --| globals |-- static char errMsg[100]; // error msg area // --| static inline wrappers |-- static inline void Fatal(char *msg) { fprintf(stderr, "%s", msg); exit(1); } static inline void FatalPerror(char *msg) { perror(msg); exit(1); } static inline int Bind(int sd, struct sockaddr *myAddr, socklen_t addrLen) { int rc; if ((rc=bind(sd, myAddr, addrLen)) == -1) FatalPerror("bind"); return rc; } static inline int Accept(int sd, struct sockaddr *clAddr, socklen_t *sinSz) { int new_fd; new_fd = accept(sd, clAddr, sinSz); if (new_fd == -1) FatalPerror("accept"); return new_fd; } static inline int Connect(int sd, struct sockaddr *srvAddr, socklen_t addrlen) { int rc; if ((rc=connect(sd, srvAddr, addrlen)) == -1) FatalPerror("connect"); return rc; } static inline struct hostent * Gethostbyname(char *name) { struct hostent *he; if ((he=gethostbyname(name)) == NULL) Fatal("gethostbyname"); return he; } static inline int Gethostname (char *name, size_t len) { int rc; char frmt[100] = "Bad return from gethostname. rc = %d\n"; if ((rc=gethostname(name,len)) != 0) { sprintf(errMsg, frmt, rc); Fatal(errMsg); } return rc; } static inline int Listen (int sd, int backlog) { int rc; if ((rc=listen(sd, backlog)) == -1) FatalPerror("listen"); return rc; } static inline void Send (int sd, char *pktAddr, int pktSz) { int n; if ((n=send(sd, pktAddr, pktSz, 0)) != pktSz) { FatalPerror("Send"); } } static inline int Socket(int domain, int type, int protocol) { int sd; if ((sd = socket(domain, type, protocol)) == -1) FatalPerror("socket"); return sd; } static inline void Gettimeofday(struct timeval *tvAddr) { if ((gettimeofday(tvAddr, 0)) == -1) FatalPerror("Gettimeofday"); } static inline void Getsockname(int sd, struct sockaddr *sockAddr, socklen_t *lenAddr) { if (getsockname (sd, sockAddr, lenAddr) == -1) { FatalPerror("Getsockname"); } } static inline void * Calloc(size_t n, size_t sz) { void *p; if ((p=calloc(n,sz))) return p; else Fatal("calloc returned NULL\n"); } static inline void Xread (int sd, char *buf, int n) { int m; char frmt[100] = "Xread: xread return = %d, not equal to %d when sd = %d\n"; m = xread (sd, buf, n); if (m != n) { // NOTE: this will also fail on EOF sprintf (errMsg, frmt, m, n, sd); FatalPerror(errMsg); } }