diff options
| author | Kyle K <kylek389@gmail.com> | 2011-09-15 02:14:13 -0500 | 
|---|---|---|
| committer | Kamil Kaminski <kamilkss@gmail.com> | 2011-09-15 02:23:41 -0500 | 
| commit | 3235e6a3bc66cf7c6667a1cd3d1485431e50197c (patch) | |
| tree | 97221e5cd03a3a45bf03de2e55a2a79da9f033e6 | |
| parent | 76765068743a956fb68d9b942426bcd43e84f092 (diff) | |
| download | sandbox-3235e6a3bc66cf7c6667a1cd3d1485431e50197c.tar.gz sandbox-3235e6a3bc66cf7c6667a1cd3d1485431e50197c.tar.bz2 sandbox-3235e6a3bc66cf7c6667a1cd3d1485431e50197c.zip  | |
tcpserver2: import
| -rw-r--r-- | tcpserver2.c | 164 | 
1 files changed, 164 insertions, 0 deletions
diff --git a/tcpserver2.c b/tcpserver2.c new file mode 100644 index 0000000..629feef --- /dev/null +++ b/tcpserver2.c @@ -0,0 +1,164 @@ +/* Kamil Kaminski + * kkamin8@uic.edu + * + * + * Note: implement content-size, if index.html is not present, generate a page + *       that lists root directory, you can use select() to deal with multiple + *       requests instead of forking + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/wait.h> + +int main(int argc, char **argv) +{ +    if (argc != 3) +    { +        fprintf(stderr, "usage: %s <port> <dir>\n", argv[0]); +        exit(1); +    } + +    int server_sockfd, ret; + +    if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) +    { +        perror("socket"); +        close(server_sockfd); +        exit(-1); +    } + +    /* allow fast reuse of ports */ +    int reuse_true = 1; +    setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_true, +               sizeof(reuse_true)); + +    struct sockaddr_in addr; +    addr.sin_family = AF_INET; +    addr.sin_port = htons(atoi(argv[1])); +    addr.sin_addr.s_addr = INADDR_ANY; + +    if (bind(server_sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) +    { +        perror("bind"); +        exit(-1); +    } + +    if (listen(server_sockfd, 0) == -1) +    { +        perror("listen"); +        exit(-1); +    } + +    while (1) +    { +        int sockfd; +        struct sockaddr_in remote_addr; +        unsigned int socklen = sizeof(remote_addr);  +        sockfd = accept(server_sockfd, (struct sockaddr *) &remote_addr, &socklen); +        if (sockfd == -1) +        { +            perror("accept"); +            continue; +        } + +        char ipstr[INET6_ADDRSTRLEN]; +        inet_ntop(remote_addr.sin_family, &remote_addr.sin_addr, ipstr, sizeof(ipstr)); +        printf("got connection from %s\n", ipstr); + +        /* read the http header request from the client */ +        char recv_buff[512] = { 0 }; +        if ((ret = recv(sockfd, recv_buff, sizeof(recv_buff), 0)) < 0) +        { +            perror("recv"); +            shutdown(sockfd, SHUT_RDWR); +            close(sockfd); +            continue; +        } +        /* printf("%s", recv_buff); */ + +        char *p; +        if (!(p = strstr(recv_buff, "GET"))) +            continue; + +        char filereq[100] = { 0 }; +        sscanf(p, "GET %s HTTP/1.*[01]\r\n", filereq); +        printf("requested file: \"%s\"\n", filereq); + +        char path[200] = { 0 }; +        sprintf(path, "%s%s", argv[2], filereq[strlen(filereq) - 1] == '/' ? +                "/index.html" : filereq); +        printf("path is: \"%s\"\n", path); + +        struct stat stat_buff; +        if (stat(path, &stat_buff) == -1) +        { +            perror("stat"); +            char err[] = "HTTP/1.0 404 Not Found\r\n\r\n"; +            send(sockfd, err, sizeof(err), 0); +        } +        else +        { +            pid_t pid; +            if ((pid = fork()) == 0) +            { +                char http_header[100] = { 0 }; +                char *p = strstr(path, "."), *type = NULL; +                if (p) +                { +                    if (strcmp(p, ".html") == 0) +                        type = "Content-Type: text/html\r\n"; +                    else if (strcmp(p, ".gif") == 0) +                        type = "Content-Type: image/gif\r\n"; +                    else if (strcmp(p, ".png") == 0) +                        type = "Content-Type: image/png\r\n"; +                    else if (strcmp(p, ".jpeg") == 0 || strcmp(p, ".jpg") == 0) +                        type = "Content-Type: image/jpeg\r\n"; +                    else if (strcmp(p, ".pdf") == 0) +                        type = "Content-Type: application/pdf\r\n"; +                } +                sprintf(http_header, "%s%s\r\n", "HTTP/1.1 200 OK\r\n", type ? type : "\r\n"); +                /* printf("http header:\n\"%s\"\n", http_header); */ + +                FILE *fp = fopen(path, "r"); +                char *file = (char *) malloc(sizeof(char) * (stat_buff.st_size + strlen(http_header))); +                if (file && fp) +                { +                    memcpy(file, http_header, strlen(http_header)); +                    fread(file + strlen(http_header), stat_buff.st_size, sizeof(char), fp); +                    send(sockfd, file, stat_buff.st_size + strlen(http_header), 0); +                    free(file); +                } +                fclose(fp); +                shutdown(sockfd, SHUT_RDWR); +                close(sockfd); +                exit(0); +            } +            else if (pid > 0) +            { +                wait(NULL); +            } +            else +            { +                perror("fork"); +                shutdown(sockfd, SHUT_RDWR); +                close(sockfd); +            } +        } +    } + +    shutdown(server_sockfd, SHUT_RDWR); +    close(server_sockfd); +} +  | 
