ref: 5c1feb0ef0b795e5de71e956f9ccddcd5c4b7f21
dir: /sys/src/cmd/ip/hproxy.c/
#include <u.h> #include <libc.h> enum { bufsize = 8*1024 }; char buf[bufsize+1], addr[128], *proto, *host, *port, *path; void main(void) { char *f[3], *p, *e; int con, fd, n, r; /* read all the headers */ n = 0; do { if(n >= bufsize) return; if((r = read(0, buf+n, bufsize-n)) <= 0) return; n += r; buf[n] = 0; } while(strstr(buf, "\r\n\r\n") == nil); /* remove keep alive headers */ if(p = cistrstr(buf, "\nConnection:")) if(e = strchr(p+1, '\n')) strcpy(p, e); if(p = cistrstr(buf, "\nProxy-Connection:")) if(e = strchr(p+1, '\n')) strcpy(p, e); /* crack first line of http request */ if(e = strchr(buf, '\n')) *e++ = 0; r = tokenize(buf, f, 3); if(r < 2) return; if(r == 2) f[2] = "HTTP/1.0"; proto = f[1]; if(p = strstr(proto, "://")){ *p = 0; host = p + 3; } else { host = proto; proto = "http"; } port = proto; path = ""; if(p = strchr(host, '/')){ *p++ = 0; path = p; } if(*host == '['){ host++; if(p = strrchr(host, ']')){ *p++ = 0; if(p = strrchr(p, ':')) port = ++p; } } else if(p = strrchr(host, ':')){ *p++ = 0; port = p; } snprint(addr, sizeof(addr), "tcp!%s!%s", host, port); alarm(30000); fd = dial(addr, 0, 0, 0); alarm(0); con = cistrcmp(f[0], "CONNECT") == 0; if(con){ if(fd < 0) print("%s 500 Connection Failed\r\n\r\n%r\n", f[2]); else print("%s 200 Connection Established\r\n\r\n", f[2]); } if(fd < 0) return; switch(rfork(RFPROC|RFFDG|RFNOWAIT)){ case -1: return; case 0: dup(fd, 0); break; default: dup(fd, 1); if(!con) print("%s /%s %s\r\nConnection: close\r\n%s", f[0], path, f[2], e); } while((r = read(0, buf, sizeof(buf))) > 0) if(write(1, buf, r) != r) break; postnote(PNGROUP, getpid(), "kill"); }