/* * forward_to_client - forward without write to cache * * used for non GET methods; * * return -1 on error * return 0 on success */ int forward_to_client(int to_client_fd, int to_server_fd) { rio_t rio_server; char buf[MAXLINE]; unsigned int length = 0, size = 0; Rio_readinitb(&rio_server, to_server_fd); // forward status line if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) { return -1; } if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) { return -1; } // forward response headers while (strcmp(buf, "\r\n") != 0 && strlen(buf) > 0) { if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) { return -1; } get_size(buf, &size); if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) { return -1; } } // forward response body if (size > 0) { while (size > MAXLINE) { if ((length = Rio_readnb(&rio_server, buf, MAXLINE)) == -1) { return -1; } if (Rio_writen(to_client_fd, buf, length) == -1) { return -1; } size -= MAXLINE; } if (size > 0) { if ((length = Rio_readnb(&rio_server, buf, size)) == -1) { return -1; } if (Rio_writen(to_client_fd, buf, length) == -1) { return -1; } } } else { while ((length = Rio_readnb(&rio_server, buf, MAXLINE)) > 0) { if (Rio_writen(to_client_fd, buf, length) == -1) { return -1; } } } return 0; }
//checks key int checkKey(rio_t *rio, unsigned int SecretKey) { size_t num; int key_size = (SecretKey == 0 ? 1 : (int)(log10(SecretKey)+1)); char buf[key_size]; unsigned int clientKey, netOrder; if((num = Rio_readnb(rio,buf,key_size)) == key_size) { memcpy(&netOrder,&buf,key_size); clientKey = ntohl(netOrder); printf("Secret Key = %d\n",clientKey); if(clientKey == SecretKey) { return 0; } else { return -1; } } return -1; }
//delete requested file from client int deleteRequest(rio_t *rio, int connfd) { size_t n; char fileNameBuf[NAME_SIZE]; char fileName[NAME_SIZE]; unsigned int netOrder, stat, replySize; unsigned int currStat = 4; char *reply; // Read file name if((n = Rio_readnb(rio, fileNameBuf, NAME_SIZE)) == NAME_SIZE) { // Copy binary data from buffer memcpy(&fileName, &fileNameBuf, NAME_SIZE); printf("Filename = %s\n", fileName); } else { printf("Filename = NONE\n"); stat = -1; } // Check if file is in list and remove it if(removeFileList(fileName) == -1) { stat = -1; } else { // Delete file if(remove(fileName) != 0) { stat = -1; } else { stat = 0; } } // Set reply size replySize = currStat; // Allocate memory for reply reply = (char*) malloc (sizeof(char*)*replySize); if(reply == NULL) { fprintf(stderr, "Memory Error\n"); return -1; } char *replyPtr = reply; // status netOrder = htonl(stat); memcpy(replyPtr, &netOrder, currStat); replyPtr += currStat; // Sender Rio_writen(connfd, reply, replySize); free(reply); return stat; }
//grabs request type int getRequest(rio_t *rio) { size_t num; char buffer[REQUEST_SIZE]; unsigned int reqType, netOrder; if((num = Rio_readnb(rio,buffer,REQUEST_SIZE)) == REQUEST_SIZE) { memcpy(&netOrder,&buffer,REQUEST_SIZE); reqType = ntohl(netOrder); return reqType; } return -1; }
void process_answer(rio_t *rio_server, int fd) { char buf[MAXLINE], content_buf[MAX_OBJECT_SIZE]; int l = 0; /* Extract content-length and pass through headers */ do { Rio_readlineb(rio_server, buf, MAXLINE); if (strcasestr(buf, content_length_hdr_strt)) sscanf(buf + strlen(content_length_hdr_strt), "%d", &l); Rio_writen(fd, buf, strlen(buf)); } while(strcmp(buf, "\r\n")); /* pass through content */ Rio_readnb(rio_server, content_buf, l); Rio_writen(fd, content_buf, l); }
/* $begin post_dynamic */ void post_dynamic(int fd, char *filename, int contentLength,rio_t *rp) { char buf[MAXLINE],length[32], *emptylist[] = { NULL },data[MAXLINE]; int p[2]; sprintf(length,"%d",contentLength); if(pipe(p)==-1) syslog(LOG_ERR,"cannot create pipe"); /* The post data is sended by client,we need to redirct the data to cgi stdin. * so, child read contentLength bytes data from fp,and write to p[1]; * parent should redirct p[0] to stdin. As a result, the cgi script can * read the post data from the stdin. */ if(!ishttps) /* https already read all data ,include post data by SSL_read() */ { if (Fork() == 0) { /* child */ close(p[0]); Rio_readnb(rp,data,contentLength); Rio_writen(p[1],data,contentLength); exit(0) ; } } else { } /* Send response headers to client */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); Dup2(p[0],STDIN_FILENO); /* Redirct p[0] to stdin */ close(p[0]); close(p[1]); setenv("CONTENT-LENGTH",length , 1); Dup2(fd,STDOUT_FILENO); /* Redirct stdout to client */ Execve(filename, emptylist, environ); }
/* * forwardRequest2Server - forward request from proxy to server * when cannot find data in cache * * Pamameters: * fd: file descriptor * request2server: store the request that will send to server * */ void forwardRequest2Server(int fd, char *request2server, char *hostname, char *uri, char *port) { dbg_printf("--------In forwardRequest2Server function--------\n"); char cache_resp[MAX_OBJECT_SIZE]; // store response from cache char server_resp[MAX_OBJECT_SIZE]; // store response from server rio_t rio_proxy_ser; unsigned int obj_size, cnt; /* open a socket descriptor ready to read and write */ int clientfd = Open_clientfd(hostname, port); Rio_readinitb(&rio_proxy_ser, clientfd); /* send connection to server */ dbg_printf("send connection to server: \n"); Rio_writen(clientfd, request2server, strlen(request2server)); /* receive data from server */ dbg_printf("start receiving data from server:\n"); // memset(cache_resp, 0, sizeof(cache_resp)); obj_size = 0; while ((cnt = Rio_readnb(&rio_proxy_ser, server_resp, sizeof(server_resp))) > 0) { /* accumulate cache object size */ obj_size += cnt; strcat(cache_resp, server_resp); dbg_printf("server response: \n '%s' \n", server_resp); Rio_writen(fd, server_resp, cnt); memset(server_resp, 0, sizeof(server_resp)); } /* check if data can be cached */ if (obj_size <= MAX_OBJECT_SIZE) { P(&mutex); caching_from_server(uri, cache_resp); V(&mutex); } /* close proxy connection with server */ Close(clientfd); dbg_printf("--------In forwardRequest2Server function END--------\n"); }
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; }
/* * forward_to_client_and_cache - forward to client and write to cache * * only write to cache when size is smaller than MAX_OBJECT_SIZE * * return -1 on error * return 0 on success */ int forward_to_client_and_cache(int to_client_fd, int to_server_fd, char *cache_id, void *cache_content) { rio_t rio_server; char buf[MAXLINE]; unsigned int cache_length = 0, length = 0, size = 0; // if size of response larger than MAX_OBJECT_SIZE // valid_obj_size is set to 0 int valid_obj_size = 1; Rio_readinitb(&rio_server, to_server_fd); // forward status line and write to cache_content if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) { return -1; } if (valid_obj_size) { valid_obj_size = append_content(cache_content, &cache_length, buf, strlen(buf)); } if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) { return -1; } // forward response headers and write to cache_content while (strcmp(buf, "\r\n") != 0 && strlen(buf) > 0) { if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) { return -1; } get_size(buf, &size); if (valid_obj_size) { valid_obj_size = append_content(cache_content, &cache_length, buf, strlen(buf)); } if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) { return -1; } } // forward response body and write to cache_content if (size > 0) { while (size > MAXLINE) { if ((length = Rio_readnb(&rio_server, buf, MAXLINE)) == -1) { return -1; } if (valid_obj_size) { valid_obj_size = append_content(cache_content, &cache_length, buf, length); } if (Rio_writen(to_client_fd, buf, length) == -1) { return -1; } size -= MAXLINE; } if (size > 0) { if ((length = Rio_readnb(&rio_server, buf, size)) == -1) { return -1; } if (valid_obj_size) { valid_obj_size = append_content(cache_content, &cache_length, buf, length); } if (Rio_writen(to_client_fd, buf, length) == -1) { return -1; } } } else { while ((length = Rio_readnb(&rio_server, buf, MAXLINE)) > 0) { if (valid_obj_size) { valid_obj_size = append_content(cache_content, &cache_length, buf, length); } if (Rio_writen(to_client_fd, buf, length) == -1) { return -1; } } } // write cache_content to cache when size smaller than MAX_OBJECT_SIZE if (valid_obj_size) { if (add_content_to_cache_sync(cache, cache_id, cache_content, cache_length) == -1) { return -1; } } return 0; }
/* * forward_to_server - forward the http request to server * * this function is little bit long since it handles both GET and * non GET methods; * * it is hard to refactor since many variables need to be passed * * return -1 when all kinds of error * return 0 for GET method * return 1 when cache hit (not forward to server) * return 2 for non GET method */ int forward_to_server(int fd, int *to_server_fd, char *cache_id, void *cache_content, unsigned int *cache_length) { char buf[MAXLINE], request_buf[MAXLINE]; char method[MAXLINE], protocol[MAXLINE]; char host_port[MAXLINE]; char remote_host[MAXLINE], remote_port[MAXLINE], resource[MAXLINE]; char version[MAXLINE]; char origin_request_line[MAXLINE]; char origin_host_header[MAXLINE]; int has_user_agent_str = 0, has_accept_str = 0, has_accept_encoding_str = 0, has_connection_str = 0, has_proxy_connection_str = 0, has_host_str = 0; rio_t rio_client; strcpy(remote_host, ""); strcpy(remote_port, "80"); memset(cache_content, 0, MAX_OBJECT_SIZE); Rio_readinitb(&rio_client, fd); if (Rio_readlineb(&rio_client, buf, MAXLINE) == -1) { return -1; } // used incase dns lookup failed strcpy(origin_request_line, buf); if (parse_request_line(buf, method, protocol, host_port, resource, version) == -1) { return -1; } parse_host_port(host_port, remote_host, remote_port); if (strstr(method, "GET") != NULL) { // GET method // compose our request line strcpy(request_buf, method); strcat(request_buf, " "); strcat(request_buf, resource); strcat(request_buf, " "); strcat(request_buf, http_version_str); // process request header while (Rio_readlineb(&rio_client, buf, MAXLINE) != 0) { if (strcmp(buf, "\r\n") == 0) { break; } else if (strstr(buf, "User-Agent:") != NULL) { strcat(request_buf, user_agent_str); has_user_agent_str = 1; } else if (strstr(buf, "Accept-Encoding:") != NULL) { strcat(request_buf, accept_encoding_str); has_accept_encoding_str = 1; } else if (strstr(buf, "Accept:") != NULL) { strcat(request_buf, accept_str); has_accept_str = 1; } else if (strstr(buf, "Connection:") != NULL) { strcat(request_buf, connection_str); has_connection_str = 1; } else if (strstr(buf, "Proxy Connection:") != NULL) { strcat(request_buf, proxy_connection_str); has_proxy_connection_str = 1; } else if (strstr(buf, "Host:") != NULL) { strcpy(origin_host_header, buf); if (strlen(remote_host) < 1) { // if host not specified in request line // get host from host header sscanf(buf, "Host: %s", host_port); parse_host_port(host_port, remote_host, remote_port); } strcat(request_buf, buf); has_host_str = 1; } else { strcat(request_buf, buf); } } // if not sent, copy in out headers if (has_user_agent_str != 1) { strcat(request_buf, user_agent_str); } if (has_accept_encoding_str != 1) { strcat(request_buf, accept_encoding_str); } if (has_accept_str != 1) { strcat(request_buf, accept_str); } if (has_connection_str != 1) { strcat(request_buf, connection_str); } if (has_proxy_connection_str != 1) { strcat(request_buf, proxy_connection_str); } if (has_host_str != 1) { sprintf(buf, "Host: %s:%s\r\n", remote_host, remote_port); strcat(request_buf, buf); } strcat(request_buf, "\r\n"); if (strcmp(remote_host, "") == 0) { return -1; } // compose cache id strcpy(cache_id, method); strcat(cache_id, " "); strcat(cache_id, remote_host); strcat(cache_id, ":"); strcat(cache_id, remote_port); strcat(cache_id, resource); strcat(cache_id, " "); strcat(cache_id, version); // search in the cache if (read_cache_node_lru_sync(cache, cache_id, cache_content, cache_length) != -1) { // cache hit return 1; } // client to server *to_server_fd = Open_clientfd(remote_host, atoi(remote_port), origin_request_line, origin_host_header); if (*to_server_fd == -1) { return -1; } else if (*to_server_fd == -2) { // dns lookup failed, write our response page // caused by invalid host strcpy(buf, client_bad_request_str); Rio_writen(fd, buf, strlen(buf)); return -1; } if (Rio_writen(*to_server_fd, request_buf, strlen(request_buf)) == -1) { return -1; } return 0; } else { // non GET method unsigned int length = 0, size = 0; strcpy(request_buf, buf); while (strcmp(buf, "\r\n") != 0 && strlen(buf) > 0) { if (Rio_readlineb(&rio_client, buf, MAXLINE) == -1) { return -1; } if (strstr(buf, "Host:") != NULL) { strcpy(origin_host_header, buf); if (strlen(remote_host) < 1) { sscanf(buf, "Host: %s", host_port); parse_host_port(host_port, remote_host, remote_port); } } get_size(buf, &size); strcat(request_buf, buf); } if (strcmp(remote_host, "") == 0) { return -1; } *to_server_fd = Open_clientfd(remote_host, atoi(remote_port), origin_request_line, origin_host_header); if (*to_server_fd < 0) { return -1; } // write request line if (Rio_writen(*to_server_fd, request_buf, strlen(request_buf)) == -1) { return -1; } // write request body while (size > MAXLINE) { if ((length = Rio_readnb(&rio_client, buf, MAXLINE)) == -1) { return -1; } if (Rio_writen(*to_server_fd, buf, length) == -1) { return -1; } size -= MAXLINE; } if (size > 0) { if ((length = Rio_readnb(&rio_client, buf, size)) == -1) { return -1; } if (Rio_writen(*to_server_fd, buf, length) == -1) { return -1; } } return 2; } }
// gets the file from server to client int retrieveFile(rio_t *rio, int connfd) { size_t num; char NameBuf[NAME_SIZE]; char fileName[NAME_SIZE]; unsigned int fileSize, netOrder, status, replySize; char *data, *reply; FILE *file; unsigned int currStat = 4; unsigned int maxBytes = 4; if((num = Rio_readnb(rio, NameBuf, NAME_SIZE)) == NAME_SIZE) { memcpy(&fileName, &NameBuf, NAME_SIZE); printf("Filename = %s\n", fileName); } else { printf("Filename = NONE\n"); status = -1; } if(checkFileList(fileName) == -1) { fileSize = 0; status = -1; } else { // Check for the eternal existence of the file in question file = fopen(fileName, "r"); if(file == 0) { fprintf(stderr, "Cannot open input file\n"); fileSize = 0; status = -1; } else { // Obtain file size fseek(file, 0, SEEK_END); fileSize = ftell(file); rewind(file); // Allocate memory for the data buffer data = (char*) malloc (sizeof(char)*fileSize); if(data == NULL) { fprintf(stderr, "Memory Error\n"); return -1; } // Copy file data into data buffer if((num = fread(data, 1, fileSize, file)) == fileSize) { fclose(file); status = 0; } else { fileSize = 0; status = -1; } } } if (fileSize == 0) { data = (char*) malloc (sizeof(char)*fileSize); } // Set reply size replySize = currStat + maxBytes + fileSize; // Allocate memory for the reply reply = (char*) malloc (sizeof(char*)*replySize); if(reply == NULL) { fprintf(stderr, "Memory Error\n"); return -1; } char *replyBuf = reply; // status netOrder = htonl(status); memcpy(replyBuf, &netOrder, currStat); replyBuf += currStat; // File Size integer netOrder = htonl(fileSize); memcpy(replyBuf, &netOrder, maxBytes); replyBuf += maxBytes; // Data memcpy(replyBuf, data, fileSize); replyBuf += fileSize; free(data); // Sender Rio_writen(connfd, reply, replySize); free(reply); return status; }
// puts file from client into memory and directory int store(rio_t *rio, int connfd) { size_t num; char nameBuf[NAME_SIZE]; char FileName[NAME_SIZE]; char FileSize[4]; unsigned int filesize, netOrder, stat, replySize; char data_in_file[FILE_SIZE]; char *data, *reply; FILE *file; unsigned int maxBytes = 4; if((num = Rio_readnb(rio, nameBuf, NAME_SIZE)) == NAME_SIZE) { memcpy(&FileName, &nameBuf, NAME_SIZE); printf("Filename = %s\n", FileName); } else { printf("Filename = NONE\n"); stat = -1; } if((num = Rio_readnb(rio,FileSize,maxBytes)) == maxBytes) { memcpy(&netOrder,&FileSize,maxBytes); filesize = ntohl(netOrder); } else { stat = -1; } if((num = Rio_readnb(rio,data_in_file,filesize)) == filesize) { data = (char*) malloc(sizeof(char)*filesize); if(data == NULL) { fprintf(stderr, "Memory Error\n"); return -1; } memcpy(data,&data_in_file,filesize); } else { stat = -1; } if((file = Fopen(nameBuf,"w")) != NULL) { Fwrite(data, sizeof(char), filesize, file); Fclose(file); if(addFileList(FileName) == 0) { stat = 0; } else { stat = -1; } } else { stat = -1; } free(data); unsigned int currStat = 4; replySize = currStat; reply = (char*) malloc (sizeof(char*)*replySize); if(reply == NULL) { fprintf(stderr, "Memory Error\n"); return -1; } char *replyBuf = reply; netOrder = htonl(stat); memcpy(replyBuf, &netOrder, currStat); replyBuf += currStat; Rio_writen(connfd, reply, replySize); free(reply); return stat; }
void processInput(int connfd, unsigned int secretKey) { size_t size; //buffers required by all commands unsigned char *secretKeyBuf = (unsigned char*)malloc(sizeof(char) * 4); unsigned char *requestBuf = (unsigned char*)malloc(sizeof(char) * 4); //get and put unsigned char *fileSizeBuf = (unsigned char*)malloc(sizeof(char) * 4); char *fileNameBuf = (char*)malloc(sizeof(char) * 80); char *fileContentsBuf; //list buffers unsigned char *returnListBuf; //return buffers unsigned char *returnCodeBuf = (unsigned char*)malloc(sizeof(char) * 4); unsigned char *returnSizeCodeBuf = (unsigned char*)malloc(sizeof(char) * 4); //RIO stuff rio_t rio; Rio_readinitb(&rio, connfd); //ints parsed from buffers unsigned int nsecretKey, request, fileSize; unsigned int bufferSize = 0; //for EOF //bools used for method logic (not necessary, but helps with reading the file) bool shouldUseFilename = false, error = false, list = false, get = false, put = false, del = false; //read in the secret key and type of request. size = Rio_readnb(&rio, secretKeyBuf, 4); if(size!=4){ error = true; } size = Rio_readnb(&rio, requestBuf, 4); if(size!=4){ error = true; } //convert the secret key and request buffers to ints nsecretKey = char4ToInt(secretKeyBuf); request = char4ToInt(requestBuf); printf("Secret Key = %d\n", nsecretKey); printf("Request Type = "); //check the secret keys and set error if (nsecretKey != secretKey) { error = true; } //print some stuff to the console depending on what command is requested switch(request) { case 0: //get printf("get\n"); printf("Filename = "); shouldUseFilename = true; get = true; break; case 1: //put printf("put\n"); printf("Filename = "); shouldUseFilename = true; put = true; break; case 2: //del printf("del\n"); printf("Filename = "); shouldUseFilename = true; del = true; break; case 3: //list printf("list\n"); printf("Filename = NONE\n"); list = true; break; default: printf("undefined: %d\n",request); printf("Filename = NONE\n"); error = true; break; } //if the command we're utilizing receives a filename, read it in. if (shouldUseFilename) { size = Rio_readnb(&rio, fileNameBuf, 80); printf("%s\n",fileNameBuf); } if (put && !error) { size = Rio_readnb(&rio, fileSizeBuf, 4); fileSize = char4ToInt(fileSizeBuf); //printf("Creating file buf of size %d\n",fileSize); fileContentsBuf = (char*)malloc(sizeof(char) * (fileSize+1)); size = Rio_readnb(&rio, fileContentsBuf, fileSize); FILE *stream; char filePath[100]; //create the file path strcpy(filePath, "./files/"); strcat(filePath, fileNameBuf); if ((stream = fopen(filePath, "w"))) { //write the file fwrite(fileContentsBuf, 1, fileSize, stream); //Debug print //printf("Write: %s\n",fileContentsBuf); fclose(stream); } else { //an error occurred writing the file perror("Put file"); error = true; } } if (list && !error) { //for end of file DIR *d, *e; struct dirent *dir; //open the files directory d = opendir("./files"); if (d) { while ((dir = readdir(d)) != NULL) { if (dir->d_type == DT_REG) { //count up the length of each filename (for the length byte) bufferSize += strlen(dir->d_name); bufferSize += 1; } } } closedir(d); returnListBuf = (unsigned char*)malloc(sizeof(char) * bufferSize); e = opendir("./files"); int counter = 0; if (e) { while ((dir = readdir(e)) != NULL) { if (dir->d_type == DT_REG) { //print each name to a buffer //printf("%s\n",dir->d_name); char temp[strlen(dir->d_name) + 1]; sprintf(temp,"%s\n",dir->d_name); memcpy(&returnListBuf[counter], temp, strlen(temp)); counter += strlen(temp); // printf("%s\n", dir->d_name); } } } } if(get && !error){ FILE *stream; fileSize = 0; char filePath[100]; strcpy(filePath, "./files/"); strcat(filePath, fileNameBuf); //try to open the file (in the files directory) if ((stream = fopen(filePath, "rb"))) { //Seek to the end of the file to determine the file size fseek(stream, 0L, SEEK_END); fileSize = ftell(stream); fseek(stream, 0L, SEEK_SET); //printf("fileSize: %d\n",fileSize); fileContentsBuf = (char*)malloc(sizeof(char) * (fileSize+1)); size=fread(fileContentsBuf,1,fileSize,stream); fileContentsBuf[size]=0; //add EOF //Debug print //printf("Read: %s\n",fileContentsBuf); //printf("Size T: %lu\n", size); fclose(stream); } else { //an error occurred opening the file. It may not exist, or permissions aren't set perror("Open file"); error = true; } } if(del && !error){ char filePath[100]; strcpy(filePath, "./files/"); strcat(filePath, fileNameBuf); //delete the file at path //printf("deleting file at path: %s\n",filePath); int delResult = unlink(filePath); if(delResult != 0){ error = true; } } //all input should be read in now. Now to handle the files themselves unsigned int returnCode; if(error){ returnCode = -1; printf("Operation Status = error\n"); } else{ returnCode = 0; printf("Operation Status = success\n"); } intToChar4(returnCode, returnCodeBuf); Rio_writen(connfd, returnCodeBuf, 4); //printf("sent\n"); //only send the get and list info if there isn't an error if(!error){ switch(request) { case 0: //get //bufferSize = strlen(fileContentsBuf) + 1; //printf("Size of file: %lu\n",size); intToChar4(size, returnSizeCodeBuf); Rio_writen(connfd, returnSizeCodeBuf, 4); Rio_writen(connfd, fileContentsBuf, size); // for (unsigned int i = 0; i < size; ++i) // { // printf("%02x",fileContentsBuf[i]); // } break; case 3: //list //printf("Size of files list: %d\n",bufferSize); intToChar4(bufferSize, returnSizeCodeBuf); Rio_writen(connfd, returnSizeCodeBuf, 4); Rio_writen(connfd, returnListBuf, bufferSize); break; default: break; } } printf("--------------------------\n"); }
/* $begin post_dynamic */ static void post_dynamic(int fd, char *filename, int contentLength,rio_t *rp) { char buf[MAXLINE],length[32], *emptylist[] = { NULL },data[MAXLINE]; int p[2]; #ifdef HTTPS int httpsp[2]; #endif sprintf(length,"%d",contentLength); memset(data,0,MAXLINE); Pipe(p); /* The post data is sended by client,we need to redirct the data to cgi stdin. * so, child read contentLength bytes data from fp,and write to p[1]; * parent should redirct p[0] to stdin. As a result, the cgi script can * read the post data from the stdin. */ /* https already read all data ,include post data by SSL_read() */ if (Fork() == 0) { /* child */ Close(p[0]); #ifdef HTTPS if(ishttps) { Write(p[1],httpspostdata,contentLength); } else #endif { Rio_readnb(rp,data,contentLength); Rio_writen(p[1],data,contentLength); } exit(0) ; } /* Send response headers to client */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); sprintf(buf, "%sServer: Tiny Web Server\r\n",buf); #ifdef HTTPS if(ishttps) SSL_write(ssl,buf,strlen(buf)); else #endif Rio_writen(fd, buf, strlen(buf)); //Wait(NULL); Dup2(p[0],STDIN_FILENO); /* Redirct p[0] to stdin */ Close(p[0]); Close(p[1]); setenv("CONTENT-LENGTH",length , 1); #ifdef HTTPS if(ishttps) /* if ishttps,we couldnot redirct stdout to client,we must use SSL_write */ { Pipe(httpsp); if(Fork()==0) { Dup2(httpsp[1],STDOUT_FILENO); /* Redirct stdout to https[1] */ Execve(filename, emptylist, environ); } //Wait(NULL); Read(httpsp[0],data,MAXLINE); SSL_write(ssl,data,strlen(data)); } else #endif { Dup2(fd,STDOUT_FILENO); /* Redirct stdout to client */ Execve(filename, emptylist, environ); } }
/* * serve - handle one HTTP request/response transaction */ void serve(int to_client_fd) { char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], hostname[MAXLINE]; char port[10]; rio_t rio_to_client; rio_t rio_to_server; int to_server_fd; /* Read request line and headers */ Rio_readinitb(&rio_to_client, to_client_fd); Rio_readlineb(&rio_to_client, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); /* if not GET method, ignore it */ if (strcasecmp(method, "GET")) { return; } /* Parse URI from GET request */ parse_uri(uri, hostname, port, filename); // strange display error in csapp page if (strcasecmp(hostname, "csapp.cs.cmu.edu") == 0) { return; } sprintf(buf, "%s %s %s\r\n", "GET", filename, "HTTP/1.0"); /* search content in cache list */ struct cache_block* ptr = search_cache(head, uri); /* cache found, directly send to client */ if (ptr) { // add the number of existing threads reading add_reading_cnt(ptr); // send cache to client Rio_writen(to_client_fd, ptr->file, ptr->size); // subtract the number of existing threads reading sub_reading_cnt(ptr); // update timestamp and reorder LRU list update_timestamp(head, ptr); return; } /* cache not found, connect with server */ to_server_fd = Open_clientfd(hostname, port); Rio_readinitb(&rio_to_server, to_server_fd); // send request line: GET HTTP/1.0 Rio_writen(to_server_fd, buf, strlen(buf)); // send host to server sprintf(buf, "Host: %s\r\n", hostname); Rio_writen(to_server_fd, buf, strlen(buf)); /* read http headers from client and write to server */ Rio_readlineb(&rio_to_client, buf, MAXLINE); while (strncmp(buf, "\r\n", MAXLINE) != 0) { if (strstr(buf, "User-Agent")) strncpy(buf, user_agent_hdr, MAXLINE); else if (strstr(buf, "Connection")) strncpy(buf, "Connection: close\r\n", MAXLINE); else if (strstr(buf, "Proxy-Connection")) strncpy(buf, "Proxy-Connection: close\r\n", MAXLINE); else if (strstr(buf, "Host")) { // ignore, because we already sent one Rio_readlineb(&rio_to_client, buf, MAXLINE); continue; } Rio_writen(to_server_fd, buf, strlen(buf)); Rio_readlineb(&rio_to_client, buf, MAXLINE); } /* terminates request headers */ Rio_writen(to_server_fd, "\r\n", 2); /* read http response from server and write to client */ memset(buf, 0, MAXLINE); Rio_readlineb(&rio_to_server, buf, MAXLINE); int content_len = 0; while (strncmp(buf, "\r\n", MAXLINE) != 0) { char* ptr = strstr(buf, "Content-length"); if (ptr) { content_len = atoi(ptr + 16); } //printf("write2: %s\n", uri); //printf("fd: %d\n", to_client_fd); //printf("%d: %s\n", strlen(buf), buf); Rio_writen(to_client_fd, buf, strlen(buf)); memset(buf, 0, MAXLINE); Rio_readlineb(&rio_to_server, buf, MAXLINE); } /* terminates response headers */ Rio_writen(to_client_fd, "\r\n", 2); int size = 0; int need_cache = 0; /* shall we cache it? */ if (content_len < MAX_OBJECT_SIZE) need_cache = 1; /* init a new cache block */ struct cache_block* blk = (struct cache_block*) malloc(sizeof(struct cache_block)); init_cache(blk); strncpy(blk->uri, uri, MAXLINE); if (content_len > 0) blk->file = (char*) malloc(sizeof(char) * content_len); else blk->file = (char*) malloc(sizeof(char) * MAX_OBJECT_SIZE); memset(buf, 0, MAXLINE); int total_size = 0; char* headptr = blk->file; /* read response contents and write to client */ while ((size = Rio_readnb(&rio_to_server, buf, MAXLINE)) > 0) { total_size += size; if (total_size > MAX_OBJECT_SIZE) need_cache = 0; if (need_cache) { memcpy(headptr, buf, size); headptr += size; } //printf("write3: %s\n", uri); Rio_writen(to_client_fd, buf, size); memset(buf, 0, MAXLINE); } /* add cache block */ if (need_cache) { blk->size = total_size; // resize block blk->file = (char*) realloc(blk->file, blk->size); // size overflow, need to evict using LRU if (blk->size + cache_size > MAX_CACHE_SIZE) evict_cache(head, blk->size); // add it add_cache(head, blk); } /* prevent memory leakage */ else { free_cache_node(blk); } Close(to_server_fd); return; }