From 620aeddc93b90ca65987a40f1e641f370d6266bf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ji=C5=99=C3=AD=20Mat=C4=9Bj=C3=A1k?= Date: Thu, 26 Apr 2018 14:03:37 +0200 Subject: [PATCH 1/1] websockets server added --- Makefile | 7 +- html/index.html | 65 ++++++++++++ mt_rfid.c | 129 +++++++++++++---------- mt_rfid.h | 10 +- mt_server.c | 264 ++++++++++++++++++++++++++++++++++++++++++++++++ mt_server.h | 9 ++ 6 files changed, 422 insertions(+), 62 deletions(-) create mode 100644 html/index.html create mode 100644 mt_server.c create mode 100644 mt_server.h diff --git a/Makefile b/Makefile index ee73c39..964d4b2 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,14 @@ SOURCE_FILES = mt_rfid.c OUTPUT_FILE = mt-rfid LIBRARIES = -lev -luFCoder-armhf -all: $(SOURCE_FILES) +all: mt-rfid mt-server + +mt-rfid: $(SOURCE_FILES) $(CC) $(CFLAGS) -o $(OUTPUT_FILE) $(SOURCE_FILES) $(LIBRARIES) +mt-server: mt_server.c + $(CC) $(CFLAGS) -o mt-server mt_server.c $(LIBRARIES) -lwebsockets + .PHONY: clean clean: diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..c5e19f3 --- /dev/null +++ b/html/index.html @@ -0,0 +1,65 @@ + + +Websocket example + + + + + + + +

+

+ + + + + + + + + + diff --git a/mt_rfid.c b/mt_rfid.c index d281371..2741277 100644 --- a/mt_rfid.c +++ b/mt_rfid.c @@ -22,11 +22,11 @@ int set_nonblock(int fd) { int flags = fcntl(fd, F_GETFL, 0); - if (flags == -1){ + if (flags == -1) { perror("fcntl (get)"); return -1; } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){ + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl (set)"); return -1; } @@ -34,76 +34,83 @@ int set_nonblock(int fd) return 0; } -int set_rts(int fd, int level) { - int uart_status; +int set_rts(int fd, int level) +{ + int uart_status; - if (ioctl(fd, TIOCMGET, &uart_status) == -1) { - perror("ioctl (TIOCMGET)"); - return -1; - } + if (ioctl(fd, TIOCMGET, &uart_status) == -1) { + perror("ioctl (TIOCMGET)"); + return -1; + } - if (level) { - uart_status |= TIOCM_RTS; + if (level) { + uart_status |= TIOCM_RTS; } else { - uart_status &= ~TIOCM_RTS; + uart_status &= ~TIOCM_RTS; } - if (ioctl(fd, TIOCMSET, &uart_status) == -1) { - perror("TIOCMSET"); + if (ioctl(fd, TIOCMSET, &uart_status) == -1) { + perror("TIOCMSET"); return -1; - } + } fprintf(stderr, "set rts %d\n", level); return 0; } -void set_baud_rate(int fd, int br) { - struct termios options; +void set_baud_rate(int fd, int br) +{ + struct termios options; - tcgetattr(fd, &options); - cfsetispeed(&options, br); - cfsetospeed(&options, br); - tcsetattr(fd, TCSANOW, &options); + tcgetattr(fd, &options); + cfsetispeed(&options, br); + cfsetospeed(&options, br); + tcsetattr(fd, TCSANOW, &options); } -int tty_open(const char *port, int baud_rate) { +int tty_open(const char *port, int baud_rate) +{ - int fd = open(port, O_RDONLY | O_NOCTTY); - if (fd < 0) { + int fd = open(port, O_RDONLY | O_NOCTTY); + if (fd < 0) { perror("open"); return fd; - } else { + } else { fprintf(stderr, "opened %s as %d\n", port, fd); } set_nonblock(fd); - set_rts(fd, 0); - set_baud_rate(fd, baud_rate); - usleep(1200000); //value by d-logic - tcflush(fd, TCIFLUSH); + set_rts(fd, 0); + set_baud_rate(fd, baud_rate); + usleep(1200000); //value by d-logic + tcflush(fd, TCIFLUSH); - return fd; + return fd; } typedef struct ev_io_ufr { ev_io w; + //lws_context *context; + //ufr_session_data *session_data; char uid_data[24]; char *uid; + int fd; } ev_io_ufr; static void sigint_cb(EV_P_ ev_signal *w, int revents) { - ev_break (EV_A_ EVBREAK_ALL); + ev_break(EV_A_ EVBREAK_ALL); } -static void ufr_read(char *uid) +static void ufr_read(char *uid, int fd) { UFR_STATUS status; uint8_t card_type; - uint8_t sak; //select acknowledge + uint8_t sak; //select acknowledge uint8_t uid_bytes[10]; //uid as bytes - uint8_t uid_size; + uint8_t size; + char *type = "rfid"; status = GetDlogicCardType(&card_type); if (status != UFR_OK) { @@ -111,21 +118,30 @@ static void ufr_read(char *uid) return; } - status = GetCardIdEx(&sak, uid_bytes, &uid_size); + status = GetCardIdEx(&sak, uid_bytes, &size); if (status != UFR_OK) { fprintf(stderr, "GetCardIdEx: %s\n", UFR_Status2String(status)); return; } JSON_START(); - JSON_NUM(card_type); JSON_NEXT(); - JSON_NUM(sak); JSON_NEXT(); - JSON_NUM(uid_size); JSON_NEXT(); - JSON_STR(uid); JSON_END(); + JSON_STR(type); + JSON_NEXT(); + JSON_NUM(card_type); + JSON_NEXT(); + JSON_NUM(sak); + JSON_NEXT(); + JSON_NUM(size); + JSON_NEXT(); + JSON_STR(uid); + JSON_END(); #ifdef UFR_BEEP - ReaderUISignal(0, 1); + ReaderUISignal(0, 1); // no light, one beep #endif + + /*lws_callback_on_writable_all_protocol(self->context, + &protocols[PROTOCOL_DUMB_INCREMENT]);*/ } static void ufr_cb(EV_P_ ev_io *w_, int revents) @@ -138,7 +154,7 @@ static void ufr_cb(EV_P_ ev_io *w_, int revents) if (uid == ASYNC_SUFFIX) { //*(w->uid - 1) = 0; w->uid = w->uid_data; - ufr_read(w->uid); + ufr_read(w->uid, w->fd); } //for one-shot events, one must manually stop the watcher with its corresponding stop function. @@ -156,15 +172,16 @@ int libev_run(int fd) struct ev_loop *loop = EV_DEFAULT; ufr_watcher.uid = ufr_watcher.uid_data; - ev_io_init (&(ufr_watcher.w), ufr_cb, fd, EV_READ); - ev_io_start (loop, (ev_io *)&ufr_watcher); + ufr_watcher.fd = 1; + ev_io_init(&(ufr_watcher.w), ufr_cb, fd, EV_READ); + ev_io_start(loop, (ev_io *)&ufr_watcher); - ev_signal_init (&int_watcher, sigint_cb, SIGINT); - ev_signal_start (loop, &int_watcher); - ev_signal_init (&term_watcher, sigint_cb, SIGTERM); - ev_signal_start (loop, &term_watcher); + ev_signal_init(&int_watcher, sigint_cb, SIGINT); + ev_signal_start(loop, &int_watcher); + ev_signal_init(&term_watcher, sigint_cb, SIGTERM); + ev_signal_start(loop, &term_watcher); - ev_run (loop, 0); + ev_run(loop, 0); return 0; } @@ -184,13 +201,13 @@ int ufr_open(unsigned reader_type, char *port_name, unsigned port_interface) fprintf(stderr, "%s\n", GetReaderDescription()); status = SetAsyncCardIdSendConfig( - 1, //enable send - 0, //disable prefix - 0, //prefix - ASYNC_SUFFIX, //suffix - 0, //disable send removed - ASYNC_BAUD_RATE - ); + 1, //enable send + 0, //disable prefix + 0, //prefix + ASYNC_SUFFIX, //suffix + 0, //disable send removed + ASYNC_BAUD_RATE + ); fprintf(stderr, "SetAsyncCardIdSendConfig: %s\n", UFR_Status2String(status)); if (status != UFR_OK) { return -1; @@ -205,12 +222,12 @@ int main(int argc, char **argv) return -1; } - int fd = tty_open(PORT_NAME, CONCAT(B,ASYNC_BAUD_RATE)); + int fd = tty_open(PORT_NAME, CONCAT(B, ASYNC_BAUD_RATE)); if (fd < 0) { return -2; } - libev_run(fd); + libev_run(fd); if (close(fd) == 0) { fprintf(stderr, "closed %d\n", fd); diff --git a/mt_rfid.h b/mt_rfid.h index 5dfe76e..44ce62a 100644 --- a/mt_rfid.h +++ b/mt_rfid.h @@ -17,10 +17,10 @@ #define UFR_BEEP // define this to annoy people // really simple JSON helpers -#define JSON_START() printf("{\n") -#define JSON_NUM(NAME) printf("\"" #NAME "\": %d", NAME) -#define JSON_NEXT() printf(",\n") -#define JSON_STR(NAME) printf("\"" #NAME "\": \"%s\"", NAME) -#define JSON_END() printf("\n}\n") +#define JSON_START() dprintf(fd,"{") +#define JSON_NUM(NAME) dprintf(fd,"\"" #NAME "\": %d", NAME) +#define JSON_NEXT() dprintf(fd,",") +#define JSON_STR(NAME) dprintf(fd,"\"" #NAME "\": \"%s\"", NAME) +#define JSON_END() dprintf(fd,"}\n") #endif diff --git a/mt_server.c b/mt_server.c new file mode 100644 index 0000000..2df7568 --- /dev/null +++ b/mt_server.c @@ -0,0 +1,264 @@ +#include +#include +#include +#include +#include + +char *uids[10] = { + "evelyn", + "sera", + "solas", + "iron bull", + "cassandra", + "varric", + "dorian", + "vivienne", + "blackwall", + "cole" +}; + +#define JSON_STRING "{" \ + "\"type\": \"rfid\"," \ + "\"uid\": \"%s\"," \ + "\"size\": %d" \ + "}\n" + +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, +}; + +typedef struct per_vhost_data__dumb_increment { + struct lws_context *context; + struct lws_vhost *vhost; + const struct lws_protocols *protocol; +} per_vhost_data__dumb_increment; + +typedef struct per_session_data__dumb_increment { + uint8_t card_type; + uint8_t sak; + uint8_t uid_size; + char *uid; + int number; +} per_session_data__dumb_increment; + +typedef struct user_data { + //ev_ufr_io *ufr; +} user_data; + + static char line[512]; + +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)); + + struct lws_context *context = lws_get_context(wsi); + user_data *data = (user_data *)lws_context_user(context); + + + unsigned char buf[LWS_PRE + 512]; + unsigned char *p = &buf[LWS_PRE]; + int n, m; + + 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) + ); + vhd->context = lws_get_context(wsi); + vhd->protocol = lws_get_protocol(wsi); + vhd->vhost = lws_get_vhost(wsi); + break; + + case LWS_CALLBACK_PROTOCOL_DESTROY: + if (!vhd) { + break; + } + 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; + } + 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"); + lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, + (unsigned char *)"seeya", 5); + return -1; + } + break; + + default: + break; + } + + 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) +{ + 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; + } +} + + + +int server_init(void *user) +{ + struct lws_context_creation_info info; + + protocols[PROTOCOL_DUMB_INCREMENT].user = (void *)line; + + memset(&info, 0, sizeof info); + info.port = 80; + info.mounts = &mount; + info.protocols = protocols; + info.max_http_header_pool = 1; + info.options |= LWS_SERVER_OPTION_LIBEV; + info.user = user; + + context = lws_create_context(&info); + if (!context) { + fprintf(stderr, "lws_create_context failed\n"); + return -1; + } + + return 0; +} + + + +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]); + } + +} + +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]); + } + + if (server_init(NULL) == -1) { + 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); + + return 0; +} diff --git a/mt_server.h b/mt_server.h new file mode 100644 index 0000000..a2cab9d --- /dev/null +++ b/mt_server.h @@ -0,0 +1,9 @@ +#ifndef MT_SERVER_H +#define MT_SERVER_H + +#include + +int mt_server_init(struct ev_loop *loop, int fd); +void mt_server_deinit(); + +#endif -- 2.39.2