summaryrefslogtreecommitdiffstats
path: root/demo/nginx_proxy/demo-3/server/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'demo/nginx_proxy/demo-3/server/test.c')
-rw-r--r--demo/nginx_proxy/demo-3/server/test.c315
1 files changed, 315 insertions, 0 deletions
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..d0e9ecb
--- /dev/null
+++ b/demo/nginx_proxy/demo-3/server/test.c
@@ -0,0 +1,315 @@
+/*
+ * 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 <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/mman.h>
+
+#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;
+}