Exemple #1
0
/*
 * forward_to_client - forward without write to cache
 *
 * used for non GET methods;
 *
 * return -1 on error
 * return 0 on success
 */
int forward_to_client(int to_client_fd, int to_server_fd) {
    rio_t rio_server;
    char buf[MAXLINE];
    unsigned int length = 0, size = 0;

    Rio_readinitb(&rio_server, to_server_fd);
    // forward status line
    if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) {
        return -1;
    }
    if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) {
        return -1;
    }
    // forward response headers
    while (strcmp(buf, "\r\n") != 0 && strlen(buf) > 0) {
        if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) {
            return -1;
        }
        get_size(buf, &size);
        if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) {
            return -1;
        }
    }
    // forward response body
    if (size > 0) {
        while (size > MAXLINE) {
            if ((length = Rio_readnb(&rio_server, buf, MAXLINE)) == -1) {
                return -1;
            }
            if (Rio_writen(to_client_fd, buf, length) == -1) {
                return -1;
            }
            size -= MAXLINE;
        }
        if (size > 0) {
            if ((length = Rio_readnb(&rio_server, buf, size)) == -1) {
                return -1;
            }
            if (Rio_writen(to_client_fd, buf, length) == -1) {
                return -1;
            }
        }
    } else {
        while ((length = Rio_readnb(&rio_server, buf, MAXLINE)) > 0) {
            if (Rio_writen(to_client_fd, buf, length) == -1) {
                return -1;
            }
        }
    }
    return 0;
}
Exemple #2
0
//checks key
int checkKey(rio_t *rio, unsigned int SecretKey)
{
	size_t num;
	int key_size = (SecretKey == 0 ? 1 : (int)(log10(SecretKey)+1));
	char buf[key_size]; 
	unsigned int clientKey, netOrder; 

	if((num = Rio_readnb(rio,buf,key_size)) == key_size)
	{

		memcpy(&netOrder,&buf,key_size); 
		clientKey = ntohl(netOrder); 

		printf("Secret Key  =  %d\n",clientKey); 

		if(clientKey == SecretKey)
		{
			return 0;
		}
		else
		{
			return -1; 
		}
	}
	return -1; 
}
Exemple #3
0
//delete requested file from client
int deleteRequest(rio_t *rio, int connfd) {
    size_t n;
    char fileNameBuf[NAME_SIZE];
    char fileName[NAME_SIZE];
    unsigned int netOrder, stat, replySize;
    unsigned int currStat = 4;
    char *reply;   
    
    // Read file name
    if((n = Rio_readnb(rio, fileNameBuf, NAME_SIZE)) == NAME_SIZE) {
        // Copy binary data from buffer
        memcpy(&fileName, &fileNameBuf, NAME_SIZE);
        printf("Filename = %s\n", fileName);
    } 
    else {
        printf("Filename = NONE\n");
        stat = -1;
    }

    // Check if file is in list and remove it
    if(removeFileList(fileName) == -1) { 
    	stat = -1;
    }
    else {
        // Delete file
        if(remove(fileName) != 0) { stat = -1; }
        else { stat = 0; }
    }

    // Set reply size 
    replySize = currStat;

    // Allocate memory for reply
    reply = (char*) malloc (sizeof(char*)*replySize);
    if(reply == NULL) { 
    	fprintf(stderr, "Memory Error\n"); return -1;
    }

    char *replyPtr = reply;

    // status
    netOrder = htonl(stat);
    memcpy(replyPtr, &netOrder, currStat);
    replyPtr += currStat;

    // Sender
    Rio_writen(connfd, reply, replySize);
    free(reply);

    return stat;
}
Exemple #4
0
//grabs request type
int getRequest(rio_t *rio)
{
	size_t num; 
	char buffer[REQUEST_SIZE];
	unsigned int reqType, netOrder;

	if((num = Rio_readnb(rio,buffer,REQUEST_SIZE)) == REQUEST_SIZE)
	{

		memcpy(&netOrder,&buffer,REQUEST_SIZE);
		reqType = ntohl(netOrder); 

		return reqType; 
	}
	return -1; 
}
void process_answer(rio_t *rio_server, int fd) {
	char buf[MAXLINE], content_buf[MAX_OBJECT_SIZE];
	int l = 0;

	/* Extract content-length and pass through headers */
	do {
		Rio_readlineb(rio_server, buf, MAXLINE);
        if (strcasestr(buf, content_length_hdr_strt))
            sscanf(buf + strlen(content_length_hdr_strt), "%d", &l);
        Rio_writen(fd, buf, strlen(buf));
    } while(strcmp(buf, "\r\n"));

    /* pass through content */
    Rio_readnb(rio_server, content_buf, l);
    Rio_writen(fd, content_buf, l);
}
Exemple #6
0
/* $begin post_dynamic */
void post_dynamic(int fd, char *filename, int contentLength,rio_t *rp)
{
    char buf[MAXLINE],length[32], *emptylist[] = { NULL },data[MAXLINE];
    int p[2];

    sprintf(length,"%d",contentLength);

    if(pipe(p)==-1)
	syslog(LOG_ERR,"cannot create pipe");

    /*       The post data is sended by client,we need to redirct the data to cgi stdin.
    *  	 so, child read contentLength bytes data from fp,and write to p[1];
    *    parent should redirct p[0] to stdin. As a result, the cgi script can
    *    read the post data from the stdin. 
    */
    if(!ishttps)  /* https already read all data ,include post data  by SSL_read() */
    {
    	if (Fork() == 0)
	{  /* child  */ 
		close(p[0]);
		Rio_readnb(rp,data,contentLength);
		Rio_writen(p[1],data,contentLength);
		exit(0)	;
	}
    }  
    else
    {
    }
    

    /* Send response headers to client */
    sprintf(buf, "HTTP/1.0 200 OK\r\n");
    Rio_writen(fd, buf, strlen(buf));
    sprintf(buf, "Server: Tiny Web Server\r\n");
    Rio_writen(fd, buf, strlen(buf));

    Dup2(p[0],STDIN_FILENO);  /* Redirct p[0] to stdin */
    close(p[0]);

    close(p[1]);
    setenv("CONTENT-LENGTH",length , 1); 
    Dup2(fd,STDOUT_FILENO);        /* Redirct stdout to client */ 
    Execve(filename, emptylist, environ); 
}
/*
 * forwardRequest2Server - forward request from proxy to server
 *							when cannot find data in cache
 *
 * Pamameters:
 *		fd:					file descriptor
 *	request2server:			store the request that will send to server
 *		
 */
void forwardRequest2Server(int fd, char *request2server, 
                            char *hostname, char *uri, char *port) {
    dbg_printf("--------In forwardRequest2Server function--------\n");

    char cache_resp[MAX_OBJECT_SIZE];   // store response from cache
    char server_resp[MAX_OBJECT_SIZE];  // store response from server
    rio_t rio_proxy_ser; 
    unsigned int obj_size, cnt;

    /* open a socket descriptor ready to read and write */
    int clientfd = Open_clientfd(hostname, port); 
    Rio_readinitb(&rio_proxy_ser, clientfd);

    /* send connection to server */
    dbg_printf("send connection to server: \n");
    Rio_writen(clientfd, request2server, strlen(request2server));

    /* receive data from server */
    dbg_printf("start receiving data from server:\n");
    // memset(cache_resp, 0, sizeof(cache_resp));
    obj_size = 0;
    while ((cnt = Rio_readnb(&rio_proxy_ser, 
            server_resp, sizeof(server_resp))) > 0) {
        
        /* accumulate cache object size */
        obj_size += cnt;
        strcat(cache_resp, server_resp);

        dbg_printf("server response: \n '%s' \n", server_resp);
        Rio_writen(fd, server_resp, cnt);
        memset(server_resp, 0, sizeof(server_resp));
    }

    /* check if data can be cached */
    if (obj_size <= MAX_OBJECT_SIZE) {
        P(&mutex);
        caching_from_server(uri, cache_resp);
        V(&mutex);
    }

    /* close proxy connection with server */
    Close(clientfd);
    dbg_printf("--------In forwardRequest2Server function END--------\n");
}
Exemple #8
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;
}
Exemple #9
0
/*
 * forward_to_client_and_cache - forward to client and write to cache
 *
 * only write to cache when size is smaller than MAX_OBJECT_SIZE
 *
 * return -1 on error
 * return 0 on success
 */
int forward_to_client_and_cache(int to_client_fd, int to_server_fd,
                                char *cache_id, void *cache_content) {
    rio_t rio_server;
    char buf[MAXLINE];
    unsigned int cache_length = 0, length = 0, size = 0;
    // if size of response larger than MAX_OBJECT_SIZE
    // valid_obj_size is set to 0
    int valid_obj_size = 1;

    Rio_readinitb(&rio_server, to_server_fd);
    // forward status line and write to cache_content
    if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) {
        return -1;
    }
    if (valid_obj_size) {
        valid_obj_size = append_content(cache_content, &cache_length, buf,
                                        strlen(buf));
    }
    if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) {
        return -1;
    }
    // forward response headers and write to cache_content
    while (strcmp(buf, "\r\n") != 0 && strlen(buf) > 0) {
        if (Rio_readlineb(&rio_server, buf, MAXLINE) == -1) {
            return -1;
        }
        get_size(buf, &size);
        if (valid_obj_size) {
            valid_obj_size = append_content(cache_content, 
                &cache_length, buf, strlen(buf));
        }
        if (Rio_writen(to_client_fd, buf, strlen(buf)) == -1) {
            return -1;
        }
    }
    // forward response body and write to cache_content
    if (size > 0) {
        while (size > MAXLINE) {
            if ((length = Rio_readnb(&rio_server, buf, MAXLINE)) == -1) {
                return -1;
            }
            if (valid_obj_size) {
                valid_obj_size = append_content(cache_content,
                                                &cache_length, buf, length);
            }
            if (Rio_writen(to_client_fd, buf, length) == -1) {
                return -1;
            }
            size -= MAXLINE;
        }
        if (size > 0) {
            if ((length = Rio_readnb(&rio_server, buf, size)) == -1) {
                return -1;
            }
            if (valid_obj_size) {
                valid_obj_size = append_content(cache_content, &cache_length,
                                                buf, length);
            }
            if (Rio_writen(to_client_fd, buf, length) == -1) {
                return -1;
            }
        }
    } else {
        while ((length = Rio_readnb(&rio_server, buf, MAXLINE)) > 0) {
            if (valid_obj_size) {
                valid_obj_size = append_content(cache_content, &cache_length,
                                                buf, length);
            }
            if (Rio_writen(to_client_fd, buf, length) == -1) {
                return -1;
            }
        }
    }
    // write cache_content to cache when size smaller than MAX_OBJECT_SIZE
    if (valid_obj_size) {
        if (add_content_to_cache_sync(cache, cache_id, cache_content,
                                      cache_length) == -1) {
            return -1;
        }
    }
    return 0;
}
Exemple #10
0
/*
 * forward_to_server - forward the http request to server
 *
 * this function is little bit long since it handles both GET and
 * non GET methods;
 *
 * it is hard to refactor since many variables need to be passed
 *
 * return -1 when all kinds of error
 * return 0 for GET method
 * return 1 when cache hit (not forward to server)
 * return 2 for non GET method
 */
int forward_to_server(int fd, int *to_server_fd, char *cache_id,
                      void *cache_content, unsigned int *cache_length) {
    char buf[MAXLINE], request_buf[MAXLINE];
    char method[MAXLINE], protocol[MAXLINE];
    char host_port[MAXLINE];
    char remote_host[MAXLINE], remote_port[MAXLINE], resource[MAXLINE];
    char version[MAXLINE];
    char origin_request_line[MAXLINE];
    char origin_host_header[MAXLINE];

    int has_user_agent_str = 0, has_accept_str = 0,
        has_accept_encoding_str = 0,
        has_connection_str = 0, has_proxy_connection_str = 0,
        has_host_str = 0;

    rio_t rio_client;

    strcpy(remote_host, "");
    strcpy(remote_port, "80");
    memset(cache_content, 0, MAX_OBJECT_SIZE);

    Rio_readinitb(&rio_client, fd);
    if (Rio_readlineb(&rio_client, buf, MAXLINE) == -1) {
        return -1;
    }
    // used incase dns lookup failed
    strcpy(origin_request_line, buf);

    if (parse_request_line(buf, method, protocol, host_port,
                           resource, version) == -1) {
        return -1;
    }
    parse_host_port(host_port, remote_host, remote_port);

    if (strstr(method, "GET") != NULL) {
        // GET method

        // compose our request line
        strcpy(request_buf, method);
        strcat(request_buf, " ");
        strcat(request_buf, resource);
        strcat(request_buf, " ");
        strcat(request_buf, http_version_str);

        // process request header
        while (Rio_readlineb(&rio_client, buf, MAXLINE) != 0) {
            if (strcmp(buf, "\r\n") == 0) {
                break;
            } else if (strstr(buf, "User-Agent:") != NULL) {
                strcat(request_buf, user_agent_str);
                has_user_agent_str = 1;
            } else if (strstr(buf, "Accept-Encoding:") != NULL) {
                strcat(request_buf, accept_encoding_str);
                has_accept_encoding_str = 1;
            } else if (strstr(buf, "Accept:") != NULL) {
                strcat(request_buf, accept_str);
                has_accept_str = 1;
            } else if (strstr(buf, "Connection:") != NULL) {
                strcat(request_buf, connection_str);
                has_connection_str = 1;
            } else if (strstr(buf, "Proxy Connection:") != NULL) {
                strcat(request_buf, proxy_connection_str);
                has_proxy_connection_str = 1;
            } else if (strstr(buf, "Host:") != NULL) {
                strcpy(origin_host_header, buf);
                if (strlen(remote_host) < 1) {
                    // if host not specified in request line
                    // get host from host header
                    sscanf(buf, "Host: %s", host_port);
                    parse_host_port(host_port, remote_host, remote_port);
                }
                strcat(request_buf, buf);
                has_host_str = 1;
            } else {
                strcat(request_buf, buf);
            }
        }
        // if not sent, copy in out headers
        if (has_user_agent_str != 1) {
            strcat(request_buf, user_agent_str);
        }
        if (has_accept_encoding_str != 1) {
            strcat(request_buf, accept_encoding_str);
        }
        if (has_accept_str != 1) {
            strcat(request_buf, accept_str);
        }
        if (has_connection_str != 1) {
            strcat(request_buf, connection_str);
        }
        if (has_proxy_connection_str != 1) {
            strcat(request_buf, proxy_connection_str);
        }
        if (has_host_str != 1) {
            sprintf(buf, "Host: %s:%s\r\n", remote_host, remote_port);
            strcat(request_buf, buf);
        }
        strcat(request_buf, "\r\n");
        if (strcmp(remote_host, "") == 0) {
            return -1;
        }

        // compose cache id
        strcpy(cache_id, method);
        strcat(cache_id, " ");
        strcat(cache_id, remote_host);
        strcat(cache_id, ":");
        strcat(cache_id, remote_port);
        strcat(cache_id, resource);
        strcat(cache_id, " ");
        strcat(cache_id, version);

        // search in the cache
        if (read_cache_node_lru_sync(cache, cache_id, cache_content,
                                     cache_length) != -1) {
            // cache hit
            return 1;
        }

        // client to server
        *to_server_fd = Open_clientfd(remote_host, atoi(remote_port),
                                    origin_request_line, origin_host_header);
        if (*to_server_fd == -1) {
            return -1;
        } else if (*to_server_fd == -2) {
            // dns lookup failed, write our response page
            // caused by invalid host
            strcpy(buf, client_bad_request_str);
            Rio_writen(fd, buf, strlen(buf));
            return -1;
        }
        if (Rio_writen(*to_server_fd, request_buf,
                       strlen(request_buf)) == -1) {
            return -1;
        }
        return 0;
    } else {
        // non GET method
        unsigned int length = 0, size = 0;
        strcpy(request_buf, buf);
        while (strcmp(buf, "\r\n") != 0 && strlen(buf) > 0) {
            if (Rio_readlineb(&rio_client, buf, MAXLINE) == -1) {
                return -1;
            }
            if (strstr(buf, "Host:") != NULL) {
                strcpy(origin_host_header, buf);
                if (strlen(remote_host) < 1) {
                    sscanf(buf, "Host: %s", host_port);
                    parse_host_port(host_port, remote_host, remote_port);
                }
            }
            get_size(buf, &size);
            strcat(request_buf, buf);
        }
        if (strcmp(remote_host, "") == 0) {
            return -1;
        }
        *to_server_fd = Open_clientfd(remote_host, atoi(remote_port),
                                    origin_request_line, origin_host_header);
        if (*to_server_fd < 0) {
            return -1;
        }
        // write request line
        if (Rio_writen(*to_server_fd, request_buf,
                       strlen(request_buf)) == -1) {
            return -1;
        }
        // write request body
        while (size > MAXLINE) {
            if ((length = Rio_readnb(&rio_client, buf, MAXLINE)) == -1) {
                return -1;
            }
            if (Rio_writen(*to_server_fd, buf, length) == -1) {
                return -1;
            }
            size -= MAXLINE;
        }
        if (size > 0) {
            if ((length = Rio_readnb(&rio_client, buf, size)) == -1) {
                return -1;
            }
            if (Rio_writen(*to_server_fd, buf, length) == -1) {
                return -1;
            }
        }
        return 2;
    }
}
Exemple #11
0
// gets the file from server to client
int retrieveFile(rio_t *rio, int connfd) 
{
	size_t num;
    char NameBuf[NAME_SIZE];
    char fileName[NAME_SIZE];
    unsigned int fileSize, netOrder, status, replySize;
    char *data, *reply;
    FILE *file;
    unsigned int currStat = 4;
    unsigned int maxBytes = 4;  
    if((num = Rio_readnb(rio, NameBuf, NAME_SIZE)) == NAME_SIZE) 
    {
        memcpy(&fileName, &NameBuf, NAME_SIZE);
        printf("Filename  = %s\n", fileName);
    } 
    else 
    {
        printf("Filename  = NONE\n");
        status = -1;
    }

    if(checkFileList(fileName) == -1) 
    	{ 
    		fileSize = 0; 
    		status = -1; 
    	}
    else 
    {
        // Check for the eternal existence of the file in question
        file = fopen(fileName, "r");

        if(file == 0) 
        { 
        	fprintf(stderr, "Cannot open input file\n"); 
    		fileSize = 0; 
    		status = -1; 
        }
        else 
        {
            // Obtain file size
            fseek(file, 0, SEEK_END);
            fileSize = ftell(file);
            rewind(file);

            // Allocate memory for the data buffer
            data = (char*) malloc (sizeof(char)*fileSize);
            if(data == NULL) { fprintf(stderr, "Memory Error\n"); return -1; }

            // Copy file data into data buffer
            if((num = fread(data, 1, fileSize, file)) == fileSize) 
            	{ 
            		fclose(file); 
            		status = 0; 
            	}
            else 
            	{ 
            		fileSize = 0; 
            		status = -1; 
            	}
        }
    }

    if (fileSize == 0) {
        data = (char*) malloc (sizeof(char)*fileSize);
    }
    // Set reply size
    replySize = currStat + maxBytes + fileSize;

    // Allocate memory for the reply
    reply = (char*) malloc (sizeof(char*)*replySize);

    if(reply == NULL) 
    	{ 
    		fprintf(stderr, "Memory Error\n"); 
    		return -1;
    	 }
    char *replyBuf = reply;

    // status
    netOrder = htonl(status);
    memcpy(replyBuf, &netOrder, currStat);
    replyBuf += currStat;

    // File Size integer
    netOrder = htonl(fileSize);
    memcpy(replyBuf, &netOrder, maxBytes);
    replyBuf += maxBytes;

    // Data
    memcpy(replyBuf, data, fileSize);
    replyBuf += fileSize;
    free(data);

    // Sender
    Rio_writen(connfd, reply, replySize);
    free(reply);

    return status;
}
Exemple #12
0
// puts file from client into memory and directory
int store(rio_t *rio, int connfd)
{
	size_t num; 
	char nameBuf[NAME_SIZE]; 
	char FileName[NAME_SIZE]; 
	char FileSize[4];
	unsigned int filesize, netOrder, stat, replySize; 
	char data_in_file[FILE_SIZE];
	char  *data, *reply; 
	FILE *file; 
	unsigned int maxBytes = 4; 

	if((num = Rio_readnb(rio, nameBuf, NAME_SIZE)) == NAME_SIZE) 
	{
        memcpy(&FileName, &nameBuf, NAME_SIZE);
        printf("Filename  = %s\n", FileName);
    } 
    else 
    {
        printf("Filename  = NONE\n");
        stat = -1;
    }

    if((num = Rio_readnb(rio,FileSize,maxBytes)) == maxBytes)
    {
    	memcpy(&netOrder,&FileSize,maxBytes);
    	filesize = ntohl(netOrder); 
    }
    else
    {
    	stat = -1; 
    }

    if((num = Rio_readnb(rio,data_in_file,filesize)) == filesize)
    {
    	data = (char*) malloc(sizeof(char)*filesize); 

    	if(data == NULL)
    	{
    		fprintf(stderr, "Memory Error\n"); 
    		return -1; 
    	}

    	memcpy(data,&data_in_file,filesize);
    }
    else
    {
    	stat = -1; 
    }

    if((file = Fopen(nameBuf,"w")) != NULL)
    {
    	Fwrite(data, sizeof(char), filesize, file);
    	Fclose(file); 

    	if(addFileList(FileName) == 0)
    	{
    		stat = 0; 
    	} 
    	else
    	{
    		stat = -1; 
    	}
    }
    else
    {
    	stat = -1; 
    }

    free(data); 
    unsigned int currStat = 4; 
    replySize = currStat;

    reply = (char*) malloc (sizeof(char*)*replySize);
    if(reply == NULL) { fprintf(stderr, "Memory Error\n"); return -1; }
    char *replyBuf = reply;

    
    netOrder = htonl(stat);
    memcpy(replyBuf, &netOrder, currStat);
    replyBuf += currStat;

    Rio_writen(connfd, reply, replySize);
    free(reply);

    return stat;

}
void processInput(int connfd, unsigned int secretKey) {
    size_t size;
    //buffers required by all commands
    unsigned char *secretKeyBuf = (unsigned char*)malloc(sizeof(char) * 4);
    unsigned char *requestBuf = (unsigned char*)malloc(sizeof(char) * 4);

    //get and put
    unsigned char *fileSizeBuf = (unsigned char*)malloc(sizeof(char) * 4);
    char *fileNameBuf = (char*)malloc(sizeof(char) * 80);
    char *fileContentsBuf;

    //list buffers
    unsigned char *returnListBuf;

    //return buffers
    unsigned char *returnCodeBuf = (unsigned char*)malloc(sizeof(char) * 4);
    unsigned char *returnSizeCodeBuf = (unsigned char*)malloc(sizeof(char) * 4);

    //RIO stuff
    rio_t rio;
    Rio_readinitb(&rio, connfd);

    //ints parsed from buffers
    unsigned int nsecretKey, request, fileSize;
    unsigned int bufferSize = 0; //for EOF
    //bools used for method logic (not necessary, but helps with reading the file)
    bool shouldUseFilename = false, error = false, list = false, get = false, put = false, del = false;
    
    //read in the secret key and type of request.
    size = Rio_readnb(&rio, secretKeyBuf, 4);
    if(size!=4){
        error = true;
    }
    size = Rio_readnb(&rio, requestBuf, 4);
    if(size!=4){
        error = true;
    }

    //convert the secret key and request buffers to ints
    nsecretKey = char4ToInt(secretKeyBuf);
    request = char4ToInt(requestBuf);
    printf("Secret Key = %d\n", nsecretKey);
    printf("Request Type = ");

    //check the secret keys and set error
    if (nsecretKey != secretKey)
    {
        error = true;
    }

    //print some stuff to the console depending on what command is requested
    switch(request) {
        case 0:
            //get
            printf("get\n");
            printf("Filename = ");
            shouldUseFilename = true;
            get = true;
            break;
        case 1:
            //put
            printf("put\n");
            printf("Filename = ");
            shouldUseFilename = true;
            put = true;
            break;
        case 2:
            //del
            printf("del\n");
            printf("Filename = ");
            shouldUseFilename = true;
            del = true;
            break;
        case 3:
            //list
            printf("list\n");
            printf("Filename = NONE\n");
            list = true;
            break;
        default:
            printf("undefined: %d\n",request);
            printf("Filename = NONE\n");
            error = true;
            break;
    }
    //if the command we're utilizing receives a filename, read it in.
    if (shouldUseFilename) {
        size = Rio_readnb(&rio, fileNameBuf, 80);
        printf("%s\n",fileNameBuf);
    }
    if (put && !error) {
        size = Rio_readnb(&rio, fileSizeBuf, 4);
        fileSize = char4ToInt(fileSizeBuf);
        //printf("Creating file buf of size %d\n",fileSize);
        fileContentsBuf = (char*)malloc(sizeof(char) * (fileSize+1));
        size = Rio_readnb(&rio, fileContentsBuf, fileSize);

        FILE *stream;
        char filePath[100];
        //create the file path
        strcpy(filePath, "./files/");
        strcat(filePath, fileNameBuf);
        if ((stream = fopen(filePath, "w")))
        {
            //write the file
            fwrite(fileContentsBuf, 1, fileSize, stream);
            //Debug print
            //printf("Write: %s\n",fileContentsBuf);
            fclose(stream);
        } else {
            //an error occurred writing the file
            perror("Put file");
            error = true;
        }
    }
    if (list && !error)
    {
         //for end of file
        DIR *d, *e;
        struct dirent *dir;
        //open the files directory
        d = opendir("./files");
        if (d)
        {
            while ((dir = readdir(d)) != NULL)
            {
                if (dir->d_type == DT_REG)
                {
                    //count up the length of each filename (for the length byte)
                    bufferSize += strlen(dir->d_name);
                    bufferSize += 1;
                }
            }
        }
        closedir(d);
        returnListBuf = (unsigned char*)malloc(sizeof(char) * bufferSize);
        e = opendir("./files");
        int counter = 0;
        if (e)
        {
            while ((dir = readdir(e)) != NULL)
            {
                if (dir->d_type == DT_REG)
                {
                    //print each name to a buffer
                    //printf("%s\n",dir->d_name);
                    char temp[strlen(dir->d_name) + 1];
                    sprintf(temp,"%s\n",dir->d_name);
                    memcpy(&returnListBuf[counter], temp, strlen(temp));
                    counter += strlen(temp);
                    // printf("%s\n", dir->d_name);   
                }
            }
        }
    }
    if(get && !error){
        FILE *stream;
        fileSize = 0;
        char filePath[100];
        strcpy(filePath, "./files/");
        strcat(filePath, fileNameBuf);
        //try to open the file (in the files directory)
        if ((stream = fopen(filePath, "rb")))
        {
            //Seek to the end of the file to determine the file size
            fseek(stream, 0L, SEEK_END);
            fileSize = ftell(stream);
            fseek(stream, 0L, SEEK_SET);
            //printf("fileSize: %d\n",fileSize);
            fileContentsBuf = (char*)malloc(sizeof(char) * (fileSize+1));
            size=fread(fileContentsBuf,1,fileSize,stream);
            fileContentsBuf[size]=0; //add EOF
            //Debug print
            //printf("Read: %s\n",fileContentsBuf);
            //printf("Size T: %lu\n", size);
            fclose(stream);
        } else {
            //an error occurred opening the file. It may not exist, or permissions aren't set
            perror("Open file");
            error = true;
        }
    }
    if(del && !error){
        char filePath[100];
        strcpy(filePath, "./files/");
        strcat(filePath, fileNameBuf);
        //delete the file at path
        //printf("deleting file at path: %s\n",filePath);
        int delResult = unlink(filePath);
        if(delResult != 0){
            error = true;
        }
    }
    //all input should be read in now. Now to handle the files themselves
    unsigned int returnCode;
    if(error){
        returnCode = -1;
        printf("Operation Status = error\n");
    } else{
        returnCode = 0;
        printf("Operation Status = success\n");
    }
    intToChar4(returnCode, returnCodeBuf);
    Rio_writen(connfd, returnCodeBuf, 4);
    //printf("sent\n");

    //only send the get and list info if there isn't an error
    if(!error){
        switch(request) {
            case 0:
                //get
                //bufferSize = strlen(fileContentsBuf) + 1;
                //printf("Size of file: %lu\n",size);
                intToChar4(size, returnSizeCodeBuf);
                Rio_writen(connfd, returnSizeCodeBuf, 4);
                Rio_writen(connfd, fileContentsBuf, size);
                // for (unsigned int i = 0; i < size; ++i)
                // {
                //     printf("%02x",fileContentsBuf[i]);
                // }
                break;
            case 3:
                //list
                //printf("Size of files list: %d\n",bufferSize);
                intToChar4(bufferSize, returnSizeCodeBuf);
                Rio_writen(connfd, returnSizeCodeBuf, 4);
                Rio_writen(connfd, returnListBuf, bufferSize);
                break;
            default:
                break;
        }
    }

    printf("--------------------------\n");
}
Exemple #14
0
/* $begin post_dynamic */
static void post_dynamic(int fd, char *filename, int contentLength,rio_t *rp)
{
    char buf[MAXLINE],length[32], *emptylist[] = { NULL },data[MAXLINE];
    int p[2];

    #ifdef HTTPS 
    int httpsp[2];
    #endif

    sprintf(length,"%d",contentLength);
    memset(data,0,MAXLINE);

    Pipe(p);

    /*       The post data is sended by client,we need to redirct the data to cgi stdin.
    *  	 so, child read contentLength bytes data from fp,and write to p[1];
    *    parent should redirct p[0] to stdin. As a result, the cgi script can
    *    read the post data from the stdin. 
    */

    /* https already read all data ,include post data  by SSL_read() */
   
    	if (Fork() == 0)
	{                     /* child  */ 
		Close(p[0]);
		#ifdef HTTPS 
		if(ishttps)
		{
			Write(p[1],httpspostdata,contentLength);	
		}
		else
		#endif
		{
			Rio_readnb(rp,data,contentLength);
			Rio_writen(p[1],data,contentLength);
		}
		exit(0)	;
	}
    
    /* Send response headers to client */
    sprintf(buf, "HTTP/1.0 200 OK\r\n");
    sprintf(buf, "%sServer: Tiny Web Server\r\n",buf);

    #ifdef HTTPS 
    if(ishttps)
    	SSL_write(ssl,buf,strlen(buf));
    else
    #endif
        Rio_writen(fd, buf, strlen(buf));

    //Wait(NULL);
    Dup2(p[0],STDIN_FILENO);  /* Redirct p[0] to stdin */
    Close(p[0]);

    Close(p[1]);
    setenv("CONTENT-LENGTH",length , 1); 

    #ifdef HTTPS 
    if(ishttps)  /* if ishttps,we couldnot redirct stdout to client,we must use SSL_write */
    {
    	Pipe(httpsp);

	if(Fork()==0)
	{
    		Dup2(httpsp[1],STDOUT_FILENO);        /* Redirct stdout to https[1] */ 
		Execve(filename, emptylist, environ); 
	}
	//Wait(NULL);
	Read(httpsp[0],data,MAXLINE);
	SSL_write(ssl,data,strlen(data));
    }
    else
    #endif
    {
    	Dup2(fd,STDOUT_FILENO);        /* Redirct stdout to client */ 
	Execve(filename, emptylist, environ); 
    }
}
Exemple #15
0
/*
 * serve - handle one HTTP request/response transaction
 */
void serve(int to_client_fd)
{
	char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
	char filename[MAXLINE], hostname[MAXLINE];
	char port[10];
	rio_t rio_to_client;
	rio_t rio_to_server;
	int to_server_fd;

	/* Read request line and headers */
	Rio_readinitb(&rio_to_client, to_client_fd);
	Rio_readlineb(&rio_to_client, buf, MAXLINE);
	sscanf(buf, "%s %s %s", method, uri, version);

	/* if not GET method, ignore it */
	if (strcasecmp(method, "GET")) {
		return;
	}

	/* Parse URI from GET request */
	parse_uri(uri, hostname, port, filename);
	// strange display error in csapp page
	if (strcasecmp(hostname, "csapp.cs.cmu.edu") == 0) {
		return;
	}

	sprintf(buf, "%s %s %s\r\n", "GET", filename, "HTTP/1.0");

	/* search content in cache list */
	struct cache_block* ptr = search_cache(head, uri);

	/* cache found, directly send to client */
	if (ptr) {
		// add the number of existing threads reading
		add_reading_cnt(ptr);
		// send cache to client
		Rio_writen(to_client_fd, ptr->file, ptr->size);
		// subtract the number of existing threads reading
		sub_reading_cnt(ptr);
		// update timestamp and reorder LRU list
		update_timestamp(head, ptr);

		return;
	}

	/* cache not found, connect with server */
	to_server_fd = Open_clientfd(hostname, port);
	Rio_readinitb(&rio_to_server, to_server_fd);
	// send request line: GET HTTP/1.0
	Rio_writen(to_server_fd, buf, strlen(buf));
	// send host to server
	sprintf(buf, "Host: %s\r\n", hostname);
	Rio_writen(to_server_fd, buf, strlen(buf));

	
	/* read http headers from client and write to server */
	Rio_readlineb(&rio_to_client, buf, MAXLINE);
	while (strncmp(buf, "\r\n", MAXLINE) != 0) {
		if (strstr(buf, "User-Agent"))
			strncpy(buf, user_agent_hdr, MAXLINE);
		else if (strstr(buf, "Connection"))
			strncpy(buf, "Connection: close\r\n", MAXLINE);
		else if (strstr(buf, "Proxy-Connection"))
			strncpy(buf, "Proxy-Connection: close\r\n", MAXLINE);
		else if (strstr(buf, "Host")) {
			// ignore, because we already sent one
			Rio_readlineb(&rio_to_client, buf, MAXLINE);
			continue;
		}
		Rio_writen(to_server_fd, buf, strlen(buf));
		Rio_readlineb(&rio_to_client, buf, MAXLINE);
	}
	/* terminates request headers */
	Rio_writen(to_server_fd, "\r\n", 2);


	/* read http response from server and write to client */
	memset(buf, 0, MAXLINE);
	Rio_readlineb(&rio_to_server, buf, MAXLINE);
	int content_len = 0;
	
	while (strncmp(buf, "\r\n", MAXLINE) != 0) {
		char* ptr = strstr(buf, "Content-length");
		if (ptr) {
			content_len = atoi(ptr + 16);
		}
		//printf("write2: %s\n", uri);
		//printf("fd: %d\n", to_client_fd);
		//printf("%d: %s\n", strlen(buf), buf);
		Rio_writen(to_client_fd, buf, strlen(buf));
		memset(buf, 0, MAXLINE);
		Rio_readlineb(&rio_to_server, buf, MAXLINE);
	}
	/* terminates response headers */
	Rio_writen(to_client_fd, "\r\n", 2);

	int size = 0;
	int need_cache = 0;
	/* shall we cache it? */
	if (content_len < MAX_OBJECT_SIZE)
		need_cache = 1;

	/* init a new cache block */
	struct cache_block* blk = (struct cache_block*) 
								malloc(sizeof(struct cache_block));
	init_cache(blk);
	strncpy(blk->uri, uri, MAXLINE);

	if (content_len > 0)
		blk->file = (char*) malloc(sizeof(char) * content_len);
	else
		blk->file = (char*) malloc(sizeof(char) * MAX_OBJECT_SIZE);

	memset(buf, 0, MAXLINE);
	int total_size = 0;
	char* headptr = blk->file;

	/* read response contents and write to client */
	while ((size = Rio_readnb(&rio_to_server, buf, MAXLINE)) > 0) {
		total_size += size;
		if (total_size > MAX_OBJECT_SIZE)
			need_cache = 0;
		if (need_cache) {
			memcpy(headptr, buf, size);
			headptr += size;
		}
		//printf("write3: %s\n", uri);
		Rio_writen(to_client_fd, buf, size);
		memset(buf, 0, MAXLINE);
	}

	/* add cache block */
	if (need_cache) {
		blk->size = total_size;
		// resize block
		blk->file = (char*) realloc(blk->file, blk->size);
		// size overflow, need to evict using LRU
		if (blk->size + cache_size > MAX_CACHE_SIZE)
			evict_cache(head, blk->size);
		// add it
		add_cache(head, blk);
	}
	/* prevent memory leakage */
	else {
		free_cache_node(blk);
	}

	Close(to_server_fd);
	return;
}