int Open_clientfd_r(char *hostname, int port) { int rc; if ((rc = open_clientfd_r(hostname, port)) < 0) { unix_error("Open_clientfd_r error"); } return rc; }
/*proxy executation routine*/ int run_proxy(int connfd) { char hostname[MAXLINE]; char req_buf[MAX_OBJECT_SIZE]; char resp_buf[MAX_OBJECT_SIZE]; char uri[MAXLINE]; int port = 80; int clientfd; rio_t rio; memset(hostname, 0, MAXLINE); memset(req_buf, 0, MAX_OBJECT_SIZE); memset(resp_buf, 0 , MAX_OBJECT_SIZE); /* read request */ if(read_request(connfd, req_buf, uri, hostname, &port) < 0) { //printf("close fd: %d, tid: %d\n", connfd, gettid()); Close(connfd); return -1; } /* open connection to server */ if((clientfd = open_clientfd_r(hostname, port)) < 0) { //printf("connfd: %d, clientfd: %d, host: %s, tid: %d\n", connfd, clientfd, hostname, gettid()); printf("Open_clientfd error\n"); fprintf(stderr, "Error: connection refused: %s !\n", hostname); Close(connfd); return -1; } if(forward_request(&rio, req_buf, clientfd) < 0) { printf("forward_request error\n"); fprintf(stderr, "Error: Send request to server failed !\n"); Close(clientfd); Close(connfd); return -1; } if(forward_response(&rio, uri, resp_buf, connfd) < 0) { printf("forward_response\n"); fprintf(stderr, "Error: Send response to client failed !\n"); Close(clientfd); Close(connfd); return -1; } Close(clientfd); Close(connfd); return 0; }
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; }
/* * handle HTTP request/response transaction of a thread * clinet-----(request)----->server * <------(data)------- */ void *doit(void *connfd) { int fd = *(int *)connfd; int fd_server; /* detach thread */ Pthread_detach(pthread_self()); rio_t rio; char buf[MAXLINE], object_buf[MAX_OBJECT_SIZE]; char method[MAXLINE], uri[MAXLINE], version[MAXLINE]; /* uri info */ char host[MAXLINE]; int port; char filename[MAXLINE]; /* Read request line and headers */ Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); /* request method is not GET */ if (strcmp(method, "GET")) { printerror(fd, method, "501", "Not Implemented", "tianqiw's proxy does not implement this method"); Close(fd); return NULL; } /* request method is GET * look for the object in cache */ cache_block *block = cache_match(cache_ptr, uri); if (block != NULL) { /* cache hit */ Rio_writen(fd, block->object, block->object_size); } else { /* cache miss */ parse_uri(uri, host, &port, filename); /* construct the request header */ char request_buf[MAXLINE]; requestHdr(&rio, request_buf, host, filename); /* send request to server */ if ((fd_server = open_clientfd_r(host, port)) < 0) { /* server connection error */ char longmsg[MAXBUF]; sprintf(longmsg, "Cannot open connection to server at <%s, %d>", host, port); printerror(fd, "Connection Failed", "404", "Not Found", longmsg); Close(fd); return NULL; } /* reset rio for server use */ memset(&rio, 0, sizeof(rio_t)); Rio_readinitb(&rio, fd_server); Rio_writen(fd_server, request_buf, strlen(request_buf)); /* get data from server and send to client */ size_t object_size = 0; size_t buflen; int is_exceed = 0; while ((buflen = Rio_readlineb(&rio, buf, MAXLINE))) { Rio_writen(fd, buf, buflen); /* size of the buffer exceeds the max object size * discard the buffer */ if ((object_size + buflen) > MAX_OBJECT_SIZE) { is_exceed = 1; } else { memcpy(object_buf + object_size, buf, buflen); object_size += buflen; } } /* if not exceed the max object size, insert to cache */ if (!is_exceed) { cache_insert(cache_ptr, uri, object_buf, object_size); } /* clear the buffer */ Close(fd_server); } Close(fd); return NULL; }