NAIUI / CSAPP ProxyLab

Created Fri, 07 Jun 2024 02:40:15 -0700 Modified Fri, 07 Jun 2024 02:40:15 -0700
390 Words

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");
}

2、缓存设计