📄 proxy.c
字号:
pthread_mutex_unlock(&gethostbyname_mu);#else /* * use gethostbyname_r */ struct hostent ServerName; struct sockaddr_in OutputSocket; /* output socket descriptor */ int sockOut, retval; char buf[1024]; int hst_errno; if ((sockOut = socket(AF_INET, SOCK_STREAM, 0)) == -1) { return ERR_SOCKET; } /* * pointers used in struct hostent ServerName will be point to space * which user give to function (the buf variable) */ if (gethostbyname_r(hote, &ServerName, buf, sizeof(buf), &hst_errno) == NULL) { if (hst_errno == ERANGE) { /* the buf is to short for store all informations */ } return ERR_GETHOSTBYNAME; } bzero((char *) &OutputSocket, sizeof(OutputSocket)); OutputSocket.sin_family = AF_INET; OutputSocket.sin_port = htons(port); bcopy((char *) ServerName.h_addr, (char *) &OutputSocket.sin_addr, ServerName.h_length);#endif alarm(timeout_out); retval = connect(sockOut, (struct sockaddr *) &OutputSocket, sizeof(OutputSocket)); alarm(0); if (retval == -1) { close(sockOut); return ERR_CONNECT; } return sockOut; /* connection OK */}/* this function should be called only by the child */void sayerror(char *msg, int sockIn, int sockOut){ struct linger linger; pthread_setspecific(key_alarm, NULL); write(sockIn, msg, strlen(msg)); linger.l_onoff = 1; linger.l_linger = 4; setsockopt(sockIn, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); linger.l_onoff = 1; linger.l_linger = 1; setsockopt(sockOut, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); close(sockOut); close(sockIn);#ifdef DEBUG { char buf[1024]; char *p, *end; p = strstr(msg, "Reason:"); end = strstr(p, "<P>"); if (!p || !end) buf[0] = 0; else { strncpy(buf, p, end - p); buf[end - p] = 0; } printf("%d --- request error %s\n", sockIn, buf); }#endif}void request_alarm(int i){ sigjmp_buf *jmp; if ((jmp = pthread_getspecific(key_alarm))) { pthread_setspecific(key_alarm, NULL); siglongjmp(*jmp, 1); }}#define METHOD_GET 1#define METHOD_POST 2#define METHOD_HEAD 3int process_request(int sockIn){ char data[LDATA]; char adr[LADR], *p; int ldata, lreq, port, req_len, req_method; FILE *fsin; sigjmp_buf timeout_jmp; int sockOut = -1; int val; /* let's reopen input socket as a file */ if ((fsin = fdopen(sockIn, "rw")) == NULL) goto serverr; /* prepares for connection abort */ /* avoid some sockets problems ... */ val = 1; setsockopt(sockIn, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));/* * here, we'll analyze the request and get rid of "http://adr:port". * The address and port willbe duplicated and used to open the connection. */ if (sigsetjmp(timeout_jmp, 1) != 0) goto timeout; pthread_setspecific(key_alarm, &timeout_jmp);#ifdef DEBUG printf("%d --- request begin\n", sockIn);#endif if (fgets(data, LDATA, fsin) == NULL) goto badreq;#ifdef DEBUG printf("%d %s", sockIn, data);#endif /* it's easy to log all requests here */ /* fprintf(stderr,"requete recue: %s",data); */ ldata = strlen(data); if (strncmp(data, "GET ", 4) == 0) { req_len = 4; req_method = METHOD_GET; } else if (strncmp(data, "POST ", 5) == 0) { req_len = 5; req_method = METHOD_POST; } else if (strncmp(data, "HEAD ", 5) == 0) { req_len = 5; req_method = METHOD_HEAD; } else goto badreq; if (!ConnectToProxy) { /* if proxy-to-proxy connection, we don't modify the request */ char *str; str = data + req_len; while (*str == ' ') str++; if (!strncmp(str, "http://", 7)) str += 7; if ((p = strchr(str, '/')) != NULL) { strncpy(adr, str, (p - str)); /* copies addresse in adr */ adr[p - str] = 0; str = p; /* points to the rest of the request (without address) */ lreq = ldata - (str - data); } else goto badreq; /* if no /, error */ /* at this stage, adr contains addr[:port], and str points to the local URL with the first '/' */ if (adr[0] == 0) goto badreq; p = strchr(adr, ':'); if (p == NULL) /* unspecified port. The default one will be used */ port = DEFAULTPORT; else { /* port is available. let's read it */ *(p++) = 0; /* ends hostname */ port = atoi(p); } /* end of request analysis. The hostname is in "adr", and the port in "port" */ if ((sockOut = connectto(adr, port, sockIn)) < 0) { switch (sockOut) { case ERR_GETHOSTBYNAME: goto servdnserr; } goto servcoerr; } /* As it becomes a local URL, we only say "GET" and the end of the request. */ alarm(timeout_out); switch (req_method) { case METHOD_GET: write(sockOut, "GET ", 4); break; case METHOD_POST: write(sockOut, "POST ", 5); break; case METHOD_HEAD: write(sockOut, "HEAD ", 5); break; } write(sockOut, str, lreq); alarm(0); } else { /* proxy-to-proxy connection ! */ if ((sockOut = connectto(NextProxyAdr, NextProxyPort, sockIn)) < 0) { switch (sockOut) { case ERR_GETHOSTBYNAME: goto servdnserr; } goto servcoerr; } alarm(timeout_out); write(sockOut, data, ldata); alarm(0); } /* now, let's copy all what we don't have copied yet */ if (req_method == METHOD_POST) { int c_len = 0; char *p; do { fgets(data, LDATA, fsin);#ifdef DEBUG printf("%d %s", sockIn, data);#endif ldata = strlen(data); if (strncasecmp(data, "Content-Length", 14) == 0) { p = data + 14; while (*p != ':') p++; c_len = atoi(++p); } write(sockOut, data, ldata); } while (ldata && data[0] != '\n' && data[0] != '\r'); if (c_len == 0) goto posterr;#ifdef DEBUG printf("%d ", sockIn);#endif while (c_len) { ldata = fread(data, 1, (LDATA > c_len ? c_len : LDATA), fsin);#ifdef DEBUG fwrite(data, 1, ldata, stdout);#endif write(sockOut, data, ldata); c_len -= ldata; }#ifdef DEBUG printf("\n");#endif } else { /* * METHOD_GET, METHOD_HEAD */ do { fgets(data, LDATA, fsin);#ifdef DEBUG printf("%d %s", sockIn, data);#endif ldata = strlen(data); if (!NoCache || (strncmp(data, "If-Mod", 6))) write(sockOut, data, ldata); } while (ldata && data[0] != '\n' && data[0] != '\r'); } /* retrieve data from server */ do { int err; do { alarm(timeout_out); ldata = read(sockOut, data, LDATA); alarm(0); } while (ldata == -1 && errno == EINTR); /* retry on interrupt */ if (ldata < 0) goto serverr; if (ldata) { /* if ldata > 0, it's not the end yet */ do { err = write(sockIn, data, ldata); } while (err == -1 && errno == EINTR); if (errno == EPIPE) { /* other end (client) closed the conection */#ifdef DEBUG printf("%d - client closed connection\n", sockIn);#endif goto end; } if (err == -1) goto serverr; } } while (ldata > 0); /* loops while more data available */ end: close(sockIn); /* close the sockets */ close(sockOut); pthread_setspecific(key_alarm, NULL);#ifdef DEBUG printf("%d --- request successful\n", sockIn);#endif return 0; /* no error */ badreq: sayerror(BADREQ, sockIn, sockOut); return -1; serverr: sayerror(SERVERR, sockIn, sockOut); return -2; timeout: sayerror(SERVTIMEOUT, sockIn, sockOut); return -3; servcoerr: sayerror(SERVCOERR, sockIn, sockOut); return -4; servdnserr: sayerror(SERVDNSERR, sockIn, sockOut); return -5; posterr: sayerror(POSTERR, sockIn, sockOut); return -6;}void *client(struct th_proxy_struct *th_proxy){ struct timespec ts; struct timeval tv; int retval; struct th_proxy_struct **th; signal(SIGPIPE, SIG_IGN); for (;;) { pthread_mutex_lock(&th_proxy->mu); while (th_proxy->sock_in < 0) {#if 0 pthread_cond_wait(&th_proxy->cond, &th_proxy->mu);#else gettimeofday(&tv, NULL); ts.tv_sec = tv.tv_sec + TIMEOUT_THREAD_EXIT; ts.tv_nsec = 0; retval = pthread_cond_timedwait( &th_proxy->cond, &th_proxy->mu, &ts); if (retval == ETIMEDOUT) { pthread_mutex_lock(&free_q_mu); th = &free_q; while (*th && *th != th_proxy) th = &((*th)->next_free); if (*th == th_proxy) { /* * remove yourself from queue * and exit */ *th = th_proxy->next_free; thread_count--; pthread_mutex_unlock(&free_q_mu); free(th_proxy); pthread_exit(0); } pthread_mutex_unlock(&free_q_mu); }#endif } pthread_mutex_unlock(&th_proxy->mu); pthread_setspecific(key_alarm, (void *) 0); process_request(th_proxy->sock_in); pthread_mutex_lock(&th_proxy->mu); th_proxy->sock_in = -1; pthread_mutex_unlock(&th_proxy->mu); pthread_mutex_lock(&free_q_mu); th_proxy->next_free = free_q; free_q = th_proxy; pthread_mutex_unlock(&free_q_mu); pthread_cond_signal(&free_q_cond); }}/* displays the right syntax to call Webroute */void displaysyntax(void){ fprintf(stderr, "Syntax:\n"); fprintf(stderr, "webroute [ -p port ] [ -x h:p ] [ -t timeout ] [ -m max_threads ] [ -n ]\n"); fprintf(stderr, "Available options are:\n"); fprintf(stderr, " -p allows you to run webroute on the port <port>.\n"); fprintf(stderr, " If you don't have superuser privileges, you must use a port > 5000.\n"); fprintf(stderr, " The default port is %d.\n", LISTENPORT); fprintf(stderr, " -x enables multi-proxy feature. This means that this instance of Webroute\n"); fprintf(stderr, " doesn't have itself access to the internet, but the one which is running\n"); fprintf(stderr, " on port <p> of host <h> can provide an access. It's possible to chain\n"); fprintf(stderr, " as many instances of Webroute as you want. That depends of your network\n"); fprintf(stderr, " topology\n"); fprintf(stderr, " -t <timeout> specifies how many seconds the connection will stay connected (or trying to connect) when\n"); fprintf(stderr, " no data arrives. After this time, the connection will be canceled.\n"); fprintf(stderr, " -n prevents browsers from retrieving web pages from their own cache when the\n"); fprintf(stderr, " user asks for a \"Reload\". The page will then always be reloaded.\n"); fprintf(stderr, " -m max count of proxy threads allocated to serve the requests\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -