X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fhtparser.c;h=5491855c4df055777bbf45a0447155a1c6a49ce5;hb=HEAD;hp=73d940449e3a9e71b17db39dd22ade50dc635920;hpb=fc253e2fa06742656bd018981ec000799c956391;p=ashd.git diff --git a/src/htparser.c b/src/htparser.c index 73d9404..5491855 100644 --- a/src/htparser.c +++ b/src/htparser.c @@ -40,7 +40,6 @@ #include "htparser.h" static int plex; -static char *pidfile = NULL; static int daemonize, usesyslog; struct mtbuf listeners; @@ -152,7 +151,7 @@ static off_t passdata(struct bufio *in, struct bufio *out, off_t max) static int recvchunks(struct bufio *in, struct bufio *out) { - size_t read, chlen; + ssize_t read, chlen; int c, r; while(1) { @@ -305,14 +304,58 @@ done: return(ret); } -void serve(struct bufio *in, struct conn *conn) +static void passduplex(struct bufio *a, int afd, struct bufio *b, int bfd) +{ + struct selected pfd[4], sel; + struct bufio *sio; + int n, ev; + + while(!bioeof(a) && !bioeof(b)) { + biocopybuf(b, a); + biocopybuf(a, b); + n = 0; + if(!a->eof) { + ev = 0; + if(biorspace(a)) + ev |= EV_READ; + if(biowdata(a)) + ev |= EV_WRITE; + if(ev) + pfd[n++] = (struct selected){.fd = afd, .ev = ev}; + } + if(!b->eof) { + ev = 0; + if(!b->eof && biorspace(b)) + ev |= EV_READ; + if(biowdata(b)) + ev |= EV_WRITE; + if(ev) + pfd[n++] = (struct selected){.fd = bfd, .ev = ev}; + } + if((sel = mblock(600, n, pfd)).ev == 0) + break; + if(sel.fd == afd) + sio = a; + else if(sel.fd == bfd) + sio = b; + else + break; + if((sel.ev & EV_READ) && (biofillsome(sio) < 0)) + break; + if((sel.ev & EV_WRITE) && (bioflushsome(sio) < 0)) + break; + } +} + +void serve(struct bufio *in, int infd, struct conn *conn) { int pfds[2]; - struct bufio *out; + struct bufio *out, *dout; + struct stdiofd *outi; struct hthead *req, *resp; char *hd, *id; off_t dlen; - int keep; + int keep, duplex; id = connid(); out = NULL; @@ -335,7 +378,7 @@ void serve(struct bufio *in, struct conn *conn) if(sendreq(plex, req, pfds[0])) break; close(pfds[0]); - out = mtbioopen(pfds[1], 1, 600, "r+", NULL); + out = mtbioopen(pfds[1], 1, 600, "r+", &outi); if(getheader(req, "content-type") != NULL) { if((hd = getheader(req, "content-length")) != NULL) { @@ -363,8 +406,20 @@ void serve(struct bufio *in, struct conn *conn) if(!getheader(resp, "server")) headappheader(resp, "Server", sprintf3("ashd/%s", VERSION)); + duplex = hasheader(resp, "x-ash-switch", "duplex"); + trimx(resp); - if(!strcasecmp(req->ver, "HTTP/1.0")) { + if(duplex) { + if(outi->rights < 0) + break; + writerespb(in, resp); + bioprintf(in, "\r\n"); + dout = mtbioopen(outi->rights, 1, 600, "r+", NULL); + passduplex(in, infd, dout, outi->rights); + outi->rights = -1; + bioclose(dout); + break; + } else if(!strcasecmp(req->ver, "HTTP/1.0")) { if(!strcasecmp(req->method, "head")) { keep = http10keep(req, resp); writerespb(in, resp); @@ -525,9 +580,12 @@ static void addport(char *spec) /* XXX: It would be nice to decentralize this, but, meh... */ if(!strcmp(nm, "plain")) { handleplain(pars.d, pars.b, vals.b); -#ifdef HAVE_GNUTLS +#if defined HAVE_GNUTLS } else if(!strcmp(nm, "ssl")) { handlegnussl(pars.d, pars.b, vals.b); +#elif defined HAVE_OPENSSL + } else if(!strcmp(nm, "ssl")) { + handleossl(pars.d, pars.b, vals.b); #endif } else { flog(LOG_ERR, "htparser: unknown port handler `%s'", nm); @@ -547,12 +605,12 @@ int main(int argc, char **argv) { int c, d; int i, s1; - char *root; + char *root, *pidfile, *pidtmp; FILE *pidout; struct passwd *pwent; daemonize = usesyslog = 0; - root = NULL; + root = pidfile = NULL; pwent = NULL; while((c = getopt(argc, argv, "+hSfu:r:p:")) >= 0) { switch(c) { @@ -566,16 +624,16 @@ int main(int argc, char **argv) usesyslog = 1; break; case 'u': - if((pwent = getpwnam(optarg)) == NULL) { + if(optarg[0] && ((pwent = getpwnam(optarg)) == NULL)) { flog(LOG_ERR, "could not find user %s", optarg); exit(1); } break; case 'r': - root = optarg; + root = optarg[0] ? optarg : NULL; break; case 'p': - pidfile = optarg; + pidfile = optarg[0] ? optarg : NULL; break; default: usage(stderr); @@ -600,8 +658,14 @@ int main(int argc, char **argv) bufadd(listeners, mustart(plexwatch, plex)); pidout = NULL; if(pidfile != NULL) { - if((pidout = fopen(pidfile, "w")) == NULL) { - flog(LOG_ERR, "could not open %s for writing: %s", pidfile, strerror(errno)); + pidtmp = sprintf3("%s.new", pidfile); + if((pidout = fopen(pidtmp, "w")) == NULL) { + flog(LOG_ERR, "could not open %s for writing: %s", pidtmp, strerror(errno)); + return(1); + } + if(rename(pidtmp, pidfile)) { + flog(LOG_ERR, "could not overwrite %s: %s", pidfile, strerror(errno)); + unlink(pidtmp); return(1); } } @@ -632,7 +696,7 @@ int main(int argc, char **argv) } if(pidout != NULL) { fprintf(pidout, "%i\n", getpid()); - fclose(pidout); + fflush(pidout); } d = 0; while(!d) { @@ -645,11 +709,17 @@ int main(int argc, char **argv) while(listeners.d > 0) resume(listeners.b[0], 0); flog(LOG_INFO, "no longer listening"); + if(pidout != NULL) { + putc('\n', pidout); + fflush(pidout); + } } else { d = 1; } break; } } + if(pidout != NULL) + ftruncate(fileno(pidout), 0); return(0); }