nbeng

a non-blocking client/server engine
git clone git://git.2f30.org/nbeng
Log | Files | Refs | README

commit 1717fb2cc1e8a41154bc2a337f60d6ed8986ba6a
parent d8db125e35204d8492b3e9b063e2e4e4bbf3dbbb
Author: dsp <dsp@2f30.org>
Date:   Tue,  3 Jul 2012 14:45:45 +0300

reintroduce lostd patches.+fixes

Diffstat:
Mnbeng.c | 161++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 111 insertions(+), 50 deletions(-)

diff --git a/nbeng.c b/nbeng.c @@ -34,6 +34,7 @@ typedef struct concontxt_t { #define SSLCON 3 unsigned int contype; /* connection type */ int confd; /* net connection fd */ + int clifd; int clifds[FD_SETSIZE]; /* for tcp connected clients */ fd_set lset; /* the set that we select() on */ struct addrinfo *clinfo; /* info on where we connect */ @@ -86,14 +87,10 @@ set_blocking(int fd) * The flag for the connection type lives in the context. */ static void -prepare_socket(concontxt *con, char *host, char *port) +prepare_socket(concontxt *con, char *host, char *port, int lflag) { struct addrinfo cli_hints, *cli_servinfo, srv_hints, *srv_servinfo, *p0; - int rv, cli_sockfd, optval = 1, i; - - /* all client fds are available */ - for (i = 0; i < FD_SETSIZE; i++) - con->clifds[i] = -1; + int rv, cli_sockfd, optval = 1; if ((con == NULL) || (host == NULL) || (port == NULL)) errx(1, "prepare_socket was passed a null arg"); @@ -126,8 +123,9 @@ prepare_socket(concontxt *con, char *host, char *port) break; } if (!p0) - errx(1, "failed to create socket"); + err(1, "socket"); /* the same for our local part */ + if (lflag) { for (p0 = srv_servinfo; p0; p0 = p0->ai_next) { if (bind(cli_sockfd, p0->ai_addr, p0->ai_addrlen) < 0) { close(cli_sockfd); @@ -137,9 +135,10 @@ prepare_socket(concontxt *con, char *host, char *port) break; } if (!p0) - errx(1, "failed to bind socket"); + err(1, "bind"); + } /* if it's a tcp connection we have to listen() */ - if (con->contype != UDPCON) + if (con->contype != UDPCON && lflag) listen(cli_sockfd, 5); /* all was ok, so we register the socket to the context */ con->confd = cli_sockfd; @@ -190,35 +189,26 @@ freex: static void writesock(concontxt *con) { - ssize_t sent; - int newfd; - int i; + ssize_t n; /* nothing to do */ if (con->buf == NULL) return; if (con->contype == UDPCON) { - sent = sendto(con->confd, con->buf, con->buflen, 0, + n = sendto(con->confd, con->buf, con->buflen, 0, con->clinfo->ai_addr, con->clinfo->ai_addrlen); - if (sent < 0) + if (n < 0) warn("sendto"); } else { - newfd = connect(con->confd, - con->clinfo->ai_addr, - con->clinfo->ai_addrlen); - printf("newfd=%d\n", newfd); - if (newfd < 0) { - warn("connect"); + n = write(con->clifd, con->buf, con->buflen); + if (n < 0) { + warn("write"); + close(con->clifd); + con->clifd = -1; goto freex; } - for (i = 0; i < FD_SETSIZE; i++) { - if (con->clifds[i] == -1) { - con->clifds[i] = newfd; - break; - } - } } freex: @@ -246,9 +236,27 @@ readsock(concontxt *con) if (con->contype == UDPCON) { n = recvfrom(con->confd, buf, sizeof (buf), MSG_DONTWAIT, (struct sockaddr *)&their_addr, &addr_len); + if (n < 0) { + warn("recvfrom"); + goto freex; + } + + /* resolv */ + r = getnameinfo((struct sockaddr *)&their_addr, addr_len, + host, sizeof (host), NULL, 0, 0); + if (r < 0) { + warn("getnameinfo"); + snprintf(host, sizeof (host), "unknown"); + } + printf("host=%s\n", host); } else { - /* code for tcp */ - n = 0; + n = read(con->clifd, buf, sizeof (buf)); + if (n == 0) { + qflag = 1; + close(con->clifd); + con->clifd = -1; + goto freex; + } } buf[n] = '\0'; @@ -259,16 +267,7 @@ readsock(concontxt *con) } memcpy(con->buf, buf, n); con->buflen = n; - - if (n > 0) { - r = getnameinfo((struct sockaddr *)&their_addr, addr_len, - host, sizeof (host), NULL, 0, 0); - if (r < 0) { - warn("getnameinfo"); - snprintf(host, sizeof (host), "unknown"); - } - } - printf("host=%s n=%zd buf=%s", host, n, buf); + printf("n=%zd buf=%s", n, buf); return; freex: @@ -294,10 +293,51 @@ writestdout(concontxt *con) return; } +static void +myaccept(concontxt *con) +{ + int r; + char host[NI_MAXHOST]; + int newfd; + struct sockaddr_storage sa; + socklen_t salen = sizeof (sa); + + newfd = accept(con->confd, (struct sockaddr *)&sa, &salen); + printf("newfd=%d\n", newfd); + if (newfd < 0) + err(1, "accept"); + con->clifd = newfd; + + /* resolv */ + r = getnameinfo((struct sockaddr *)&sa, salen, + host, sizeof (host), NULL, 0, 0); + if (r < 0) { + warn("getnameinfo"); + snprintf(host, sizeof (host), "unknown"); + } + printf("host=%s\n", host); + return; +} + +static void +myconnect(concontxt *con) +{ + int r; + + r = connect(con->confd, + con->clinfo->ai_addr, + con->clinfo->ai_addrlen); + if (r < 0) + warn("connect"); + con->clifd = con->confd; + con->confd = -1; + return; +} + int main(int argc, char *argv[]) { - int c, i; + int c; int highsock, readsocks; struct timeval timeout; char *host, *port; @@ -325,13 +365,14 @@ main(int argc, char *argv[]) con = (concontxt *) malloc(sizeof (concontxt)); if (con == NULL) - errx(1,"malloc"); + err(1, "malloc"); /* defaults */ con->wfd = fileno(stdin); con->lfd = fileno(stdout); con->contype = (tflag || sflag) ? TCPCON : UDPCON; + con->clifd = -1; - prepare_socket(con, host, port); + prepare_socket(con, host, port, 1); timeout.tv_sec = 1; timeout.tv_usec = 0; @@ -339,18 +380,21 @@ main(int argc, char *argv[]) while (1) { FD_ZERO(&(con->lset)); FD_SET(con->wfd, &(con->lset)); - FD_SET(con->confd, &(con->lset)); - highsock = con->confd; - /* add all connected clients */ - for (i = 0; i < FD_SETSIZE && con->clifds[i] != -1; i++) { - FD_SET(con->clifds[i], &(con->lset)); + highsock = con->wfd; + if (con->confd != -1) { + FD_SET(con->confd, &(con->lset)); + highsock = con->confd; + } + if (con->clifd != -1) { + FD_SET(con->clifd, &(con->lset)); + highsock = con->clifd; } if (qflag) goto freex; readsocks = select(highsock + 1, &(con->lset), (fd_set *)0, (fd_set *)0, &timeout); if (readsocks < 0) { - warnx("select error"); + warn("select"); goto freex; } if (readsocks == 0) { @@ -359,10 +403,26 @@ main(int argc, char *argv[]) fflush(stdout); } else { if (FD_ISSET(con->wfd, &(con->lset))) { - readstdin(con); - writesock(con); + if (con->clifd == -1 + && con->contype != UDPCON) { + close(con->confd); + prepare_socket(con, host, port, 0); + myconnect(con); + } + readstdin(con); + writesock(con); + } + if (con->confd != -1 && + FD_ISSET(con->confd, &(con->lset))) { + if (con->contype == UDPCON) { + readsock(con); + writestdout(con); + } else { + myaccept(con); + } } - if (FD_ISSET(con->confd, &(con->lset))) { + if (con->clifd != -1 && + FD_ISSET(con->clifd, &(con->lset))) { readsock(con); writestdout(con); } @@ -373,6 +433,7 @@ freex: printf("exiting\n"); if (con != NULL) { close(con->confd); + close(con->clifd); free(con); } return (0);