// // gcc mongoose.c diuhttp.c -o diuhttp // #include "mongoose.h" #include #define _SLEN 1024 static const char *s_http_port = "60535"; static struct mg_serve_http_opts s_http_server_opts; static int is_websocket(const struct mg_connection *nc) { return nc->flags & MG_F_IS_WEBSOCKET; } long long int _get_usec_time() { struct timeval tv; gettimeofday(&tv,NULL); return (long long int)tv.tv_usec + (1000000 * (long long int)tv.tv_sec); } // // ui wants status information // static void handle_status_input(struct mg_connection *nc, struct http_message *hm) { char buf[_SLEN]; char msg[][_SLEN] = { "fail error", "ok .", }; //DEBUG sample message snprintf(buf, _SLEN, "ok msg=status\nroute=%s|trip=%s|stop=%s|gps=%i|tunnel=%i|date=%s|eqiupno=%s|nmsg=%s|last_token=%s|config=%s|firmware=%s|imei=%s|imsi=%s|eth0=%s", "9900", "1", "0", 1, 1, "2019-08-13 09;23:00", "9999", "0", "", "20190730v403 2019-11-05 02:36:43", "1.11 2019-07-30 16:33:08", "356136074279052", "310260877138191", "00:80:66:10:E8:8A"); /* printf(">> status:\nbuf(%i):\n%s\n", (int)strlen(buf), buf); //snprintf(buf, _SLEN, "ok xxx=foo bar;yyy=baz qux;..."); printf(">> status\n"); */ mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(buf), buf); } // driver logout // static void handle_logout_input(struct mg_connection *nc, struct http_message *hm) { char msg[][_SLEN] = { "fail error", "ok .", }; printf(">> logout\n"); mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[1]), msg[1]); } // (manual) next stop pressed // static void handle_nextstop_input(struct mg_connection *nc, struct http_message *hm) { char msg[][_SLEN] = { "fail error", "ok .", }; printf(">> nextstop\n"); mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[1]), msg[1]); } // (manual) previous stop pressed // static void handle_prevstop_input(struct mg_connection *nc, struct http_message *hm) { char msg[][_SLEN] = { "fail error", "ok .", }; printf(">> prevstop\n"); mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[1]), msg[1]); } // generic fare input // static void handle_fare_input(struct mg_connection *nc, struct http_message *hm) { int ret; char s_fare[_SLEN], s_count[_SLEN]; char msg[][_SLEN] = { "fail error", "ok .", }; ret = mg_get_http_var(&(hm->body), "fare", s_fare, _SLEN); if (ret<=0) { mg_http_send_error(nc, 404, NULL); return; } printf("got fare %s\n", s_fare); ret = mg_get_http_var(&(hm->body), "count", s_count, _SLEN); if (ret<=0) { mg_http_send_error(nc, 404, NULL); return; } printf("got count %s\n", s_count); mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[1]), msg[1]); } // driver paddle (route) input // static void handle_paddle_input(struct mg_connection *nc, struct http_message *hm) { int ret; char s_paddle[_SLEN]; char msg[][_SLEN] = { "fail paddle_unknown", "ok paddle", }; ret = mg_get_http_var(&(hm->body), "paddle", s_paddle, _SLEN); if (ret<=0) { mg_http_send_error(nc, 404, NULL); return; } //DEBUG printf("#got paddle %s\n", s_paddle); //DEBUG if (strncmp(s_paddle,"9900", strlen("9900"))!=0) { mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[0]), msg[0]); return; } mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[1]), msg[1]); } // driver login // static void handle_driver_login(struct mg_connection *nc, struct http_message *hm) { int ret; char s_driver[_SLEN], s_pin[_SLEN]; char msg[][_SLEN] = { "fail driver_not_found", "fail pin_invalid", "ok driver", "ok admin", }; ret = mg_get_http_var(&(hm->body), "driver", s_driver, _SLEN); if (ret<=0) { mg_http_send_error(nc, 404, NULL); return; } ret = mg_get_http_var(&(hm->body), "pin", s_pin, _SLEN); if (ret<=0) { mg_http_send_error(nc, 404, NULL); return; } //DEBUG printf("#got %s %s\n", s_driver, s_pin); //DEBUG if (strncmp(s_driver,"81000", strlen("81000"))!=0) { mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[0]), msg[0]); return; } if (strncmp(s_pin,"81000", strlen("81000"))!=0) { mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[1]), msg[1]); return; } mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s", (unsigned long)strlen(msg[3]), msg[3]); } // api point // static void handle_req(struct mg_connection *nc, struct http_message *hm) { int ret; char s_action[_SLEN]; char _default_msg[_SLEN] = ""; struct mg_str hdr; ret = mg_get_http_var(&(hm->body), "action", s_action, _SLEN); if (ret==0) { printf(">>> %p\n", s_action); mg_http_send_error(nc, 404, NULL); return; } printf("#req: action: (%s)\n", s_action); if (strncmp(s_action, "driverlogin", strlen("driverlogin"))==0) { handle_driver_login(nc, hm); } else if (strncmp(s_action, "paddleinput", strlen("paddleinput"))==0) { handle_paddle_input(nc, hm); } else if (strncmp(s_action, "prevstop", strlen("prevstop"))==0) { handle_prevstop_input(nc, hm); } else if (strncmp(s_action, "nextstop", strlen("nextstop"))==0) { handle_nextstop_input(nc, hm); } else if (strncmp(s_action, "status", strlen("status"))==0) { handle_status_input(nc, hm); } else if (strncmp(s_action, "logout", strlen("logout"))==0) { handle_logout_input(nc, hm); } else if (strncmp(s_action, "fare", strlen("fare"))==0) { handle_fare_input(nc, hm); } else { mg_http_send_error(nc, 404, NULL); } } static void process_ws_message(struct websocket_message *ws_msg) { int i; char *data; data = (char *)(ws_msg->data); printf("#ws, got(%i)\n:", (int)(ws_msg->size)); for (i=0; isize; i++) { printf("%c", data[i]); } printf("\n"); } static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { struct http_message *hm = (struct http_message *) ev_data; int debug_print = 0; int i; char buf[1024]; if (debug_print) { mg_sock_addr_to_str(&(nc->sa), buf, 1023, MG_SOCK_STRINGIFY_IP); printf("%s\n", buf); } switch (ev){ case MG_EV_HTTP_REQUEST: if (mg_vcmp(&hm->uri, "/req")==0) { handle_req(nc, (struct http_message *)ev_data); } else { mg_serve_http(nc, (struct http_message *) ev_data, s_http_server_opts); } break; case MG_EV_WEBSOCKET_HANDSHAKE_DONE: printf("ws handshake done\n"); break; case MG_EV_WEBSOCKET_FRAME: process_ws_message((struct websocket_message *)ev_data); break; case MG_EV_CLOSE: if (is_websocket(nc)) { printf("ws closed\n"); } break; default: //printf("? %i\n", ev); break; } } static void foo(struct mg_mgr *mgr) { int n; char buf[_SLEN]; struct mg_connection *c; for (c=mg_next(mgr, NULL); c ; c = mg_next(mgr, c)) { printf("...\n"); snprintf(buf, _SLEN, "hello"); n = strlen(buf); mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, n); } } static void send_ws_heartbeat(struct mg_connection *nc) { int n; char buf[_SLEN]; struct mg_connection *c; for (c=mg_next(nc->mgr, NULL); c ; c = mg_next(nc->mgr, c)) { if (c==nc) { continue; } if (!is_websocket(c)) { continue; } printf("...\n"); snprintf(buf, _SLEN, "hello"); n = strlen(buf); mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, n); } } int main(void) { struct mg_mgr mgr; struct mg_connection *nc; struct timeval tv_now, tv_prv; long long int _tnow, _tprv; mg_mgr_init(&mgr, NULL); printf("Starting web server on port %s\n", s_http_port); nc = mg_bind(&mgr, s_http_port, ev_handler); if (nc == NULL) { printf("Failed to create listener\n"); return 1; } // Set up HTTP server parameters mg_set_protocol_http_websocket(nc); s_http_server_opts.document_root = "html"; s_http_server_opts.enable_directory_listing = "no"; _tprv = _get_usec_time(); for (;;) { mg_mgr_poll(&mgr, 1000); _tnow = _get_usec_time(); if ((_tnow - _tprv) > 1000) { send_ws_heartbeat(nc); _tprv = _tnow; } //foo(&mgr); } mg_mgr_free(&mgr); return 0; }