Ejemplo n.º 1
0
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
  }
}
Ejemplo n.º 2
0
/* $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;
}
Ejemplo n.º 3
0
/*
 * 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 */
}
Ejemplo n.º 4
0
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);
	}
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
Archivo: tiny.c Proyecto: akxxsb/tiny
/*
 * 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
    }
}
Ejemplo n.º 7
0
Archivo: tiny.c Proyecto: 4179e1/misc
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);
	}
}
Ejemplo n.º 8
0
/*
 * 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);
    }
}
Ejemplo n.º 9
0
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 suport this method yet.");
        return;
    }
    read_requesthdrs(&rio);

    /* 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 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);

    }
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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);
        }
    }
}
Ejemplo n.º 12
0
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;
    }
}
Ejemplo n.º 13
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; 
    } 
}
Ejemplo n.º 14
0
/* $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;
}
Ejemplo n.º 15
0
/* $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 */
        }
    }
Ejemplo n.º 16
0
// 
// 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);
	}
}
Ejemplo n.º 17
0
/*
 * doit - handle one HTTP request/response transaction
 *		  (please refer tiny.c for this part)
 *
 * Pamameters:
 *		fd:		file descriptor
 */
void doit(int fd) {

    dbg_printf("--------In doit function--------\n");

    char buf[MAXLINE];
    char method[MAXLINE], url[MAXLINE], version[MAXLINE], uri[MAXLINE];         
    char *port;
    char *default_port;
    char hostname[MAXBUF], request2server[MAXLINE];          
    rio_t rio;             
    
    /* set the default HTTP port, which is port 80 */
    // port = malloc(sizeof(int));
    port = malloc(sizeof(char));
    default_port = "80";                      

    /* receive request from client */
    Rio_readinitb(&rio, fd);
    if (!Rio_readlineb(&rio, buf, MAXLINE)) { //read request
        dbg_printf("Error: cannot receive request\n");
        return;
    }
    dbg_printf("Receive request from client: %s", buf);

    /* parse request */
    sscanf(buf, "%s %s %s", method, url, version);  

    /* check correctness of client reqeust */
    checkClientRequest(fd, method, url, version);

    /* read request headers */
    read_requesthdrs(&rio);

    /* Parse URI from GET request */
    parse_url(url, hostname, port);  
    dbg_printf("port after parse: %s\n", port);
    /* if no port specified, use "80" */
    if (strcmp(port, "") == 0) { 
        port = default_port;
    }

    strcpy(uri, url);     
    sprintf(request2server, "%s %s %s\r\n", method, uri, version);
    dbg_printf("request from proxy to server: %s\n", request2server);

    /* generate request to server */
    createReqestHeader(buf, request2server, hostname);

    /* check cache before send request to server */
    char cache_resp[MAX_OBJECT_SIZE];   // store response from cache
    /* load data from cache */
    if (search_data_from_cache(uri, cache_resp)) {
        dbg_printf("found data in cache! \n");
        Rio_writen(fd, cache_resp, sizeof(cache_resp));
        memset(cache_resp, 0, sizeof(cache_resp)); 
        dbg_printf("finish response from cache!\n");
    }
    /* no data in cache, send reqeust to server */
    else { 
    	dbg_printf("No data in cache, send request to server! \n");  
    	/* forward request to server */
    	forwardRequest2Server(fd, request2server, hostname, url, port);       
    }

    dbg_printf("--------In doit function END--------\n");
}
Ejemplo n.º 18
0
    void mainloop(){
    
    rio_t rp_client, rp_server;
    int  hostport;
    char hostname[MAXLINE], pathname[MAXLINE];
    char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
    while (1) {
        char buffer[MAX_UINT];
        while (queue->isEmpty()) {
            sleep(1);
            continue;
        }
        clientsock = queue->Pop();
        if(clientsock == -1){
            //printf("Fake Client sockID:%d \n", clientsock);
            continue;
        }
        //printf("Get Client sockID:%d \n", clientsock);
        // Init read structure for client-proxy connection
        Rio_readinitb(&rp_client, clientsock);
        
        // Parse the HTTP request
        read_requesthdrs(&rp_client, method, uri, version);
        
        // Parse the URI of the request
        parse_uri(uri, hostname, pathname, &hostport);
        //printf("%s %s %d\n", hostname, pathname, hostport);
        /*****  If method is GET *****/
        if (strcmp(method, "GET")!=0) {
            char buf2[] = "500 'Internal Error' \r\n";
            Rio_writenb_w(clientsock, buf2, strlen(buf2));
            //printf("It is not GET method:%s socket:%d \n", method, clientsock);
            Rio_close(clientsock);
            continue;
        }
        
#ifdef WITH_CACHE
        //find url in cache and return [FIXME]
        if(pmap->find(uri)!=pmap->end()){ //not found the topic
            
            proxy_cache *pcache = (*pmap)[uri];
            
            for (int i =0; i<pcache->size; i++) {
                Rio_writen_w(clientsock, pcache->buf[i], strlen(pcache->buf[i]));
            }
            Rio_close(clientsock);
            continue;
        }
        // Make cache entry [FIXME]
        proxy_cache *pcache = new proxy_cache();
        std::string urlstr = *new std::string(uri);
        std::pair<std::string, proxy_cache *> newpair(urlstr,pcache);
        pmap->insert(newpair);
#endif
        // Open connection to requested web server
        char strport[10]={0};
        sprintf(strport, "%d",hostport);
        proxysock = open_targetfd(hostname, strport);
        
        if (proxysock < 0) {
            char buf2[] = "500 'Internal Error' \r\n";
            Rio_writenb_w(clientsock, buf2, strlen(buf2));
            Rio_close(clientsock);
            continue;
        }
        
        // Init read struct for proxy-webserver connection
        Rio_readinitb(&rp_server, proxysock);
        
        sprintf(buf, "%s %s %s\r\n", method, pathname, "HTTP/1.0");
        Rio_writenb_w(proxysock, buf, strlen(buf));
        //printf("%s", buf);
        sprintf(buf, "Host: %s\r\n", hostname);
        Rio_writenb_w(proxysock, buf, strlen(buf));
        //printf("%s", buf);

        // Read from client request
        // and write to web server
        while(strcmp(buf, "\r\n")) {
            Rio_readlineb_w(&rp_client, buf, MAXLINE);
            
            if (!strcmp(buf, "\r\n")) {
                char buf2[] = "Connection: close\r\n";
                Rio_writenb_w(proxysock, buf2, strlen(buf2));
                //printf("%s", buf2);
            }
            if (!strncmp(buf, "Connection: keep-alive", 22) ||
                !strncmp(buf, "Host:", 5)) {
                //printf("%s", buf);
                continue;
            }
            
            Rio_writenb_w(proxysock, buf, strlen(buf));
            //printf("%s", buf);
            
        }
        
        // Read the respons from webserver and
        // forward it to the requesting client
        ssize_t n = 0;
        while ((n = Rio_readnb_w(proxysock, buffer, MAX_UINT)) > 0) {
#ifdef WITH_CACHE
            char *cache = (char*)malloc(sizeof(char)*(n+1));
            if(cache == NULL){
                perror("Alloc memory failed, cache emited");
            }
            memset(cache, 0, n+1);
            strncpy(cache,buffer,n);
#endif
            Rio_writenb_w(clientsock, buffer, n);
            
        }
        
        Rio_close(clientsock);
        Rio_close(proxysock);
    }
}
Ejemplo n.º 19
0
/**
 * 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;
}
Ejemplo n.º 20
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);
}