|
|
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