Example #1
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 */
        }
    }
Example #2
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; 
    } 
}
Example #3
0
/* Takes a request and forwards it to its destination server by opening a client
 * connection. Returns the response of the destination server.
 * This function frees memory allocated for the request also using free_req() 
 */
void forward_request(int fd, req_t request){
    int server;
    size_t n, total_read;
    cache_obj* entry;
    char *name, *portstr, http[1024], buf[MAXLINE], cachebuf[MAX_OBJECT_SIZE];
    rio_t rio;

    cachebuf[0] = '\0';
    name = strtok(request.domain, ":");
    portstr = strtok(NULL, ":");
    if(name == NULL){ 
        free_req(request);
        return;
    }
    if(portstr == NULL) portstr = "80";
    
    // checking the cache is still updating it (age)
    P(&w);
    if((entry = in_cache(request.path, num_entries, cache)) != NULL){
        V(&w);
        Rio_writen(fd, entry->buf, entry->obj_size);
    } else {
        V(&w);
         server = Open_clientfd_r(name, atoi(portstr));
         if(server != -1){
            sprintf(http, "GET /%s HTTP/1.0\r\n", request.path);
            strcat(http, request.hdrs);
            Rio_writen(server, http, strlen(http));
            Rio_writen(server, "\r\n", 2);
        } else {
            reparse(&request);
            char *wdpath;
            wdpath = getcwd(NULL,0);
            wdpath = Realloc(wdpath, strlen(wdpath) + strlen(request.path) +1);
            strcat(wdpath, request.path);
            server = open(wdpath, O_RDONLY);
            Free(wdpath);
            if(server == -1){
                not_found(fd);
                free_req(request);
                return;
            }
        }
    	Rio_readinitb(&rio, server);

    	total_read = 0;
    	while((n = Rio_readlineb(&rio, buf, MAXLINE)) > 0){
            if(total_read+n <= MAX_OBJECT_SIZE){
                strcat(cachebuf, buf);
            }
            total_read += n;
            Rio_writen(fd, buf, n);
    	}
        // cache update, critical section
        if(total_read <= MAX_OBJECT_SIZE){
            P(&w);
            cache = cache_write(request.path, cachebuf, num_entries, cache);
            num_entries++;
            V(&w);
        } 
    }
    free_req(request);
}