From 224195a2c6144aa2a2c6ca06794115b3c654469d Mon Sep 17 00:00:00 2001 From: rainbow_0206 Date: Tue, 25 Dec 2018 11:39:02 +0800 Subject: Feat: Nginx demo with rsocket and kernel Change-Id: Iaaf27f3cdf7b99e9bd8c46889a1bda753834bda5 Signed-off-by: rainbow_0206 --- demo/nginx_proxy/demo-3/server/index.html | 31 +++ demo/nginx_proxy/demo-3/server/test.c | 320 ++++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+) create mode 100644 demo/nginx_proxy/demo-3/server/index.html create mode 100644 demo/nginx_proxy/demo-3/server/test.c (limited to 'demo/nginx_proxy/demo-3/server') diff --git a/demo/nginx_proxy/demo-3/server/index.html b/demo/nginx_proxy/demo-3/server/index.html new file mode 100644 index 0000000..9ab30e1 --- /dev/null +++ b/demo/nginx_proxy/demo-3/server/index.html @@ -0,0 +1,31 @@ + + + + + + + + Hello, world + + + + + +

Hello, world

+ + +

Click on the button to fetch the message.

+ + + diff --git a/demo/nginx_proxy/demo-3/server/test.c b/demo/nginx_proxy/demo-3/server/test.c new file mode 100644 index 0000000..9ffde09 --- /dev/null +++ b/demo/nginx_proxy/demo-3/server/test.c @@ -0,0 +1,320 @@ +/* + * httpd.c + * + * Copyright Adin Scannell 2011 + * + * This code is intended for demo purposes only, + * please don't actually use it to do anything. + * + * To compile, use: + * gcc -o httpd httpd.c + * Then, create a file 'index.html' in the directory + * that you are running the server from. Put stuff in + * it. + * Then go to http://localhost:8888 and see the file. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define HTTP_BAD_REQUEST "HTTP/1.0 404 Not Found\r\n" +#define HTTP_GOOD_REQUEST "HTTP/1.0 200\r\n" +#define HTTP_CONTENT_TYPE "Content-Type: text/html\r\n" +#define HTTP_CONTENT_LENGTH "Content-Length: %ld\r\n\r\n" +#define MAX_REQUEST_SIZE 4096 +#define DEFAULT_PATH "index.html" + +#define DEBUG +#ifdef DEBUG +#define log(fmt, args...) fprintf(stderr, fmt "\n", ## args) +#else +#define log(fmt, args...) +#endif + +int +send_error (int fd) +{ + write (fd, HTTP_BAD_REQUEST, strlen (HTTP_BAD_REQUEST)); + write (fd, HTTP_CONTENT_TYPE, strlen (HTTP_CONTENT_TYPE)); + return 0; +} + +int +send_file (int fd, char *path) +{ + int iofd = open (path, O_RDONLY); + + int ret = 0; + if (iofd < 0) + { + write (fd, HTTP_BAD_REQUEST, strlen (HTTP_BAD_REQUEST)); + write (fd, HTTP_CONTENT_TYPE, strlen (HTTP_CONTENT_TYPE)); + log ("error opening file"); + } + else + { + char length[MAX_REQUEST_SIZE]; + struct stat statinfo; + if (fstat (iofd, &statinfo) < 0) + { + /* Can't get the length. */ + write (fd, HTTP_BAD_REQUEST, strlen (HTTP_BAD_REQUEST)); + write (fd, HTTP_CONTENT_TYPE, strlen (HTTP_CONTENT_TYPE)); + log ("error fetching size"); + } + else + { + ret = write (fd, HTTP_GOOD_REQUEST, strlen (HTTP_GOOD_REQUEST)); + + log ("write HTTP_GOOD_REQUEST %s ret %d", HTTP_GOOD_REQUEST, ret); + ret = write (fd, HTTP_CONTENT_TYPE, strlen (HTTP_CONTENT_TYPE)); + log ("write HTTP_CONTENT_TYPE %s ret %d", HTTP_CONTENT_TYPE, ret); + snprintf (length, MAX_REQUEST_SIZE, + HTTP_CONTENT_LENGTH, statinfo.st_size); + + ret = write (fd, length, strlen (length)); + log ("write %s ret %d", length, ret); + +#if 1 +#if 1 + //char *source = NULL; + //source = malloc(sizeof(char) * (statinfo.st_size + 1)); + void *file_addr = NULL; + file_addr = + mmap (NULL, statinfo.st_size, PROT_READ, MAP_PRIVATE, iofd, 0); + + if (write (fd, file_addr, statinfo.st_size) < 0) + { + perror ("wyl new"); + } + +#else +// if( write(fd, length, strlen(length)) < 0 || + if (sendfile (fd, iofd, NULL, statinfo.st_size) < 0) + { + /* Error sending the file. Nothing can be done. */ + perror ("error writing file"); + } +#endif + +#endif + close (fd); + } + + close (iofd); + } + + return 0; +} + +int +process (int fd, char *header) +{ + char npath[MAX_REQUEST_SIZE]; + + char *eol = strchr (header, '\r'); + + /* Nuts to thread-safe, this demo uses it's own process :P */ + char *method = strtok (header, " "); + char *path = strtok (NULL, " "); + char *http = strtok (NULL, " "); + + if (eol != NULL) + { + *eol = '\0'; + } + + /* Debug output here, just in case anyone is watching. */ + log (" * method = %s", method); + log (" * path = %s", path); + log (" * http = %s", http); + + /* Ensure that we can process it. */ + if (strcmp (method, "GET") || + (strcmp (http, "HTTP/1.0") && strcmp (http, "HTTP/1.1"))) + { + log ("bad request"); + return send_error (fd); + } + else + { + if (path[0] == '/' && path[1] == '\0') + { + path = DEFAULT_PATH; + } + else if (path[0] == '/') + { + snprintf (npath, MAX_REQUEST_SIZE, ".%s", path); + path = npath; + } + log ("sending %s to %d", path, fd); + return send_file (fd, path); + } +} + +int +service (int fd) +{ + char buffer[MAX_REQUEST_SIZE]; + int readbytes = 0, scanned = 0; + + /* Attempt to read a chunk of bytes, but not process forever. */ + while (readbytes < (MAX_REQUEST_SIZE - 1)) + { + log ("read from %d", fd); + int cur = + read (fd, &(buffer[readbytes]), (MAX_REQUEST_SIZE - 1) - readbytes); + if (cur < 0) + { + perror ("read failed"); + return -1; + } + else + { + buffer[readbytes + cur + 1] = '\0'; + readbytes += cur; + } + + /* Check for the \n\n found at the end of the header. */ + for (; scanned < readbytes - 3; scanned++) + { + if (buffer[scanned] == '\r' && buffer[scanned + 1] == '\n' && + buffer[scanned + 2] == '\r' && buffer[scanned + 3] == '\n') + { + buffer[scanned] = '\0'; + return process (fd, buffer); + } + } + } + + /* Failed to find the end of the header. */ + log ("header too long"); + return -1; +} + +int +main (int argc, char *argv[]) +{ + + struct sockaddr_in servaddr; + int serversock = socket (AF_INET, SOCK_STREAM, 0); + int on = 1; + + if (NULL == argv[1]) + { + log ("please set the ip argument"); + return 1; + } + + /* Create socket. */ + if (serversock < 0) + { + perror ("error creating socket"); + return 1; + } + + /* Tweak it for reuse. Not necessary for fork, just useful * + * when one is killing and running this server a few times. */ + if (setsockopt (serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) + { + perror ("unable to tweak socket options"); + } + + /* Bind to port 8888. */ + memset (&servaddr, 0, sizeof (servaddr)); + servaddr.sin_family = AF_INET; + //servaddr.sin_addr.s_addr = inet_addr("192.168.21.180"); + servaddr.sin_addr.s_addr = inet_addr (argv[1]); + servaddr.sin_port = htons (8888); + if (bind (serversock, (struct sockaddr *) &servaddr, sizeof (servaddr)) < 0) + { + perror ("couldn't bind to given address"); + return 1; + } + log ("bound to %s:8888", argv[1]); + + /* Start listening, queue size 10. */ + if (listen (serversock, 10) < 0) + { + perror ("listen failed"); + return 1; + } + log ("listening"); + + /* Enter the service loop. */ + while (1) + { + int clientsock, pid, childstatus; + log ("waiting for next request"); + + /* Grab the next request. */ + clientsock = accept (serversock, NULL, NULL); + if (clientsock < 0) + { + perror ("accept failed"); + break; + } + log ("accepted connection %d from %d, forking ", clientsock, + serversock); + + /* Fork off a handler. */ + //pid = fork(); + pid = 0; + if (pid < 0) + { + perror ("fork failed"); + close (clientsock); + continue; + } + else if (pid > 0) + { + close (clientsock); + } + else + { + //close(serversock); + log ("servicing connection (as child) sfd %d cfd %d", serversock, + clientsock); + service (clientsock); + //return 0; + } + + /* Collect any exit statuses (lazy). */ + +#if 0 + while (1) + { + pid = waitpid (-1, &childstatus, WNOHANG); + if (pid < 0) + { + perror ("waitpid error?"); + break; + } + else if (pid == 0) + { + break; + } + else if (WIFEXITED (childstatus)) + { + log ("child %d exited with status %d", pid, + WEXITSTATUS (childstatus)); + } + } +#endif + + } + + /* Should never arrive here. */ + return 254; +} -- cgit