X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fhtparser.c;h=348a9407f3a9733ff66e3ded9e34248dd5d9c1d4;hb=5599a52ae7067a2c2afd0fda9edd3046043847c1;hp=73d940449e3a9e71b17db39dd22ade50dc635920;hpb=fc253e2fa06742656bd018981ec000799c956391;p=ashd.git diff --git a/src/htparser.c b/src/htparser.c index 73d9404..348a940 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); @@ -547,7 +602,7 @@ int main(int argc, char **argv) { int c, d; int i, s1; - char *root; + char *root, *pidfile, *pidtmp; FILE *pidout; struct passwd *pwent; @@ -600,8 +655,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 +693,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 +706,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); }