SHOW:
|
|
- or go back to the newest paste.
1 | // libwebsocketsserver.cpp : Defines the entry point for the console application. | |
2 | // | |
3 | ||
4 | #include "stdafx.h" | |
5 | #include <stdio.h> | |
6 | #include <stdlib.h> | |
7 | #include <string.h> | |
8 | #ifdef _WIN32 | |
9 | #include <io.h> | |
10 | #else | |
11 | #include <unistd.h> | |
12 | #endif | |
13 | #include <signal.h> | |
14 | #include <libwebsockets.h> | |
15 | ||
16 | #define KGRN "\033[0;32;32m" | |
17 | #define KCYN "\033[0;36m" | |
18 | #define KRED "\033[0;32;31m" | |
19 | #define KYEL "\033[1;33m" | |
20 | #define KMAG "\033[0;35m" | |
21 | #define KBLU "\033[0;32;34m" | |
22 | #define KCYN_L "\033[1;36m" | |
23 | #define RESET "\033[0m" | |
24 | ||
25 | static int destroy_flag = 0; | |
26 | ||
27 | static void INT_HANDLER(int signo) { | |
28 | destroy_flag = 1; | |
29 | } | |
30 | ||
31 | ||
32 | static int callback_http( | |
33 | struct lws *wsi, | |
34 | enum lws_callback_reasons reason, void *user, | |
35 | void *in, size_t len) | |
36 | { | |
37 | ||
38 | switch (reason) { | |
39 | // http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/libwebsockets.h#n260 | |
40 | case LWS_CALLBACK_CLIENT_WRITEABLE: | |
41 | printf("connection established\n"); | |
42 | ||
43 | // http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/libwebsockets.h#n281 | |
44 | case LWS_CALLBACK_HTTP: { | |
45 | char *requested_uri = (char *)in; | |
46 | printf("requested URI: %s\n", requested_uri); | |
47 | ||
48 | /*if (strcmp(requested_uri, "/") == 0) { | |
49 | lws_return_http_status(wsi, 200, "Hello, World!\0"); | |
50 | // http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/libwebsockets.h#n597 | |
51 | //lws_write(wsi, universal_response, | |
52 | // strlen((const char*)universal_response), LWS_WRITE_HTTP); | |
53 | lws_http_transaction_completed(wsi); | |
54 | break; | |
55 | ||
56 | } | |
57 | else {*/ | |
58 | if (strcmp(requested_uri, "index.html\0") != 0 && strcmp(requested_uri, "/\0") != 0) { | |
59 | printf("returning 404\n"); | |
60 | lws_return_http_status(wsi, 404, "Only index.html is returned"); | |
61 | lws_http_transaction_completed(wsi); | |
62 | break; | |
63 | } | |
64 | ||
65 | ||
66 | char *resource_path = "./index_cpp.html"; | |
67 | printf("Returned resource path: %s\n", resource_path); | |
68 | char *mime = "text/html"; | |
69 | // by default non existing resources return code 400 | |
70 | // for more information how this function handles headers | |
71 | // see it's source code | |
72 | // http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/parsers.c#n1896 | |
73 | lws_serve_http_file(wsi, resource_path, mime,"",0); | |
74 | //} | |
75 | ||
76 | // close connection | |
77 | lws_http_transaction_completed(wsi); | |
78 | break; | |
79 | } | |
80 | //The following callbacks are ignored due to not being used | |
81 | case LWS_CALLBACK_LOCK_POLL: | |
82 | /* | |
83 | * lock mutex to protect pollfd state | |
84 | * called before any other POLL related callback | |
85 | * if protecting wsi lifecycle change, len == 1 | |
86 | */ | |
87 | break; | |
88 | ||
89 | case LWS_CALLBACK_UNLOCK_POLL: | |
90 | /* | |
91 | * unlock mutex to protect pollfd state when | |
92 | * called after any other POLL related callback | |
93 | * if protecting wsi lifecycle change, len == 1 | |
94 | */ | |
95 | break; | |
96 | case LWS_CALLBACK_GET_THREAD_ID: | |
97 | break; | |
98 | case LWS_CALLBACK_PROTOCOL_INIT: | |
99 | break; | |
100 | //If something unexpected pops up | |
101 | default: | |
102 | printf("unhandled callback %d\n ", reason); | |
103 | break; | |
104 | } | |
105 | ||
106 | ||
107 | ||
108 | return 0; | |
109 | } | |
110 | ||
111 | ||
112 | char *randstring(int length) { | |
113 | static int mySeed = 25011984; | |
114 | char *string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!"; | |
115 | size_t stringLen = strlen(string); | |
116 | char *randomString = NULL; | |
117 | ||
118 | srand((unsigned int)time(NULL) * length + ++mySeed); | |
119 | ||
120 | if (length < 1) { | |
121 | length = 1; | |
122 | } | |
123 | ||
124 | randomString = (char *)malloc(sizeof(char) * (length + 1)); | |
125 | ||
126 | if (randomString) { | |
127 | short key = 0; | |
128 | ||
129 | for (int n = 0; n < length; n++) { | |
130 | key = rand() % stringLen; | |
131 | randomString[n] = string[key]; | |
132 | } | |
133 | ||
134 | randomString[length] = '\0'; | |
135 | ||
136 | return randomString; | |
137 | } | |
138 | else { | |
139 | printf("No memory"); | |
140 | exit(1); | |
141 | } | |
142 | } | |
143 | ||
144 | const int replySize = 30000; | |
145 | ||
146 | char *reply_string = randstring(replySize); | |
147 | ||
148 | ||
149 | ||
150 | /* * | |
151 | * websocket_write_back: write the string data to the destination wsi. | |
152 | */ | |
153 | int websocket_write_back(struct lws *wsi_in, char *str, int str_size_in) | |
154 | { | |
155 | - | //if (str == NULL || wsi_in == NULL) |
155 | + | |
156 | - | // return -1; |
156 | + | |
157 | unsigned char *out = NULL; | |
158 | ||
159 | char *write_what = reply_string; | |
160 | ||
161 | out = (unsigned char *)malloc(sizeof(char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING)); | |
162 | //* setup the buffer*/ | |
163 | memcpy(out + LWS_SEND_BUFFER_PRE_PADDING, write_what, len); | |
164 | - | //if (str_size_in < 1) |
164 | + | |
165 | - | len = strlen(write_what); |
165 | + | |
166 | - | //else |
166 | + | |
167 | - | //len = str_size_in; |
167 | + | |
168 | free(out); | |
169 | ||
170 | return n; | |
171 | } | |
172 | ||
173 | static int ws_service_callback( | |
174 | struct lws *wsi, | |
175 | - | //printf(KBLU"[websocket_write_back] %s\n"RESET, write_what); |
175 | + | |
176 | void *user, | |
177 | void *in, size_t len) | |
178 | { | |
179 | ||
180 | printf("Got a ws request %d\n", reason); | |
181 | ||
182 | switch (reason) { | |
183 | ||
184 | case LWS_CALLBACK_ESTABLISHED: | |
185 | printf(KYEL"[Main Service] Connection established\n"RESET); | |
186 | break; | |
187 | ||
188 | //* If receive a data from client*/ | |
189 | case LWS_CALLBACK_RECEIVE: | |
190 | printf(KCYN_L"[Main Service] Server recvived:\n"RESET/*, (char *)in*/); | |
191 | ||
192 | //* echo back to client*/ | |
193 | websocket_write_back(wsi, (char *)in, -1); | |
194 | ||
195 | break; | |
196 | case LWS_CALLBACK_CLOSED: | |
197 | printf(KYEL"[Main Service] Client close.\n"RESET); | |
198 | break; | |
199 | ||
200 | default: | |
201 | break; | |
202 | } | |
203 | ||
204 | return 0; | |
205 | } | |
206 | ||
207 | struct per_session_data { | |
208 | int fd; | |
209 | }; | |
210 | ||
211 | bool got_sighup = false; | |
212 | bool got_sigint = false; | |
213 | ||
214 | void handle_signal(int signal) { | |
215 | switch (signal) { | |
216 | #ifdef _WIN32 | |
217 | case SIGTERM: | |
218 | case SIGABRT: | |
219 | case SIGBREAK: | |
220 | #else | |
221 | case SIGHUP: | |
222 | #endif | |
223 | got_sighup = true; | |
224 | break; | |
225 | case SIGINT: | |
226 | got_sigint = true; | |
227 | break; | |
228 | } | |
229 | } | |
230 | #ifdef _WIN32 | |
231 | ||
232 | void usleep(__int64 usec) | |
233 | { | |
234 | HANDLE timer; | |
235 | LARGE_INTEGER ft; | |
236 | ||
237 | ft.QuadPart = -(10 * usec); // Convert to 100 nanosecond interval, negative value indicates relative time | |
238 | ||
239 | timer = CreateWaitableTimer(NULL, TRUE, NULL); | |
240 | SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); | |
241 | WaitForSingleObject(timer, INFINITE); | |
242 | CloseHandle(timer); | |
243 | } | |
244 | #endif | |
245 | ||
246 | struct per_session_data__http { | |
247 | lws_filefd_type fd; | |
248 | char post_string[256]; | |
249 | #ifdef LWS_WITH_CGI | |
250 | struct lws_cgi_args args; | |
251 | #endif | |
252 | #if defined(LWS_WITH_CGI) || !defined(LWS_NO_CLIENT) | |
253 | int reason_bf; | |
254 | #endif | |
255 | unsigned int client_finished : 1; | |
256 | }; | |
257 | ||
258 | ||
259 | static struct lws_protocols protocols[] = { | |
260 | /* first protocol must always be HTTP handler */ | |
261 | ||
262 | { | |
263 | "http-only", /* name */ | |
264 | callback_http, /* callback */ | |
265 | sizeof(struct per_session_data__http), /* per_session_data_size */ | |
266 | 0, /* max frame size / rx buffer */ | |
267 | }, | |
268 | { | |
269 | "tspp", | |
270 | ws_service_callback, | |
271 | sizeof(struct per_session_data), | |
272 | 0, /* rx buf size must be >= permessage-deflate rx size */ | |
273 | }, | |
274 | { NULL, NULL, 0, 0 } /* terminator */ | |
275 | }; | |
276 | ||
277 | ||
278 | int _tmain(int argc, _TCHAR* argv[]) | |
279 | { | |
280 | // server url will usd port 5000 | |
281 | int port = 5000; | |
282 | const char *interface = NULL; | |
283 | struct lws_context_creation_info info; | |
284 | struct lws_context *context; | |
285 | // Not using ssl | |
286 | const char *cert_path = NULL; | |
287 | const char *key_path = NULL; | |
288 | // no special options | |
289 | int opts = 0; | |
290 | ||
291 | #ifdef _WIN32 | |
292 | signal(SIGINT, handle_signal); | |
293 | signal(SIGTERM, handle_signal); | |
294 | signal(SIGABRT, handle_signal); | |
295 | #else | |
296 | ||
297 | //* register the signal SIGINT handler */ | |
298 | struct sigaction act; | |
299 | act.sa_handler = INT_HANDLER; | |
300 | act.sa_flags = 0; | |
301 | sigemptyset(&act.sa_mask); | |
302 | sigaction(SIGINT, &act, 0); | |
303 | #endif | |
304 | ||
305 | //* setup websocket protocol */ | |
306 | ||
307 | //* setup websocket context info*/ | |
308 | memset(&info, 0, sizeof info); | |
309 | info.port = port; | |
310 | info.iface = interface; | |
311 | info.protocols = protocols; | |
312 | ||
313 | info.extensions = lws_get_internal_extensions(); | |
314 | info.ssl_cert_filepath = cert_path; | |
315 | info.ssl_private_key_filepath = key_path; | |
316 | info.gid = -1; | |
317 | info.uid = -1; | |
318 | info.options = opts; | |
319 | ||
320 | //* create libwebsocket context. */ | |
321 | context = lws_create_context(&info); | |
322 | if (context == NULL) { | |
323 | printf(KRED"[Main] Websocket context create error.\n"RESET); | |
324 | return -1; | |
325 | } | |
326 | ||
327 | printf(KGRN"[Main] Websocket context create success.\n"RESET); | |
328 | ||
329 | //* websocket service */ | |
330 | while (!destroy_flag) { | |
331 | lws_service(context, 0); | |
332 | } | |
333 | usleep(10); | |
334 | lws_context_destroy(context); | |
335 | ||
336 | return 0; | |
337 | return 0; | |
338 | } |