/* ************************************** * proxy.c * Xiaoyin Li * xiaoyinl@andrew * * Only part 1 is worked on - manually tested, everything works out * but I can't figure out for the life of me why this doesn't work * out when I'm running the tests. :'( * * ************************************** */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "csapp.h" #define DEFAULT_PORT 80 /* Contains the parsed HTTP request line */ typedef struct http_request_type { char* host; char* path; char* url; int port; int version; } http_request; /* Function prototypes */ int parse_request(char * req_str, http_request * req); void free_http_request(http_request* req); /* Main routine */ int main(int arc, char *argv[]) { int port=0, listenfd, connfd, serverfd, n; struct sockaddr_in serveraddr; struct http_request_type httpreq; int serverln=sizeof(serveraddr); rio_t rio, rio_server; char buf[MAXLINE]; port=atoi(argv[1]); listenfd = open_listenfd(port); while (1){ /* connect */ connfd = Accept(listenfd, (SA*)&serveraddr, &serverln); rio_readinitb(&rio, connfd); rio_readlineb(&rio, buf, MAXLINE); n=parse_request(buf, &httpreq); if (n<0){ printf("Error on parse.\n"); exit(0); } serverfd = open_clientfd(httpreq.host, 80); rio_readinitb(&rio_server, serverfd); sprintf(buf,"GET %s HTTP/1.0\r\n\r\n", httpreq.url); rio_writen(serverfd, buf, MAXLINE); while ( (n=rio_readnb(&rio_server, buf, MAXLINE))>0){ rio_writen(connfd, buf, n); } Close(connfd); Close(serverfd); } printf("Byebye from proxy.\n"); exit(0); } /* * free_http_request - Frees the http_request structure */ void free_http_request(http_request* req) { free(req->host); req->host = NULL; free(req->path); req->path = NULL; free(req->url); req->url = NULL; } /* * parse_request - Parses the first line of a browser-formatted HTTP request * * req_str - a NULL terminated string containing the HTTP request * req - the http request structure to store the parsed information * * Returns 0 on success and -1 on failure */ int parse_request(char * req_str, http_request * req) { char * url_begin, * url_end, * host_begin, * host_end, * path; printf("%s\n", req_str); /* check for valid request method*/ if (strncmp( req_str, "GET ", strlen("GET ") )) { printf("process_request: client issued an invalid request.\n"); return -1; } /* parse out url from request */ if((url_begin = strchr(req_str, ' ')) == NULL) return -1; url_begin++; if((url_end = strchr(url_begin, ' ')) == NULL) return -1; /* check for valid request version */ if (!strncmp(url_end + 1, "HTTP/1.0\r\n", strlen("HTTP/1.0\r\n"))) { req->version = 0; } else if (!strncmp(url_end + 1, "HTTP/1.1\r\n", strlen("HTTP/1.1\r\n"))) { req->version = 1; } else { printf("process_request: client issued an invalid request.\n"); return -1; } /* mallocs occur beyond this point - beware memory leaks */ /* copy request url */ req->url = strndup(url_begin, (int)(url_end - url_begin)); /* parse out host server string from original request string */ if((host_begin = strstr(req_str, "//")) == NULL) host_begin = url_begin; else host_begin += 2; host_end = strpbrk(host_begin , ":/ "); req->host = strndup(host_begin, (int)(host_end - host_begin)); /* parse out optional port */ req->port = DEFAULT_PORT; if(*host_end == ':') { req->port = atoi(host_end + 1); } /* parse out optional uri path */ if((path = strchr(host_end, '/')) != NULL && path < url_end) { req->path = strndup(path, (int)(url_end - path)); } else { req->path = strdup("/\0"); } /* check all strndup and strdup's allocated memory successfully */ if(req->url == NULL || req->host == NULL || req->port == 0 || req->path == NULL) { free_http_request(req); return -1; } return 0; }