1 /*
2 * Copyright (c) 2014 - 2016 Kulykov Oleh <info@resident.name>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <aos/kernel.h>
26 #include <librws.h>
27
28 #if AOS_COMP_CLI
29 #include <aos/cli.h>
30 #endif
31
32 #define WEBSOCKET_CONNECTED (0x01)
33 #define WEBSOCKET_DISCONNECTED (0x02)
34 #define WEBSOCKET_DATA_NOT_RECVED (0x04)
35
36 #define WEBSOCKET_SSL_TEST 0
37 #define WEBSOCKET_BIN_DATA_TEST 0
38
39 #if WEBSOCKET_SSL_TEST
40
41 const char *ECHO_WEBSOCKET_CER = {
42 "-----BEGIN CERTIFICATE-----\r\n"
43 "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\r\n"
44 "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\r\n"
45 "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\r\n"
46 "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\r\n"
47 "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\r\n"
48 "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\r\n"
49 "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\r\n"
50 "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\r\n"
51 "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\r\n"
52 "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\r\n"
53 "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\r\n"
54 "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\r\n"
55 "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\r\n"
56 "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\r\n"
57 "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\r\n"
58 "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\r\n"
59 "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\r\n"
60 "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\r\n"
61 "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\r\n"
62 "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\r\n"
63 "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\r\n"
64 "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\r\n"
65 "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\r\n"
66 "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\r\n"
67 "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\r\n"
68 "-----END CERTIFICATE-----\r\n"
69 };
70 #endif
71
72 static rws_socket _socket = NULL;
73 static int state_flags = 0;
74
on_socket_received_text(rws_socket socket,const char * text,const unsigned int length,bool is_finish)75 static void on_socket_received_text(rws_socket socket, const char *text, const unsigned int length, bool is_finish)
76 {
77 char *buff = NULL;
78
79 if (!socket || !text || !length) {
80 DBG("%s: Invalid parameter(s).", __FUNCTION__);
81 return;
82 }
83
84 buff = (char *)aos_malloc(length + 1);
85 if (!buff) {
86 DBG("%s: Not enough memory. len:%d", __FUNCTION__, length + 1);
87 return;
88 }
89
90 state_flags &= (~WEBSOCKET_DATA_NOT_RECVED);
91
92 memcpy(buff, text, length);
93 buff[length] = 0;
94
95 DBG("%s: Socket text: %s", __FUNCTION__, buff);
96 aos_free(buff);
97 buff = NULL;
98 }
99
on_socket_received_bin(rws_socket socket,const void * data,const unsigned int length,bool is_finish)100 static void on_socket_received_bin(rws_socket socket, const void * data, const unsigned int length, bool is_finish)
101 {
102 char *buff = NULL;
103
104 if (!socket || !data || !length) {
105 DBG("%s: Invalid parameter(s).", __FUNCTION__);
106 return;
107 }
108
109 buff = (char *)aos_malloc(length + 1);
110 if (!buff) {
111 DBG("%s: Not enough memory. len:%d", __FUNCTION__, length + 1);
112 return;
113 }
114
115 state_flags &= ~WEBSOCKET_DATA_NOT_RECVED;
116
117 memcpy(buff, data, length);
118 buff[length] = 0;
119
120 DBG("%s: Socket bin: \n%s", __FUNCTION__, buff);
121 aos_free(buff);
122 buff = NULL;
123 }
124
on_socket_received_pong(rws_socket socket)125 static void on_socket_received_pong(rws_socket socket)
126 {
127 if (!socket) {
128 DBG("%s: Invalid parameter(s).", __FUNCTION__);
129 return;
130 }
131 DBG("received pong!!!!!!!!!!!");
132 }
133
on_socket_connected(rws_socket socket)134 static void on_socket_connected(rws_socket socket)
135 {
136 const char * test_send_text =
137 "{\"version\":\"1.0\",\"supportedConnectionTypes\":[\"websocket\"],\"minimumVersion\":\"1.0\",\"channel\":\"/meta/handshake\"}";
138
139 DBG("%s: Socket connected", __FUNCTION__);
140
141 state_flags |= WEBSOCKET_CONNECTED;
142 state_flags &= ~WEBSOCKET_DISCONNECTED;
143 rws_socket_send_text(socket, test_send_text);
144 }
145
on_socket_disconnected(rws_socket socket)146 static void on_socket_disconnected(rws_socket socket)
147 {
148 rws_error error = rws_socket_get_error(socket);
149 if (error) {
150 DBG("%s: Socket disconnect with code, error: %i, %s",
151 __FUNCTION__,
152 rws_error_get_code(error),
153 rws_error_get_description(error));
154 }
155
156 state_flags &= ~WEBSOCKET_CONNECTED;
157 state_flags |= WEBSOCKET_DISCONNECTED;
158 _socket = NULL;
159 }
160
161
websoc_cli_test_int(const char * scheme,const char * host,const char * path,const int port,const char * cert)162 int websoc_cli_test_int(const char *scheme, const char *host,
163 const char *path, const int port,
164 const char *cert)
165 {
166 int sleep_count = 0;
167 int ret = 0;
168
169 if (!scheme || !host || !path) {
170 DBG("%s: Invalid parameter(s).", __FUNCTION__);
171 return -1;
172 }
173
174 if (_socket) {
175 DBG("%s: Socket is not closed.", __FUNCTION__);
176 return -2;
177 }
178
179 _socket = rws_socket_create(); // create and store socket handle
180
181 state_flags = 0;
182 state_flags |= WEBSOCKET_DATA_NOT_RECVED;
183
184 rws_socket_set_scheme(_socket, scheme);
185 rws_socket_set_host(_socket, host);
186 rws_socket_set_path(_socket, path);
187 rws_socket_set_port(_socket, port);
188
189 #ifdef WEBSOCKET_SSL_ENABLE
190 if (cert) {
191 rws_socket_set_server_cert(_socket, cert, strlen(cert) + 1);
192 }
193 #endif
194
195 rws_socket_set_on_disconnected(_socket, &on_socket_disconnected);
196 rws_socket_set_on_connected(_socket, &on_socket_connected);
197 rws_socket_set_on_received_text(_socket, &on_socket_received_text);
198 rws_socket_set_on_received_bin(_socket, &on_socket_received_bin);
199 rws_socket_set_on_received_pong(_socket, &on_socket_received_pong);
200
201 rws_socket_connect(_socket);
202
203 /* Connecting */
204 while ((!(state_flags & WEBSOCKET_CONNECTED)) &&
205 (!(state_flags & WEBSOCKET_DISCONNECTED))) {
206 rws_thread_sleep(1000);
207 DBG("Wait for websocket connection\n");
208 sleep_count++;
209 if (30 == sleep_count) {
210 if (!(state_flags & WEBSOCKET_CONNECTED)) {
211 ERR("Connect timeout\n");
212 ret = -1;
213 }
214 break;
215 }
216 }
217
218
219 /* Receiving data */
220 sleep_count = 0;
221 if (state_flags & WEBSOCKET_CONNECTED) {
222 while ((state_flags & WEBSOCKET_DATA_NOT_RECVED) && _socket &&
223 (rws_true == rws_socket_is_connected(_socket))) {
224 rws_thread_sleep(1000);
225 sleep_count++;
226 if (20 == sleep_count) {
227 if (state_flags & WEBSOCKET_DATA_NOT_RECVED) {
228 ERR("recv timeout\n");
229 ret = -1;
230 }
231 break;
232 }
233 }
234 }
235
236 #if WEBSOCKET_BIN_DATA_TEST
237 static const char *text_arr[] = {
238 "-----BEGIN CERTIFICATE-----"
239 "MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN"
240 "MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu"
241 "VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN"
242 "MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0"
243 "MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi"
244 "MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7"
245 "ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy"
246 "RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS"
247 "bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF"
248 "/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R"
249 "3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw"
250 "EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy"
251 "9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V"
252 "GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ"
253 "2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV"
254 "WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD"
255 "W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/"
256 "BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN"
257 "AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj"
258 "t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV"
259 "DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9"
260 "TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G"
261 "lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW"
262 "mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df"
263 "WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5"
264 "+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ"
265 "tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA"
266 "GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv"
267 "8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c"
268 "-----END CERTIFICATE-----",
269 "AABBsdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfasdfasdf",
270 "09840523490582034850-2385023845023845023840523orjoewjrt0932u4ojt[iq3w04tu32094503u4t32u4059",
271 ";';,,'s'd,fdg;sm;lsdf;g,s;d ;s,g ;,df;gl s;dg, ;sd,;gf,sd; g,",
272 "46s4f64s6df4a6sd4f64sdgf654segf654df66dsfg4e4rt65w4t6w4et64ewr6g4sd64fg65ds4fg",
273 "sdfasdg4sag64a6g45sd4 64365 46 4d6f4asd64 f6as4 f6as74f987s6543654165JJKK",
274 NULL
275 };
276
277 rws_socket_send_bin_start(_socket, "start", strlen("start"));
278 int i = 0;
279 while(text_arr[i] != NULL) {
280 rws_socket_send_bin_continue(_socket, text_arr[i], strlen(text_arr[i]));
281 // aos_msleep(100);
282 i++;
283 }
284 rws_socket_send_bin_finish(_socket, "finish", strlen("finish"));
285 #endif
286
287 if (_socket) {
288 rws_socket_disconnect_and_release(_socket);
289 }
290
291 _socket = NULL;
292
293 return ret;
294 }
295
websoc_cli_test_entry(void * arg)296 void websoc_cli_test_entry(void *arg)
297 {
298 int ret = 0, ssl_ret = 0;
299
300 #if WEBSOCKET_SSL_TEST
301 char *cert = (char *)ECHO_WEBSOCKET_CER;
302 printf("Test client wss.");
303 ssl_ret = websoc_cli_test_int("wss", "echo.websocket.org", "/", 443, cert);
304 #else
305 printf("Test client ws.");
306 // ret = websoc_cli_test_int("ws", "echo.websocket.org", "/", 80, NULL);
307 ret = websoc_cli_test_int("ws", "121.40.165.18", "/", 8800, NULL);
308 #endif
309
310 if (0 == ret && 0 == ssl_ret) {
311 printf("example websocket test success!");
312 } else {
313 printf("example websocket test failed! ret:%d, ssl_ret:%d", ret, ssl_ret);
314 }
315 }
316
websocket_comp_example(int argc,char ** argv)317 void websocket_comp_example(int argc, char **argv)
318 {
319 aos_task_new("ws-test", websoc_cli_test_entry, NULL, 10 * 1024);
320 }
321
322
323 #if AOS_COMP_CLI
324 /* reg args: fun, cmd, description*/
325 ALIOS_CLI_CMD_REGISTER(websocket_comp_example, websocket_example, websocket component base example)
326 #endif
327