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

📄 proxy.c

📁 linux 下的线程库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Simple WEB Proxy for Linux and perhaps other systems *     by Willy Tarreau * *             This program is used to redirect HTTP requests *             it receives to the right HTTP server, or to *             another instance of itself, on an other host. *             It acts like a proxy and all the Web browsers *             that will have to use it must be setup to use *             it as the HTTP Proxy. It then allows several *             hosts on a network to access the Web via one *             only server, which is particularly interesting *             in case of a server connected to an Internet *             provider via a modem with PPP. * *             One interesting aspect is that it doesn't require *             superuser privileges to run  :-) * * Authors:    based on stuff by *                 Willy Tarreau <tarreau@aemiaif.ibp.fr> *  *             Multithreaded code, POST http method, SIGPIPE, fixes, ...  * 		   (rework) *                 Pavel Krauz <kra@fsid.cvut.cz> *  *  * Todo:       - Make a list of hosts and network which can be *               accessed directly, and those which need another *               proxy. *             - add an option to supply an access log with *               hostnames and requests. * *  Copyright (C) 1996  <Willy Tarreau> *  E-mail: tarreau@aemiaif.ibp.fr *  *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/wait.h>#include <netinet/in.h>#include <netdb.h>#include <signal.h>#include <string.h>#include <unistd.h>#include <setjmp.h>#include <pthread.h>/* default listen port */#define LISTENPORT  8080/*  * default timeout for any read or write, in seconds  */#define TIMEOUT_OUT 		60/*  * exit timeout for idle thread */#define TIMEOUT_THREAD_EXIT	15/* length of data buffer in chars */#define LDATA       1024/* length of remote server address */#define LADR        128/* default port to connect to if unspecified */#define DEFAULTPORT 80/* * max proxy threads for requests */#if 1#define MAX_PROXY_THREADS	64#else#define MAX_PROXY_THREADS	4#endifint ConnectToProxy = 0;		/* 1 here means this program will connect to another instance of it				   0 means we'll connect directly to the Internet */char NextProxyAdr[128];		/* the name of the host where the next instance of the program runs */int NextProxyPort;		/* and its port */int NoCache = 0;		/* if not 0, prevents web browsers from retrieving pages in their own				   cache when the users does a "Reload" action */int timeout_out = TIMEOUT_OUT;int max_proxy_threads = MAX_PROXY_THREADS;struct th_proxy_struct {	pthread_t th;		/* only for server */	struct th_proxy_struct *next_free;	pthread_mutex_t mu;	pthread_cond_t cond;	int sock_in;};pthread_mutex_t free_q_mu;pthread_cond_t free_q_cond;struct th_proxy_struct *free_q;int thread_count = 0;	/* protected with free_q_mu */pthread_key_t key_alarm;pthread_mutex_t gethostbyname_mu;	/* used for protect gethostbyname 					 * for gethostbyname_r it isn't needed					 */void request_alarm(int n);void server(int sockListen, struct sockaddr_in *inputSocket);void *client(struct th_proxy_struct *th_proxy);void displaysyntax(void);char *BADREQ ="HTTP/1.0 400 ERROR\r\n""Server: thproxyd\r\n""Content-type: text/html\r\n""\r\n""<HEAD><TITLE>400 Bad Request</TITLE></HEAD>\n""<BODY><H1>400 Bad Request</H1>\n""Your client sent a query that this server could not\n""understand.<P>\n""Reason: Invalid or unsupported method.<P>\n""</BODY>\n";char *SERVERR ="HTTP/1.0 500 ERROR\r\n""Server: thproxyd\r\n""Content-type: text/html\r\n""\r\n""<HEAD><TITLE>500 Server Error</TITLE></HEAD>\n""<BODY><H1>500 Server Error</H1>\n""Internal proxy error while processing your query.<P>\n""Reason: Internal proxy error.<P>\n""</BODY>\n";char *SERVCOERR ="HTTP/1.0 500 ERROR\r\n""Server: thproxyd\r\n""Content-type: text/html\r\n""\r\n""<HEAD><TITLE>500 Server Error</TITLE></HEAD>\n""<BODY><H1>500 Server Error</H1>\n""Internal proxy error while processing your query.<P>\n""Reason: Invalid connection.<P>\n""</BODY>\n";char *SERVDNSERR ="HTTP/1.0 500 ERROR\r\n""Server: thproxyd\r\n""Content-type: text/html\r\n""\r\n""<HEAD><TITLE>500 Server Error</TITLE></HEAD>\n""<BODY><H1>500 Server Error</H1>\n""Internal proxy error while processing your query.<P>\n""Reason: Bad address - DNS cann't resolve address.<P>\n""</BODY>\n";char *SERVTIMEOUT ="HTTP/1.0 500 ERROR\r\n""Server: thproxyd\r\n""Content-type: text/html\r\n""\r\n""<HEAD><TITLE>500 Server Error</TITLE></HEAD>\n""<BODY><H1>500 Server Error</H1>\n""Internal proxy error while processing your query.<P>\n""Reason: Server time out while connection establishment or data transfer.<P>\n""</BODY>\n";char *POSTERR ="HTTP/1.0 500 ERROR\r\n""Server: thproxyd\r\n""Content-type: text/html\r\n""\r\n""<HEAD><TITLE>500 Proxy Server Error</TITLE></HEAD>\n""<BODY><H1>500 Proxy Server Error</H1>\n""Failed to POST.<P>\n""Reason: post method error ???.<P>\n""</BODY>\n";void main(int argc, char **argv){	int listenport = LISTENPORT;	struct sockaddr_in ListenSocket;	int sockListen;	struct sigaction sa;	int opt, val;	while ((opt = getopt(argc, argv, "p:x:t:nm:")) != -1) {		switch (opt) {		case ':':	/* missing parameter */		case '?':	/* unknown option */			displaysyntax();			exit(1);		case 'p':	/* port */			listenport = atoi(optarg);			break;		case 'x':{	/* external proxy */				char *p;				p = strchr(optarg, ':');				if (p == NULL) {	/* unspecified port number. let's quit */					fprintf(stderr, "missing port for next proxy\n");					displaysyntax();					exit(1);				}				*(p++) = 0;	/* ends hostname */				NextProxyPort = atoi(p);				strcpy(NextProxyAdr, optarg);				ConnectToProxy = 1;				break;			}		case 't':	/* disconnect time-out */			timeout_out = atoi(optarg);			break;		case 'n':	/* no cache */			NoCache = 1;			break;		case 'm':			max_proxy_threads = atoi(optarg);			break;		}		/* end of switch() */	}			/* end of while() */	/* initialization of listen socket */	pthread_mutex_init(&free_q_mu, NULL);	pthread_mutex_init(&gethostbyname_mu, NULL);	pthread_cond_init(&free_q_cond, NULL);	free_q = NULL;	pthread_key_create(&key_alarm, NULL);	sa.sa_handler = request_alarm;	sigemptyset(&sa.sa_mask);	sa.sa_flags = SA_RESTART;	sigaction(SIGALRM, &sa, NULL);	if ((sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {		perror("Webroute(socket)");		exit(1);	}	val = 1;	if ((setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) == -1) {		perror("Webroute(setsockopt)");		exit(1);	}	bzero((char *) &ListenSocket, sizeof(ListenSocket));	ListenSocket.sin_family = AF_INET;	ListenSocket.sin_addr.s_addr = htonl(INADDR_ANY);	ListenSocket.sin_port = htons(listenport);	if (bind(sockListen, (struct sockaddr *) &ListenSocket, sizeof(ListenSocket)) == -1) {		perror("Webroute(bind)");		exit(1);	}	if (listen(sockListen, 5) == -1) {		perror("Webroute(listen)");		exit(1);	}	/* the socket is ready. Let's wait for requests ... */	/* let's close stdin, stdout, stderr to prevent messages from appearing on the console */#ifndef DEBUG	close(0);	close(1);	close(2);#endif	server(sockListen, &ListenSocket);}				/* end of main() */static struct th_proxy_struct *new_proxy_th(void){	struct th_proxy_struct *th_proxy;	pthread_attr_t attr;	if (!(th_proxy = malloc(sizeof(struct th_proxy_struct))))		 return NULL;	memset(th_proxy, 0, sizeof(struct th_proxy_struct));	pthread_mutex_init(&th_proxy->mu, NULL);	pthread_cond_init(&th_proxy->cond, NULL);	th_proxy->next_free = NULL;	th_proxy->sock_in = -1;	pthread_attr_init(&attr);	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);	if (pthread_create(&th_proxy->th, &attr, (void *((*)(void *))) client, th_proxy) != 0) {		free(th_proxy);		return NULL;	}	return th_proxy;}static struct th_proxy_struct *alloc_proxy_th(void){	struct th_proxy_struct *th_proxy;	pthread_mutex_lock(&free_q_mu);	do {		th_proxy = free_q;		if (free_q)			free_q = free_q->next_free;		else {			if (thread_count < max_proxy_threads) {				if ((th_proxy = new_proxy_th()))					thread_count++;			}			if (!th_proxy)				pthread_cond_wait(&free_q_cond, &free_q_mu);		}	} while (!th_proxy);	pthread_mutex_unlock(&free_q_mu);	return th_proxy;}void server(int sockListen, struct sockaddr_in *inputSocket){	int lgInputSocket;	int sockIn;	struct th_proxy_struct *th_proxy;	for (;;) {		/* infinite loop */		lgInputSocket = sizeof(*inputSocket);		do {			sockIn = accept(sockListen, (struct sockaddr *) inputSocket, &lgInputSocket);		} while (sockIn == -1 && errno == EINTR);	/* retries if interrupted */		if (sockIn == -1) {	/* if there's an error, we exit */			exit(1);	/* don't wait when daemon is going sick ! */		}		/* process request, alloc thread for it */		th_proxy = alloc_proxy_th();		pthread_mutex_lock(&th_proxy->mu);		th_proxy->sock_in = sockIn;		pthread_mutex_unlock(&th_proxy->mu);		pthread_cond_signal(&th_proxy->cond);	}}#define ERR_SOCKET		-5#define ERR_GETHOSTBYNAME	-6#define ERR_CONNECT		-7#define ERR_CONNECT_TIMEOUT	-8int connectto(char *hote, int port, int sockIn){#if 0	/*	 * use gethostbyname 	 */	struct hostent *ServerName;	struct sockaddr_in OutputSocket;	/* output socket descriptor */	int sockOut, retval;	if ((sockOut = socket(AF_INET, SOCK_STREAM, 0)) == -1) {		return ERR_SOCKET;	}	pthread_mutex_lock(&gethostbyname_mu);	if ((ServerName = gethostbyname(hote)) == NULL) {		pthread_mutex_unlock(&gethostbyname_mu);		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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -