示例#1
0
void Rio_writen(int fd, void *usrbuf, size_t n) 
{
    if (rio_writen(fd, usrbuf, n) != n)
	unix_error("Rio_writen error");
}
示例#2
0
/* Analyze the request from browser and decide whether retrieve from
 * cache or connect to the server*/
void* request (void* data){
    pthread_detach(pthread_self());
    Signal(SIGPIPE,SIG_IGN);
    signal(SIGPIPE,SIG_IGN);
    int serverfd=*(int*)data;
    int clientfd;
    char headerBuff[MAXHEADERSIZE],Buffer[MAXBUFFERSIZE];
    char hostname[300],uriname[MAXHEADERSIZE],urlname[MAXHEADERSIZE];
    char* cache_buff;
    int getbyte,error;
    int cachehit = 0;
    int cache_size = 0;
    free(data);
    rio_t serverrio_t;

    rio_readinitb(&serverrio_t,serverfd);

    rio_readlineb(&serverrio_t,headerBuff,sizeof(headerBuff));
    if (takeHostUriUrl(headerBuff,hostname,uriname,urlname) ==0){
        perror("Get Host Uri Url error\n");
        close(serverfd);
        pthread_exit(NULL);
    }
    /* Try to get cached data, must check no thread writing the cache,
     *      * and use FILO architecture to lock when there threads reading cache*/

    P(&mutex);
    readcnt++;
    if(readcnt == 1)
        P(&w);
    V(&mutex);
    if( Get_cachedata(urlname,serverfd) > 0){
        cachehit = 1;
    }

    P(&mutex);
    readcnt--;
    if(readcnt == 0)
        V(&w);
    V(&mutex);

    if(cachehit){
        printf("Cache Hit!!!!\n");
        close(serverfd);
        pthread_exit(NULL);
    }




    if( (clientfd=socket(AF_INET,SOCK_STREAM,0))<0){
        perror("socket");
        close(serverfd);
        pthread_exit(NULL);
    }
    /*get server's address info*/
    struct addrinfo *hostinfo;
    if( (error=getaddrinfo(hostname,"http",NULL,&hostinfo)) >0){
        perror("hostinfo");
        close(serverfd);
        close(clientfd);
        pthread_exit(NULL);
    }
    /* connect to the server*/
    if( (connect(clientfd,hostinfo->ai_addr,hostinfo->ai_addrlen))<0){
        perror("connect");
        close(serverfd);
        close(clientfd);
        return NULL;
    }

    cache_buff = (char*) malloc(MAX_OBJECT_SIZE*sizeof(char));
    cache_size = 0;

    /* Send the request to the server */

    SendRequest(clientfd,serverrio_t,hostname,uriname);
    /*read the information from web server and send it to browser*/
    while(1){
        getbyte = rio_readn(clientfd,Buffer,sizeof(Buffer));
        if(getbyte <= 0 )
            break;
        if(cache_size + getbyte < MAX_OBJECT_SIZE){
            memcpy(cache_buff + cache_size,Buffer,getbyte);
        }
        cache_size += getbyte;

        rio_writen(serverfd,Buffer,getbyte);
    }
    /* if size fit in cache, write into cache, else free the content*/
    if(cache_size < MAX_OBJECT_SIZE){
        char* new_cache_buff = realloc(cache_buff,cache_size);
        free(cache_buff);
        if(new_cache_buff == NULL){
            perror("Realloc fail\n");
            close(clientfd);
            close(serverfd);
            pthread_exit(NULL);
        }

        P(&w);
        char *saveurlname = (char*)malloc(strlen(urlname)*sizeof(char));
        memcpy(saveurlname,urlname,strlen(urlname));
        Create_cache(saveurlname,new_cache_buff,cache_size);
        V(&w);

    }
    else{
        free(cache_buff);
    }


    close(clientfd);
    close(serverfd);
    pthread_exit(NULL);

}
int main(int argc, char *argv[]){

  int target_port,local_port;
  char *target_ip,*local_ip;
  if(argc !=5){
	  printf("please enter arguments in format:./name target_ip,target_port,local_ip,local_port\n");
  }
  target_ip = argv[1]; // reserver ip information for future extension
  target_port = atoi(argv[2]);
  local_ip =argv[3];
  local_port = atoi(argv[4]);
  // printf("the target ip is :%s\nthe target port is:%d\n",target_ip,target_port);

  //start listening
  int args[2];
  args[0] = local_port;
  args[1] = target_port;
  pthread_t hear;
  Pthread_create(&hear,NULL,start_listen,(void*)args);
  Pthread_detach(hear);

  //create connectionfd with server
  int targetfd;
  targetfd = open_clientfd(target_ip,target_port);
  if(targetfd < 0){
    printf("targetfd error!\n");
    return EXIT_FAILURE;
   }
 
  char *cmd, *signature;
  //hand shake start

  //_____________send client hello infromation to server with protocol infromation_______________
  char content[MAXLINE];
  sprintf(content, "ClientHello,sslv2.0");
  rio_writen(targetfd,content,strlen(content));
  //receive response from server, confirm protocol
  int len;
  char answer[MAXLINE];
  len = rio_readp(targetfd,answer,MAXLINE);
  printf("content received from server is: %s\n",answer);
  if(strstr(answer,"ServerHello")!=NULL){
    printf("hello ends\n");
  }

  //______________________DH exchange___________________________
  int dh_g = 3;
  int dh_b = 7;
  int dh_a = 0;
  int *g_ptr = &dh_g;
  int *a_ptr = &dh_a;
  int *b_ptr = &dh_b;
  DH_change_client (targetfd, g_ptr, a_ptr,b_ptr);
  printf("After DH function: g is %d,a is %d,b is %d\n", dh_g, dh_a, dh_b);

 //receive ditial singature from server and authenticate
  len = rio_readp(targetfd,answer,MAXLINE);
    for(int i = 0;i<strlen(answer)-1;i++){
    answer[i] = answer[i]+dh_a;
  }
  cmd = strtok_r(answer,",",&signature);
  printf("signature is %s\n",signature);
  if(strcmp(signature,target_ip) == 0){
    printf("digital signature verified\n");
  }


  //create private key-public key pair and send public key to server uisng DH method
  int p = 11;
  int q = 19;
  int public_n;
  int public_e;
  int private_n;
  int private_d;
  int *public_n_ptr = &public_n;
  int *private_n_ptr = &private_n;
  int *public_e_ptr = &public_e;
  int *private_d_ptr = &private_d;
    
  RSA_generate(p,q,public_n_ptr,private_n_ptr,public_e_ptr,private_d_ptr);
  printf("public <n,e> = <%d,%d>\n", public_n, public_e);
  printf("private <n,d> = <%d,%d>\n", private_n, private_d);
  
  
   memset(content,0,sizeof(content));
  sprintf(content,"ClientKeyExchange,RSA %d %d,TLSv1",p,q);
  for (int i = 0; i<strlen(content);i++){
    content[i] = content[i]+dh_a;
  }
  rio_writen(targetfd,content,strlen(content));


  //__________________first talk______________________
  //receive infromation from server and decryption by RSA method
  memset(answer, 0, sizeof(answer));
  len = rio_readp(targetfd,answer,MAXLINE);
  char count_buffer[MAXLINE];
  memset(count_buffer, 0, sizeof(count_buffer));
  len = rio_readp(targetfd, count_buffer, MAXLINE);
  int word_count = atoi(count_buffer);
  printf("word count is: %d\n", word_count);
  char *decrypt = NULL;
  long long *ip2 = (long long *)answer;
  decrypt = decryption(ip2, word_count, private_n);
  printf("After decryption:%s\n", decrypt);



  //______________second talk_______________________
  memset(content,0,sizeof(content));
  sprintf(content,"ClientFinish");
  //encryption
  int ans_len = strlen(content);
  long long *ip = NULL;
  word_count = 0;
  int *word_count_ptr = &word_count;
  ip = encryption(content,ans_len, word_count_ptr, public_e, public_n);
  printf("Before encryption: %s\n", content);
  printf("After encryption,send:");
  char *ch = (char*)ip;
  printf("%s\n", ch);
//send content
  rio_writen(targetfd,ch,sizeof(ch)*word_count);
  //send word count
  memset(content, 0, sizeof(content));
  sprintf(content, "%d", word_count);
  printf("word count: %s\n", content);
  rio_writen(targetfd, content, sizeof(content));
  memset(content, 0, sizeof(content));
  printf("===============hand shake ends==================\n");
 
 
  printf("please input your message now\n\n");
  //start talking
  while (1){
    //send information to server
    printf("Client:");
    memset(content, 0, sizeof(content));
    scanf("%s", content);
    ans_len = strlen(content);
    ip = NULL;
    word_count = 0;
    word_count_ptr = &word_count;
    ip = encryption(content, ans_len, word_count_ptr, public_e, public_n);;
    char *ch = (char*)ip;
    //send content
    rio_writen(targetfd, ch, sizeof(ch)*word_count);
    //send word count
    memset(content, 0, sizeof(content));
    sprintf(content, "%d", word_count);
    rio_writen(targetfd, content, sizeof(content));
    memset(content, 0, sizeof(content));
    
    
    //receive information from server
    printf("Server:");
    memset(answer, 0, sizeof(answer));
    len = rio_readp(targetfd, answer, MAXLINE);
    if (strcmp(answer, "You end the talk. Sever disconnect.") == 0){
      printf("%s\n", answer);
      break;
    }
    memset(count_buffer, 0, sizeof(count_buffer));
    len = rio_readp(targetfd, count_buffer, MAXLINE);
    word_count = atoi(count_buffer);
    decrypt = NULL;
    ip2 = (long long *)answer;
    decrypt = decryption(ip2, word_count, private_n);
    printf("%s\n", decrypt);
  }
  close (targetfd);
  return EXIT_SUCCESS;
}
示例#4
0
/* 
 * 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;
}
示例#5
0
void Rio_writen_s(int fd, void *usrbuf, size_t n){
	if (rio_writen(fd, usrbuf, n) != n)
		printf("Rio_writen error\n");
	
}
示例#6
0
文件: proxy.c 项目: swananan/Wu-CSAPP
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;
}
示例#7
0
/*
 * handle_request - handle one HTTP request from client and 
 * make request for actual server. It will wait for response
 * and forward response back to client.
 */
void handle_request(int clientfd)
{
    char buf[MAXLINE], method[MAXLINE], url[MAXLINE];
    char hostname[MAXLINE], uri[MAXLINE], version[MAXLINE];

    rio_t rio;
    char port[] = "80"; /* http request use port 80 */

    /* Read request line and headers */
    Rio_readinitb(&rio, clientfd);
    Rio_readlineb(&rio, buf, MAXLINE);
    sscanf(buf, "%s %s %s", method, url, version);
    if (strcasecmp(method, "GET")) { 
        clienterror(clientfd, method, "501", "Not Implemented",
                "Proxy does not implement this method");
        return;
    }
    
    parse_url(url, hostname, uri);

    /* connect to host server by hostname */
    int serverfd;
    if ((serverfd = open_clientfd(hostname, port)) < 0)
    {
        pthread_mutex_lock(&print_lock);  
        printf("Open_clientfd error\n");
        pthread_mutex_unlock(&print_lock);  
        return;
    }

    /* construct a new request line */
    char requestLine[MAXLINE];
    strcpy(requestLine, method);
    strcat(requestLine, uri);
    strcat(requestLine, "HTTP/1.0");
    rio_readinitb(&rio, serverfd);
    rio_writen(serverfd, buf, strlen(buf)); /* send request line to server */

    /* read and send request header to server */
    char requesthrds[MAXLINE];
    cat_requesthdrs(requesthrds, hostname);
    rio_writen(serverfd, requesthrds, strlen(requesthrds));

    //rio_readlineb(&rio, buf, MAXLINE);
    //rio_writen(serverfd, buf, strlen(buf));
    //while(strcmp(buf, "\r\n")) 
    //{
    //    rio_readlineb(&rio, buf, MAXLINE);
    //    rio_writen(serverfd, buf, strlen(buf));
    //} 
    char emptyline[] = "\r\n";
    rio_writen(serverfd, emptyline, strlen(emptyline));

    /* get response from server and send it back to client */
    rio_writen(clientfd, emptyline, strlen(emptyline));
    read_requesthdrs(&rio);
    size_t n;
    while ((n = rio_readlineb(&rio, buf, MAXLINE)) != 0) 
        rio_writen(clientfd, buf, strlen(buf));

    /* close connection to server */
    int rc;
    if ((rc = close(serverfd)) < 0)
    {
        pthread_mutex_lock(&print_lock);
        printf("Close error\n");
        pthread_mutex_unlock(&print_lock); 
    }
    pthread_mutex_lock(&print_lock); 
    printf("Connection to server closed.\n");  
    pthread_mutex_unlock(&print_lock);
}
示例#8
0
void send_msg_back(int connfd,char* msg){
    //DEBUG
    printf(" # MSG BACK TO %d:\n\t%s\n", connfd,msg);
    rio_writen(connfd,msg,strlen(msg));
}
/* $begin doit */
void doit(int fd_client)
{
    rio_t rio_client;
    rio_t rio_server;
    
    int fd_server=0;
    int is_cached=0;
    
    char buf[MAXLINE],method[MAXLINE],uri[MAXLINE],version[MAXLINE];
    char pathname[MAXLINE],hostname[MAXLINE],hdr_server[MAXLINE];
    char *port=(char*)malloc(sizeof(port));
    
    strcpy(port,PORT_DEFAULT);
    
    rio_readinitb(&rio_client,fd_client);
    rio_readlineb(&rio_client,buf,MAXLINE);
    
    sscanf(buf,"%s %s %s",method,uri,version);
    
    if (strcasecmp(method, "GET")) {
        clienterror(fd_client, method, "501", "Not Implemented",
                    "Tiny does not implement this method");
        return;
    }
    
    is_cached = in_cache(mycache, uri);
    if (is_cached) {
        printf("Cache hit\n");
        doit_cached(mycache, uri, fd_client);
    }
    
    else {
    printf("Cache miss\n");
    parse_uri(uri,pathname,hostname,port);
    
    
    fd_server=Open_clientfd(hostname,port);
    hdr_concat(&rio_client,hdr_server,hostname,pathname);
    // printf("%s",hdr_server);
    rio_writen(fd_server, hdr_server, strlen(hdr_server));
    rio_readinitb(&rio_server,fd_server);
    
    char buf_server[MAXLINE],file_buf[MAX_OBJECT_SIZE];
    int n=0;
    int size=0;
    memset(buf_server, 0, MAXLINE);
        
    while((n=rio_readlineb(&rio_server,buf_server,MAXLINE))!=0){
        if (size+n <= MAX_OBJECT_SIZE) {
            memcpy(file_buf+size, buf_server, n);
            size += n;
        }
        rio_writen(fd_client, buf_server, n);
        memset(buf_server, 0, n);
    }
        if (size <= MAX_OBJECT_SIZE) {
            insert(mycache, uri, file_buf, size);
        }
    close(fd_server);
    free(port);
    }
}
/* $begin doit_cached */
void doit_cached (Cache *proxy, char *uri, int fd_client) {
    Block *found_block =search(proxy, uri);
    if (rio_writen(fd_client, found_block->data, found_block->size) < 0) {
        printf("Error writing from cache to client\n");
    }
}
示例#11
0
void* HttpRequest::RequestParse(void*arg)
{
	int n;
    int again_flag = true;   //again flag decide to close the fd or try again
    while(true)
    {
        errno = 0;                        //this is important
        memset(usr_buf,0,RIO_BUFSIZE);    //reset the buf
        n = rio_readn(fd,(void*)usr_buf,RIO_BUFSIZE-1);
        
        if(n==-1)
        {
            debug("error.");
            again_flag = false;
    	    break;
        }
        else if(n==0)
        {
            if(errno==EAGAIN)
            {
                //debug("again read");
                again_flag = true;
            }
            else  //EOF
            {
                //debug("EOF read close fd");
                again_flag = false;
            }
            //debug("there is not any more data,errno is: %d",errno);
            break;
        }

        read_data = usr_buf;
        /*
        cout<<"read data:--------------------------------------------"<<endl;
        cout<<read_data<<endl;
        cout<<"-------------------------------------------------------"<<endl;
        */
        //debug_cpp(read_data.size());
        CommandParse();    //requese line parse
        HeaderParse();     //head parse

        //int data_n = read_data.size();
        if(read_data.size()!=0)
        {
            BodyParse();   //body parse
        }

        /*parse complete,do method,url ,version check*/
        HttpError e;
        int check_res = e.RequireCheck(command,head,out,file_stat);


        if(check_res!=D_OK)
        {

            //debug("require error: %d",check_res);    //then send the wrong information page 
            command.uri = "/40x.html";
            // reset the file_stat;
            string file_name = file_root+command.uri;
            stat(file_name.c_str(),&file_stat);
            out.SetStaticServer(true);
        }
        
        /**********check over,send the result to the client********/

        if(out.GetStaticServer())  
        {
              //set the length
            out.SetFileSize(file_stat.st_size);
        
            auto out_line = out.SetOutLine_C();
            out_line += out.SetOutHeaders_C(head); 
            char* res_line_buf = const_cast<char*>(out_line.c_str());
            n = rio_writen(fd,(void*)res_line_buf,strlen(res_line_buf));  //write command line

            //debug("send Response line and Out Header.");
            StaticServer();
            //debug("----------static server over-----------");
        }
        else //dynamic server
        {
            //debug("----------dynamic server on-------------");
            DynamicServer();
            //debug("----------dynamic server over-----------");
        }

        //server -------**over**----------
        
        if(head.head.find("Connection")==head.head.end()) //keep alive
        {
            again_flag = false;
            //debug("-----------no keep alive,will break---------");
            break;
        }
        else
        {
            again_flag = true;
        }
        
    }
    
    if(!again_flag)
    {
      //debug("close fd ,%d",fd);
      close(fd);    //close fd ,there is no other request
    }
    else
    {
        
        head.head.clear();                //clear the request head
        read_data="";
        again_flag = true;
        out.clear();                      //clear the output data
        

        InitHttpRequest(ep,fd,epfd);      //no need to initialize.because the ep,fd,and the epfd etc do not change
        ep->SetEpollEvent((void*)this,D_EPOLLIN|D_EPOLLET|D_EPOLLONESHOT);  //set event
        ep->EpollCTL(D_EPOLL_CTL_MOD,fd); //add fd to the event module

      
    }

    return NULL;
}