|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T u
Length: 7565 (0x1d8d) Types: TextFile Names: »udp.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/compat/udp.c«
/* udp.c - UDP/IP abstractions */ #ifndef lint static char *rcsid = "$Header: /f/osi/compat/RCS/udp.c,v 6.0 89/03/18 23:25:57 mrose Rel $"; #endif /* * $Header: /f/osi/compat/RCS/udp.c,v 6.0 89/03/18 23:25:57 mrose Rel $ * * * $Log: udp.c,v $ * Revision 6.0 89/03/18 23:25:57 mrose * Release 5.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ /* LINTLIBRARY */ #include <errno.h> #include <stdio.h> #include "general.h" #include "manifest.h" #include "tailor.h" /* \f */ #ifdef TCP #include "internet.h" extern int errno; /* \f */ struct udpconn { int udp_parent; struct sockaddr_in udp_peer; struct qbuf udp_queue; }; static int maxpeers = 0; static struct udpconn *peers = NULL; /* \f */ #ifdef SOCKETS /* ARGSUSED */ int start_udp_server (sock, backlog, opt1, opt2) struct sockaddr_in *sock; int backlog, opt1, opt2; { register int port; int sd; register struct udpconn *up, *vp; if (peers == NULL) { maxpeers = getdtablesize (); peers = (struct udpconn *) calloc ((unsigned) maxpeers, sizeof *peers); if (peers == NULL) return NOTOK; for (vp = (up = peers) + maxpeers; up < vp; up++) { up -> udp_parent = NOTOK; up -> udp_queue.qb_forw = up -> udp_queue.qb_back = &up -> udp_queue; } } if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK) return NOTOK; if (sock -> sin_port != 0) { if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK) goto got_socket; (void) close (sd); return NOTOK; } else sock -> sin_family = AF_INET; for (port = IPPORT_RESERVED;; port++) { sock -> sin_port = htons ((u_short) port); if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK) break; switch (errno) { case EADDRINUSE: continue; case EADDRNOTAVAIL: default: (void) close (sd); return NOTOK; } } got_socket: ; if (opt1) (void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0); if (opt2) (void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0); return (peers[sd].udp_parent = sd); } #endif /* \f */ /* \f */ int join_udp_aux (fd, sock, newfd) int fd, newfd; struct sockaddr_in *sock; { int nfds, sd; fd_set ifds; register struct qbuf *qb; register struct udpconn *up; if (fd < 0 || fd >= maxpeers || peers[fd].udp_parent != fd) { errno = EINVAL; return NOTOK; } if (newfd) { FD_ZERO (&ifds); nfds = fd + 1; FD_SET (fd, &ifds); if (select_udp_socket (nfds, &ifds, NULLFD, NULLFD, OK) == NOTOK) return NOTOK; up = &peers[fd]; if ((qb = up -> udp_queue.qb_forw) == &up -> udp_queue) { errno = EWOULDBLOCK; return NOTOK; } if ((sd = dup (fd)) == NOTOK) return NOTOK; up = &peers[sd]; *sock = *((struct sockaddr_in *) qb -> qb_base); /* struct copy */ remque (qb); insque (qb, up -> udp_queue.qb_back); } else up = &peers[fd]; up -> udp_parent = fd; bcopy ((char *) sock, (char *) &up -> udp_peer, sizeof up -> udp_peer); return (newfd ? sd : OK); } /* \f */ int read_udp_socket (fd, q) int fd; struct qbuf **q; { int nfds; fd_set ifds, mask; register struct qbuf *qb; register struct udpconn *up; if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> udp_parent == NOTOK) { errno = EINVAL; return NOTOK; } if ((qb = up -> udp_queue.qb_forw) == &up -> udp_queue) { FD_ZERO (&ifds); nfds = fd + 1; FD_SET (fd, &mask); for (ifds = mask;; ifds = mask) { if (select_udp_socket (nfds, &ifds, NULLFD, NULLFD, NOTOK) == NOTOK) return NOTOK; if ((qb = up -> udp_queue.qb_forw) != &up -> udp_queue) break; } } remque (qb); *q = qb; return qb -> qb_len; } /* \f */ int write_udp_socket (fd, qb) int fd; register struct qbuf *qb; { register struct udpconn *up; if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> udp_parent == NOTOK || up -> udp_peer.sin_family == 0) { errno = EINVAL; return NOTOK; } #ifdef SOCKETS return sendto (fd, qb -> qb_data, qb -> qb_len, NULL, (struct sockaddr *) &up -> udp_peer, sizeof up -> udp_peer); #endif } /* \f */ int close_udp_socket (fd) int fd; { register struct qbuf *qb, *qp; register struct udpconn *up, *vp; if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> udp_parent == NOTOK) { errno = EINVAL; return NOTOK; } up -> udp_parent = NOTOK; bzero ((char *) &up -> udp_peer, sizeof up -> udp_peer); for (qb = up -> udp_queue.qb_forw; qb != &up -> udp_queue; qb = qp) { qp = qb -> qb_forw; remque (qb); free ((char *) qb); } for (vp = (up = peers) + maxpeers; up < vp; up++) if (up -> udp_parent == fd) up -> udp_parent = up - peers; #ifdef SOCKETS return close (fd); #endif } /* \f */ int select_udp_socket (nfds, rfds, wfds, efds, secs) int nfds; fd_set *rfds, *wfds, *efds; int secs; { register int fd; int cc, len, mfds, result; fd_set ifds, jfds; register struct qbuf *qb; register struct udpconn *up, *vp; struct udpconn *wp; struct sockaddr_in *sock; if (rfds) { jfds = *rfds; if (secs != OK) for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++) if (up -> udp_parent != NOTOK && FD_ISSET (fd, &jfds) && up -> udp_queue.qb_forw != &up -> udp_queue) { secs = OK; break; } } if ((result = selsocket (nfds, rfds, wfds, efds, secs)) == NOTOK || rfds == NULLFD) return result; ifds = *rfds; if ((mfds = nfds) > maxpeers) mfds = maxpeers; for (fd = 0, up = peers; fd < mfds; fd++, up++) if (FD_ISSET (fd, &ifds)) { if (up -> udp_parent == NOTOK) continue; #ifdef SOCKETS if ((qb = (struct qbuf *) malloc (sizeof *qb + sizeof *sock + MAXUDP)) == NULL) return NOTOK; #endif sock = (struct sockaddr_in *) qb -> qb_base; qb -> qb_data = qb -> qb_base + sizeof *sock; #ifdef SOCKETS len = sizeof *sock; if ((cc = recvfrom (fd, qb -> qb_data, MAXUDP, NULL, (struct sockaddr *) sock, &len)) == NOTOK) { free ((char *) qb); return NOTOK; } qb -> qb_len = cc; #endif if (bcmp ((char *) &up -> udp_peer, (char *) sock, sizeof *sock) == 0) { insque (qb, up -> udp_queue.qb_back); continue; } for (wp = (vp = peers) + maxpeers; vp < wp; vp++) if (vp != up && vp -> udp_parent == up -> udp_parent && bcmp ((char *) &vp -> udp_peer, (char *) sock, sizeof *sock) == 0) break; if (vp >= wp && (vp = &peers[up -> udp_parent]) -> udp_peer.sin_family != 0) { free ((char *) qb); continue; } insque (qb, vp -> udp_queue.qb_back); } for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++) if (up -> udp_parent != NOTOK && FD_ISSET (fd, &jfds)) if (up -> udp_queue.qb_forw != &up -> udp_queue) FD_SET (fd, rfds); else FD_CLR (fd, rfds); result = 0; ifds = *rfds; if (wfds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, wfds)) FD_SET (fd, &ifds); if (efds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, efds)) FD_SET (fd, &ifds); for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, &ifds)) result++; return result; } #endif