int main(int argc, char **argv) { if(!(argc >=2) ) //If commandline args are not provided { printf("No file provided\n"); return -1; } //Use csapp Open to get fd number (creates files) int fd = Open(argv[1],O_CREAT | O_WRONLY,0); int n; //Number of bytes rio_t rio; //RIO type that contains file info char buf[MAXLINE]; //Character buffer with max size defined by csapp //Associate a descriptor with a read buffer and reset buffer //the POSIX <unistd.h> definition is STDIN_FILENO Rio_readinitb(&rio,STDIN_FILENO); while((n = rio_readnb(&rio, buf, MAXLINE)) != 0) //While it has read more than zero bytes { Rio_writen(fd, buf, n);//Write n bytes from buf } Close(fd); exit(0); }
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) { ssize_t rc; if ((rc = rio_readnb(rp, usrbuf, n)) < 0) unix_error("Rio_readnb error"); return rc; }
ssize_t Rio_readnb_s(rio_t *rp, void *usrbuf, size_t n){ ssize_t rc; if ((rc = rio_readnb(rp, usrbuf, n)) < 0){ printf("Rio_readnb error\n"); rc = 0; } return rc; }
void load_dataset_output(rio_t *rp, dataset *d){ int i; uint8_t label; for(i = 0; i < d->N; i++){ rio_readnb(rp, &d->output[i], sizeof(uint8_t)); } }
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) { ssize_t rt; rt = rio_readnb(rp, usrbuf, n); if (rt == -1) unix_error("Rio_readnb error"); return rt; }
void load_dataset_blas_output(rio_t *rp, dataset_blas *d){ int i; uint8_t label; for(i = 0; i < d->N; i++){ rio_readnb(rp, &d->output[i], sizeof(uint8_t)); d->label[i*d->nlabel + d->output[i]] = 1; } }
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) { ssize_t rc; if ((rc = rio_readnb(rp, usrbuf, n)) < 0) { if (errno != ECONNRESET) unix_error("Rio_readnb error"); } return rc; }
/* miss_handler handles miss case. It passes client's request * to server and passes server's response to client. If the * response satisfies size requirements, store the response * into cache. */ void miss_handler(int clientfd, struct client_request *request) { int serverfd, length, response_size; char buf[MAXBUF], object_buf[MAX_OBJECT_SIZE]; struct cache_cell *cell; rio_t rio_server; response_size = length = 0; /* acts as a client and writes request to server */ Pthread_mutex_lock(&open_mutex); serverfd = open_serverfd_h(request, clientfd); Pthread_mutex_unlock(&open_mutex); rio_readinitb(&rio_server, serverfd); if (rio_writen(serverfd, request->request, request->request_length) != request->request_length) { write(2, "write error\n", strlen("write error\n")); close_connection(request, clientfd, serverfd); } /* passes server's response to client */ while (1) { if ((length = rio_readnb(&rio_server, buf, MAXBUF)) < 0) close_connection(request, clientfd, serverfd); if (response_size + length <= MAX_OBJECT_SIZE) memcpy(object_buf + response_size, buf, length); response_size += length; if (rio_writen(clientfd, buf, length) < length) break; if (length != MAXBUF) break; } /* if response satisfies size requirement, store the response * into cache */ if (response_size <= MAX_OBJECT_SIZE) { /* need a mutex to prevent inserting the same cell twice * into cache in race condition */ Pthread_mutex_lock(&dup_mutex); if (search_cell_variant(request->request_line) == 0) { cell = allocate_cell(); set_cell(cell, request->request_line, object_buf, response_size); add_to_list(cell); } Pthread_mutex_unlock(&dup_mutex); } close_connection(request, clientfd, serverfd); }
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) { ssize_t rc; int max=3; while (((rc = rio_readnb(rp, usrbuf, n)) < 0)) { sleep(1); max--; if (max==0){ return -1; } } return rc; }
int main(int argc, char ** argv) { int n; rio_t rio; char buf[MAXBUF]; printf("%d\n",MAXBUF); rio_readinitb(&rio, STDIN_FILENO); while((n = rio_readnb(&rio, buf, MAXBUF)) != 0) { rio_writen(STDOUT_FILENO, buf, n); } return 0; }
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) { ssize_t rc; if ((rc = rio_readnb(rp, usrbuf, n)) < 0) { // we ran into an error if (errno == ECONNRESET) { printf("The Connection was reset\n"); pthread_exit(NULL); return 0; //return rc; } unix_error("Rio_readnb error"); } return rc; }
void load_dataset_blas_input(rio_t *rp, dataset_blas *d){ int i, j, k; int idx; uint8_t pixel; #ifdef DEBUG printf("loading input data...\n"); #endif for(i = 0; i < d->N; i++){ for(j = 0; j < d->nrow * d->ncol; j++){ idx = i * d->nrow * d->ncol + j; rio_readnb(rp, &pixel, sizeof(uint8_t)); d->input[idx] = (double)pixel / 255.0; } } #ifdef DEBUG printf("data loaded\n"); fflush(stdout); #endif }
void load_model(crbm *m, char *filename){ rio_t rio_model; int fd_model; if((fd_model = open(filename, O_RDONLY)) == -1){ printf("open %s failed\n", filename); } rio_readinitb(&rio_model, fd_model, 0); rio_readnb(&rio_model, &m->nvisible, sizeof(int)); rio_readnb(&rio_model, &m->nhidden, sizeof(int)); rio_readnb(&rio_model, &m->ncat, sizeof(int)); m->w = (double*)malloc(m->nhidden * m->nvisible * sizeof(double)); m->u = (double*)malloc(m->nhidden * m->ncat * sizeof(double)); m->bv = (double*)malloc(m->nvisible * sizeof(double)); m->bh = (double*)malloc(m->nhidden * sizeof(double)); m->by = (double*)malloc(m->ncat * sizeof(double)); rio_readnb(&rio_model, m->w, m->nvisible * m->nhidden * sizeof(double)); rio_readnb(&rio_model, m->u, m->ncat * m->nhidden * sizeof(double)); rio_readnb(&rio_model, m->bv, m->nvisible * sizeof(double)); rio_readnb(&rio_model, m->bh, m->nhidden * sizeof(double)); rio_readnb(&rio_model, m->by, m->ncat * sizeof(double)); close(fd_model); }
int write_cache_and_client (char *request, size_t size) { int value = -1; cache_object *cur_object; P(&nowrite); P(&noread); if (size <= MAX_OBJECT_SIZE) { if (rio_readnb(clientrio, buf, size) != -1) { cur_object = Malloc(sizeof(cur_object)); cur_object->buf = buf; strcpy(cur_object->request, request); cur_object->size = size; cur_object->next = my_cache->front; cur_object->prev = NULL; insert(cur_object); value = 0; } } V(&noread); V(&nowrite) }
/*forward response (lines/headers/body) to client*/ int forward_response(rio_t *rio_server, char *uri, char *resp_buf, int connfd) { char response[MAX_OBJECT_SIZE]; char resp_body[MAX_OBJECT_SIZE]; char resp_line[MAXLINE]; int resp_size = 0; int length = 0; int body_size = 0; int content_len = -1; int cont_size = 0; #if 1 if((web_load(uri, response)) == 0) { printf("Cache hit!\n"); if(rio_writen(connfd, response, sizeof(response)) < 0) { fprintf(stderr, "rio_writen send cache response error\n"); return -1; } memset(response, 0, sizeof(response)); return 0; } #endif /*send reponse line and headers to client*/ while((length = rio_readlineb(rio_server, resp_line, MAXLINE)) > 0) { strcat(response, resp_line); /* send headers to clinet*/ if (rio_writen(connfd, resp_line, length) < 0) { fprintf(stderr, "Error: rio_writen() in forward_response header: %s\n", strerror(errno)); DEBUG_PRINT("Error: rio_writen() in forward_response header\n"); return -1; } /*empty line between headers and body*/ if(strcmp(resp_line, "\r\n") == 0) break; /* get size of response body from response header: Content-Length */ if (strstr(resp_line, "Content-Length: ")) { content_len = parse_num(resp_line); if(content_len < 0) { fprintf(stderr, "Error get Content-Length: %s", resp_line); DEBUG_PRINT("Error get Content-Length\n"); Close(connfd); return -1; } } memset(resp_line, 0, sizeof(resp_line)); resp_size += length; } /*w/o content length in response headers*/ if(content_len == -1) content_len = MAX_OBJECT_SIZE; cont_size = MIN(content_len, MAX_OBJECT_SIZE); /* Send response body to client */ #if DEBUG /* send fake response body */ Rio_writen(connfd, test, strlen(test)); #else while((length = rio_readnb(rio_server, resp_body, cont_size)) > 0) { strcat(response, resp_body); if (rio_writen(connfd, resp_body, length) < 0) { fprintf(stderr, "rio_writen in forward_response body error: %s!", strerror(errno)); DEBUG_PRINT("rio_writen in forward_response body error!"); return -1; } body_size += length; } #endif #if 1 resp_size += body_size; if(resp_size <= MAX_OBJECT_SIZE) { if(web_store(uri, response) < 0) //store response in cache { printf("web_store, cache error!\n"); return -1; } } #endif #if 0 srcfd = Open(filename, O_RDONLY, 0); srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0); Close(srcfd); Rio_writen(fd, srcp, filesize); Munmap(srcp, filesize); #endif return 0; }
/* * Listens for incoming connections on a port number specified on the command * line. Once a connection is established, it reads the entirety of the * request from the client and parse the request. It determines whether the * client has sent a valid HTTP request; if so, it then establishes its own * connection to the appropriate web server then requests the object the client * specified. Finally, the proxy reads the server’s response and forwards it to * the client. */ void doit(int fd) { int isnot_safe; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE], temp[MAXLINE], host[MAXLINE], clientheaders[MAXLINE], readRequests[MAXLINE], path[MAXLINE]; char *data = malloc(MAX_OBJECT_SIZE*sizeof(char)); size_t sizeOfTotalData = 0; char *dataBuffer = malloc(MAX_OBJECT_SIZE*sizeof(char)); char *temporaryData = dataBuffer; char* port_pointer; int port = 80, len, len2; rio_t rio, rio1; int serverConn_fd; cache_node *fileObj = NULL; //cache_node *addFile = malloc(sizeof(cache_node)); //associates rio with the descriptor Rio_readinitb(&rio, fd); //reads and flushes the buf with the request Rio_readlineb(&rio, buf, MAXLINE); //parsing the initial request isnot_safe = safe_scan(sscanf(buf, "%s %s %s\r\n", method, uri, version)); if (isnot_safe) return; //cannot perform if it is not a Get method if (strcasecmp(method, "GET")) { printf("501 Not Implemented Proxy does not handle this method"); return; } //printf("Does it reach here after Get?\n"); //Parse the URL properly if (strstr(uri, "http://")) { isnot_safe = safe_scan(sscanf(uri, "%[^'/']%s", temp, uri)); if (isnot_safe) return; memmove(uri, uri+2, strlen(uri)); } //printf("%s\n", uri); if(strchr(uri, '/') != NULL) { isnot_safe = safe_scan(sscanf(uri, "%[^'/']%s", host, path)); if (isnot_safe) return; } else { //if no path is specified then it is just "/". strcpy(path, "/"); strcpy(host, uri); } //printf("HOST %s\n", host); //Get the port if it is specified if ((port_pointer = strchr(host, ':')) != NULL){ isnot_safe = safe_scan(sscanf(port_pointer, ":%d", &port)); if (isnot_safe) return; isnot_safe = safe_scan(sscanf(host, "%[^0-9:]", host)); if (isnot_safe) return; } //Look up the object in the cache if ((fileObj = find(uri)) != NULL) { rio_writen(fd, fileObj->file, fileObj->size); return; } //flush the readRequests associated with the path and host sprintf(readRequests, "GET %s HTTP/1.0\r\nHost: %s\r\n", path, host); //open a server connection with the host and port serverConn_fd = Open_clientfd(host, port); //associate the file descriptor and write to it from readRequests Rio_readinitb(&rio1, serverConn_fd); isnot_safe = safe_rio(rio_writen(serverConn_fd, readRequests, strlen(readRequests))); if (isnot_safe) return; //Send in all necessary headers isnot_safe = safe_rio(rio_writen(serverConn_fd, (void *) user_agent_hdr, strlen(user_agent_hdr))); if (isnot_safe) return; isnot_safe = safe_rio(rio_writen(serverConn_fd, (void *) accept_hdr, strlen(accept_hdr))); if (isnot_safe) return; isnot_safe = safe_rio(rio_writen(serverConn_fd, (void *) accept_encoding_hdr, strlen(accept_encoding_hdr))); if (isnot_safe) return; isnot_safe = safe_rio(rio_writen(serverConn_fd, "Proxy-Connection: close\r\nConnection:\tclose\r\n\r\n", 52)); if (isnot_safe) return; //Get additional requests by clients that are not already passed and //pass them through without changing them while((len = rio_readlineb(&rio, readRequests, MAXBUF)) && strcmp(readRequests, "\r\n")) { //Get the headers isnot_safe = safe_scan(sscanf(readRequests, "%s ",clientheaders)); if (isnot_safe) return; //see if the headers are not the ones we already passed. if(!strstr(clientheaders, "Host:")&& !strstr(clientheaders,"Connection:") && !strstr(clientheaders, "User-Agent:") && !strstr(clientheaders, "Accept-Encoding:") && !strstr(clientheaders,"Accept:") && !strstr(clientheaders,"Proxy-Connection:")) { isnot_safe = safe_rio(rio_writen(serverConn_fd, readRequests, len)); if (isnot_safe) return; } } //Finally write to the client desciptor what the server responds with while((len2 = rio_readnb(&rio1, data, MAXLINE))){ sizeOfTotalData += len2; //Keep writing to the memory at temporaryData as long as size of the data //so far is less than max object size if (sizeOfTotalData < MAX_OBJECT_SIZE){ memcpy(temporaryData,data,len2); temporaryData += len2; } rio_writen(fd, data, len2); } //We shouldn't add the object to the cache if the size of the //data exceeds the max object size or is 0 if(sizeOfTotalData <= MAX_OBJECT_SIZE && sizeOfTotalData != 0) { pthread_rwlock_wrlock(&lock); addToFront(uri, dataBuffer, sizeOfTotalData); pthread_rwlock_unlock(&lock); } free(data); 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; } }
void read_uint32(rio_t *rp, uint32_t *data){ rio_readnb(rp, data, sizeof(uint32_t)); *data = ntohl(*data); }
void forward_response(int client_fd, int server_fd, Response *response) { #ifdef DEBUG printf("enter forward_response\n"); #endif size_t n; int length = -1; char header_buffer[MAXLINE]; char content_buffer[MAX_OBJECT_SIZE]; int read_size; rio_t server_rio; int header_line = 0; int move_flag = 0; char move_new_address[MAXLINE]; rio_readinitb(&server_rio, server_fd); while ((n = rio_readlineb(&server_rio, header_buffer, MAXLINE)) != 0) { strcat(response->header, header_buffer); //parse response //if return status code is 3XX //address moved. //need to send another request to the indicated place //until get 2XX or 4XX or 5XX. header_line ++; //status code 3XX if((header_line == 1) && (header_buffer[state_offset] == '3')) { move_flag =1; } if((move_flag == 1) && strstr(header_buffer,"Location:")) { //moved to new address. //I suggest change the address in request and return. then send request again. strcat(move_new_address, (header_buffer+move_offset)); } //add exit here /* if (rio_writen(client_fd, header_buffer, n) < 0) { proxy_error("rio_writen in forward_response header error"); }*/ if (strstr(header_buffer, "Content-Length: ")) { sscanf(header_buffer + 16, "%d", &length); } if (!strcmp(header_buffer, "\r\n")) { break; } } if (length == -1) read_size = MAX_OBJECT_SIZE; else read_size = min(length, MAX_OBJECT_SIZE); #ifdef DEBUG printf("finish response header\n"); #endif int sum = 0; while ((n = rio_readnb(&server_rio, content_buffer, read_size)) != 0) { if (rio_writen(client_fd, content_buffer, n) < 0) { proxy_error("rio_writen in forward_response content error"); Close(client_fd); } sum += n; } #ifdef DEBUG printf("read byte size:%u\n", sum); #endif if (sum <= MAX_OBJECT_SIZE) { response->content = Malloc(sizeof(char) * sum); memcpy(response->content, content_buffer, sum * sizeof(char)); response->content_size = sum; } else { response->content_size = sum; } #ifdef DEBUG printf("leave forward_response\n"); #endif }
void *thread(void *vargp){ struct connfd_timed *clientconnfd = (struct connfd_timed *)vargp; int connfd = clientconnfd->connfd; int timestamp = clientconnfd->timestamp; rio_t rio; char buf[MAX_LINE], method[MAX_LINE], version[MAX_LINE], url[MAX_LINE]; char host[MAX_LINE], port[MAX_LINE], query[MAX_LINE]; char *response; int clientfd; int count; int content_length; /* read socket */ rio_readinitb(&rio, connfd); rio_readlineb(&rio, buf, MAX_LINE); sscanf(buf, "%s %s %s", method, url, version); /* only GET */ if(strcasecmp(method, "GET")){ Close(connfd); return NULL; } /* cache hit */ response=(char*)Malloc(MAX_OBJECT_SIZE); response[0]='\0'; if (cache_read(url, response, timestamp)){ rio_writen(connfd, response, strlen(response)); Close(connfd); free(response); return NULL; } /* cache miss, create http request to real server*/ /* illegal url */ if (parse_url(url, host, port, query)){ Close(connfd); return NULL; } /* connect server failed */ if((clientfd = connect_server(host, port, query)) < 0){ Close(connfd); return NULL; } /* read http response head, store content length */ response = (char*)Malloc(MAX_OBJECT_SIZE); rio_readinitb(&rio, clientfd); content_length = 0; while ((count = rio_readlineb(&rio, buf, MAX_LINE)) > 0){ rio_writen(connfd, buf, count); strncat(response, buf, count); if(strstr(buf, "Content-length")){ sscanf(buf, "Content-length: %d\r\n", &content_length); } if (strcmp(buf,"\r\n") == 0){ break; } } /* too big to cache */ if(content_length + strlen(response) >= MAX_OBJECT_SIZE){ while ((count = rio_readnb(&rio, buf, MAX_LINE)) > 0){ rio_writen(connfd, buf, count); } Close(clientfd); Close(connfd); free(response); return NULL; } /* add to cache */ while ((count = rio_readnb(&rio, buf, MAX_LINE)) > 0){ strncat(response, buf, count); rio_writen(connfd, buf, count); } cache_write(response, url, timestamp); Close(clientfd); Close(connfd); free(response); return NULL; }
/* Wrapper for read (buffered) */ ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) { ssize_t rc; rc = rio_readnb(rp, usrbuf, n); return rc; }
/* * forward_response - send request to server, then store resposne content * in cache if necessary */ int forward_response(int client_fd, int server_fd, Response *response) { #ifdef DEBUG printf("enter forward_response\n"); #endif size_t n; int length = -1; int read_size; rio_t server_rio; char header_buffer[MAXLINE]; char temp_buffer[MAX_OBJECT_SIZE]; char buffer[10 * MAX_OBJECT_SIZE]; char content_buffer[10 * MAX_OBJECT_SIZE]; rio_readinitb(&server_rio, server_fd); int buffer_pos = 0; while ((n = rio_readlineb(&server_rio, header_buffer, MAXLINE)) != 0) { memcpy(response->header + buffer_pos, header_buffer, sizeof(char) * n); buffer_pos += n; /*specify content-length info if header has this info */ if (strstr(header_buffer, "Content-Length: ")) { sscanf(header_buffer + 16, "%d", &length); } if (!strcmp(header_buffer, "\r\n")) { break; } } if (length == -1) read_size = MAX_OBJECT_SIZE; else read_size = min(length, MAX_OBJECT_SIZE); #ifdef DEBUG printf("finish response header\n"); #endif int sum = 0; while ((n = rio_readnb(&server_rio, temp_buffer, read_size)) != 0) { memcpy(content_buffer + sum, temp_buffer, sizeof(char) * n); sum += n; } memcpy(buffer, response->header, sizeof(char) * buffer_pos); memcpy(buffer + buffer_pos, content_buffer, sizeof(char) * sum); if (rio_writen(client_fd, buffer, buffer_pos + sum) < 0) { sleep(1); if (rio_writen(client_fd, buffer, buffer_pos + sum) < 0) { sleep(2); if (rio_writen(client_fd, buffer, buffer_pos + sum) < 0) proxy_error("rio_writen in forward_response" " header content error"); return -1; } } #ifdef DEBUG printf("read byte size:%u\n", sum); #endif if (sum <= MAX_OBJECT_SIZE) { response->content = Malloc(sizeof(char) * sum); memcpy(response->content, content_buffer, sum * sizeof(char)); response->content_size = sum; } else { response->content_size = sum; } #ifdef DEBUG printf("leave forward_response\n"); #endif return 1; }
/* * * 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; }
void *thread(void *p) { //可以自动释放线程 Pthread_detach(pthread_self()); int connfd=((struct args*)p)->connfd,turn=((struct args*)p)->turn; free(p); char buf[MAXLINE]; char method[MAXLINE],version[MAXLINE],url[MAXLINE]; char host[MAXLINE],query[MAXLINE]; char url_tmp[300],*data_tmp; rio_t rio; int index,port,content_length; int serverfd; rio_readinitb(&rio,connfd); rio_readlineb(&rio,buf,MAXLINE); sscanf(buf,"%s %s %s",method,url,version); if(strcasecmp(method,"GET")) { printf("Not GET\r\n"); Close(connfd); return NULL; } //忽视客户端的请求 do { rio_readlineb(&rio,buf,MAXLINE-1); }while(strcmp(buf,"\r\n")); /* find cache block */ for(index=0;index<10;index++) { cache_read_url(index,url_tmp); /* the block'url is same as current url */ if(!strcmp(url,url_tmp)) break; } data_tmp=(char*)Malloc(MAX_OBJECT_SIZE); data_tmp[0]='\0'; if(index <10) { /* if have cached */ cache_read_data(index,data_tmp,turn); rio_writen(connfd,data_tmp,strlen(data_tmp)); Close(connfd); free(data_tmp); return NULL; } /* connect to server */ parse_url(url,host,query,&port); if((serverfd=connect_server(host,port,query))<0) { /* connect to server failed, return */ free(data_tmp); Close(connfd); return NULL; } rio_readinitb(&rio,serverfd); content_length=0; /* read response head line */ do { int t=rio_readlineb(&rio,buf,MAXLINE-1); if(t<=0) break; strncat(data_tmp,buf,t); if(strstr(buf,"Content-length")!=NULL) sscanf(buf,"Content-length: %d\r\n",&content_length); rio_writen(connfd,buf,t); }while(strcmp(buf,"\r\n")); /* read response body */ /* response is small enough to cache */ if(content_length+strlen(data_tmp)<MAX_OBJECT_SIZE) { while(content_length>0) { int t= rio_readnb(&rio,buf,(content_length<MAXLINE-1)?content_length:MAXLINE-1); if(t<=0) continue; content_length-=t; strncat(data_tmp,buf,t); rio_writen(connfd,buf,t); } index=0; int i; /* least-recently-used */ for(i=1;i<10;i++) { if(cache_read_turn(i)<cache_read_turn(index)) { index=i; } } /* cache write */ cache_write(index,url,data_tmp,turn); } /* ignore store and write to client */ else { while(content_length>0) { int t= rio_readnb(&rio,buf,(content_length<MAXLINE-1)?content_length:MAXLINE-1); if(t<=0) break; content_length-=t; rio_writen(connfd,buf,t); } } Close(connfd); Close(serverfd); free(data_tmp); return NULL; }