CSAPP ProxyLab
1、代理服务器和并发
#include "csapp.h"
#include <stdio.h>
/* Recommended max cache and object sizes */
#define MAX_CACHE_SIZE 1049000
#define MAX_OBJECT_SIZE 102400
void *thread(void *vargp);
static void doit(int connfd);
static void parse_uri(char *uri, char *hostname, char *port, char *filepath);
static void build_request_header(rio_t *rp, char *reqhd, char *hostname);
/* You won't lose style points for including this long line in your code */
static const char *user_agent_hdr = "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3) Gecko/20120305 Firefox/10.0.3\r\n";
int main(int argc, char *argv[])
{
// printf("%s", user_agent_hdr);
if (argc != 2) {
printf("usage: %s <port>\n", argv[0]);
exit(0);
}
int listenfd, *connfd;
char hostname[MAXLINE], port[MAXLINE];
socklen_t clientlen;
struct sockaddr_storage clientaddr;
pthread_t tid;
Signal(SIGPIPE,SIG_IGN);
listenfd = Open_listenfd(argv[1]);
while (1) {
clientlen = sizeof(struct sockaddr_storage);
connfd = Malloc(sizeof(int));
*connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
//doit(*connfd);
//Close(*connfd);
//Getnameinfo((SA *) &clientaddr, clientlen, hostname, MAXLINE, port, MAXLINE, 0);
Pthread_create(&tid, NULL, thread, connfd);
}
return 0;
}
void *thread(void *vargp)
{
int connfd = *((int *)vargp);
Pthread_detach(pthread_self());
Free(vargp);
doit(connfd);
Close(connfd);
return NULL;
}
static void doit(int fd)
{
rio_t rio_server;
rio_t rio_client;
char buf[MAXLINE];
char method[MAXLINE], uri[MAXLINE], version[MAXLINE];
char hostname[MAXLINE], filepath[MAXLINE], server_port[MAXLINE];
int clientfd;
char reqhd[MAXLINE];
Rio_readinitb(&rio_server, fd);
if (!rio_readlineb(&rio_server, buf, MAXLINE))
{
return;
}
sscanf(buf, "%s %s %s", method, uri, version);
if (strcasecmp(method, "GET")) { // only deal with "GET"
return ;
}
if (!strcmp(version, "HTTP/1.1")) strcpy(version, "HTTP/1.0");
parse_uri(uri, hostname, server_port, filepath);
sprintf(uri, "%s %s %s\r\n", method, filepath, version);
clientfd = open_clientfd(hostname, server_port);
Rio_readinitb(&rio_client, clientfd);
strcpy(reqhd, uri);
build_request_header(&rio_server, reqhd, hostname);
Rio_writen(clientfd, reqhd, strlen(reqhd));
ssize_t n;
while ( (n = Rio_readlineb(&rio_client, buf, MAXLINE))) {
Rio_writen(fd, buf, n);
}
Close(clientfd);
}
static void parse_uri(char *uri, char *hostname, char *port, char *filepath)
{
char *ptr1, *ptr2;
uri += 7; // HTTP://
ptr1 = index(uri, ':'); //default port is 80
*ptr1 = '\0';
ptr1++;
strcpy(hostname, uri);
ptr2 = index(ptr1, '/');
*ptr2 = '\0';
strcpy(port, ptr1);
strcpy(filepath, "/");
strcat(filepath, ptr2+1);
}
static void build_request_header(rio_t *rp, char *reqhd, char *hostname)
{
char buf[MAXLINE];
while (rio_readlineb(rp, buf, MAXLINE) > 0) {
if (!strcmp(buf, "\r\n")) break;
if (strstr(buf, "Host:") != NULL) continue;
if (strstr(buf, "User-Agent:") != NULL) continue;
if (strstr(buf, "Connection:") != NULL) continue;
if (strstr(buf, "Proxy-Connection:") != NULL) continue;
strcat(reqhd, buf);
}
sprintf(buf, "Host: %s\r\n", hostname);
strcat(reqhd, buf);
sprintf(buf, "User-Agent: %s", user_agent_hdr);
strcat(reqhd, buf);
strcat(reqhd, "Connection: false\r\n");
strcat(reqhd, "Proxy-Connection: false\r\n");
strcat(reqhd, "\r\n");
}