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

📄 http_proxy.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1996-2000 University of Utah and the Flux Group. * All rights reserved. *  * This file is part of the Flux OSKit.  The OSKit is free software, also known * as "open source;" you can redistribute it and/or modify it under the terms * of the GNU General Public License (GPL), version 2, as published by the Free * Software Foundation (FSF).  To explore alternate licensing terms, contact * the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271. *  * The OSKit 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 GPL for more details.  You should have * received a copy of the GPL along with the OSKit; see the file COPYING.  If * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA. *//* * HTTP Proxy: This example is intended to demonstrate a multi-threaded * program that uses the BSD socket layer. This is a simple HTTP proxy * that listens on port 6969. It can handle basic methods like GET, HEAD, * CONNECT, and POST, but is by no means a correct, complete, or optimal * implementation of the HTTP spec. Its just a demonstration. * * Big Picture: For each new connection received on port 6969, 3 new threads * are launched. The first parses the connection request and gets it sent * off to the actual server. The other two threads simply loop, reading from * the client and server sides, passing data along to the other side. When * either side closes it connection (usually the server when the file has * been transferred), all the connections are torn down and the 3 threads * are terminated. * * To test this with Netscape you need to tell it to use a proxy. * Under version 3 this is done through the Options -> Network Preferences -> * Proxies -> Manual -> Config -> View dialog box. * Set HTTP and Security to machine name and port 6969. * Under version 4 this is done through the Preferences -> Advanced -> * Proxies -> Manual -> View dialog box. * * Note: the filesytem stuff is only so libstartup can set up things in /etc * for us (like /etc/resolv.conf). * We could use the bmodfs but we use the netbsd filesystem to test more stuff. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/inet.h>#include <sys/ioctl.h>#include <errno.h>#include <ctype.h>#include <strings.h>#include <string.h>#include <dirent.h>#include <fcntl.h>#include <oskit/threads/pthread.h>#include <oskit/startup.h>#include <oskit/clientos.h>#include <assert.h>#include <sys/stat.h>#include <oskit/queue.h>#include <time.h>#if !defined(OSKIT_UNIX) && defined(OSKIT_X86)#include <oskit/x86/base_gdt.h>#endifint		proxy_socket;int		death_socket;int		create_listener_socket(int port);void		*deathwatch(void *foo);pthread_mutex_t gethostname_mutex;int           threads_stack_back_trace(int, int);#include <oskit/dev/dev.h>#include <oskit/dev/linux.h>#ifdef  OSKIT_UNIXvoid	start_fs_native_pthreads(char *root);#endif/* * Each connection has this associated data structure. */typedef struct _connection {	int		client_sock;	/* Connection from the client */	int		server_sock;	/* Connection to the server */	pthread_mutex_t mutex;		/* A lock to protect this structure */	pthread_cond_t  condvar;	/* Condition for signal */	int		died;		/* One side or the other died. */} connection_t;void	*connection_manager(void *arg);/* * Act as simple HTTP proxy. */intmain(){	int		length, sock;	struct sockaddr client;	pthread_t	death_tid, tid;	extern int	threads_debug;	/*	 * Init the OS.	 */	oskit_clientos_init_pthreads();	start_clock();	start_pthreads();	threads_debug = 0;	#ifndef OSKIT_UNIX	start_world_pthreads();#else#ifdef  REALSTUFF	start_fs_pthreads("/dev/oskitfs", 0);	start_network_pthreads();#else	start_fs_native_pthreads("/tmp");	start_network_native_pthreads();#endif#endif	pthread_mutex_init(&gethostname_mutex, 0);	proxy_socket = create_listener_socket(6969);	death_socket = create_listener_socket(6666);	/*	 * Create a thread so I can talk to the program via telnet.	 */	pthread_create(&death_tid, 0, deathwatch, (void *) 0);		/*	 * The main thread will do nothing except look for new	 * connections.	 */	while (1) {		sock = accept(proxy_socket, &client, &length);		if (sock < 0) {			if (errno == ECONNABORTED) {				/*				 * The deathwatch has cut us off at the				 * knees. Just wait for the end.				 */				oskit_pthread_sleep(100000);			}			perror("accept");			exit(1);		}		/*		 * Create a thread to manage this connection.		 */		pthread_create(&tid, 0, connection_manager, (void *) sock);		pthread_detach(tid);	}	return 0;}/* * This program creates a datagram socket, binds a name to it, then reads * from the socket. */intcreate_listener_socket(int port){	int sock, length, data;	struct sockaddr_in name;	/* Create socket from which to read. */	sock = socket(AF_INET, SOCK_STREAM, 0);	if (sock < 0) {		perror("opening datagram socket");		exit(1);	}		data = 1;	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &data, sizeof(data))	    < 0) {		perror("setsockopt");		exit(1);	}	/* Create name with wildcards. */	name.sin_family = AF_INET;	name.sin_addr.s_addr = INADDR_ANY;	name.sin_port = htons(port);	if (bind(sock, (struct sockaddr *) &name, sizeof(name))) {		perror("binding datagram socket");		exit(1);	}	/* Find assigned port value and print it out. */	length = sizeof(name);	if (getsockname(sock, (struct sockaddr *) &name, &length)) {		perror("getting socket name");		exit(1);	}	printf("Socket has port #%d\n", ntohs(name.sin_port));	if (listen(sock, 20) < 0) {		perror("listen on socket");		exit(1);	}	return sock;}intconnect_to_host(char *host, char *port, int *server_sock){	int			sock, data;	struct sockaddr_in	name;	struct hostent		*hp, *gethostbyname();	struct timeval		timeo;	/* Create socket on which to send. */	sock = socket(AF_INET, SOCK_STREAM, 0);	if (sock < 0) {		perror("connect_to_host: opening datagram socket");		return 1;	}	data = 1024 * 32;	if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &data, sizeof(data)) < 0) {		perror("setsockopt SO_SNDBUF");		return 1;	}		data = 1024 * 32;	if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &data, sizeof(data)) < 0) {		perror("setsockopt SO_RCVBUF");		return 1;	}			data = 1;	if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &data, sizeof(data))	    < 0) {		perror("setsockopt SO_KEEPALIVE");		return 1;	}	timeo.tv_sec  = 30;	timeo.tv_usec = 0;	if (setsockopt(sock,		       SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)) < 0) {		perror("setsockopt SO_RCVTIMEO");#if 0		panic("SETSOCKOPT");#endif	}	/*	 * Construct name, with no wildcards, of the socket to send to.	 * Gethostbyname() returns a structure including the network address	 * of the specified host.  The port number is taken from the command	 * line. 	 */	pthread_mutex_lock(&gethostname_mutex);	hp = gethostbyname(host);	pthread_mutex_unlock(&gethostname_mutex);	if (hp == 0) {		printf("connect_to_host: unknown host: %s\n", host);		return 1;	}	bcopy(hp->h_addr, &name.sin_addr, hp->h_length);	name.sin_family = AF_INET;	name.sin_port = htons((port ? atoi(port) : 80));	if (connect(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {		perror("connect_to_host: connecting stream socket");		return 1;	}		*server_sock = sock;	return 0;}/* * Setup a new connection. */intsetup_connection(int client_sock, connection_t **return_connp){	int		data, c, len, server_sock, tunneling = 0;	char		buf[BUFSIZ], str[BUFSIZ], *bp;	char		*last = 0, *method, *url, *rest, *host, *port;	connection_t	*connp;	struct timeval  timeo;	data = 1;	if (setsockopt(client_sock,		       SOL_SOCKET, SO_KEEPALIVE, &data, sizeof(data)) < 0) {		perror("setsockopt SO_KEEPALIVE");		return 1;	}	/*	 * Set the recv timeout so that reads do not block forever. 	 */	timeo.tv_sec  = 10;	timeo.tv_usec = 0;	if (setsockopt(client_sock,		       SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)) < 0) {		perror("setsockopt SO_RCVTIMEO");#if 0		return 1;#endif	}	/*	 * Read the first block of data to get the URL info.	 */	bzero(buf, BUFSIZ);	if ((c = recv(client_sock, buf, BUFSIZ, 0)) <= 0) {		if (c <= 0) {			if (c == 0) {				printf("Closing down Client side\n");				return 1;			}			if (errno && errno != EINTR) {				perror("First read on client side");				return 1;			}		}	}	/*	 * Parse the URL info.	 */	bp = buf;	if ((method = strtok_r(bp, " \t\n\r", &last)) == NULL) {		printf("Bad Method: %s\n", buf);		return 1;	}		if ((url = strtok_r(NULL, " \t\n\r", &last)) == NULL) {		printf("Bad URL(1): %s\n", buf);		return 1;	}	printf("%d: %s %s\n", (int) pthread_self(), method, url);	rest = &url[strlen(url)];	rest++;		/*	 * Look at the method. Support just GET/POST/HEAD and CONNECT.	 */	if (strncasecmp(method, "GET",  3) == 0 ||	    strncasecmp(method, "POST", 4) == 0 ||	    strncasecmp(method, "HEAD", 4) == 0) {		/*		 * Separate the host name from the actual url.		 */		if (strncasecmp(url, "http://", 7) != 0) {			printf("Bad URL(2): %s\n", url);			return 1;		}		host = url+7;	}	else if (strncasecmp(method, "CONNECT", 7) == 0) {		printf("%d: %s\n", (int) pthread_self(), rest);		host      = url;		tunneling = 1;	}	else {		printf("%d: Bad METHOD: %s %s\n",		       (int) pthread_self(), method, url);		return 1;	}	/*	 * Extract the port and the url.	 */	bp   = host;	port = (char *) 0;	while (*bp && !(*bp == '/' || *bp == ':'))		++bp;	if (*bp == 0) {		url  = (char *) 0;	}	else {		if (*bp == ':') {

⌨️ 快捷键说明

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