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; }
/* $begin ServeClient */ void ServeClient(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; cgiargs[0] = 0; /* 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") == 0 ) { is_static = parse_uri(uri, filename, cgiargs); } else if ( strcasecmp(method, "POST") == 0 ) { is_static = parse_uri(uri, filename, cgiargs); } else { clienterror(fd, method, "501", "Not Implemented", "Server does not implement this method"); return; } 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, &rio); } }
/* parse_request_h is a error handling version of parse_request */ void parse_request_h(struct client_request *request, int clientfd) { int ret; ret = parse_request(request, clientfd); if (ret == 0) return; if (ret == -1) clienterror(clientfd, "URI", "400", "Bad request", "Request could not be understood by proxy"); if (ret == -2) clienterror(clientfd, "method", "501", "Not Implemented", "Proxy does not implement this method"); close_connection(request, clientfd, -1); }
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); }
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 - 处理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 } }
/* * 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 HttpSession::Handler(){ int is_static; struct stat sbuf; char buf[MAXLINE]; char method[MAXLINE],uri[MAXLINE],version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; //以上都可作为类私有成员,但觉得作用不大 rio.rio_readlineb(buf,MAXLINE); sscanf(buf,"%s %s %s",method,uri,version); if(strcasecmp(method,"GET")){ clienterror(fd,method,"501","Not Implement", "Server doesn't implement this method"); read_requestdrs(); } is_static = parse_uri(uri,filename,cgiargs); if(stat(filename,&sbuf)<0){ clienterror(fd,filename,"404","Not found", "Server 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", "server couldn't read the filem"); return; } server_static(fd,filename,sbuf.st_size); } else{ if(!(S_ISREG(sbuf.st_mode))||(!S_IRUSR& sbuf.st_mode)){ clienterror(fd,filename,"403","Forbidden", "Server couldn't run the program"); return; } //server_dynamic(); //调用动态内容 } }
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) { rio_t rio; Rio_readinitb(&rio, fd); char *request = read_request(&rio); if (request == NULL) return; write_to_file(request); char method[MAXLINE], uri[MAXLINE], version[MAXLINE]; sscanf(request, "%s %s %s", method, uri, version); free(request); if (strcasecmp(method, "GET") && strcasecmp(method, "HEAD")) { clienterror(fd, method, "501", "Not implemented", "Tiny does not implement this method"); return; } char filename[MAXLINE], cgiargs[MAXLINE]; int is_static = parse_uri(uri, filename, cgiargs); struct stat sbuf; if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't read the 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 filetype"); return; } serve_static(fd, filename, sbuf.st_size, method); } 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, method); } }
/* * 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 */ }
/* * checkClientRequest - check the correctness of request from client * * Pamameters: * fd: file descriptor * method: GET method * url: parsed url * version: HTTP/1.0 * */ void checkClientRequest(int fd, char *method, char *url, char *version) { /* check request method, only accept GET method for now */ if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Proxy does not implement this method"); return; } /* check reqeust url */ char url_prefix[7]; // using for checking "http://" strncpy(url_prefix, url, 7); if (strcasecmp(url_prefix, "http://")) { clienterror(fd, url, "400", "Bad Request", "Proxy cannot understand this url"); return; } /* check request version, should use "HTTP/1.0" */ if (strcasecmp(version, "HTTP/1.0")) { dbg_printf("Attention: only accept HTTP/1.0, change to HTTP/1.0\n"); strcpy(version, "HTTP/1.0"); } }
/* open_serverfd_h is a wrapper for open_clientfd and handles errors. */ int open_serverfd_h(struct client_request *request, int clientfd) { int serverfd; serverfd = open_clientfd(request->host, request->server_port); if (serverfd >= 0) return serverfd; if (serverfd == -1) /* socket_error */ close_connection(request, clientfd, -1); if (serverfd == -2) /* DNS error */ clienterror(clientfd, "http address", "404", "Not found", "Proxy could not find server"); close_connection(request, clientfd, -1); abort(); /* flow should never reach here */ }
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); }
/* * handle_request - handle one HTTP request/response transaction */ void handle_request(int fd) { struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char headers[MAXBUF]; char request[MAXLINE], hostname[MAXLINE], arguments[MAXLINE], port[MAXLINE]; int serverfd; rio_t rio_client; rio_t rio_server; /* Read request line and headers */ Rio_readinitb(&rio_client, fd); if (!Rio_readlineb(&rio_client, buf, MAXLINE)) return; printf("%s", buf); sscanf(buf, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Proxy does not implement this method"); return; } process_uri(uri, hostname, arguments, port); process_hdrs(&rio_client, headers, hostname); printf("%s\n", request); printf("%s\n", headers); sprintf(request, "GET %s HTTP/1.0 \r\n", arguments); /* send request to server */ serverfd = Open_clientfd(hostname, port); Rio_writen(serverfd, request, strlen(request)); Rio_writen(serverfd, headers, strlen(headers)); /* answer to client */ Rio_readinitb(&rio_server, serverfd); process_answer(&rio_server, fd); }
/* $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; }
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; } }
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, put them into a file */ char *request = NULL; Rio_readinitb(&rio, fd); for (;;) { Rio_readlineb(&rio, buf, MAXLINE); /* * Firefox will sent \x16\x3. * \x16: Synchronous Idle, \x3: End of Text */ if (!strncmp(buf, "\x16\x3", 2)) { free(request); return; } int buflen = strlen(buf); char *old_request = request; int old_reqlen = old_request==NULL ? 0 : strlen(old_request); request = realloc(old_request, buflen + old_reqlen + 1); if (request == NULL) { fprintf(stderr, "realloc: run out of memory\n"); free(old_request); return; } memmove(request+old_reqlen, buf, buflen+1); if (!strcmp(buf, "\r\n")) /* Copy before stop */ break; } sscanf(request, "%s %s %s", method, uri, version); if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not implemented", "Tiny does not implement this method"); return; } FILE *out = fopen("tiny-request.txt", "w+"); if (out == NULL) { perror("fopen"); free(request); return; } fprintf(out, "%s", request); fflush(out); fclose(out); free(request); /* 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 read the 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 filetype"); 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 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; } }
/* $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 */ } }
/** * 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; }
int main(int argc, char **argv) { int listenfd,connfd, port,clientlen; pid_t pid; struct sockaddr_in clientaddr; char isdaemon=0,*portp=NULL,*logp=NULL,tmpcwd[MAXLINE]; #ifdef HTTPS int sslport; char dossl=0,*sslportp=NULL; #endif openlog(argv[0],LOG_NDELAY|LOG_PID,LOG_DAEMON); cwd=(char*)get_current_dir_name(); strcpy(tmpcwd,cwd); strcat(tmpcwd,"/"); /* parse argv */ #ifdef HTTPS parse_option(argc,argv,&isdaemon,&portp,&logp,&sslportp,&dossl); sslportp==NULL ?(sslport=atoi(Getconfig("https"))) : (sslport=atoi(sslportp)); if(dossl==1||strcmp(Getconfig("dossl"),"yes")==0) dossl=1; #else parse_option(argc,argv,&isdaemon,&portp,&logp); #endif portp==NULL ?(port=atoi(Getconfig("http"))) : (port=atoi(portp)); Signal(SIGCHLD,sigChldHandler); /* init log */ if(logp==NULL) logp=Getconfig("log"); initlog(strcat(tmpcwd,logp)); /* whethe show dir */ if(strcmp(Getconfig("dir"),"no")==0) isShowdir=0; clientlen = sizeof(clientaddr); if(isdaemon==1||strcmp(Getconfig("daemon"),"yes")==0) Daemon(1,1); writePid(1); /* $https start */ #ifdef HTTPS if(dossl) { if((pid=Fork())==0) { listenfd= Open_listenfd(sslport); ssl_init(); while(1) { connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); if(access_ornot(inet_ntoa(clientaddr.sin_addr))==0) { clienterror(connfd,"maybe this web server not open to you!" , "403", "Forbidden", "Tiny couldn't read the file"); continue; } if((pid=Fork())>0) { Close(connfd); continue; } else if(pid==0) { ishttps=1; doit(connfd); exit(1); } } } } #endif /* $end https */ listenfd = Open_listenfd(port); while (1) { connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); if(access_ornot(inet_ntoa(clientaddr.sin_addr))==0) { clienterror(connfd,"maybe this web server not open to you!" , "403", "Forbidden", "Tiny couldn't read the file"); continue; } if((pid=Fork())>0) { Close(connfd); continue; } else if(pid==0) { doit(connfd); exit(1); } } }
//************************************************* void *handle_http(void *arg) { http_request_t *request = (http_request_t *)arg; int fd = request->fd; int rcode = 0; int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[SHORTLINE], header_key[MAXLINE], header_value[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; int n; /* Read request line and headers */ while (1) { printf("[INFO] read from fd %d\n", fd); n = read(fd, request->last, (uint64_t)request->buf + MAX_BUF - (uint64_t)request->last); printf("[INFO] n = %d\n", n); if (n == 0) { goto err; } if (n < 0) { if (errno != EAGAIN) { log_err("read error, errno = %d", errno); goto err; } break; } request->last += n; rcode = http_parse_request_line(request); if (rcode == SERVER_AGAIN) { continue; } else if (rcode != SERVER_OK) { log_err("parse request line error, rcode = %d", rcode); goto err; } strncpy(method, request->request_start, request->method_end - request->request_start); strncpy(uri, request->uri_start, request->uri_end - request->uri_start); sprintf(version, "%d.%d", request->http_major, request->http_minor); if (request->method != HTTP_GET) { debug("error method: %s\n", method); debug("error uri: %s\n", uri); debug("error version: %s\n", version); clienterror(fd, method, "501", "Not Implemented", "Server does not implement this method"); return NULL; } debug("http request line"); debug("method = %s", method); debug("uri = %s", uri); debug("version = %s", version); rcode = http_parse_request_body(request); if (rcode == SERVER_AGAIN) { continue; } else if (rcode != SERVER_OK) { log_err("parse request body error, rcode = %d", rcode); goto err; } debug("number of headers = %d", request->num_headers); if (request->num_headers > 0) { list_node_t *head = request->head->next; int i; for (i = 0; i < request->num_headers; i++) { http_header_t *header = (http_header_t *)head->ptr; memset(header_key, 0, sizeof(header_key)); memset(header_value, 0, sizeof(header_value)); memcpy(header_key, header->key_start, header->key_end - header->key_start); memcpy(header_value, header->value_start, header->value_end - header->value_start); debug("%s: %s", header_key, header_value); head = head->next; } } is_static = parse_uri(uri, filename, cgiargs); if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Server couldn't find this file"); continue; } if (is_static) { if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Server couldn't read the file"); continue; } serve_static(fd, filename, sbuf.st_size); } goto close; } return NULL; err: close: debug("closing fd %d", fd); close(fd); }
/* $begin doit */ void doit(int fd) { int is_static,contentLength=0,isGet=1; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE],httpspostdata[MAXLINE]; rio_t rio; memset(buf,0,MAXLINE); if(ishttps) { ssl=SSL_new(ssl_ctx); SSL_set_fd(ssl,fd); if(SSL_accept(ssl)==0) { ERR_print_errors_fp(stderr); exit(1); } SSL_read(ssl,buf,sizeof(buf)); printf(".............\n"); printf("%s",buf); printf(".............\n"); } else { /* 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")!=0&&strcasecmp(method,"POST")!=0) { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } */ /* Parse URI from GET request */ is_static = parse_uri(uri, filename, cgiargs); if (lstat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if(S_ISDIR(sbuf.st_mode)&&isShowdir) serve_dir(fd,filename); if (strcasecmp(method, "POST")==0) isGet=0; if (is_static) { /* Serve static content */ if(!ishttps) get_requesthdrs(&rio); /* because https already read the headers -> SSL_read() */ 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; } if(isGet) { if(!ishttps) get_requesthdrs(&rio); /* because https already read headers by SSL_read() */ get_dynamic(fd, filename, cgiargs); } else { printf("ishttps:%d\n",ishttps); if(ishttps) https_getlength(buf,&contentLength); else post_requesthdrs(&rio,&contentLength); post_dynamic(fd, filename,contentLength,&rio); } } }
int main(int argc, char **argv) { int listenfd, connfd, port, clientlen; pid_t pid; struct sockaddr_in clientaddr; char daemon=0,*portp=NULL,*logp=NULL,tmpcwd[MAXLINE]; cwd=(char*)get_current_dir_name(); strcpy(tmpcwd,cwd); strcat(tmpcwd,"/"); /* parse argv */ parse_option(argc,argv,&daemon,&portp,&logp); portp==NULL ?(port=atoi(getconfig("port"))) : (port=atoi(portp)); /* init log */ if(logp==NULL) logp=getconfig("log"); initlog(strcat(tmpcwd,logp)); /* whethe show dir */ if(strcmp(getconfig("dir"),"no")==0) isShowdir=0; if(daemon==1||strcmp(getconfig("daemon"),"yes")==0) init_daemon(); listenfd = Open_listenfd(port); /* $https start */ if((pid=Fork())==0) { listenfd= Open_listenfd(4444); ssl_init(); while(1) { clientlen = sizeof(clientaddr); connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); if(access_ornot(inet_ntoa(clientaddr.sin_addr))==0) { clienterror(connfd,"maybe this web server not open to you!" , "403", "Forbidden", "Tiny couldn't read the file"); continue; } if((pid=Fork())>0) { close(connfd); continue; } else if(pid==0) { ishttps=1; doit(connfd); } } } /* $end https */ while (1) { clientlen = sizeof(clientaddr); connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); if(access_ornot(inet_ntoa(clientaddr.sin_addr))==0) { clienterror(connfd,"maybe this web server not open to you!" , "403", "Forbidden", "Tiny couldn't read the file"); continue; } if((pid=Fork())>0) { close(connfd); continue; } else if(pid==0) { doit(connfd); } } }
void doit(int fd) { printf("doit %d\n",fd); char buf[MAX_OBJECT_SIZE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char hostname[MAXLINE]; char path[MAXLINE]="\0"; int req_port=0; char host[MAXLINE]; int serverfd,serverlen; struct sockaddr_in serveraddr; rio_t rio; int err=0; char reqhdr[MAX_OBJECT_SIZE]; //cache char cache_buf[MAX_OBJECT_SIZE]; ssize_t size; size=0; cache_node *cache_hit=NULL; /* Read request line and headers */ Rio_readinitb(&rio, fd); if ((err=rio_readlineb(&rio, buf, MAX_OBJECT_SIZE))<0){ clienterror(fd,"get wrong","400","bad request","bad get"); return; } sscanf(buf, "%s %s %s", method, uri, version); printf("get[%s]",buf); if (strcmp(buf,"\0")==0){ clienterror(fd,"get 0","400","Bad Request","invalid request"); return; } if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Proxy does not implement this method"); return; } //parse uri if (parse_uri(uri,host,hostname,path,&req_port)<0){ clienterror(fd,uri,"400","Bad Request","invalid request"); return; } printf("uri %s %s %s %s %d\n",uri,host,hostname,path,req_port); cache_hit=find_fit(cache_head,uri); if (cache_hit!=NULL){ //cache hit if (cache_to_client(fd,cache_head,cache_hit)<0){ clienterror(fd,"cache","505","read cache error","cache error");} return; } // not hit // establish connection with the web server serverlen=sizeof(serveraddr); serverfd=open_clientfd_r(hostname,req_port); printf("server %d\n",serverfd); if (serverfd<=0){ clienterror(fd,"serverfd","400","bad request","connection error"); return; } //built http request to the server sprintf(reqhdr,"GET %s HTTP/1.0\r\n",path); strcat(reqhdr,"Host: "); strcat(reqhdr,host); strcat(reqhdr,"\r\n"); strcat(reqhdr,user_agent_hdr); strcat(reqhdr,accept_hdr); strcat(reqhdr,accept_encoding_hdr); //send addtional header parse_requesthdrs(&rio,reqhdr); Rio_writen(serverfd,reqhdr,strlen(reqhdr)); //read from server rio_t server_rio; Rio_readinitb(&server_rio,serverfd); char read_server[MAX_OBJECT_SIZE]; ssize_t length = 0; cache_node *new_node = NULL; while((length=Rio_readnb(&server_rio,read_server,MAX_OBJECT_SIZE))>0){ printf("length%lu\n",length); //printf("%s",read_server); //forward to the client Rio_writen(fd,read_server,length); size+=length; if (size<=MAX_OBJECT_SIZE){ sprintf(cache_buf,"%s",read_server); } } printf("buf size%lu\n",size); //Rio_writen(fd,read_server,MAXLINE); if (size<=MAX_OBJECT_SIZE){ new_node=build_node(uri,size,cache_buf); printf("new node%p %lu\n",new_node,new_node->size); server_to_cache(cache_head,new_node); } Close(serverfd); return; }
/* * * doit - handle one HTTP request/response transaction * */ void* doit(void* pt1) { //signal(SIGPIPE, SIG_IGN); pt_helper* pt = (pt_helper*)pt1; int fd = pt->connfd; int serverFile, amountRead; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE], request[MAXLINE]; char *host, *website, *filename; int port; rio_t rio, tmprio; counter++; website = uri; /* Read request line and headers */ Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); //some error checking. if(strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "FoxyProxy does not implement this method"); Close(pt->connfd); free(pt); return NULL; } port = parse_website(&website,&filename,&host); int n; int found=0; for(n = 0; n < CACHEL; n++) { if(names[n] != NULL){ // printf("blah blah %s\n",names[n]); // printf("foo foo %s\n",website); } if(names[n] != NULL && !strcmp(website, names[n])) { found = 1; break; } } if(found) { P(&mut); readLock++; if(readLock == 1) { P(&writeLock); } V(&mut); times[n] = counter;//time(NULL); rio_writen(fd, pages[n], sizes[n]); //close(serverFile); printf("cached!\n"); P(&mut); readLock--; if(readLock == 0) { V(&writeLock); } V(&mut); Close(pt->connfd); free(pt); return NULL; } serverFile = open_clientfd(host, port); //add in request print stuff here strcpy(request, method); strcat(request, " "); strcat(request, filename); strcat(request, " HTTP/1.0\r\n"); strcat(request, HTTPHDR); rio_writen(serverFile, request, strlen(request)); //XXX //printf(request); send_requesthdrs(&rio, serverFile, host); rio_readinitb(&tmprio, serverFile); char* buf2 = (char*)malloc(MAX_OBJECT_SIZE); int totalRead = 0; while ( (amountRead = rio_readnb(&tmprio, buf, MAXBUF)) > 0 ) { rio_writen(fd, buf, amountRead); if(totalRead+amountRead <= MAX_OBJECT_SIZE) { memcpy(buf2+totalRead,buf,amountRead); } totalRead+=amountRead; } amountRead = totalRead; //TODO lock cache //FIXME how to delete enough stuff? if(amountRead <= MAX_OBJECT_SIZE) { // printf("Lock: %d\n", writeLock); P(&writeLock); // printf("Lock2: %d\n", writeLock); if(amountRead + cachesize <= MAX_CACHE_SIZE) { time_t lowtime = counter;//time(NULL); int leastrecent = -1; int n; for(n = 0; n < CACHEL; n++) { if(times[n] < lowtime) { leastrecent = n; lowtime = times[n]; } if(pages[n] == NULL) { leastrecent = n; break; } } n = leastrecent; if(pages[n] != NULL) { free(pages[n]); pages[n] = NULL; free(names[n]); names[n] = NULL; } void* page = (void*)malloc(amountRead); memcpy(page, buf2, amountRead); printf("page: \n"); printf("%s",page); char* website_cpy = (char*)malloc(strlen(website)+1); strncpy(website_cpy,website,strlen(website)); website_cpy[strlen(website)]='\0'; pages[n] = page; times[n] = counter;//time(NULL); cachesize-=sizes[n]; sizes[n] = amountRead; cachesize+=amountRead; names[n] = website_cpy; } else { while(cachesize + amountRead > MAX_CACHE_SIZE) { time_t lowtime = counter;//time(NULL); int leastrecent = -1; int n; for(n = 0; n < CACHEL; n++) { if(times[n] < lowtime && pages[n] != NULL) { leastrecent = n; lowtime = times[n]; } } n = leastrecent; free(pages[n]); pages[n] = NULL; free(names[n]); names[n] = NULL; cachesize -= sizes[n]; sizes[n] = 0; times[n] = 0; } int n; for(n = 0; n < CACHEL; n++) { if(pages[n] == NULL) break; } void* page = (void*)malloc(amountRead); memcpy(page, buf2, amountRead); pages[n] = page; char* website_cpy = (char*)malloc(strlen(website)); strncpy(website_cpy,website,strlen(website)); times[n] = counter;//time(NULL); names[n] = website_cpy; sizes[n] = amountRead; cachesize += amountRead; } V(&writeLock); //TODO unlock cache } free(buf2); close(serverFile); Close(pt->connfd); free(pt); return NULL; }
// // 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); } }