DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T u

⟦ff2d87829⟧ TextFile

    Length: 7565 (0x1d8d)
    Types: TextFile
    Names: »udp.c«

Derivation

└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape
    └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« 
        └─⟦d3ac74d73⟧ 
            └─⟦this⟧ »isode-5.0/compat/udp.c« 

TextFile

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