From ec88921b39b86ed5a20c38d0bc74ea8a765baca0 Mon Sep 17 00:00:00 2001 From: Per Cederqvist <ceder@lysator.liu.se> Date: Wed, 15 Apr 1992 18:56:09 +0000 Subject: [PATCH] Initial revision --- src/libraries/libisc-new/src/Makefile | 150 +++++++++ src/libraries/libisc-new/src/isc_handler.c | 112 +++++++ src/libraries/libisc-new/src/isc_socket.c | 250 ++++++++++++++ src/libraries/libisc-new/src/isc_tcp.c | 349 ++++++++++++++++++++ src/libraries/libisc-new/src/isc_udp.c | 360 +++++++++++++++++++++ 5 files changed, 1221 insertions(+) create mode 100644 src/libraries/libisc-new/src/Makefile create mode 100644 src/libraries/libisc-new/src/isc_handler.c create mode 100644 src/libraries/libisc-new/src/isc_socket.c create mode 100644 src/libraries/libisc-new/src/isc_tcp.c create mode 100644 src/libraries/libisc-new/src/isc_udp.c diff --git a/src/libraries/libisc-new/src/Makefile b/src/libraries/libisc-new/src/Makefile new file mode 100644 index 000000000..a9db699b6 --- /dev/null +++ b/src/libraries/libisc-new/src/Makefile @@ -0,0 +1,150 @@ +# +# Makefile for libisc +# +# Copyright (c) 1992 Peter Eriksson and Per Cederqvist of the +# Lysator Academic Computer Association. +# +INSTROOT=/usr/local +# +LIBDIR=$(INSTROOT)/lib +INCDIR=$(INSTROOT)/include +# +INCLUDES=-I$(HOME)/include -I/usr/local/include +CC=gcc +CFLAGS=-g -O -I. -pipe -Wall -ansi $(INCLUDES) +# +SOURCES=isc_event.c isc_session.c isc_abort.c isc_alloc.c isc_master.c\ + isc_output.c isc_queue.c isc_message.c isc_handler.c\ + isc_stdout.c isc_socket.c isc_tcp.c isc_udp.c printf.c +OBJECTS=isc_event.o isc_session.o isc_abort.o isc_alloc.o isc_master.o\ + isc_output.o isc_queue.o isc_message.o isc_handler.o\ + isc_stdout.o isc_socket.o isc_tcp.o isc_udp.o printf.o + + +all: libisc.a + +install: $(LIBDIR)/libisc.a $(INCDIR)/isc.h + +$(LIBDIR)/libisc.a: libisc.a + cp libisc.a $(LIBDIR) + ranlib $(LIBDIR)/libisc.a + +$(INCDIR)/isc.h: isc.h + cp isc.h $(INCDIR) + +tags: + etags -t *.[hc] + +depend: + gmkdep $(INCLUDES) $(SOURCES) + + +clean: + rm -f *~ *.o libisc.a core \#*\# + + +libisc.a: $(OBJECTS) + touch libisc.a + rm -f libisc.a + ar q libisc.a $(OBJECTS) + ranlib libisc.a + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +isc_event.o : isc_event.c /usr/include/stdio.h \ + /usr/gnu/lib/gcc-include/stdarg.h /usr/local/include/stdlib.h \ + /usr/include/time.h /usr/include/sys/stdtypes.h /usr/include/sys/types.h \ + /usr/include/sys/sysmacros.h /usr/include/sys/time.h /usr/include/errno.h \ + /usr/include/sys/errno.h /home/kolix2/elev/d89/d89peter/include/stddef.h \ + /usr/include/string.h isc.h /usr/include/sys/socket.h intern.h +isc_session.o : isc_session.c /usr/include/sys/types.h \ + /usr/include/sys/stdtypes.h /usr/include/sys/sysmacros.h \ + /usr/include/errno.h /usr/include/sys/errno.h /usr/local/include/stdlib.h \ + /home/kolix2/elev/d89/d89peter/include/stddef.h /usr/include/string.h \ + /usr/include/fcntl.h /usr/include/sys/fcntlcom.h /usr/include/sys/stat.h \ + isc.h /usr/include/time.h /usr/gnu/lib/gcc-include/stdarg.h \ + /usr/include/sys/socket.h intern.h +isc_abort.o : isc_abort.c /usr/include/stdio.h /usr/local/include/stdlib.h \ + /home/kolix2/elev/d89/d89peter/include/stddef.h /usr/include/sys/stdtypes.h \ + isc.h /usr/include/time.h /usr/gnu/lib/gcc-include/stdarg.h \ + /usr/include/sys/types.h /usr/include/sys/sysmacros.h \ + /usr/include/sys/socket.h intern.h +isc_alloc.o : isc_alloc.c /usr/local/include/stdlib.h \ + /home/kolix2/elev/d89/d89peter/include/stddef.h /usr/include/sys/stdtypes.h \ + /usr/include/string.h isc.h /usr/include/time.h \ + /usr/gnu/lib/gcc-include/stdarg.h /usr/include/sys/types.h \ + /usr/include/sys/sysmacros.h /usr/include/sys/socket.h intern.h +isc_master.o : isc_master.c /usr/include/errno.h /usr/include/sys/errno.h \ + /usr/local/include/stdlib.h /home/kolix2/elev/d89/d89peter/include/stddef.h \ + /usr/include/sys/stdtypes.h /usr/include/sys/file.h \ + /usr/include/sys/types.h /usr/include/sys/sysmacros.h \ + /usr/include/sys/fcntlcom.h /usr/include/sys/stat.h isc.h \ + /usr/include/time.h /usr/gnu/lib/gcc-include/stdarg.h \ + /usr/include/sys/socket.h intern.h +isc_output.o : isc_output.c /usr/local/include/stdlib.h \ + /home/kolix2/elev/d89/d89peter/include/stddef.h /usr/include/sys/stdtypes.h \ + /usr/include/errno.h /usr/include/sys/errno.h /usr/include/string.h \ + /usr/include/sys/file.h /usr/include/sys/types.h \ + /usr/include/sys/sysmacros.h /usr/include/sys/fcntlcom.h \ + /usr/include/sys/stat.h isc.h /usr/include/time.h \ + /usr/gnu/lib/gcc-include/stdarg.h /usr/include/sys/socket.h intern.h +isc_queue.o : isc_queue.c /usr/local/include/stdlib.h \ + /home/kolix2/elev/d89/d89peter/include/stddef.h /usr/include/sys/stdtypes.h \ + isc.h /usr/include/time.h /usr/gnu/lib/gcc-include/stdarg.h \ + /usr/include/sys/types.h /usr/include/sys/sysmacros.h \ + /usr/include/sys/socket.h intern.h +isc_message.o : isc_message.c /usr/local/include/stdlib.h \ + /home/kolix2/elev/d89/d89peter/include/stddef.h /usr/include/sys/stdtypes.h \ + /usr/include/string.h isc.h /usr/include/time.h \ + /usr/gnu/lib/gcc-include/stdarg.h /usr/include/sys/types.h \ + /usr/include/sys/sysmacros.h /usr/include/sys/socket.h intern.h +isc_stdout.o : isc_stdout.c /usr/gnu/lib/gcc-include/stdarg.h \ + /usr/include/string.h /usr/include/sys/stdtypes.h isc.h /usr/include/time.h \ + /usr/include/sys/types.h /usr/include/sys/sysmacros.h \ + /usr/include/sys/socket.h +isc_socket.o : isc_socket.c /usr/include/stdio.h \ + /usr/gnu/lib/gcc-include/stdarg.h /usr/local/include/stdlib.h \ + /usr/include/time.h /usr/include/sys/stdtypes.h /usr/include/sys/types.h \ + /usr/include/sys/sysmacros.h /usr/include/sys/time.h \ + /usr/include/netinet/in.h /usr/include/sys/socket.h \ + /usr/local/include/arpa/inet.h /usr/include/sys/file.h \ + /usr/include/sys/fcntlcom.h /usr/include/sys/stat.h \ + /usr/include/sys/ioctl.h /usr/gnu/lib/gcc-include/sys/ttychars.h \ + /usr/include/sys/ttydev.h /usr/gnu/lib/gcc-include/sys/ttold.h \ + /usr/gnu/lib/gcc-include/sys/ioccom.h /usr/gnu/lib/gcc-include/sys/ttycom.h \ + /usr/gnu/lib/gcc-include/sys/filio.h /usr/gnu/lib/gcc-include/sys/sockio.h \ + /usr/include/errno.h /usr/include/sys/errno.h /usr/local/include/netdb.h \ + /home/kolix2/elev/d89/d89peter/include/stddef.h /usr/include/string.h \ + /usr/include/fcntl.h isc.h intern.h +isc_tcp.o : isc_tcp.c /usr/include/errno.h /usr/include/sys/errno.h \ + /usr/local/include/stdlib.h /home/kolix2/elev/d89/d89peter/include/stddef.h \ + /usr/include/sys/stdtypes.h /usr/include/ctype.h /usr/include/sys/types.h \ + /usr/include/sys/sysmacros.h /usr/include/sys/socket.h \ + /usr/include/netinet/in.h /usr/local/include/arpa/inet.h \ + /usr/include/sys/file.h /usr/include/sys/fcntlcom.h /usr/include/sys/stat.h \ + /usr/include/sys/ioctl.h /usr/gnu/lib/gcc-include/sys/ttychars.h \ + /usr/include/sys/ttydev.h /usr/gnu/lib/gcc-include/sys/ttold.h \ + /usr/gnu/lib/gcc-include/sys/ioccom.h /usr/gnu/lib/gcc-include/sys/ttycom.h \ + /usr/gnu/lib/gcc-include/sys/filio.h /usr/gnu/lib/gcc-include/sys/sockio.h \ + /usr/local/include/netdb.h /usr/include/string.h /usr/include/fcntl.h isc.h \ + /usr/include/time.h /usr/gnu/lib/gcc-include/stdarg.h intern.h +isc_udp.o : isc_udp.c /usr/include/sys/types.h /usr/include/sys/stdtypes.h \ + /usr/include/sys/sysmacros.h /usr/include/errno.h /usr/include/sys/errno.h \ + /usr/local/include/stdlib.h /home/kolix2/elev/d89/d89peter/include/stddef.h \ + /usr/include/ctype.h /usr/include/netinet/in.h /usr/include/sys/socket.h \ + /usr/local/include/arpa/inet.h /usr/include/sys/file.h \ + /usr/include/sys/fcntlcom.h /usr/include/sys/stat.h \ + /usr/include/sys/ioctl.h /usr/gnu/lib/gcc-include/sys/ttychars.h \ + /usr/include/sys/ttydev.h /usr/gnu/lib/gcc-include/sys/ttold.h \ + /usr/gnu/lib/gcc-include/sys/ioccom.h /usr/gnu/lib/gcc-include/sys/ttycom.h \ + /usr/gnu/lib/gcc-include/sys/filio.h /usr/gnu/lib/gcc-include/sys/sockio.h \ + /usr/local/include/netdb.h /usr/include/string.h /usr/include/fcntl.h isc.h \ + /usr/include/time.h /usr/gnu/lib/gcc-include/stdarg.h intern.h +printf.o : printf.c /usr/include/sys/types.h /usr/include/sys/stdtypes.h \ + /usr/include/sys/sysmacros.h /usr/gnu/lib/gcc-include/varargs.h \ + /usr/gnu/lib/gcc-include/va-sparc.h /usr/include/stdio.h \ + /usr/include/ctype.h /usr/include/string.h /usr/local/include/stdlib.h \ + /usr/include/math.h /usr/include/floatingpoint.h /usr/include/sys/ieeefp.h + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/src/libraries/libisc-new/src/isc_handler.c b/src/libraries/libisc-new/src/isc_handler.c new file mode 100644 index 000000000..c0a18671a --- /dev/null +++ b/src/libraries/libisc-new/src/isc_handler.c @@ -0,0 +1,112 @@ +/* +** isc_handler.c Routines to handle IscSession handlers +** +** Copyright (c) 1992 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 920211 pen initial coding +*/ + +#include <stdio.h> + +#include "isc.h" +#include "intern.h" + + + +IscHandler * +isc_copyhandler(IscHandler *hcb) +{ + IscHandler *nhcb; + + + ISC_XNEW(nhcb); + *nhcb = *hcb; + + return nhcb; +} + + + +IscHandler * +isc_newhandler(void) +{ + IscHandler *hcb; + + + ISC_XNEW(hcb); + + hcb->read = NULL; + hcb->write = NULL; + hcb->close = NULL; + hcb->poll = NULL; + hcb->accept = NULL; + hcb->destroy = NULL; + hcb->parse = NULL; + + return hcb; +} + + + +void +isc_freehandler(IscHandler *hcb) +{ + isc_free(hcb); +} + + + +void +isc_pushhandler(IscSession *scb, IscHandler *hcb) +{ + IscHandlerList *ihl; + + + ISC_XNEW(ihl); + ihl->hcb = hcb; + ihl->old = scb->fun; + ihl->next = scb->handlers; + + scb->handlers = ihl; + + if (hcb->read) + scb->fun.read = ihl; + if (hcb->write) + scb->fun.write = ihl; + if (hcb->close) + scb->fun.close = ihl; + if (hcb->poll) + scb->fun.poll = ihl; + if (hcb->accept) + scb->fun.accept = ihl; + if (hcb->destroy) + scb->fun.destroy = ihl; + if (hcb->parse) + scb->fun.parse = ihl; +} + + +IscHandler * +isc_pophandler(IscSession *scb) +{ + IscHandlerList *ip; + IscHandler *hcb; + + + if (scb->handlers == NULL) + return NULL; + + ip = scb->handlers; + scb->handlers = ip->next; + scb->fun = ip->old; + hcb = ip->hcb; + + isc_free(ip); + + return hcb; +} + + + diff --git a/src/libraries/libisc-new/src/isc_socket.c b/src/libraries/libisc-new/src/isc_socket.c new file mode 100644 index 000000000..680541da4 --- /dev/null +++ b/src/libraries/libisc-new/src/isc_socket.c @@ -0,0 +1,250 @@ +/* +** isc_socket.c Socket specified code +** +** Copyright (c) 1992 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 920210 pen initial coding +*/ + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <time.h> +#include <sys/types.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <netdb.h> +#include <stddef.h> +#include <string.h> +#include <fcntl.h> +#include <sys/file.h> + +#include "isc.h" +#include "intern.h" + + + +/* + * External function declarations. + */ +extern void *bzero(void *buf, unsigned length); +extern void *memcpy(void *, const void *, int); +extern int getsockname(int fd, struct sockaddr *, int *); +extern int getpeername(int fd, struct sockaddr *, int *); +extern time_t time(time_t *buf); +extern int select(int setsize, + fd_set *rs, fd_set *rw, fd_set *es, + struct timeval *wait); +extern int accept(int fd, struct sockaddr *sock, int *len); + + + +#if defined(__GNUC__) && defined(__sparc__) +/* +** inet_ntoa() is buggy on SPARCs running SunOS 4.1.1, so +** we use our own +*/ +#ifdef inet_ntoa +#undef inet_ntoa +#endif + +static char *inet_ntoa(ad) + struct in_addr ad; +{ + u_long s_ad; + int a, b, c, d; + static char addr[20]; + + s_ad = ad.s_addr; + d = s_ad % 256; + s_ad /= 256; + c = s_ad % 256; + s_ad /= 256; + b = s_ad % 256; + a = s_ad / 256; + sprintf(addr, "%d.%d.%d.%d", a, b, c, d); + + return addr; +} +#endif + + + +IscAddress * +isc_mkipaddress(struct sockaddr *addr) +{ + IscAddress *ia; + + + ISC_XNEW(ia); + memcpy(&ia->ip.saddr, addr, sizeof(ia->ip.saddr)); + + return ia; +} + + + + +IscAddress * +isc_getladdress(IscSession *scb) +{ + struct sockaddr addr; + int len; + + + if (scb->type != ISC_TYPE_TCP && + scb->type != ISC_TYPE_UDP) + return NULL; + + len = sizeof(addr); + if (getsockname(scb->fd, &addr, &len) < 0) + return NULL; + + return isc_mkipaddress(&addr); +} + + + +IscAddress * +isc_getraddress(IscSession *scb) +{ + struct sockaddr addr; + int len; + + + if (scb->type != ISC_TYPE_TCP && + scb->type != ISC_TYPE_UDP) + return NULL; + + len = sizeof(addr); + if (getpeername(scb->fd, &addr, &len) < 0) + return NULL; + + return isc_mkipaddress(&addr); +} + + +void +isc_freeaddress(IscAddress *addr) +{ + isc_free(addr); +} + + +IscAddress * +isc_copyaddress(IscAddress *addr) +{ + IscAddress *new_addr; + + ISC_XNEW(new_addr); + *new_addr = *addr; + + return new_addr; +} + + + +char *isc_getipnum(IscAddress *ia, char *buf, int len) +{ + static char hostname[256]; + struct sockaddr_in *addr; + + + if (!buf) + { + buf = hostname; + len = sizeof(hostname)-1; + } + + addr = (struct sockaddr_in *) &ia->ip.saddr; + + strncpy(buf, inet_ntoa(addr->sin_addr), len); + buf[len] = '\0'; + + return buf; +} + + + +char *isc_gethostname(IscAddress *ia, char *buf, int len) +{ + static char hostname[256]; + struct sockaddr_in *addr; + struct hostent *hp; + + + if (!buf) + { + buf = hostname; + len = sizeof(hostname)-1; + } + + addr = (struct sockaddr_in *) &ia->ip.saddr; + + hp = gethostbyaddr(&addr->sin_addr,sizeof(struct in_addr),AF_INET); + if (!hp) + return NULL; + + strncpy(buf, hp->h_name, len); + buf[len] = '\0'; + + return buf; +} + + + +int isc_getportnum(IscAddress *ia) +{ + struct sockaddr_in *addr; + + + addr = (struct sockaddr_in *) &ia->ip.saddr; + + return ntohs(addr->sin_port); +} + + +char *isc_getservice(IscAddress *ia, + char *buf, + int len, + IscSessionType type) +{ + static char servbuf[256]; + struct sockaddr_in *addr; + struct servent *sp; + + if (!buf) + { + buf = servbuf; + len = sizeof(servbuf)-1; + } + + addr = (struct sockaddr_in *) &ia->ip.saddr; + + switch (type) + { + case ISC_TYPE_TCP: + sp = getservbyport(ntohs(addr->sin_port), "tcp"); + break; + + case ISC_TYPE_UDP: + sp = getservbyport(ntohs(addr->sin_port), "udp"); + break; + + default: + return NULL; + } + + if (!sp) + return NULL; + + strncpy(buf, sp->s_name, len); + return buf; +} diff --git a/src/libraries/libisc-new/src/isc_tcp.c b/src/libraries/libisc-new/src/isc_tcp.c new file mode 100644 index 000000000..3a436cf11 --- /dev/null +++ b/src/libraries/libisc-new/src/isc_tcp.c @@ -0,0 +1,349 @@ +/* +** isc_tcp.c Routines to handle TCP ISC sessions +** +** Copyright (c) 1992 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 920209 pen code extracted from isc_session.c +*/ + +#include <errno.h> +#include <stdlib.h> +#include <stddef.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <netdb.h> +#include <string.h> +#include <fcntl.h> + +#include "isc.h" +#include "intern.h" + + + +/* +** External function declarations +*/ +extern void *memset(void *, int, int); +extern void *memcpy(void *, const void *, int); +extern int socket(int, int, int); +extern int setsockopt(int, int, int, char *, int); +extern int listen(int, int); +extern int connect(int, struct sockaddr *, int); +extern int bind(int, struct sockaddr *, int); +extern int close(int); +extern int atoi(const char *str); +extern time_t sleep(time_t); +extern int accept(int fd, struct sockaddr *sock, int *len); + + + +IscSession * +isc_tcp_accept_fn(IscHandlerList *hl, + IscSession *scb, + IscMessage *msg) +{ + IscSession *new_scb; + int fd; + + + if ((fd = accept(scb->fd, + (struct sockaddr *) NULL, + (int *) NULL)) < 0) + return NULL; + + new_scb = isc_createtcp(scb->cfg, fd); + if (!new_scb) + { + close(fd); + return NULL; + } + + /* Fill in the session info structure */ + new_scb->fd = fd; + new_scb->state = ISC_STATE_RUNNING; + new_scb->mode = O_RDWR; + new_scb->info.tcp.raddr = isc_getraddress(new_scb); + new_scb->info.tcp.laddr = isc_getladdress(new_scb); + + return new_scb; +} + + + + + +void +isc_tcp_destroy_fn(IscHandlerList *hl, + IscSession *scb) +{ + if (scb->info.tcp.raddr) + { + isc_freeaddress(scb->info.tcp.raddr); + scb->info.tcp.raddr = NULL; + } + + if (scb->info.tcp.laddr) + { + isc_freeaddress(scb->info.tcp.laddr); + scb->info.tcp.laddr = NULL; + } +} + + + +/* +** TCP I/O functions structure +*/ +static IscHandler isc_tcp_funs = +{ + &isc_default_read_fn, + &isc_default_write_fn, + &isc_default_close_fn, + NULL, + &isc_tcp_accept_fn, + &isc_tcp_destroy_fn, + NULL +}; + + + +/* +** Create a TCP Session Address +*/ +IscAddress * +isc_mktcpaddress(const char *address, + const char *service) +{ + struct sockaddr_in addr; + struct hostent *hp; + struct servent *sp; + + + memset(&addr, 0, sizeof(addr)); + + /* Any local address? */ + if (address == NULL) + { + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + } + else if (isdigit(address[0])) + { + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(address); + if (addr.sin_addr.s_addr == -1) + return NULL; + } + else if ((hp = gethostbyname(address)) == NULL) + return NULL; + else + { + addr.sin_family = hp->h_addrtype; + memcpy(&addr.sin_addr, hp->h_addr, sizeof(addr.sin_addr)); + } + + if (isdigit(service[0])) + addr.sin_port = htons(atoi(service)); + else if ((sp = getservbyname(service, "tcp")) == NULL) + return NULL; + else + addr.sin_port = sp->s_port; + + return isc_mkipaddress((struct sockaddr *)&addr); +} + + + +/* +** Create a TCP session +*/ +IscSession * +isc_createtcp(IscSessionConfig *cfg, int fd) +{ + IscSession *scb; + int res; + + + if (fd == -1) + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return NULL; + + /* Set non blocking write mode */ + if ((res = fcntl(fd, F_GETFL, 0)) == -1) + { + close(fd); + return NULL; + } + + if (fcntl(fd, F_SETFL, res | FNDELAY) == -1) + { + close(fd); + return NULL; + } + + setsockopt(fd, SOL_SOCKET, SO_DONTLINGER, 0, 0); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 0, 0); + + scb = isc_create(cfg, &isc_tcp_funs); + if (!scb) + return NULL; + + scb->type = ISC_TYPE_TCP; + scb->fd = fd; + + scb->info.tcp.raddr = NULL; + scb->info.tcp.laddr = NULL; + + return scb; +} + + + +/* +** Bind a TCP session to a local port and address +*/ +int +isc_bindtcp(IscSession *scb, + const char *address, + const char *service) +{ + IscAddress *ia; + + + if (scb->type != ISC_TYPE_TCP) + return -1; + + ia = isc_mktcpaddress(address, service); + + if (!ia) + return -1; + + if (bind(scb->fd, &ia->ip.saddr, sizeof(ia->ip.saddr)) < 0) + return -1; + + scb->info.tcp.laddr = ia; + + return 0; +} + + + +/* +** Connect a TCP session to a remove service. +*/ +int +isc_connecttcp(IscSession *scb, + const char *address, + const char *service) +{ + IscAddress *ia; + int res; + + + if (scb->type != ISC_TYPE_TCP) + return -1; + + /* Local connection? */ + if (address == NULL) + address = "localhost"; + + ia = isc_mktcpaddress(address, service); + + if (!ia) + return -1; + + res = connect(scb->fd, &ia->ip.saddr, sizeof(ia->ip.saddr)); + if (res < 0 && errno != EINPROGRESS) + return -1; + + scb->state = (res < 0 ? ISC_STATE_CONNECTING : ISC_STATE_RUNNING); + + scb->info.tcp.raddr = ia; + if (scb->info.tcp.laddr == NULL) + scb->info.tcp.laddr = isc_getladdress(scb); + + return 0; +} + + + +/* +** Establish a session with a remote TCP service, then insert it +** into a master control structure- +*/ +IscSession * +isc_opentcp(IscMaster *mcb, + const char *address, + const char *service) +{ + IscSession *scb; + + + scb = isc_createtcp(&mcb->scfg, -1); + if (!scb) + return NULL; + + if (isc_connecttcp(scb, address, service) < 0) + { + isc_destroy(NULL, scb); + return NULL; + } + + (void) isc_insert(mcb, scb); + + return scb; +} + + + +/* +** Establish a port to listen at for new TCP connections +*/ +IscSession * +isc_listentcp(IscMaster *mcb, + const char *address, + const char *service) +{ + IscSession *scb; + int retries; + int errcode; + + + scb = isc_createtcp(&mcb->scfg, -1); + if (!scb) + return NULL; + + errno = 0; + for (retries = 0; retries < scb->cfg->max.openretries; sleep(1), retries++) + if (isc_bindtcp(scb, address, service) >= 0 || errno != EADDRINUSE) + break; + + if (retries >= scb->cfg->max.openretries || errno != 0) + { + errcode = errno; + isc_destroy(NULL, scb); + errno = errcode; + return NULL; + } + + if (listen(scb->fd, scb->cfg->max.backlog) < 0) + { + errcode = errno; + isc_destroy(NULL, scb); + errno = errcode; + return NULL; + } + + scb->state = ISC_STATE_LISTENING; + + (void) isc_insert(mcb, scb); + + return scb; +} diff --git a/src/libraries/libisc-new/src/isc_udp.c b/src/libraries/libisc-new/src/isc_udp.c new file mode 100644 index 000000000..01a42ac4f --- /dev/null +++ b/src/libraries/libisc-new/src/isc_udp.c @@ -0,0 +1,360 @@ +/* +** isc_udp.c Routines to handle UDP ISC sessions +** +** Copyright (c) 1992 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 920209 pen code extracted from isc_session.c +*/ + +#include <sys/types.h> +#include <errno.h> +#include <stdlib.h> +#include <stddef.h> +#include <ctype.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <netdb.h> +#include <string.h> +#include <fcntl.h> + +#include "isc.h" +#include "intern.h" + + + +extern void *memset(void *, int, int); +extern void *memcpy(void *, const void *, int); +extern int socket(int, int, int); +extern int setsockopt(int, int, int, char *, int); +extern int connect(int, struct sockaddr *, int); +extern int bind(int, struct sockaddr *, int); +extern int close(int); +extern int atoi(const char *str); +extern int recvfrom(int fd, char *buf, int len, int flags, + struct sockaddr *from, int *flen); +extern int sendto(int fd, char *buf, int len, int flags, + struct sockaddr *from, int flen); +extern int sprintf(char *, const char *, ...); + + + +/* +** Receive an UDP message and put it into an IscMessage +*/ +IscMessage *isc_udp_read_fn(IscHandlerList *hl, + IscSession *scb) +{ + IscMessage *msg; + struct sockaddr addr; + int len; + int status; + + + msg = isc_allocmsg(scb->cfg->max.msgsize); + + len = sizeof(addr); + + status = recvfrom(scb->fd, msg->buffer, msg->size, + 0, + &addr, &len); + if (status < 0) + { + isc_freemsg(msg); + return NULL; + } + + msg->length = status; + msg->buffer[msg->length] = '\0'; + msg->address = isc_mkipaddress(&addr); + + return msg; +} + + + +/* +** Transmit an UDP message to a remote service +*/ +int isc_udp_write_fn(IscHandlerList *hl, + IscSession *scb, + IscMessage *msg) +{ + /* No target and no default target? Then fail. */ + if (!msg->address && !scb->info.udp.raddr) + { + errno = ENOTCONN; + return -1; + } + + /* Not target specified? Use default target */ + if (!msg->address) + return ISC_HCALLFUN2(hl, write, scb, msg); + + return sendto(scb->fd, msg->buffer, msg->length, + 0, + &msg->address->ip.saddr, + sizeof(msg->address->ip.saddr)); +} + + + +void +isc_udp_destroy_fn(IscHandlerList *hl, + IscSession *scb) +{ + if (scb->info.udp.raddr) + { + isc_freeaddress(scb->info.udp.raddr); + scb->info.udp.raddr = NULL; + } + + if (scb->info.udp.laddr) + { + isc_freeaddress(scb->info.udp.laddr); + scb->info.udp.laddr = NULL; + } +} + + + +/* +** Create an UDP Session Address +*/ +IscAddress * +isc_mkudpaddress(const char *address, + const char *service) +{ + struct sockaddr_in addr; + struct hostent *hp; + struct servent *sp; + + + memset(&addr, 0, sizeof(addr)); + + /* Any local address? */ + if (address == NULL) + { + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + } + else if (strcmp(address, "*") == 0) + { + /* Broadcast address */ + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + } + else if (isdigit(address[0])) + { + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(address); + if (addr.sin_addr.s_addr == -1) + return NULL; + } + else if ((hp = gethostbyname(address)) == NULL) + return NULL; + else + { + addr.sin_family = hp->h_addrtype; + memcpy(&addr.sin_addr, hp->h_addr, sizeof(addr.sin_addr)); + } + + if (isdigit(service[0])) + addr.sin_port = htons(atoi(service)); + else if ((sp = getservbyname(service, "udp")) == NULL) + return NULL; + else + addr.sin_port = sp->s_port; + + return isc_mkipaddress((struct sockaddr *) &addr); +} + + + +static IscHandler isc_udp_funs = +{ + &isc_udp_read_fn, + &isc_udp_write_fn, + &isc_default_close_fn, + NULL, + NULL, + &isc_udp_destroy_fn, + NULL +}; + + + +/* +** Create an UDP session +*/ +IscSession * +isc_createudp(IscSessionConfig *cfg) +{ + IscSession *scb; + int fd, res; + + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return NULL; + + /* Set non blocking write mode */ + if ((res = fcntl(fd, F_GETFL, 0)) == -1) + { + close(fd); + return NULL; + } + + if (fcntl(fd, F_SETFL, res | FNDELAY) == -1) + { + close(fd); + return NULL; + } + + setsockopt(fd, SOL_SOCKET, SO_DONTLINGER, 0, 0); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 0, 0); + + scb = isc_create(cfg, &isc_udp_funs); + if (!scb) + return NULL; + + scb->type = ISC_TYPE_UDP; + scb->fd = fd; + + scb->info.udp.raddr = NULL; + scb->info.udp.laddr = NULL; + + return scb; +} + + + + + + +/* +** Bind an UDP session to a local port and address +*/ +int +isc_bindudp(IscSession *scb, + const char *address, + const char *service) +{ + IscAddress *ia; + + + if (scb->type != ISC_TYPE_UDP) + return -1; + + ia = isc_mkudpaddress(address, service); + + if (!ia) + return -1; + + if (bind(scb->fd, &ia->ip.saddr, sizeof(ia->ip.saddr)) < 0) + return -1; + + scb->state = ISC_STATE_RUNNING; + scb->info.udp.laddr = ia; + + return 0; +} + + + +/* +** Connect an UDP session to a remove service. +*/ +int +isc_connectudp(IscSession *scb, + const char *address, + const char *service) +{ + IscAddress *ia; + int res; + + + if (scb->type != ISC_TYPE_UDP) + return -1; + + if (address == NULL) + address = "localhost"; + + ia = isc_mkudpaddress(address, service); + + if (!ia) + return -1; + + res = connect(scb->fd, &ia->ip.saddr, sizeof(ia->ip.saddr)); + if (res < 0 && errno != EINPROGRESS) + return -1; + + scb->state = (res < 0 ? ISC_STATE_CONNECTING : ISC_STATE_RUNNING); + + scb->info.udp.raddr = ia; + if (scb->info.udp.laddr == NULL) + scb->info.udp.laddr = isc_getladdress(scb); + + return 0; +} + + + +/* +** Establish a session with a remote UDP service, then insert it +** into a master control structure- +*/ +IscSession * +isc_openudp(IscMaster *mcb, + const char *address, + const char *service) +{ + IscSession *scb; + + + scb = isc_createudp(&mcb->scfg); + if (!scb) + return NULL; + + if (isc_connectudp(scb, address, service) < 0) + { + isc_destroy(NULL, scb); + return NULL; + } + + (void) isc_insert(mcb, scb); + + return scb; +} + + + +/* +** Create an UDP session, prepare it for incoming messages +** and insert it into the master structure +*/ +IscSession * +isc_listenudp(IscMaster *mcb, + const char *address, + const char *service) +{ + IscSession *scb; + + + scb = isc_createudp(&mcb->scfg); + if (!scb) + return NULL; + + if (isc_bindudp(scb, address, service) < 0) + { + isc_destroy(NULL, scb); + return NULL; + } + + (void) isc_insert(mcb, scb); + + return scb; +} -- GitLab