]> rtime.felk.cvut.cz Git - coffee/mt-apps.git/blob - mt_server.c
almost ready
[coffee/mt-apps.git] / mt_server.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "mt_server.h"
6 #include "ev_signal_exit.h"
7
8 static const struct lws_http_mount mount = {
9     /* .mount_next */            NULL,         /* linked-list "next" */
10     /* .mountpoint */            "/",          /* mountpoint URL */
11     /* .origin */                "/usr/share/mt-server", /* serve from dir */
12     /* .def */                   "index.html", /* default filename */
13     /* .protocol */              NULL,
14     /* .cgienv */                NULL,
15     /* .extra_mimetypes */       NULL,
16     /* .interpret */             NULL,
17     /* .cgi_timeout */           0,
18     /* .cache_max_age */         0,
19     /* .auth_mask */             0,
20     /* .cache_reusable */        0,
21     /* .cache_revalidate */      0,
22     /* .cache_intermediaries */  0,
23     /* .origin_protocol */       LWSMPRO_FILE, /* files in a dir */
24     /* .mountpoint_len */        1,            /* char count */
25     /* .basic_auth_login_file */ NULL,
26 };
27
28 typedef struct per_vhost_data__dumb_increment {
29     struct lws_context *context;
30     struct lws_vhost *vhost;
31     const struct lws_protocols *protocol;
32 } per_vhost_data__dumb_increment;
33
34 typedef struct per_session_data__dumb_increment {
35     uint8_t card_type;
36     uint8_t sak;
37     uint8_t uid_size;
38     char *uid;
39     int number;
40 } per_session_data__dumb_increment;
41
42 #define JSON_EMPTY "{\"type\":\"empty\"}"
43
44 enum protocols {
45     PROTOCOL_HTTP = 0, // always first
46     PROTOCOL_MERICA_TERMINAL
47 };
48
49 static int callback_merica_terminal(struct lws *wsi,
50                                     enum lws_callback_reasons reason,
51                                     void *user, void *in, size_t len);
52
53 /* list of supported protocols and callbacks */
54
55 static struct lws_protocols protocols[] = {
56     /* first protocol must always be HTTP handler */
57     {"http", lws_callback_http_dummy, 0, 0},
58     {
59         "dumb-increment-protocol",
60         callback_merica_terminal,
61         sizeof(struct per_session_data__dumb_increment),
62         128, /* rx buf size must be >= permessage-deflate rx size
63              * dumb-increment only sends very small packets, so we set
64              * this accordingly.  If your protocol will send bigger
65              * things, adjust this to match */
66     },
67     {NULL, NULL, 0, 0} /* terminator */
68 };
69
70 static int callback_merica_terminal(struct lws *wsi,
71                                     enum lws_callback_reasons reason,
72                                     void *user, void *in, size_t len)
73 {
74     struct lws_vhost *vhost = lws_get_vhost(wsi);
75     const struct lws_protocols *prot = lws_get_protocol(wsi);
76     per_session_data__dumb_increment *pss =
77         (per_session_data__dumb_increment *)user;
78     per_vhost_data__dumb_increment *vhd =
79         (per_vhost_data__dumb_increment *)
80         lws_protocol_vh_priv_get(vhost, prot);
81
82     int n, m;
83
84     char *line = (char *)prot->user;
85
86     switch (reason) {
87         case LWS_CALLBACK_PROTOCOL_INIT:
88             vhd = lws_protocol_vh_priv_zalloc(
89                       vhost, prot,
90                       sizeof(struct per_vhost_data__dumb_increment)
91                   );
92             vhd->context = lws_get_context(wsi);
93             vhd->protocol = prot;
94             vhd->vhost = vhost;
95             break;
96
97         case LWS_CALLBACK_PROTOCOL_DESTROY:
98             if (!vhd) {
99                 break;
100             }
101             break;
102
103         case LWS_CALLBACK_ESTABLISHED:
104             break;
105
106         case LWS_CALLBACK_SERVER_WRITEABLE:
107             n = strlen(line);
108             m = lws_write(wsi, line, n, LWS_WRITE_TEXT);
109             if (m < n) {
110                 printf("ERROR %d writing to di socket\n", n);
111                 return -1;
112             }
113             break;
114
115         case LWS_CALLBACK_RECEIVE:
116             if (strcmp((const char *)in, "reset") == 0) {
117                 strcpy(line, JSON_EMPTY);
118                 lws_callback_on_writable_all_protocol(lws_get_context(wsi),
119                                                       &protocols[PROTOCOL_MERICA_TERMINAL]);
120             } else if (strcmp((const char *)in, "close") == 0) {
121                 printf("dumb_inc: closing as requested\n");
122                 lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY,
123                                  (unsigned char *)"seeya", 5);
124                 return -1;
125             }
126             break;
127
128         default:
129             break;
130     }
131
132     return 0;
133 }
134
135 /*static void ev_timeout_cb(EV_P_ ev_timer *w, int revents)
136 {
137     lws_callback_on_writable_all_protocol(context,
138                                           &protocols[PROTOCOL_MERICA_TERMINAL]);
139 }*/
140
141
142 static void fd_cb(EV_P_ ev_io *w_, int revents)
143 {
144     ev_io_ws *w = (ev_io_ws *)w_;
145
146     char *pos = w->pos++;
147
148     read(w->w.fd, pos, 1);
149
150     if (*pos == '\n') {
151         *pos = 0;
152         w->pos = w->text;
153         lws_callback_on_writable_all_protocol(w->context,
154                                               &protocols[PROTOCOL_MERICA_TERMINAL]);
155     }
156
157 }
158
159 int mt_server_init(mt_server_t *self, struct ev_loop *loop, int fd)
160 {
161     struct lws_context_creation_info info;
162
163     memset(&info, 0, sizeof(info));
164     info.port = 80;
165     info.mounts = &mount;
166     info.protocols = protocols;
167     info.max_http_header_pool = 1;
168     info.options |= LWS_SERVER_OPTION_LIBEV;
169
170     struct lws_context *context = lws_create_context(&info);
171     if (!context) {
172         fprintf(stderr, "lws_create_context failed\n");
173         return -1;
174     }
175
176     self->context = context;
177
178     ev_io_ws *w = &(self->fd_watcher);
179     w->context = context;
180     w->text = (char *)malloc(512*sizeof(char));
181     if (!w->text) {
182         perror("malloc");
183         return -1;
184     }
185     strcpy(w->text, JSON_EMPTY);
186     w->pos = w->text;
187     protocols[PROTOCOL_MERICA_TERMINAL].user = (void *)w->text;
188     ev_io_init(&(w->w), fd_cb, fd, EV_READ);
189     ev_io_start(loop, (ev_io *)w);
190
191     return lws_ev_initloop(context, loop, 0);
192 }
193
194 void mt_server_deinit(mt_server_t *self)
195 {
196     //free(self->fd_watcher.text);
197     //protocols[PROTOCOL_MERICA_TERMINAL].user = NULL;
198     lws_context_destroy(self->context);
199 }
200
201 #ifdef IS_MAIN
202 int main(int argc, const char **argv)
203 {
204     struct ev_loop *loop = ev_default_loop(0);
205     mt_server_t server;
206
207     set_signal_exit(loop);
208
209     if (mt_server_init(&server, loop, STDIN_FILENO) == -1) {
210         return -1;
211     }
212
213     //ev_timer timeout_watcher;
214     //ev_timer_init(&timeout_watcher, ev_timeout_cb, 1, 1);
215     //ev_timer_start(loop, &timeout_watcher);
216
217     ev_run(loop, 0);
218
219     mt_server_deinit(&server);
220
221     return 0;
222 }
223 #endif