void parse_request(request_b *rb) { int is_static; struct stat sbuf; char line[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; int is_head = 0; if (verbose) { printf("the rb->buf start and end:%zu %zu\n", rb->pos, rb->last); } getlinefrombuf(rb, line); sscanf(line, "%s %s %s", method, uri, version); if (verbose) { printf("the firstline of request\n%s", line); } if (!strcasecmp(method, "GET")) { // read_requesthdrs(rb); is_static = parse_uri(uri, filename, cgiargs); } else if (!strcasecmp(method, "HEAD")) { read_requesthdrs(rb); is_static = parse_uri(uri, filename, cgiargs); is_head = 1; } else if (!strcasecmp(method, "POST")) { parse_post_request(rb, cgiargs, uri, filename); is_static = 0; // always dynamic follow by parse_uri printf("cgiargs parameter is %s\n", cgiargs); } else { clienterror(rb->fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } if (stat(filename, &sbuf) < 0) { clienterror(rb->fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if (is_static) { /* Serve static content */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(rb->fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); return; } serve_static(rb->fd, filename, sbuf.st_size, is_head); } else { /* Serve dynamic content */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { // line:netp:doit:executable clienterror(rb->fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(rb->fd, filename, cgiargs, is_head); // line:netp:doit:servedynamic } }
/* $begin doit */ void * doit( void * fd_ptr) { int fd = * (int *)fd_ptr; printf("\nFile Desc = %d", fd); int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; /* Read request line and headers */ Rio_readinitb(&rio, fd); if (!Rio_readlineb(&rio, buf, MAXLINE)) { //line:netp:doit:readrequest { pthread_exit(NULL); return NULL; } printf("%s", buf); sscanf(buf, "%s %s %s", method, uri, version); //line:netp:doit:parserequest if (strcasecmp(method, "GET")) { //line:netp:doit:beginrequesterr clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); pthread_exit(NULL); return NULL; } //line:netp:doit:endrequesterr read_requesthdrs(&rio); //line:netp:doit:readrequesthdrs /* Parse URI from GET request */ is_static = parse_uri(uri, filename, cgiargs); //line:netp:doit:staticcheck if (stat(filename, &sbuf) < 0) { //line:netp:doit:beginnotfound clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); pthread_exit(NULL); return NULL; } //line:netp:doit:endnotfound if (is_static) { /* Serve static content */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { //line:netp:doit:readable clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); pthread_exit(NULL); return NULL; } serve_static(fd, filename, sbuf.st_size); //line:netp:doit:servestatic } else { /* Serve eynamic content */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { //line:netp:doit:executable clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); pthread_exit(NULL); return NULL; } serve_dynamic(fd, filename, cgiargs); //line:netp:doit:servedynamic } Close(fd); pthread_exit(NULL); return NULL; }
/* * doit - handle one HTTP request/response transaction */ void doit(int fd) { int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio_c, rio_h; /* Ren's Local Vars */ char host[MAXLINE], url[MAXLINE], request[MAXLINE], header[MAXLINE]; int hostfd; /* Ren's Local Vars END */ /* Read request line and headers */ Rio_readinitb(&rio_c, fd); Rio_readlineb(&rio_c, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } printf("STUFF FROM THE CLIENT:\n"); printf("%s\n",buf); read_requesthdrs(&rio_c); /* Ren's code */ parseURL(buf, host, uri, version); /* parse url for hostname and uri */ hostfd = Open_clientfd(host, PORT); /* connect to host as client */ Rio_readinitb(&rio_h, hostfd); /* set up host file discriptor */ /* generate and send request to host*/ genrequest(request, method, uri); genheader(host, header); strcat(request, header); printf("%s\n",request); Rio_writen(hostfd, request, strlen(request)); /* stream information from server to client */ printf("STUFF FROM THE SERVER:\n"); while(Rio_readlineb(&rio_h, buf, MAXLINE)){ printf("%s\n",buf); Rio_writen(fd, buf, MAXLINE); } printf("stream ended\n"); /* Ren's code */ }
void doit(int fd) { int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET"))//仅支持GET方法 { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } read_requesthdrs(&rio);//忽略任何请求报头 is_static = parse_uri(uri, filename, cgiargs);//URI解析(动态或是静态) if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if (is_static) { if(!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read this file"); return; } serve_static(fd, filename, sbuf.st_size); } else { if(!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(fd, filename, cgiargs); } }
void doit(int fd) { int clientfd, port, size = 0; ssize_t linecounter; rio_t client_rio, server_rio; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE], serveraddr[MAXLINE], path[MAXLINE], message[MAXLINE]; //read the HTTP request rio_readinitb(&client_rio, fd); rio_readlineb(&client_rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); if(strcasecmp(method, "GET") != 0) { clienterror(fd, method, "501", "Not Implemented", "Proxy does not implement this method"); return; } read_requesthdrs(&client_rio); //parse it to determine the name of the end server port = parse_uri(uri, serveraddr, path); //filter if(is_blocked_address(serveraddr)) { clienterror(fd, serveraddr, "403", "Forbidden", "Proxy does not access this server"); return; } //open a connection to the end server if((clientfd = open_clientfd(serveraddr, port)) < 0) { clienterror(fd, serveraddr, "404", "Not Found", "Proxy does not found this server"); return; } //send it the request sprintf(message, "GET %s HTTP/1.0\r\n", path); rio_writen(clientfd, message, strlen(message)); sprintf(message, "HOST: %s\r\n\r\n", serveraddr); rio_writen(clientfd, message, strlen(message)); //receive the reply, and forward the reply to the browser if the request is not blocked. rio_readinitb(&server_rio, clientfd); while((linecounter = rio_readlineb(&server_rio, message, MAXLINE)) != 0) { rio_writen(fd, message, linecounter); size += linecounter; } //log sem_wait(&mutex); log_report(serveraddr, size); sem_post(&mutex); }
/* * doit - 处理http请求 */ void doit(int fd) { int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; /* 读取请求行和报头 */ Rio_readinitb(&rio, fd); if (!Rio_readlineb(&rio, buf, MAXLINE)) return; printf("%s", buf); sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { //判断是否是GET方法 clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } read_requesthdrs(&rio); //处理报头 /* 解析uri */ is_static = parse_uri(uri, filename, cgiargs); if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if (is_static) { /* 服务静态内容 */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); return; } serve_static(fd, filename, sbuf.st_size); } else { /*服务动态内容 */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(fd, filename, cgiargs); //line:netp:doit:servedynamic } }
void doit (int fd) { bool is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; wp_rio_t *rio; rio = wp_rio_new (fd); wp_rio_readlineb (rio, buf, sizeof (buf)); sscanf (buf, "%s %s %s", method, uri, version); if (strcasecmp (method, "GET") != 0) { clienterror (fd, method, "501", "not Implemented", "Tiny does not implement this method"); return; } read_requesthdrs (rio); is_static = parse_uri (uri, filename, cgiargs); if (wp_stat(filename, &sbuf) < 0) { clienterror (fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if (is_static) { if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror (fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); return; } serve_static (fd, filename, sbuf.st_size); } else { if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror (fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic (fd, filename, cgiargs); } }
/* * doit - handle an HTTP transaction */ void doit(int connfd) { char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; int is_static; struct stat filestat; /* parse request, for Tiny Server, it's typically "GET / HTTP/1.0" */ Rio_readinitb(&rio, connfd); /* subsequent read will read from connfd */ Rio_readlineb(&rio, buf, MAXLINE); /* read first line of HTTP request */ sscanf(buf, "%s %s %s", method, uri, version); /* format */ if (strcasecmp(method, "GET")) { /* Tiny Server can only handle GET method */ clienterror(connfd, method, "501", "Not Implemented", "Tiny does not support the method "); return; } read_requesthdrs(&rio); /* parse uri, put requested file name into `filename`, and put arguments */ /* into cgiargs if any */ is_static = parse_uri(uri, filename, cgiargs); if (stat(filename, &filestat) < 0) { clienterror(connfd, filename, "404", "Not Found", "Tiny couldn't find the file "); return; } if (is_static) { /* serve static content */ if (!S_ISREG(filestat.st_mode) || !(S_IRUSR & filestat.st_mode)) { clienterror(connfd, filename, "403", "Forbidden", "Tiny couldn't read the file "); return; } serve_static(connfd, filename, filestat); } else { if (!S_ISREG(filestat.st_mode) || !(S_IXUSR & filestat.st_mode)) { clienterror(connfd, filename, "403", "Forbidden", "Tiny couldn't execute the cgi file "); return; } serve_dynamic(connfd, filename, cgiargs); } }
void doit(int fd) { int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; /* Read request line and headers. */ Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); if(strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Tiny does not suport this method yet."); return; } read_requesthdrs(&rio); /* Parse URI from GET request. */ is_static = parse_uri(uri, filename, cgiargs); if(stat(filename, &sbuf) < 0 ) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if(is_static) { /* Serve static content */ if(!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); return; } serve_static(fd, filename, sbuf.st_size); } else { /* Serve dynamic content */ if(!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(fd, filename, cgiargs); } }
void *proxy_thread(void *vargp) { int fd = *(int *)vargp; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; rio_t rio; Pthread_detach(Pthread_self()); Rio_readinitb(&rio, fd); RIO_realineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Proxy does not support this method"); return; } read_requesthdrs(&rio); }
void doit(int fd) { int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; // read request line and headers Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } Rio_writen(rio.rio_fd, "OK!\n", 4); read_requesthdrs(&rio); Rio_writen(rio.rio_fd, "OK!\n", 4); // parse uri from GET request is_static = parse_uri(uri, filename, cgiargs); if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find the file"); return; } if (is_static) { // server static content if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny could't read the file"); return; } runtimeLogFmt("arrive line : %d", __LINE__); serve_static(fd, filename, sbuf.st_size); } else { // serve dynamic content if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; serve_dynamic(fd, filename, cgiargs); } } }
void doit (int fd) { int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); // get request // e.g. GET / HTTP/1.1 if (!strcasecmp(method, "GET") || !strcasecmp(method, "HEAD")) { read_requesthdrs(&rio); int head = strcasecmp(method, "HEAD") ? 0 : 1; is_static = parse_uri(uri, filename, cgiargs); if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if (is_static) { //serve static content if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); return; } serve_static(fd, filename, sbuf.st_size, head); } else { // serve dynamic content if(!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(fd, filename, cgiargs, head); } } else if (!strcmp(method, "POST")) { read_requesthdrs(&rio); parse_uri(uri, filename, cgiargs); Rio_readlineb(&rio, cgiargs, MAXLINE); Rio_readlineb(&rio, buf, MAXLINE); if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if(!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(fd, filename, cgiargs, 0); } else { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } }
void doit(int fd) { char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char hostname[MAXLINE], path[MAXLINE], port[MAXLINE]; char host_header[MAXLINE], remaining_headers[MAXLINE]; char request[MAXLINE], server_buf[MAXLINE]; rio_t rio; rio_t server_rio; memset(buf, 0, MAXLINE); memset(method, 0, MAXLINE); memset(uri, 0, MAXLINE); memset(version, 0, MAXLINE); memset(hostname, 0, MAXLINE); memset(path, 0, MAXLINE); memset(port, 0, MAXLINE); memset(host_header, 0, MAXLINE); memset(remaining_headers, 0, MAXLINE); memset(request, 0, MAXLINE); memset(server_buf, 0, MAXLINE); /* Read request line and headers */ Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } cache_node *cache_hit = check_for_hit(proxy_cache, uri); if (cache_hit != NULL){ if(rio_writen(fd, cache_hit->data, cache_hit->data_size) < 0){ pthread_rwlock_unlock(&lock); return; } } pthread_rwlock_unlock(&lock); if (cache_hit == NULL) { char *response_data = Malloc(sizeof(char)); unsigned int data_size = 0; read_requesthdrs(&rio, host_header, remaining_headers); /* Parse URI from GET request */ if (parse_uri(uri, hostname, path, port) < 0) { return; } if (strncmp(host_header, "Host: ", strlen("Host: ")) != 0){ sprintf(host_header, "Host: %s\r\n", hostname); } // printf("%s %s %s\n", hostname, path, port); compile_request(request, host_header, path, remaining_headers); int port_num = atoi(port); int server_fd = Open_clientfd_r(hostname, port_num); if (rio_writen(server_fd, request, strlen(request)) < 0){ return; } Rio_readinitb(&server_rio, server_fd); int len; while ((len = rio_readnb(&server_rio, server_buf, MAXLINE)) > 0){ if (rio_writen(fd, server_buf, len) < 0){ return; } response_data = Realloc(response_data, data_size + len); memcpy(response_data + data_size, server_buf, len); data_size += len; } add_to_cache(proxy_cache, uri, response_data, data_size); Close(server_fd); Free(response_data); return; } }
/* $begin doit */ void *doit(void *_fd) { int fd = (int)_fd; int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; fprintf(stderr," %d\n",fd); /* Read request line and headers */ Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); //line:netp:doit:readrequest sscanf(buf, "%s %s %s", method, uri, version); //line:netp:doit:parserequest if (strcasecmp(method, "GET") && strcasecmp(method,"POST")) { //line:netp:doit:beginrequesterr clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); goto ext; } //line:netp:doit:endrequesterr read_requesthdrs(&rio); //line:netp:doit:readrequesthdrs /* Parse URI from GET request */ fprintf(stderr,"URI: %s \n",uri); fprintf(stderr,"FILENAME: %s \n",filename); is_static = parse_uri(uri, filename, cgiargs); //line:netp:doit:staticcheck if(!strcasecmp(method,"POST")){ Rio_readlineb(&rio, cgiargs, MAXLINE); cgiargs[strlen(cgiargs)-2]=0; } fprintf(stderr,"ARG: %s \n",cgiargs); fprintf(stderr,"URI: %s \n",uri); fprintf(stderr,"FILENAME: %s \n",filename); if (is_static) { /* Serve static content */ if (stat(filename, &sbuf) < 0 ) { //line:netp:doit:beginnotfound clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); goto ext; } //line:netp:doit:endnotfound if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { //line:netp:doit:readable clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); goto ext; } serve_static(fd, filename, sbuf.st_size); //line:netp:doit:servestatic } else { /* Serve dynamic content */ if (stat(filename, &sbuf) < 0 ) { //line:netp:doit:beginnotfound clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); goto ext; } //line:netp:doit:endnotfound if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { //line:netp:doit:executable clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); goto ext; } serve_dynamic(fd, filename, cgiargs); //line:netp:doit:servedynamic } ext: Close(fd); return 0; }
/* $begin proxy */ void proxy(int fd) { char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char buf_internet[MAXLINE], payload[MAX_OBJECT_SIZE]; char host[MAXLINE], path[MAXLINE]; int port, fd_internet; int found = 0; size_t n; size_t sum = 0; mio_t mio_user, mio_internet; cnode_t * node; /* Read request line and headers */ Mio_readinitb(&mio_user, fd); Mio_readlineb(&mio_user, buf, MAXLINE); printf("Request: %s\n", buf); if (strcmp(buf, "") == 0) return; sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Ming does not implement this method"); return; } read_requesthdrs(&mio_user); /* Parse URI from GET request */ if (!parse_uri(uri, host, &port, path)) { clienterror(fd, uri, "404", "Not found", "Ming couldn't parse the request"); return; } printf("uri = \"%s\"\n", uri); if (VERBOSE) { printf("host = \"%s\", ", host); printf("port = \"%d\", ", port); printf("path = \"%s\"\n", path); } if (CACHE_ENABLE) { /* Critcal readcnt section begin */ P(&mutex); readcnt++; if (readcnt == 1) // First in P(&w); V(&mutex); /* Critcal readcnt section end */ /* Critcal reading section begin */ Cache_check(); if ((node = match(host, port, path)) != NULL) { printf("Cache hit!\n"); delete(node); enqueue(node); Mio_writen(fd, node->payload, node->size); printf("Senting respond %u bytes from cache\n", (unsigned int)node->size); //fprintf(stdout, node->payload); found = 1; } /* Critcal reading section end */ /* Critcal readcnt section begin */ P(&mutex); readcnt--; if (readcnt == 0) V(&w); V(&mutex); /* Critcal readcnt section end */ if (found == 1) { printf("Proxy is exiting\n\n"); return; } printf("Cache miss!\n"); } fd_internet = Open_clientfd_r(host, port); Mio_readinitb(&mio_internet, fd_internet); /* Forward request */ sprintf(buf_internet, "GET %s HTTP/1.0\r\n", path); Mio_writen(fd_internet, buf_internet, strlen(buf_internet)); sprintf(buf_internet, "Host: %s\r\n", host); Mio_writen(fd_internet, buf_internet, strlen(buf_internet)); Mio_writen(fd_internet, user_agent_hdr, strlen(user_agent_hdr)); Mio_writen(fd_internet, accept_hdr, strlen(accept_hdr)); Mio_writen(fd_internet, accept_encoding_hdr, strlen(accept_encoding_hdr)); Mio_writen(fd_internet, connection_hdr, strlen(connection_hdr)); Mio_writen(fd_internet, pxy_connection_hdr, strlen(pxy_connection_hdr)); /* Forward respond */ strcpy(payload, ""); while ((n = Mio_readlineb(&mio_internet, buf_internet, MAXLINE)) != 0) { //printf("Fd = %d, Sum = %d, n = %d\n", mio_internet.mio_fd, sum, n); sum += n; if (sum <= MAX_OBJECT_SIZE) strcat(payload, buf_internet); Mio_writen(fd, buf_internet, n); } printf("Forward respond %d bytes\n", sum); if (CACHE_ENABLE) { if (sum <= MAX_OBJECT_SIZE) { node = new(host, port, path, payload, sum); /* Critcal write section begin */ P(&w); Cache_check(); while (cache_load + sum > MAX_CACHE_SIZE) { printf("!!!!!!!!!!!!!!!!!Cache evicted!!!!!!!!!!!!!!!!!!\n"); dequeue(); } enqueue(node); printf("The object has been cached\n"); printf("Current cache size is %d \n", cache_count); printf("Current cache load is %d bytes\n", cache_load); //fprintf(stdout, payload); Cache_check(); V(&w); /* Critcal write section end */ } }
// // name: 未知 // @param // @return // void doit(int fd) { printf("-------------------doit-----------------\n"); int is_static; struct stat sbuf; int n; char buf[MAXLINE] = {0}; char method[MAXLINE] = {0}; char uri[MAXLINE] = {0}; char version[MAXLINE] = {0}; char filename[MAXLINE] = {0}; char cgiargs[MAXLINE] = {0}; rio_t rio; rio_readinitb(&rio, fd); n = rio_readlineb(&rio, buf, MAXLINE); if(n > 0) { printf("Read [%d] bytes data from cache\n",n); } else printf("No data or Error\n"); sscanf(buf, "%s %s %s", method, uri, version); printf("Method is [%s]\nUri is [%s]\nVersion is [%s]",method,uri,version); if(strcasecmp(method, "GET") != 0) { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } /* read msg, and print*/ read_requesthdrs(&rio); is_static = parse_uri(uri, filename, cgiargs); if(stat(filename, &sbuf) < 0) { printf("Can't find %s\n",filename); clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if(is_static) { if(!(S_ISREG(sbuf.st_mode))||!(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); return; } serve_static(fd, filename, sbuf.st_size); } else { if(!(S_ISREG(sbuf.st_mode))||!(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(fd, filename, cgiargs); } }
/* * doit - handle one HTTP request/response transaction * (please refer tiny.c for this part) * * Pamameters: * fd: file descriptor */ void doit(int fd) { dbg_printf("--------In doit function--------\n"); char buf[MAXLINE]; char method[MAXLINE], url[MAXLINE], version[MAXLINE], uri[MAXLINE]; char *port; char *default_port; char hostname[MAXBUF], request2server[MAXLINE]; rio_t rio; /* set the default HTTP port, which is port 80 */ // port = malloc(sizeof(int)); port = malloc(sizeof(char)); default_port = "80"; /* receive request from client */ Rio_readinitb(&rio, fd); if (!Rio_readlineb(&rio, buf, MAXLINE)) { //read request dbg_printf("Error: cannot receive request\n"); return; } dbg_printf("Receive request from client: %s", buf); /* parse request */ sscanf(buf, "%s %s %s", method, url, version); /* check correctness of client reqeust */ checkClientRequest(fd, method, url, version); /* read request headers */ read_requesthdrs(&rio); /* Parse URI from GET request */ parse_url(url, hostname, port); dbg_printf("port after parse: %s\n", port); /* if no port specified, use "80" */ if (strcmp(port, "") == 0) { port = default_port; } strcpy(uri, url); sprintf(request2server, "%s %s %s\r\n", method, uri, version); dbg_printf("request from proxy to server: %s\n", request2server); /* generate request to server */ createReqestHeader(buf, request2server, hostname); /* check cache before send request to server */ char cache_resp[MAX_OBJECT_SIZE]; // store response from cache /* load data from cache */ if (search_data_from_cache(uri, cache_resp)) { dbg_printf("found data in cache! \n"); Rio_writen(fd, cache_resp, sizeof(cache_resp)); memset(cache_resp, 0, sizeof(cache_resp)); dbg_printf("finish response from cache!\n"); } /* no data in cache, send reqeust to server */ else { dbg_printf("No data in cache, send request to server! \n"); /* forward request to server */ forwardRequest2Server(fd, request2server, hostname, url, port); } dbg_printf("--------In doit function END--------\n"); }
void mainloop(){ rio_t rp_client, rp_server; int hostport; char hostname[MAXLINE], pathname[MAXLINE]; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; while (1) { char buffer[MAX_UINT]; while (queue->isEmpty()) { sleep(1); continue; } clientsock = queue->Pop(); if(clientsock == -1){ //printf("Fake Client sockID:%d \n", clientsock); continue; } //printf("Get Client sockID:%d \n", clientsock); // Init read structure for client-proxy connection Rio_readinitb(&rp_client, clientsock); // Parse the HTTP request read_requesthdrs(&rp_client, method, uri, version); // Parse the URI of the request parse_uri(uri, hostname, pathname, &hostport); //printf("%s %s %d\n", hostname, pathname, hostport); /***** If method is GET *****/ if (strcmp(method, "GET")!=0) { char buf2[] = "500 'Internal Error' \r\n"; Rio_writenb_w(clientsock, buf2, strlen(buf2)); //printf("It is not GET method:%s socket:%d \n", method, clientsock); Rio_close(clientsock); continue; } #ifdef WITH_CACHE //find url in cache and return [FIXME] if(pmap->find(uri)!=pmap->end()){ //not found the topic proxy_cache *pcache = (*pmap)[uri]; for (int i =0; i<pcache->size; i++) { Rio_writen_w(clientsock, pcache->buf[i], strlen(pcache->buf[i])); } Rio_close(clientsock); continue; } // Make cache entry [FIXME] proxy_cache *pcache = new proxy_cache(); std::string urlstr = *new std::string(uri); std::pair<std::string, proxy_cache *> newpair(urlstr,pcache); pmap->insert(newpair); #endif // Open connection to requested web server char strport[10]={0}; sprintf(strport, "%d",hostport); proxysock = open_targetfd(hostname, strport); if (proxysock < 0) { char buf2[] = "500 'Internal Error' \r\n"; Rio_writenb_w(clientsock, buf2, strlen(buf2)); Rio_close(clientsock); continue; } // Init read struct for proxy-webserver connection Rio_readinitb(&rp_server, proxysock); sprintf(buf, "%s %s %s\r\n", method, pathname, "HTTP/1.0"); Rio_writenb_w(proxysock, buf, strlen(buf)); //printf("%s", buf); sprintf(buf, "Host: %s\r\n", hostname); Rio_writenb_w(proxysock, buf, strlen(buf)); //printf("%s", buf); // Read from client request // and write to web server while(strcmp(buf, "\r\n")) { Rio_readlineb_w(&rp_client, buf, MAXLINE); if (!strcmp(buf, "\r\n")) { char buf2[] = "Connection: close\r\n"; Rio_writenb_w(proxysock, buf2, strlen(buf2)); //printf("%s", buf2); } if (!strncmp(buf, "Connection: keep-alive", 22) || !strncmp(buf, "Host:", 5)) { //printf("%s", buf); continue; } Rio_writenb_w(proxysock, buf, strlen(buf)); //printf("%s", buf); } // Read the respons from webserver and // forward it to the requesting client ssize_t n = 0; while ((n = Rio_readnb_w(proxysock, buffer, MAX_UINT)) > 0) { #ifdef WITH_CACHE char *cache = (char*)malloc(sizeof(char)*(n+1)); if(cache == NULL){ perror("Alloc memory failed, cache emited"); } memset(cache, 0, n+1); strncpy(cache,buffer,n); #endif Rio_writenb_w(clientsock, buffer, n); } Rio_close(clientsock); Rio_close(proxysock); } }
/** * Handles HTTP Requests that are sent from the client. * * Heavily based on the Tiny Server Implementation. */ void *service(void *conn) { //Make sure we deallocate our file descriptor int fd = *((int *) conn); char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; Rio_readinitb(&rio, fd); if (Rio_readlineb(&rio, buf, MAXLINE) <= 0) { close(fd); return NULL; } sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "METHOD NOT ALLOWED", "METHOD NOW ALLOWED"); close(fd); return NULL; } read_requesthdrs(&rio); parse_uri(uri, filename, cgiargs); char json[MAXLINE]; if (strstr(uri, "junk") != NULL) { clienterror(fd, method, "404", "NOT FOUND", version); close(fd); return NULL; } else if (strstr(uri, "/runloop") != NULL) { sendResponse(fd, "Started 15 second spin.", "text/html", version, strlen("Started 15 second spin.")); time_t curTime = time(NULL); time_t endTime = curTime; while ((endTime - curTime) < 15) { endTime = time(NULL); } } else if (strstr(uri, "/allocanon") != NULL) { if (allocatedCount > MAX_ALLOC_ALLOWED) { sendResponse(fd, "Reached maximum of 3 blocks, request denied.", "text/html", version, strlen("Reached maximum of 6 blocks, request denied.")); close(fd); return NULL; } else { char *block = mmap(0, 256000000, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (block == MAP_FAILED) printf("Error occured during mmap call\n"); memset(block, '0', 256000000); allocatedBlocks[allocatedCount] = block; allocatedCount++; char msg[512]; sprintf(msg, "Mapped and touched 256MB anonymous memory, now have %d blocks allocated in total.", allocatedCount); sendResponse(fd, msg, "text/html", version, strlen(msg)); } } else if (strstr(uri, "/freeanon") != NULL) { if (allocatedCount == 0) { sendResponse(fd, "No blocks allocated.", "text/html", version, strlen("No blocks allocated.")); close(fd); return NULL; } else { allocatedCount--; if (munmap(allocatedBlocks[allocatedCount], 256000000) != 0) printf("Error occured during munmap call\n"); char msg[512]; sprintf(msg, "Unmapped 256MB, %d blocks left.", allocatedCount); sendResponse(fd, msg, "text/html", version, strlen(msg)); } } else if (strstr(uri, "/loadavg") != NULL || strstr(uri, "/loadavg?callback=") != NULL || (strstr(uri, "/loadavg?") != NULL && strstr(uri, "&callback=") != NULL)) { FILE *file = fopen("/proc/loadavg", "r"); if (file != NULL) { char loadAvgString[512]; fgets(loadAvgString, sizeof(loadAvgString), file); fclose(file); char a1[20], a2[20], a3[20], numThreads[20]; char *runThreads, *totalThreads; sscanf(loadAvgString, "%s %s %s %s", a1, a2, a3, numThreads); runThreads = strtok(numThreads, "/"); totalThreads = strtok(NULL, " "); strcat(json, "{\"total_threads\": \""); strcat(json, totalThreads); strcat(json, "\", \"loadavg\": [\""); strcat(json, a1); strcat(json, "\", \""); strcat(json, a2); strcat(json, "\", \""); strcat(json, a3); strcat(json, "\"], \""); strcat(json, "running_threads\": \""); strcat(json, runThreads); strcat(json, "\"}"); } char *callback; if (strstr(uri, "/loadavg?callback=") != NULL) callback = strstr(uri, "?callback="); else callback = strstr(uri, "&callback="); // char *callback = strstr(uri, "?callback="); if (callback != NULL) { callback += 10; char *string = strtok(callback, "& "); char function[512]; function[0] = '\0'; strcat(function, string); strcat(function, "("); strcat(function, json); strcat(function, ")"); sendResponse(fd, function, "application/javascript", version, strlen(function)); } else { sendResponse(fd, json, "application/json", version, strlen(json)); } } else if (strstr(uri, "/meminfo") != NULL || strstr(uri, "/meminfo?callback=") != NULL || (strstr(uri, "/meminfo?") != NULL && strstr(uri, "&callback=") != NULL)) { FILE *file = fopen("/proc/meminfo", "r"); strcat(json, "{"); if (file != NULL) { char line[512]; while (fgets(line, sizeof(line), file) != NULL) { char name[20]; char size[20]; sscanf(line, "%s %s", name, size); name[strlen(name) - 1] = '\0'; //printf("%s: %s\n", name, size); strcat(json, "\""); strcat(json, name); strcat(json, "\": \""); strcat(json, size); strcat(json, "\", "); } json[strlen(json) - 2] = '\0'; fclose(file); strcat(json, "}"); } char *callback; if (strstr(uri, "/meminfo?callback=") != NULL) callback = strstr(uri, "?callback="); else callback = strstr(uri, "&callback="); if (callback != NULL) { callback += 10; char *string = strtok(callback, "& "); char function[512]; function[0] = '\0'; strcat(function, string); strcat(function, "("); strcat(function, json); strcat(function, ")"); sendResponse(fd, function, "application/javascript", version, strlen(function)); } else { sendResponse(fd, json, "application/json", version, strlen(json)); } } //Provides all of the necessary functions for file serving else { if (strstr(filename, "..") != NULL) { clienterror(fd, method, "403", "Forbidden", "File pathname not allowed"); return NULL; } char *type; if (strstr(filename, ".html") != NULL || strstr(filename, ".htm") != NULL) type = "text/html"; else if (strstr(filename, ".gif") != NULL) type = "image/gif"; else if (strstr(filename, ".jpg") != NULL) type = "image/jpeg"; else if (strstr(filename, ".js") != NULL) type = "application/javascript"; else if (strstr(filename, ".css") != NULL) type = "text/css"; else type = "text/plain"; printf("\n%s\n", filename); FILE *file = fopen(filename, "r"); if (file == NULL) { clienterror(fd, method, "404", "NOT FOUND", "File Not Found"); return NULL; } fseek(file, 0, SEEK_END); int length = ftell(file); fseek(file, 0, SEEK_SET); char *data = (char *) malloc(length); fread(data, length, 1, file); printf("\n%s\n", data); sendResponse(fd, data, type, version, length); } close(fd); pthread_exit(NULL); //return NULL; }
/* * handle_request - handle one HTTP request from client and * make request for actual server. It will wait for response * and forward response back to client. */ void handle_request(int clientfd) { char buf[MAXLINE], method[MAXLINE], url[MAXLINE]; char hostname[MAXLINE], uri[MAXLINE], version[MAXLINE]; rio_t rio; char port[] = "80"; /* http request use port 80 */ /* Read request line and headers */ Rio_readinitb(&rio, clientfd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, url, version); if (strcasecmp(method, "GET")) { clienterror(clientfd, method, "501", "Not Implemented", "Proxy does not implement this method"); return; } parse_url(url, hostname, uri); /* connect to host server by hostname */ int serverfd; if ((serverfd = open_clientfd(hostname, port)) < 0) { pthread_mutex_lock(&print_lock); printf("Open_clientfd error\n"); pthread_mutex_unlock(&print_lock); return; } /* construct a new request line */ char requestLine[MAXLINE]; strcpy(requestLine, method); strcat(requestLine, uri); strcat(requestLine, "HTTP/1.0"); rio_readinitb(&rio, serverfd); rio_writen(serverfd, buf, strlen(buf)); /* send request line to server */ /* read and send request header to server */ char requesthrds[MAXLINE]; cat_requesthdrs(requesthrds, hostname); rio_writen(serverfd, requesthrds, strlen(requesthrds)); //rio_readlineb(&rio, buf, MAXLINE); //rio_writen(serverfd, buf, strlen(buf)); //while(strcmp(buf, "\r\n")) //{ // rio_readlineb(&rio, buf, MAXLINE); // rio_writen(serverfd, buf, strlen(buf)); //} char emptyline[] = "\r\n"; rio_writen(serverfd, emptyline, strlen(emptyline)); /* get response from server and send it back to client */ rio_writen(clientfd, emptyline, strlen(emptyline)); read_requesthdrs(&rio); size_t n; while ((n = rio_readlineb(&rio, buf, MAXLINE)) != 0) rio_writen(clientfd, buf, strlen(buf)); /* close connection to server */ int rc; if ((rc = close(serverfd)) < 0) { pthread_mutex_lock(&print_lock); printf("Close error\n"); pthread_mutex_unlock(&print_lock); } pthread_mutex_lock(&print_lock); printf("Connection to server closed.\n"); pthread_mutex_unlock(&print_lock); }