]> rtime.felk.cvut.cz Git - coffee/mt-apps.git/blob - mt_server.c
websockets server added
[coffee/mt-apps.git] / mt_server.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <libwebsockets.h>
4 #include <string.h>
5 #include <ev.h>
6
7 char *uids[10] = {
8     "evelyn",
9     "sera",
10     "solas",
11     "iron bull",
12     "cassandra",
13     "varric",
14     "dorian",
15     "vivienne",
16     "blackwall",
17     "cole"
18 };
19
20 #define JSON_STRING "{" \
21     "\"type\": \"rfid\"," \
22     "\"uid\": \"%s\"," \
23     "\"size\": %d" \
24     "}\n"
25
26 static const struct lws_http_mount mount = {
27     /* .mount_next */            NULL,         /* linked-list "next" */
28     /* .mountpoint */            "/",          /* mountpoint URL */
29     /* .origin */                "/usr/share/mt-server", /* serve from dir */
30     /* .def */                   "index.html", /* default filename */
31     /* .protocol */              NULL,
32     /* .cgienv */                NULL,
33     /* .extra_mimetypes */       NULL,
34     /* .interpret */             NULL,
35     /* .cgi_timeout */           0,
36     /* .cache_max_age */         0,
37     /* .auth_mask */             0,
38     /* .cache_reusable */        0,
39     /* .cache_revalidate */      0,
40     /* .cache_intermediaries */  0,
41     /* .origin_protocol */       LWSMPRO_FILE, /* files in a dir */
42     /* .mountpoint_len */        1,            /* char count */
43     /* .basic_auth_login_file */ NULL,
44 };
45
46 typedef struct per_vhost_data__dumb_increment {
47     struct lws_context *context;
48     struct lws_vhost *vhost;
49     const struct lws_protocols *protocol;
50 } per_vhost_data__dumb_increment;
51
52 typedef struct per_session_data__dumb_increment {
53     uint8_t card_type;
54     uint8_t sak;
55     uint8_t uid_size;
56     char *uid;
57     int number;
58 } per_session_data__dumb_increment;
59
60 typedef struct user_data {
61     //ev_ufr_io *ufr;
62 } user_data;
63
64     static char line[512];
65
66 static int callback_dumb_increment(struct lws *wsi,
67                                    enum lws_callback_reasons reason,
68                                    void *user, void *in, size_t len)
69 {
70     per_session_data__dumb_increment *pss =
71         (per_session_data__dumb_increment *)user;
72     per_vhost_data__dumb_increment *vhd =
73         (per_vhost_data__dumb_increment *)
74         lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi));
75
76     struct lws_context *context = lws_get_context(wsi);
77     user_data *data = (user_data *)lws_context_user(context);
78
79
80     unsigned char buf[LWS_PRE + 512];
81     unsigned char *p = &buf[LWS_PRE];
82     int n, m;
83
84     switch (reason) {
85         case LWS_CALLBACK_PROTOCOL_INIT:
86             vhd = lws_protocol_vh_priv_zalloc(
87                       lws_get_vhost(wsi),
88                       lws_get_protocol(wsi),
89                       sizeof(struct per_vhost_data__dumb_increment)
90                   );
91             vhd->context = lws_get_context(wsi);
92             vhd->protocol = lws_get_protocol(wsi);
93             vhd->vhost = lws_get_vhost(wsi);
94             break;
95
96         case LWS_CALLBACK_PROTOCOL_DESTROY:
97             if (!vhd) {
98                 break;
99             }
100             break;
101
102         case LWS_CALLBACK_ESTABLISHED:
103             pss->number = 0;
104             break;
105
106         case LWS_CALLBACK_SERVER_WRITEABLE:
107             n = sprintf((char *)p, JSON_STRING, uids[pss->number % 10], pss->number);
108             pss->number++;
109                         n = strlen(line);
110             m = lws_write(wsi, line, n, LWS_WRITE_TEXT);
111             if (m < n) {
112                 printf("ERROR %d writing to di socket\n", n);
113                 return -1;
114             }
115             break;
116
117         case LWS_CALLBACK_RECEIVE:
118             if (len < 6) {
119                 break;
120             }
121             if (strcmp((const char *)in, "reset\n") == 0) {
122                 pss->number = 0;
123             }
124             if (strcmp((const char *)in, "close\n") == 0) {
125                 printf("dumb_inc: closing as requested\n");
126                 lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY,
127                                  (unsigned char *)"seeya", 5);
128                 return -1;
129             }
130             break;
131
132         default:
133             break;
134     }
135
136     return 0;
137 }
138
139 enum demo_protocols {
140     /* always first */
141     PROTOCOL_HTTP = 0,
142
143     PROTOCOL_DUMB_INCREMENT,
144     PROTOCOL_LWS_MIRROR,
145     PROTOCOL_LWS_STATUS,
146
147     /* always last */
148     DEMO_PROTOCOL_COUNT
149 };
150
151 /* list of supported protocols and callbacks */
152
153 static struct lws_protocols protocols[] = {
154     /* first protocol must always be HTTP handler */
155     {"http", lws_callback_http_dummy, 0, 0},
156     {
157         "dumb-increment-protocol",
158         callback_dumb_increment,
159         sizeof(struct per_session_data__dumb_increment),
160         128, /* rx buf size must be >= permessage-deflate rx size
161              * dumb-increment only sends very small packets, so we set
162              * this accordingly.  If your protocol will send bigger
163              * things, adjust this to match */
164     },
165     {NULL, NULL, 0, 0} /* terminator */
166 };
167
168 struct lws_context *context;
169
170 static void ev_timeout_cb(EV_P_ ev_timer *w, int revents)
171 {
172     lws_callback_on_writable_all_protocol(context,
173                                           &protocols[PROTOCOL_DUMB_INCREMENT]);
174 }
175
176 static void signal_cb(EV_P_ ev_signal *w, int revents)
177 {
178     fprintf(stderr, "signal caught, terminating\n");
179     switch (w->signum) {
180         case SIGTERM:
181         case SIGINT:
182             ev_break(loop, EVBREAK_ALL);
183             break;
184         default:
185             signal(SIGABRT, SIG_DFL);
186             abort();
187             break;
188     }
189 }
190
191
192
193 int server_init(void *user)
194 {
195     struct lws_context_creation_info info;
196
197         protocols[PROTOCOL_DUMB_INCREMENT].user = (void *)line;
198
199     memset(&info, 0, sizeof info);
200     info.port = 80;
201     info.mounts = &mount;
202     info.protocols = protocols;
203     info.max_http_header_pool = 1;
204     info.options |= LWS_SERVER_OPTION_LIBEV;
205     info.user = user;
206
207     context = lws_create_context(&info);
208     if (!context) {
209         fprintf(stderr, "lws_create_context failed\n");
210         return -1;
211     }
212
213     return 0;
214 }
215
216
217
218 static void stdin_cb(EV_P_ ev_io *w, int revents)
219 {
220     static int pos = 0;
221
222     read(w->fd, &line[pos++], 1);
223
224     if (line[pos-1] == '\n') {
225         line[pos] = 0;
226         pos = 0;
227 //        puts(line);
228         lws_callback_on_writable_all_protocol(context,
229                                               &protocols[PROTOCOL_DUMB_INCREMENT]);
230     }
231
232 }
233
234 int main(int argc, const char **argv)
235 {
236     int sigs[] = { SIGINT, SIGKILL, SIGTERM, SIGSEGV, SIGFPE };
237     struct ev_signal signals[ARRAY_SIZE(sigs)];
238     ev_io stdin_watcher;
239     struct ev_loop *loop = ev_default_loop(0);
240     ev_timer timeout_watcher;
241
242     for (int n = 0; n < ARRAY_SIZE(sigs); n++) {
243         ev_init(&signals[n], signal_cb);
244         ev_signal_set(&signals[n], sigs[n]);
245         ev_signal_start(loop, &signals[n]);
246     }
247
248     if (server_init(NULL) == -1) {
249         return -1;
250     }
251     lws_ev_initloop(context, loop, 0);
252
253     ev_io_init(&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
254     ev_io_start(loop, &stdin_watcher);
255
256     ev_timer_init(&timeout_watcher, ev_timeout_cb, 1, 1);
257     //ev_timer_start(loop, &timeout_watcher);
258
259     ev_run(loop, 0);
260
261     lws_context_destroy(context);
262
263     return 0;
264 }