piumsgd.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright (c) 2021 Clementine Computing LLC.
  3. *
  4. * This file is part of PopuFare.
  5. *
  6. * PopuFare is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * PopuFare is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  18. *
  19. */
  20. /*
  21. * PIU interface server.
  22. * piumsgd is in charge of passing messages from the underlying system
  23. * to the passenger via a websocket connection.
  24. *
  25. * piumsgd also acts as the web server to serve the local passenger
  26. * interface HTML/CSS/JS files.
  27. */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <errno.h>
  31. #include <getopt.h>
  32. #include <string.h>
  33. #include "mongoose.h"
  34. struct mg_mgr g_mgr;
  35. //char s_web_directory[] = ".";
  36. char s_web_directory[] = "/home/bus/config/html";
  37. /*
  38. void ws_send(struct mg_mgr *mgr, char *msg) {
  39. struct mg_connection *conn;
  40. for (conn = mg_next(mgr, NULL); conn; conn = mg_next(mgr, conn)) {
  41. if (!is_websocket(conn)) { continue; }
  42. mg_send_websocket_frame(conn, WEBSOCKET_OP_TEXT, msg, strlen(msg));
  43. }
  44. }
  45. */
  46. void _ws_send(struct mg_mgr *mgr, char *msg, size_t msg_n) {
  47. int i;
  48. struct mg_connection *con;
  49. printf(" ... ");
  50. for (i=0; i<msg_n; i++) { printf("%c", msg[i]); }
  51. printf("\n");
  52. for (con = mgr->conns; con; con = con->next) {
  53. printf(" ...con %i %i\n", con->is_websocket, con->is_client);
  54. //if (con->is_websocket && con->is_client) {
  55. if (con->is_websocket && con->is_accepted) {
  56. printf(" !!\n");
  57. mg_ws_send(con, msg, msg_n, WEBSOCKET_OP_TEXT);
  58. }
  59. }
  60. }
  61. /*
  62. void _ws_send_str(struct mg_connection *mgc, char *msg) {
  63. size_t msg_n;
  64. msg_n = strlen(msg);
  65. _ws_send(mgc, msg, msg_n);
  66. }
  67. */
  68. static void _cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
  69. int i;
  70. size_t n;
  71. struct mg_http_message *hm = NULL;
  72. if (ev == MG_EV_HTTP_MSG) {
  73. printf("bang\n"); fflush(stdout);
  74. hm = (struct mg_http_message *) ev_data;
  75. //DEBUG
  76. //ptr len
  77. /*
  78. printf("body:\n");
  79. for (i=0; i<hm->body.len; i++) {
  80. printf("%i (%c)\n", hm->body.ptr[i], hm->body.ptr[i]);
  81. }
  82. printf("message:\n");
  83. for (i=0; i<hm->message.len; i++) {
  84. printf("%c", hm->message.ptr[i], hm->message.ptr[i]);
  85. }
  86. printf("\n\n");
  87. */
  88. if (mg_http_match_uri(hm, "/ws")) {
  89. // Upgrade to websocket. From now on, a connection is a full-duplex
  90. // Websocket connection, which will receive MG_EV_WS_MSG events.
  91. //
  92. printf("ws request?\n"); fflush(stdout);
  93. mg_ws_upgrade(c, hm, NULL);
  94. }
  95. else if (mg_http_match_uri(hm, "/")) {
  96. printf("html request? (1)\n"); fflush(stdout);
  97. struct mg_http_serve_opts opts = {.root_dir = s_web_directory};
  98. mg_http_serve_dir(c, hm, &opts);
  99. }
  100. else if (mg_http_match_uri(hm, "/rest")) {
  101. printf("other req?\n");
  102. // Serve REST response
  103. //
  104. mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123);
  105. }
  106. else {
  107. printf("cp x\n");
  108. // Serve static files
  109. //
  110. struct mg_http_serve_opts opts = {.root_dir = s_web_directory};
  111. mg_http_serve_dir(c, (mg_http_message *)ev_data, &opts);
  112. }
  113. } else if (ev == MG_EV_WS_MSG) {
  114. // Got websocket frame. Received data is wm->data. Echo it back!
  115. //
  116. struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
  117. printf(">>> ");
  118. for (int i=0; i<wm->data.len; i++) {
  119. printf("%c", *(wm->data.ptr + i));
  120. }
  121. printf("\n"); fflush(stdout);
  122. n = strlen("relay ");
  123. if (wm->data.len < n) {
  124. n = wm->data.len;
  125. }
  126. if (n < wm->data.len) {
  127. if (strncmp("relay ", (char *)(wm->data.ptr), n)==0) {
  128. _ws_send(&g_mgr, ((char *)(wm->data.ptr)) + n, wm->data.len - n);
  129. }
  130. }
  131. mg_ws_send(c, wm->data.ptr, wm->data.len, WEBSOCKET_OP_TEXT);
  132. mg_iobuf_delete(&c->recv, c->recv.len);
  133. printf("broadcasting...\n");
  134. n = strlen("broadcast");
  135. _ws_send(&g_mgr, (char *)"broadcast", n);
  136. }
  137. (void) fn_data;
  138. }
  139. int main(int argc, char **argv) {
  140. //struct pollfd fds[32];
  141. int nfd=0;
  142. int poll_return;
  143. int read_return;
  144. time_t now;
  145. struct mg_conneciton *nc;
  146. // setup mongoose web server
  147. //
  148. mg_mgr_init(&g_mgr);
  149. //mg_http_listen(&g_mgr, "http://127.0.0.1:8001", _cb, NULL);
  150. mg_http_listen(&g_mgr, "http://0.0.0.0:8001", _cb, NULL);
  151. for (;;) {
  152. mg_mgr_poll(&g_mgr, 200);
  153. }
  154. mg_mgr_free(&g_mgr);
  155. return 0;
  156. }