* Separated shared memory management and HTTP server code.
authorUrban Wallasch <urban.wallasch@freenet.de>
Sun, 21 Jul 2019 19:09:27 +0000 (21:09 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Sun, 21 Jul 2019 19:09:27 +0000 (21:09 +0200)
* Improved Makefile logic.

.gitignore
Makefile
shmget.c
shmget.h [new file with mode: 0644]
telehttpd.c [new file with mode: 0644]

index 7345d5c3a956447dc7a47dbd11db3365343ee044..c6d1916f130b3ab390311780a25eecf7a93ac700 100644 (file)
@@ -1,3 +1,3 @@
 *.o
 *.so
-shmget
+telehttpd
index 8500317c493a36de88360f29e6673c7e479ca254..e4156d456d6653bcda4b48c4ebcb71b544bcbd43 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,34 +1,40 @@
-.PHONY: all clean
 
-all: shmget telemetry.so
+SELF := $(lastword $(MAKEFILE_LIST))
 
 SDK_HEADERS=\
-       sdk/include/*.h \
-       sdk/include/common/*.h \
-       sdk/include/amtrucks/*.h \
-       sdk/include/eurotrucks2/*.h
+  sdk/include/*.h \
+  sdk/include/common/*.h \
+  sdk/include/amtrucks/*.h \
+  sdk/include/eurotrucks2/*.h
 
 SDK_INCLUDES=\
-       -Isdk/include \
-       -Isdk/include/common/ \
-       -Isdk/include/amtrucks/ \
-       -Isdk/include/eurotrucks2
+  -Isdk/include \
+  -Isdk/include/common/ \
+  -Isdk/include/amtrucks/ \
+  -Isdk/include/eurotrucks2
 
-CFLAGS=-Wall -std=gnu99 -DDEBUG -I.
+CFLAGS=-Wall -Wextra -std=gnu99 -DDEBUG -I.
 
 UNAME:= $(shell uname -s)
 
 ifeq ($(UNAME),Darwin)
-LIB_NAME_OPTION=-install_name
+  LIB_NAME_OPTION=-install_name
 else
-LIB_NAME_OPTION=-soname
+  LIB_NAME_OPTION=-soname
 endif
 
+.PHONY: all clean
+
+all: telehttpd telemetry.so
+
 telemetry.so: telemetry.cpp $(SDK_HEADERS)
        g++ -o $@ -fPIC -Wall --shared -Wl,$(LIB_NAME_OPTION),$@ $(SDK_INCLUDES) telemetry.cpp
 
-shmget: shmget.o net.o fserv.o ntime.o
-               $(CC) $(LDFLAGS) -o $@ -pthread $^
+telehttpd: telehttpd.o shmget.o net.o fserv.o ntime.o
+       $(CC) $(LDFLAGS) -o $@ -pthread $^
+
+%.o: %.c $(SELF)
+       $(CC) -c $(CFLAGS) -o $*.o $*.c
 
 clean:
-       @rm -f -- *.so *.o shmget
+       @rm -f -- *.so *.o telehttpd
index 2a29955ec10cc9d184ba2415b89ed5314f198d27..dbf5660ededb8c70c89443412c1a36cd0c555e69 100644 (file)
--- a/shmget.c
+++ b/shmget.c
+#include <stdio.h>
+#include <stdlib.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
-#include <stdio.h>
-
 #include <errno.h>
-#include <poll.h>
-
-#include <pthread.h>
 
 #include <unistd.h>
-#include <signal.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
 
-#include "fserv.h"
-#include "net.h"
+#include "shmget.h"
 #include "log.h"
-#include "telemetry.h"
 
 struct telemetry_state_t *telemetry;
 
-static volatile int force_quit;
-
-static void handle_signal(int sig) {
-    fprintf (stderr, "SIGNAL: %d\n", sig);
-    switch (sig){
-    case SIGTERM:
-    case SIGINT:
-        force_quit = 1;
-        break;
-    }
-}
-
-enum respond_code {
-    r_index,
-    r_json,
-    r_none
-};
-
-static void respond(int fd, const char *req, int code) {
-    char buf[4096];
-    char origin[256] = "http://localhost";
-    char host[256] = "localhost";
-    const char *s;
-    switch (code) {
-    case r_json:
-    case r_index:
-        s = strstr(req, "Origin:");
-        if (s){
-            s += 8; //strlen("Origin: ");
-            const char *e = strstr(s, "\r\n");
-            strncpy(origin, s, e-s);
-        }
-        s = strstr(req, "Host:");
-        if (s){
-            s += 6;//strlen("Host: ");
-            const char *e = strstr(s, "\r\n");
-            strncpy(host, s, e-s);
-        }
-
-        write(fd, buf, sprintf (buf, "HTTP/1.1 200 OK\r\n"));
-        write(fd, buf, sprintf (buf, "Host: %s\r\n", host));
-        if (r_json == code){
-            write(fd, buf, sprintf (buf, "Access-Control-Allow-Origin: %s\r\n", origin));
-            write(fd, buf, sprintf (buf, "Content-type: text/json\r\n"));
-            write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
-            write(fd, buf, sprintf (buf, "{ \"fc_avg\": %3.2f, \"speed\": %3.2f, \"cc\": %3.2f }",
-                        100.0 * telemetry->fc_avg , telemetry -> speed * 3.6, telemetry -> cc * 3.6));
-        } else {
-            struct file_info_t fi;
-            if (0 == fserv_open_server("index.html", &fi)){
-                write(fd, buf, sprintf (buf, "Content-type: text/html\r\n"));
-                write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
-                fserv_sendfile(fd, &fi);
-                fserv_close(&fi);
-            } else {
-                write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
-                write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
-                write(fd, buf, sprintf (buf, "Tough luck"));
-            }
-        }
-        break;
-    case r_none:
-        write(fd, buf, sprintf (buf, "HTTP/1.1 404 Not Found\r\n"));
-        write(fd, buf, sprintf (buf, "Host: localhost\r\n"));
-        write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
-        write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
-        write(fd, buf, sprintf (buf, "Fuck you 404!"));
-        break;
-    default:
-        write(fd, buf, sprintf (buf, "HTTP/1.1 500 Internal Server Error\r\n"));
-        write(fd, buf, sprintf (buf, "Host: localhost\r\n"));
-        write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
-        write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
-        write(fd, buf, sprintf (buf, "Fuck you 500!"));
-        break;
-    }
-}
-
-static int receive(int fd, int timeout) {
-    struct pollfd pe;
-    int res;
-    pe.fd = fd;
-    char buf[2048];
-    int bread, total;
-
-    total = 0;
-    *buf = 0;
-    do {
-        pe.events = POLLIN;
-        pe.revents = 0;
-        res = poll(&pe, 1, timeout);
-        if ( 0 < res && pe.revents == POLLIN ) {
-            errno = 0;
-            bread = read(fd, buf + total, sizeof buf - total);
-            if ( 0 > bread ) {
-                switch (errno) {
-                case EAGAIN:
-                //case EWOULDBLOCK:
-                case EINTR:
-                    break;
-                default:
-                    res = -1;
-                    break;
-                }
-            }
-            else if ( 0 == bread && 0 == errno ) {
-                res = -1;
-            }
-            else {
-                total += bread;
-                buf[total] = 0;
-                if ( strstr(buf, "\r\n\r\n" ) ) {
-                    fprintf (stderr, "%s", buf);
-                    if (0 == strncmp(buf, "GET /json HTTP", 10))
-                        respond(fd, buf, r_json);
-                    else if (0 == strncmp(buf, "GET / HTTP", 10))
-                        respond(fd, buf, r_index);
-                    else
-                        respond(fd, NULL, r_none);
-                    *buf = 0;
-                    res = 0;
-                }
-            }
-        }
-        timeout = 200;
-    } while ( 1 == res && pe.revents == POLLIN && !force_quit );
-    return res;
-}
-
-static void *handle_conn( void *p ) {
-    int sock = *(int*)p;
-    int err;
-
-    DPRINT( "sock: %d\n", sock );
-    do {
-        err = receive(sock, 1000);
-    } while ( 0 < err && !force_quit );
-    net_close( sock );
-    return p;
-}
-
-static int shmgetter(void) {
-    int ret;
+int init_shm(void) {
     int shmid;
-    int as, ss;
-    pthread_t tid;
-    pthread_attr_t attr;
 
     shmid = shmget(SHM_KEY, sizeof *telemetry,  0);
     if ( 0 > shmid ) {
         EPRINT( "shmget failed\n" );
-        ret = -1;
-        goto err_shmget;
+        return -1;
     }
-
     telemetry = shmat(shmid, NULL, SHM_RDONLY);
     if ((void *)-1 == telemetry) {
         EPRINT( "shmget failed\n" );
-        ret = -2;
-        goto err_shmat;
-    }
-
-    ss = net_open_server( 8837, "*" );
-    if ( ss < 0 ) {
-        EPRINT( "net_open_server failed!\n" );
-        ret = -3;
-        goto err_open_server;
-    }
-
-    while ( !force_quit ) {
-        if ( (as = net_accept( ss )) > 0 ) {
-            pthread_attr_init(&attr);
-            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-            pthread_create(&tid, &attr, handle_conn, &as);
-            usleep (100);
-        }
+        shmdt(telemetry);
+        return -2;
     }
-
-err_open_server:
-err_shmat:
-    shmdt(telemetry);
-err_shmget:
-    return ret;
-}
-
-int main(int argc, char *argv[]) {
-    int res;
-
-    //install signal handlers
-    signal(SIGTERM, handle_signal);
-    signal(SIGINT,  handle_signal);
-    res = shmgetter();
-    puts("");
-    return res;
+    return 0;
 }
diff --git a/shmget.h b/shmget.h
new file mode 100644 (file)
index 0000000..4082785
--- /dev/null
+++ b/shmget.h
@@ -0,0 +1,11 @@
+#ifndef SHMGET_H_
+#define SHMGET_H_
+
+#include "telemetry.h"
+
+extern struct telemetry_state_t *telemetry;
+
+extern int init_shm(void);
+
+#endif /* SHMGET_H_ */
+
diff --git a/telehttpd.c b/telehttpd.c
new file mode 100644 (file)
index 0000000..90240c9
--- /dev/null
@@ -0,0 +1,194 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <poll.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include "fserv.h"
+#include "net.h"
+#include "log.h"
+#include "shmget.h"
+
+static volatile int force_quit;
+
+static void handle_signal(int sig) {
+    fprintf (stderr, "SIGNAL: %d\n", sig);
+    switch (sig){
+    case SIGTERM:
+    case SIGINT:
+        force_quit = 1;
+        break;
+    }
+}
+
+enum respond_code {
+    r_index,
+    r_json,
+    r_none
+};
+
+static void respond(int fd, const char *req, int code) {
+    char buf[4096];
+    char origin[256] = "http://localhost";
+    char host[256] = "localhost";
+    const char *s;
+    switch (code) {
+    case r_json:
+    case r_index:
+        s = strstr(req, "Origin:");
+        if (s){
+            s += 8; //strlen("Origin: ");
+            const char *e = strstr(s, "\r\n");
+            strncpy(origin, s, e-s);
+        }
+        s = strstr(req, "Host:");
+        if (s){
+            s += 6;//strlen("Host: ");
+            const char *e = strstr(s, "\r\n");
+            strncpy(host, s, e-s);
+        }
+
+        write(fd, buf, sprintf (buf, "HTTP/1.1 200 OK\r\n"));
+        write(fd, buf, sprintf (buf, "Host: %s\r\n", host));
+        if (r_json == code){
+            write(fd, buf, sprintf (buf, "Access-Control-Allow-Origin: %s\r\n", origin));
+            write(fd, buf, sprintf (buf, "Content-type: text/json\r\n"));
+            write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
+            write(fd, buf, sprintf (buf, "{ \"fc_avg\": %3.2f, \"speed\": %3.2f, \"cc\": %3.2f }",
+                        100.0 * telemetry->fc_avg , telemetry -> speed * 3.6, telemetry -> cc * 3.6));
+        } else {
+            struct file_info_t fi;
+            if (0 == fserv_open_server("index.html", &fi)){
+                write(fd, buf, sprintf (buf, "Content-type: text/html\r\n"));
+                write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
+                fserv_sendfile(fd, &fi);
+                fserv_close(&fi);
+            } else {
+                write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
+                write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
+                write(fd, buf, sprintf (buf, "Tough luck"));
+            }
+        }
+        break;
+    case r_none:
+        write(fd, buf, sprintf (buf, "HTTP/1.1 404 Not Found\r\n"));
+        write(fd, buf, sprintf (buf, "Host: localhost\r\n"));
+        write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
+        write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
+        write(fd, buf, sprintf (buf, "Fuck you 404!"));
+        break;
+    default:
+        write(fd, buf, sprintf (buf, "HTTP/1.1 500 Internal Server Error\r\n"));
+        write(fd, buf, sprintf (buf, "Host: localhost\r\n"));
+        write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
+        write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
+        write(fd, buf, sprintf (buf, "Fuck you 500!"));
+        break;
+    }
+}
+
+static int receive(int fd, int timeout) {
+    struct pollfd pe;
+    int res;
+    pe.fd = fd;
+    char buf[2048];
+    int bread, total;
+
+    total = 0;
+    *buf = 0;
+    do {
+        pe.events = POLLIN;
+        pe.revents = 0;
+        res = poll(&pe, 1, timeout);
+        if ( 0 < res && pe.revents == POLLIN ) {
+            errno = 0;
+            bread = read(fd, buf + total, sizeof buf - total);
+            if ( 0 > bread ) {
+                switch (errno) {
+                case EAGAIN:
+                //case EWOULDBLOCK:
+                case EINTR:
+                    break;
+                default:
+                    res = -1;
+                    break;
+                }
+            }
+            else if ( 0 == bread && 0 == errno ) {
+                res = -1;
+            }
+            else {
+                total += bread;
+                buf[total] = 0;
+                if ( strstr(buf, "\r\n\r\n" ) ) {
+                    fprintf (stderr, "%s", buf);
+                    if (0 == strncmp(buf, "GET /json HTTP", 10))
+                        respond(fd, buf, r_json);
+                    else if (0 == strncmp(buf, "GET / HTTP", 10))
+                        respond(fd, buf, r_index);
+                    else
+                        respond(fd, NULL, r_none);
+                    *buf = 0;
+                    res = 0;
+                }
+            }
+        }
+        timeout = 200;
+    } while ( 1 == res && pe.revents == POLLIN && !force_quit );
+    return res;
+}
+
+static void *handle_conn( void *p ) {
+    int sock = *(int*)p;
+    int err;
+
+    DPRINT( "sock: %d\n", sock );
+    do {
+        err = receive(sock, 1000);
+    } while ( 0 < err && !force_quit );
+    net_close( sock );
+    return p;
+}
+
+static int serve_http(void) {
+    int as, ss;
+    pthread_t tid;
+    pthread_attr_t attr;
+
+    ss = net_open_server( 8837, "*" );
+    if ( ss < 0 ) {
+        EPRINT( "net_open_server failed!\n" );
+        return -1;
+    }
+
+    while ( !force_quit ) {
+        if ( (as = net_accept( ss )) > 0 ) {
+            pthread_attr_init(&attr);
+            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+            pthread_create(&tid, &attr, handle_conn, &as);
+            usleep (100);
+        }
+    }
+
+    return 0;
+}
+
+int main(int argc, char *argv[]) {
+    signal(SIGTERM, handle_signal);
+    signal(SIGINT,  handle_signal);
+
+    if ( 0 != init_shm() )
+        exit( EXIT_FAILURE);
+
+    if ( 0 != serve_http() )
+        exit( EXIT_FAILURE);
+
+    exit( EXIT_SUCCESS );
+    (void)argc; (void)argv;
+}