X-Git-Url: http://www.dolda2000.com/gitweb/?p=ashd.git;a=blobdiff_plain;f=src%2Fplaintcp.c;h=56fc81c5fb2be80b5d32240d46e8526713eb1b5c;hp=864efe1598c2f2585043855b820cee708adfcdf5;hb=595adb9922885c2a05bc6917ee8f8f02f496e618;hpb=41fe6c390c31ccb7f70d26a13418bd772fc7b5e4 diff --git a/src/plaintcp.c b/src/plaintcp.c index 864efe1..56fc81c 100644 --- a/src/plaintcp.c +++ b/src/plaintcp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -44,9 +45,10 @@ struct tcpport { struct tcpconn { struct sockaddr_storage name; struct tcpport *port; + int fd; }; -static int listensock4(int port) +int listensock4(int port) { struct sockaddr_in name; int fd; @@ -63,14 +65,15 @@ static int listensock4(int port) close(fd); return(-1); } - if(listen(fd, 16) < 0) { + if(listen(fd, 128) < 0) { close(fd); return(-1); } + fcntl(fd, F_SETFD, FD_CLOEXEC); return(fd); } -static int listensock6(int port) +int listensock6(int port) { struct sockaddr_in6 name; int fd; @@ -87,25 +90,56 @@ static int listensock6(int port) close(fd); return(-1); } - if(listen(fd, 16) < 0) { + if(listen(fd, 128) < 0) { close(fd); return(-1); } + fcntl(fd, F_SETFD, FD_CLOEXEC); return(fd); } +char *formathaddress(struct sockaddr *name, socklen_t namelen) +{ + static char buf[128]; + struct sockaddr_in *v4; + struct sockaddr_in6 *v6; + + switch(name->sa_family) { + case AF_INET: + v4 = (struct sockaddr_in *)name; + if(!inet_ntop(AF_INET, &v4->sin_addr, buf, sizeof(buf))) + return(NULL); + return(buf); + case AF_INET6: + v6 = (struct sockaddr_in6 *)name; + if(IN6_IS_ADDR_V4MAPPED(&v6->sin6_addr)) { + if(!inet_ntop(AF_INET, ((char *)&v6->sin6_addr) + 12, buf, sizeof(buf))) + return(NULL); + } else { + if(!inet_ntop(AF_INET6, &v6->sin6_addr, buf, sizeof(buf))) + return(NULL); + } + return(buf); + default: + errno = EPFNOSUPPORT; + return(NULL); + } +} + static int initreq(struct conn *conn, struct hthead *req) { struct tcpconn *tcp = conn->pdata; - char nmbuf[256]; + struct sockaddr_storage sa; + socklen_t salen; - if(tcp->name.ss_family == AF_INET) { - headappheader(req, "X-Ash-Address", inet_ntop(AF_INET, &((struct sockaddr_in *)&tcp->name)->sin_addr, nmbuf, sizeof(nmbuf))); + headappheader(req, "X-Ash-Address", formathaddress((struct sockaddr *)&tcp->name, sizeof(sa))); + if(tcp->name.ss_family == AF_INET) headappheader(req, "X-Ash-Port", sprintf3("%i", ntohs(((struct sockaddr_in *)&tcp->name)->sin_port))); - } else if(tcp->name.ss_family == AF_INET6) { - headappheader(req, "X-Ash-Address", inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&tcp->name)->sin6_addr, nmbuf, sizeof(nmbuf))); + else if(tcp->name.ss_family == AF_INET6) headappheader(req, "X-Ash-Port", sprintf3("%i", ntohs(((struct sockaddr_in6 *)&tcp->name)->sin6_port))); - } + salen = sizeof(sa); + if(!getsockname(tcp->fd, (struct sockaddr *)&sa, &salen)) + headappheader(req, "X-Ash-Server-Address", formathaddress((struct sockaddr *)&sa, sizeof(sa))); headappheader(req, "X-Ash-Server-Port", sprintf3("%i", tcp->port->sport)); headappheader(req, "X-Ash-Protocol", "http"); return(0); @@ -116,41 +150,57 @@ void servetcp(struct muth *muth, va_list args) vavar(int, fd); vavar(struct sockaddr_storage, name); vavar(struct tcpport *, stcp); - FILE *in; + struct bufio *in; struct conn conn; struct tcpconn tcp; memset(&conn, 0, sizeof(conn)); memset(&tcp, 0, sizeof(tcp)); - in = mtstdopen(fd, 1, 60, "r+"); + in = mtbioopen(fd, 1, 60, "r+", NULL); conn.pdata = &tcp; conn.initreq = initreq; + tcp.fd = fd; tcp.name = name; tcp.port = stcp; - serve(in, &conn); + serve(in, fd, &conn); } static void listenloop(struct muth *muth, va_list args) { vavar(struct tcpport *, tcp); - int ns; + int i, ns, n; struct sockaddr_storage name; socklen_t namelen; + fcntl(tcp->fd, F_SETFL, fcntl(tcp->fd, F_GETFL) | O_NONBLOCK); while(1) { namelen = sizeof(name); - block(tcp->fd, EV_READ, 0); - ns = accept(tcp->fd, (struct sockaddr *)&name, &namelen); - if(ns < 0) { - flog(LOG_ERR, "accept: %s", strerror(errno)); + if(block(tcp->fd, EV_READ, 0) == 0) goto out; + n = 0; + while(1) { + ns = accept(tcp->fd, (struct sockaddr *)&name, &namelen); + if(ns < 0) { + if(errno == EAGAIN) + break; + if(errno == ECONNABORTED) + continue; + flog(LOG_ERR, "accept: %s", strerror(errno)); + goto out; + } + mustart(servetcp, ns, name, tcp); + if(++n >= 100) + break; } - mustart(servetcp, ns, name, tcp); } out: close(tcp->fd); free(tcp); + for(i = 0; i < listeners.d; i++) { + if(listeners.b[i] == muth) + bufdel(listeners, i); + } } void handleplain(int argc, char **argp, char **argv) @@ -163,7 +213,8 @@ void handleplain(int argc, char **argp, char **argv) for(i = 0; i < argc; i++) { if(!strcmp(argp[i], "help")) { printf("plain handler parameters:\n"); - printf("\tport=TCP-PORT (default is 80)\n"); + printf("\tport=TCP-PORT [80]\n"); + printf("\t\tThe TCP port to listen on.\n"); exit(0); } else if(!strcmp(argp[i], "port")) { port = atoi(argv[i]); @@ -179,7 +230,7 @@ void handleplain(int argc, char **argp, char **argv) omalloc(tcp); tcp->fd = fd; tcp->sport = port; - mustart(listenloop, tcp); + bufadd(listeners, mustart(listenloop, tcp)); if((fd = listensock4(port)) < 0) { if(errno != EADDRINUSE) { flog(LOG_ERR, "could not listen on IPv4 (port %i): %s", port, strerror(errno)); @@ -189,6 +240,6 @@ void handleplain(int argc, char **argp, char **argv) omalloc(tcp); tcp->fd = fd; tcp->sport = port; - mustart(listenloop, tcp); + bufadd(listeners, mustart(listenloop, tcp)); } }