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/README.md | 11 +- demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md | 26 ++ demo/nginx_proxy/demo-3/proxy_nginx.conf | 81 +++++++ demo/nginx_proxy/demo-3/rd_config.json | 23 ++ demo/nginx_proxy/demo-3/rsocket.png | Bin 0 -> 10614 bytes demo/nginx_proxy/demo-3/server/index.html | 31 +++ demo/nginx_proxy/demo-3/server/test.c | 320 +++++++++++++++++++++++++ 7 files changed, 489 insertions(+), 3 deletions(-) create mode 100644 demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md create mode 100644 demo/nginx_proxy/demo-3/proxy_nginx.conf create mode 100644 demo/nginx_proxy/demo-3/rd_config.json create mode 100644 demo/nginx_proxy/demo-3/rsocket.png create mode 100644 demo/nginx_proxy/demo-3/server/index.html create mode 100644 demo/nginx_proxy/demo-3/server/test.c diff --git a/demo/nginx_proxy/README.md b/demo/nginx_proxy/README.md index b8a9705..4085cc9 100644 --- a/demo/nginx_proxy/README.md +++ b/demo/nginx_proxy/README.md @@ -13,7 +13,12 @@ Procedures and details of how to run this demo is inside each demo directory. This demo use NGINX as a reverse proxy server. The server uses lwip as client facing stack and kernel tcp/ip stack as upstream server facing stack. -##demo-2 +##demo-2 -This demo NGINX as a reverse proxy server. The server uses lwip as client facing stack and kernel tcp/ip stack -as upstream server facing stack for UDP, vpp-hoststack for another updtream server facing stack for TCP. \ No newline at end of file +This demo NGINX as a reverse proxy server. The server uses lwip as client facing stack and kernel tcp/ip stack +as upstream server facing stack for UDP, vpp-hoststack for another updtream server facing stack for TCP. + +##demo-3 + +This demo NGINX as a reverse proxy server. The server uses kernel tcp/ip as client facing stack and rsocket +stack as upstream server facing stack. diff --git a/demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md b/demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md new file mode 100644 index 0000000..6deb348 --- /dev/null +++ b/demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md @@ -0,0 +1,26 @@ +# Demo: NGINX working with multi-stack using DMM + +![image](rsocket.png) + + + +In above diagram NGINX box in the middle is working as reverse proxy. +One of the NIC ( client facing) is using kernel tcp/ip stack whereas the +other NIC is connected to upstream server using rsocket tcp/ip stack. + +you can use test.c to compile a server depend on libnStackAPI.so. It bind the +port 8888 by default and you can change it to other port. Then copy the +module_config.json rd_config.json to the folder of server. Then you can start the +server as follow: +./server 162.128.1.16 + +####More Information: +https://wiki.fd.io/view/DMM +https://www.nginx.com/blog/ip-transparency-direct-server-return-nginx-plus-transparent-proxy/ + + + + + + + diff --git a/demo/nginx_proxy/demo-3/proxy_nginx.conf b/demo/nginx_proxy/demo-3/proxy_nginx.conf new file mode 100644 index 0000000..fb085ac --- /dev/null +++ b/demo/nginx_proxy/demo-3/proxy_nginx.conf @@ -0,0 +1,81 @@ +user root; +worker_processes 1; +daemon off; +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server { + listen 192.168.131.181:80 default_server; + server_name 192.168.131.181; + + location / { + proxy_bind 192.168.21.181; + proxy_pass http://192.168.21.180:8888; + proxy_set_header X-Real-IP $remote_addr; + sendfile off; + proxy_buffering off; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} + } + + +} diff --git a/demo/nginx_proxy/demo-3/rd_config.json b/demo/nginx_proxy/demo-3/rd_config.json new file mode 100644 index 0000000..51fa4a5 --- /dev/null +++ b/demo/nginx_proxy/demo-3/rd_config.json @@ -0,0 +1,23 @@ +{ + "ip_route": [ + { + "subnet": "192.168.131.1/24", + "stack_name": "kernel", + }, + { + "subnet": "192.168.21.1/24", + "stack_name": "rsocket", + }, + ], + "prot_route": [ + { + "proto_type": "1", + "stack_name": "rsocket", + }, + { + "proto_type": "2", + "stack_name": "kernel", + } + ], +} + diff --git a/demo/nginx_proxy/demo-3/rsocket.png b/demo/nginx_proxy/demo-3/rsocket.png new file mode 100644 index 0000000..389ae19 Binary files /dev/null and b/demo/nginx_proxy/demo-3/rsocket.png differ 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 1.2.3-korg