X-Git-Url: https://rtime.felk.cvut.cz/gitweb/coffee/mt-apps.git/blobdiff_plain/620aeddc93b90ca65987a40f1e641f370d6266bf..HEAD:/mt_server.c diff --git a/mt_server.c b/mt_server.c index 2df7568..3b617bd 100644 --- a/mt_server.c +++ b/mt_server.c @@ -1,96 +1,177 @@ +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include #include #include -#include #include -#include - -char *uids[10] = { - "evelyn", - "sera", - "solas", - "iron bull", - "cassandra", - "varric", - "dorian", - "vivienne", - "blackwall", - "cole" -}; +#include + +#include "mt_server.h" +#include "signal_exit.h" +#include "mt_blank.h" + +char *new_line() +{ + char *line = (char *)malloc((LWS_PRE + INPUT_LINE_LENGTH)*sizeof(char)); + if (!line) { + perror("malloc"); + return NULL; + } + return line + LWS_PRE; +} + +char *copy_line(char *line) { + char *copy = new_line(); + if (!copy) { + return NULL; + } + strncpy(copy, line, INPUT_LINE_LENGTH); +} + +void free_line(char *line) +{ + free(line - LWS_PRE); +} -#define JSON_STRING "{" \ - "\"type\": \"rfid\"," \ - "\"uid\": \"%s\"," \ - "\"size\": %d" \ - "}\n" +node *node_init(char *line) +{ + node *res = (node *)malloc(sizeof(node)); + if (!res) { + perror("malloc"); + return res; + } + res->line = line;; + res->next = NULL; + return res; +} + +list *list_init() +{ + list *res = (list *)calloc(1, sizeof(list)); + if (!res) { + perror("malloc"); + } + return res; +} + +int list_add(list *in, char *line) +{ + node *new = node_init(line); + if (!new) { + return -1; + } + if (!in->first) { + in->first = new; + } else { + in->last->next = new; + } + in->last = new; + return 0; +} + +void list_remove(list *in) +{ + node *tmp = in->first; + if (tmp) { + in->first = tmp->next; + if (!tmp->next) { + in->last = NULL; + } + free_line(tmp->line); + free(tmp); + } +} + +void list_deinit(list *in) +{ + while (in->first) { + list_remove(in); + } + free(in); +} static const struct lws_http_mount mount = { - /* .mount_next */ NULL, /* linked-list "next" */ - /* .mountpoint */ "/", /* mountpoint URL */ - /* .origin */ "/usr/share/mt-server", /* serve from dir */ - /* .def */ "index.html", /* default filename */ - /* .protocol */ NULL, - /* .cgienv */ NULL, - /* .extra_mimetypes */ NULL, - /* .interpret */ NULL, - /* .cgi_timeout */ 0, - /* .cache_max_age */ 0, - /* .auth_mask */ 0, - /* .cache_reusable */ 0, - /* .cache_revalidate */ 0, - /* .cache_intermediaries */ 0, - /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ - /* .mountpoint_len */ 1, /* char count */ - /* .basic_auth_login_file */ NULL, + .mount_next = NULL, /* linked-list "next" */ + .mountpoint = HTTP_MOUNTPOINT, + .origin = HTTP_ORIGIN, /* serve from dir */ + .def = HTTP_DEFAULT, /* default filename */ + .protocol = NULL, + .cgienv = NULL, + .extra_mimetypes = NULL, + .interpret = NULL, + .cgi_timeout = 0, + .cache_max_age = 0, + .auth_mask = 0, + .cache_reusable = 0, + .cache_revalidate = 0, + .cache_intermediaries = 0, + .origin_protocol = LWSMPRO_FILE, /* files in a dir */ + .mountpoint_len = 1, /* char count */ + .basic_auth_login_file = NULL, }; -typedef struct per_vhost_data__dumb_increment { +typedef struct per_vhost_data__merica_terminal { struct lws_context *context; struct lws_vhost *vhost; const struct lws_protocols *protocol; -} per_vhost_data__dumb_increment; +} per_vhost_data__merica_terminal; -typedef struct per_session_data__dumb_increment { - uint8_t card_type; - uint8_t sak; - uint8_t uid_size; - char *uid; +/* +typedef struct per_session_data__merica_terminal { int number; -} per_session_data__dumb_increment; +} per_session_data__merica_terminal; +*/ -typedef struct user_data { - //ev_ufr_io *ufr; -} user_data; +enum protocols { + PROTOCOL_HTTP = 0, // always first + PROTOCOL_MERICA_TERMINAL +}; - static char line[512]; +static int callback_merica_terminal(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len); -static int callback_dumb_increment(struct lws *wsi, - enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - per_session_data__dumb_increment *pss = - (per_session_data__dumb_increment *)user; - per_vhost_data__dumb_increment *vhd = - (per_vhost_data__dumb_increment *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); +// list of supported protocols and callbacks +static struct lws_protocols protocols[] = { + // first protocol must always be HTTP handler + {"http", lws_callback_http_dummy, 0, 0}, + { + "merica-terminal-protocol", + callback_merica_terminal, + 0, //sizeof(struct per_session_data__merica_terminal), + MT_PROTOCOL_RX_BUFFER_SIZE + }, + {NULL, NULL, 0, 0} // terminator +}; +static int callback_merica_terminal(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ struct lws_context *context = lws_get_context(wsi); - user_data *data = (user_data *)lws_context_user(context); - + struct lws_vhost *vhost = lws_get_vhost(wsi); + const struct lws_protocols *prot = lws_get_protocol(wsi); + /* + per_session_data__merica_terminal *pss = + (per_session_data__merica_terminal *)user; + */ + per_vhost_data__merica_terminal *vhd = + (per_vhost_data__merica_terminal *) + lws_protocol_vh_priv_get(vhost, prot); - unsigned char buf[LWS_PRE + 512]; - unsigned char *p = &buf[LWS_PRE]; int n, m; + list *lines = (list *)lws_context_user(context); + char *line; + switch (reason) { case LWS_CALLBACK_PROTOCOL_INIT: vhd = lws_protocol_vh_priv_zalloc( - lws_get_vhost(wsi), - lws_get_protocol(wsi), - sizeof(struct per_vhost_data__dumb_increment) + vhost, prot, + sizeof(struct per_vhost_data__merica_terminal) ); - vhd->context = lws_get_context(wsi); - vhd->protocol = lws_get_protocol(wsi); - vhd->vhost = lws_get_vhost(wsi); + vhd->context = context; + vhd->protocol = prot; + vhd->vhost = vhost; break; case LWS_CALLBACK_PROTOCOL_DESTROY: @@ -100,29 +181,28 @@ static int callback_dumb_increment(struct lws *wsi, break; case LWS_CALLBACK_ESTABLISHED: - pss->number = 0; break; case LWS_CALLBACK_SERVER_WRITEABLE: - n = sprintf((char *)p, JSON_STRING, uids[pss->number % 10], pss->number); - pss->number++; - n = strlen(line); - m = lws_write(wsi, line, n, LWS_WRITE_TEXT); - if (m < n) { - printf("ERROR %d writing to di socket\n", n); - return -1; + if (lines->first) { + line = lines->first->line; + n = strlen(line); + m = lws_write(wsi, (unsigned char *)line, n, LWS_WRITE_TEXT); + list_remove(lines); + if (lines->first) { + lws_callback_on_writable_all_protocol(context, + &protocols[PROTOCOL_MERICA_TERMINAL]); + } + if (m < n) { + fprintf(stderr, "ERROR %d writing to di socket\n", n); + return -1; + } } break; case LWS_CALLBACK_RECEIVE: - if (len < 6) { - break; - } - if (strcmp((const char *)in, "reset\n") == 0) { - pss->number = 0; - } - if (strcmp((const char *)in, "close\n") == 0) { - printf("dumb_inc: closing as requested\n"); + if (strcmp((const char *)in, "close") == 0) { + fprintf(stderr, "closing websocket\n"); lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *)"seeya", 5); return -1; @@ -136,129 +216,105 @@ static int callback_dumb_increment(struct lws *wsi, return 0; } -enum demo_protocols { - /* always first */ - PROTOCOL_HTTP = 0, - - PROTOCOL_DUMB_INCREMENT, - PROTOCOL_LWS_MIRROR, - PROTOCOL_LWS_STATUS, - - /* always last */ - DEMO_PROTOCOL_COUNT -}; - -/* list of supported protocols and callbacks */ - -static struct lws_protocols protocols[] = { - /* first protocol must always be HTTP handler */ - {"http", lws_callback_http_dummy, 0, 0}, - { - "dumb-increment-protocol", - callback_dumb_increment, - sizeof(struct per_session_data__dumb_increment), - 128, /* rx buf size must be >= permessage-deflate rx size - * dumb-increment only sends very small packets, so we set - * this accordingly. If your protocol will send bigger - * things, adjust this to match */ - }, - {NULL, NULL, 0, 0} /* terminator */ -}; - -struct lws_context *context; - -static void ev_timeout_cb(EV_P_ ev_timer *w, int revents) -{ - lws_callback_on_writable_all_protocol(context, - &protocols[PROTOCOL_DUMB_INCREMENT]); -} - -static void signal_cb(EV_P_ ev_signal *w, int revents) +static void fd_cb(EV_P_ ev_io *w_, int revents) { - fprintf(stderr, "signal caught, terminating\n"); - switch (w->signum) { - case SIGTERM: - case SIGINT: - ev_break(loop, EVBREAK_ALL); - break; - default: - signal(SIGABRT, SIG_DFL); - abort(); - break; + ev_io_ws *w = (ev_io_ws *)w_; + + char *pos = w->pos++; + + read(w->w.fd, pos, 1); + + if (*pos == '\n' || (w->pos - w->text) == INPUT_LINE_LENGTH) { +#ifdef NO_MAIN + mt_blank_wake(); +#endif + *pos = 0; + syslog(LOG_INFO, "%s", w->text); + char *line = new_line(); + if (line) { + if (list_add(w->lines, w->text) == 0) { + w->text = line; + w->pos = w->text; + lws_callback_on_writable_all_protocol(w->context, + &protocols[PROTOCOL_MERICA_TERMINAL]); + return; + } + free_line(line); + } + fprintf(stderr, "cannot malloc new line\n"); } } - - -int server_init(void *user) +int mt_server_init(mt_server_t *self, struct ev_loop *loop, int fd) { struct lws_context_creation_info info; - protocols[PROTOCOL_DUMB_INCREMENT].user = (void *)line; + list *l = list_init(); + if (!l) { + return -1; + } - memset(&info, 0, sizeof info); - info.port = 80; + openlog(program_invocation_short_name, LOG_PID | LOG_PERROR, LOG_DAEMON); + + memset(&info, 0, sizeof(info)); + info.port = HTTP_PORT; info.mounts = &mount; info.protocols = protocols; info.max_http_header_pool = 1; info.options |= LWS_SERVER_OPTION_LIBEV; - info.user = user; + info.user = l; - context = lws_create_context(&info); + struct lws_context *context = lws_create_context(&info); if (!context) { fprintf(stderr, "lws_create_context failed\n"); + list_deinit(l); return -1; } - return 0; -} + self->context = context; + ev_io_ws *w = &(self->fd_watcher); + w->context = context; + w->lines = l; - -static void stdin_cb(EV_P_ ev_io *w, int revents) -{ - static int pos = 0; - - read(w->fd, &line[pos++], 1); - - if (line[pos-1] == '\n') { - line[pos] = 0; - pos = 0; -// puts(line); - lws_callback_on_writable_all_protocol(context, - &protocols[PROTOCOL_DUMB_INCREMENT]); + char *line = new_line(); + if (!line) { + list_deinit(l); + return -1; } + w->text = line; + w->pos = w->text; + ev_io_init(&(w->w), fd_cb, fd, EV_READ); + ev_io_start(loop, (ev_io *)w); + + return lws_ev_initloop(context, loop, 0); +} +void mt_server_deinit(mt_server_t *self) +{ + free_line(self->fd_watcher.text); + list_deinit(self->fd_watcher.lines); + lws_context_destroy(self->context); + closelog(); } +#ifndef NO_MAIN int main(int argc, const char **argv) { - int sigs[] = { SIGINT, SIGKILL, SIGTERM, SIGSEGV, SIGFPE }; - struct ev_signal signals[ARRAY_SIZE(sigs)]; - ev_io stdin_watcher; - struct ev_loop *loop = ev_default_loop(0); - ev_timer timeout_watcher; - - for (int n = 0; n < ARRAY_SIZE(sigs); n++) { - ev_init(&signals[n], signal_cb); - ev_signal_set(&signals[n], sigs[n]); - ev_signal_start(loop, &signals[n]); - } + struct ev_loop *loop = EV_DEFAULT; + mt_server_t server; + + set_signal_exit(loop); - if (server_init(NULL) == -1) { + if (mt_server_init(&server, loop, STDIN_FILENO) != 0) { return -1; } - lws_ev_initloop(context, loop, 0); - - ev_io_init(&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); - ev_io_start(loop, &stdin_watcher); - - ev_timer_init(&timeout_watcher, ev_timeout_cb, 1, 1); - //ev_timer_start(loop, &timeout_watcher); ev_run(loop, 0); - lws_context_destroy(context); + mt_server_deinit(&server); + ev_loop_destroy(loop); return 0; } +#endif