⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxy.c

📁 linux 下的线程库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -