From: Urban Wallasch Date: Sun, 21 Jul 2019 19:09:27 +0000 (+0200) Subject: * Separated shared memory management and HTTP server code. X-Git-Tag: v0.1.0~88 X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=27f3e0d27e66143d877ed6ad10106d560682764e;p=ets2_tele.git * Separated shared memory management and HTTP server code. * Improved Makefile logic. --- diff --git a/.gitignore b/.gitignore index 7345d5c..c6d1916 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ *.o *.so -shmget +telehttpd diff --git a/Makefile b/Makefile index 8500317..e4156d4 100644 --- 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 diff --git a/shmget.c b/shmget.c index 2a29955..dbf5660 100644 --- a/shmget.c +++ b/shmget.c @@ -1,217 +1,32 @@ +#include +#include #include #include #include -#include - #include -#include - -#include #include -#include #include #include -#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 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 index 0000000..90240c9 --- /dev/null +++ b/telehttpd.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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; +}