1 /*
2 * Copyright (c) 2014 - 2019 Oleh Kulykov <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
24 #include "librws.h"
25 #include "rws_socket.h"
26 #include "rws_memory.h"
27 #include "rws_string.h"
28 #include <assert.h>
29 #include <signal.h>
30
31 // public
rws_socket_connect(rws_socket socket)32 rws_bool rws_socket_connect(rws_socket socket) {
33 const char * params_error_msg = NULL;
34 if (!socket) {
35 return rws_false;
36 }
37
38 rws_error_delete_clean(&socket->error);
39
40 if (socket->port <= 0) {
41 params_error_msg = "No URL port provided";
42 }
43 if (!socket->scheme) {
44 params_error_msg = "No URL scheme provided";
45 }
46 if (!socket->host) {
47 params_error_msg = "No URL host provided";
48 }
49 if (!socket->path) {
50 params_error_msg = "No URL path provided";
51 }
52 if (!socket->on_disconnected) {
53 params_error_msg = "No on_disconnected callback provided";
54 }
55 socket->received_len = 0;
56 if (params_error_msg) {
57 socket->error = rws_error_new_code_descr(rws_error_code_missed_parameter, params_error_msg);
58 return rws_false;
59 }
60 return rws_socket_create_start_work_thread(socket);
61 }
62
rws_socket_disconnect_and_release(rws_socket socket)63 void rws_socket_disconnect_and_release(rws_socket socket) {
64 if (!socket) {
65 return;
66 }
67
68 rws_mutex_lock(socket->work_mutex);
69
70 rws_socket_delete_all_frames_in_list(socket->send_frames);
71 rws_list_delete_clean(&socket->send_frames);
72
73 if (socket->is_connected) { // connected in loop
74 socket->command = COMMAND_DISCONNECT;
75 } else if (socket->work_thread) { // disconnected in loop
76 socket->command = COMMAND_END;
77 }
78
79 rws_mutex_unlock(socket->work_mutex);
80
81 rws_sem_wait(socket->exit_sem, RWS_WAIT_FOREVER);
82
83 rws_socket_delete(socket);
84 }
85
rws_socket_send_bin_start(rws_socket socket,const char * bin,size_t len)86 rws_bool rws_socket_send_bin_start(rws_socket socket, const char *bin, size_t len) {
87 rws_bool r = rws_false;
88 if (socket) {
89 rws_mutex_lock(socket->send_mutex);
90 if (socket->socket != RWS_INVALID_SOCKET && socket->is_connected)
91 r = rws_socket_send_bin_priv(socket, bin, len, rws_binary_start);
92 rws_mutex_unlock(socket->send_mutex);
93 }
94 return r;
95 }
96
rws_socket_send_bin_continue(rws_socket socket,const char * bin,size_t len)97 rws_bool rws_socket_send_bin_continue(rws_socket socket, const char *bin, size_t len) {
98 rws_bool r = rws_false;
99 if (socket) {
100 rws_mutex_lock(socket->send_mutex);
101 if (socket->socket != RWS_INVALID_SOCKET && socket->is_connected)
102 r = rws_socket_send_bin_priv(socket, bin, len, rws_binary_continue);
103 rws_mutex_unlock(socket->send_mutex);
104 }
105 return r;
106 }
107
rws_socket_send_bin_finish(rws_socket socket,const char * bin,size_t len)108 rws_bool rws_socket_send_bin_finish(rws_socket socket, const char *bin, size_t len) {
109 rws_bool r = rws_false;
110 if (socket) {
111 rws_mutex_lock(socket->send_mutex);
112 if (socket->socket != RWS_INVALID_SOCKET && socket->is_connected)
113 r = rws_socket_send_bin_priv(socket, bin, len, rws_binary_finish);
114 rws_mutex_unlock(socket->send_mutex);
115 }
116 return r;
117 }
118
rws_socket_send_text(rws_socket socket,const char * text)119 rws_bool rws_socket_send_text(rws_socket socket, const char * text) {
120 rws_bool r = rws_false;
121 if (socket) {
122 rws_mutex_lock(socket->send_mutex);
123 if (socket->socket != RWS_INVALID_SOCKET && socket->is_connected)
124 r = rws_socket_send_text_priv(socket, text);
125 rws_mutex_unlock(socket->send_mutex);
126 }
127 return r;
128 }
129
rws_socket_send_ping(rws_socket socket)130 rws_bool rws_socket_send_ping(rws_socket socket) {
131 rws_bool r = rws_false;
132 if (socket) {
133 rws_mutex_lock(socket->send_mutex);
134 if (socket->socket != RWS_INVALID_SOCKET && socket->is_connected)
135 r = rws_socket_send_ping_priv(socket);
136 rws_mutex_unlock(socket->send_mutex);
137 }
138 return r;
139 }
140
141 /*void rws_socket_handle_sigpipe(int signal_number) {
142 printf("\nlibrws handle sigpipe %i", signal_number);
143 (void)signal_number;
144 return;
145 }*/
146
147 #define STRING_I(s) #s
148 #define TO_STRING(s) STRING_I(s)
149 #define BUFF_SIZE 8192
150
rws_socket_check_info(const char * info)151 void rws_socket_check_info(const char * info) {
152 assert(info);
153 (void)info;
154 }
155
rws_socket_create(void)156 rws_socket rws_socket_create(void) {
157 rws_socket s = (rws_socket)rws_malloc_zero(sizeof(struct rws_socket_struct));
158 if (!s) {
159 return NULL;
160 }
161
162 s->recv_buffer = (char *) rws_malloc(BUFF_SIZE);
163 if (NULL == s->recv_buffer) {
164 rws_free(s);
165 return NULL;
166 }
167 s->recv_buffer_size = BUFF_SIZE;
168
169 s->port = -1;
170 s->socket = RWS_INVALID_SOCKET;
171 s->command = COMMAND_NONE;
172
173 s->work_mutex = rws_mutex_create_recursive();
174 s->send_mutex = rws_mutex_create_recursive();
175 s->exit_sem = rws_sem_create();
176
177 static const char * info = "librws ver: " TO_STRING(RWS_VERSION_MAJOR) "." TO_STRING(RWS_VERSION_MINOR) "." TO_STRING(RWS_VERSION_PATCH) "\n";
178 rws_socket_check_info(info);
179
180 return s;
181 }
182
rws_socket_delete(rws_socket s)183 void rws_socket_delete(rws_socket s) {
184 rws_socket_close(s);
185
186 rws_free_clean(&s->received);
187 s->received_size = 0;
188 s->received_len = 0;
189
190 rws_socket_delete_all_frames_in_list(s->send_frames);
191 rws_list_delete_clean(&s->send_frames);
192 rws_socket_delete_all_frames_in_list(s->recvd_frames);
193 rws_list_delete_clean(&s->recvd_frames);
194
195 rws_string_delete_clean(&s->scheme);
196 rws_string_delete_clean(&s->host);
197 rws_string_delete_clean(&s->path);
198 rws_string_delete_clean(&s->sec_ws_protocol);
199 rws_string_delete_clean(&s->sec_ws_accept);
200 rws_error_delete_clean(&s->error);
201
202 rws_mutex_delete(s->work_mutex);
203 s->work_mutex = NULL;
204
205 rws_mutex_delete(s->send_mutex);
206 s->send_mutex = NULL;
207
208 rws_sem_delete(s->exit_sem);
209 s->exit_sem = NULL;
210
211 rws_free(s->recv_buffer);
212 s->recv_buffer = NULL;
213 s->recv_buffer_size = 0;
214
215 rws_free(s);
216 }
217
rws_socket_set_url(rws_socket socket,const char * scheme,const char * host,const int port,const char * path)218 void rws_socket_set_url(rws_socket socket,
219 const char * scheme,
220 const char * host,
221 const int port,
222 const char * path) {
223 if (socket) {
224 rws_string_delete(socket->scheme);
225 socket->scheme = rws_string_copy(scheme);
226
227 rws_string_delete(socket->host);
228 socket->host = rws_string_copy(host);
229
230 rws_string_delete(socket->path);
231 socket->path = rws_string_copy(path);
232
233 socket->port = port;
234 }
235 }
236
rws_socket_set_scheme(rws_socket socket,const char * scheme)237 void rws_socket_set_scheme(rws_socket socket, const char * scheme) {
238 if (socket) {
239 rws_string_delete(socket->scheme);
240 socket->scheme = rws_string_copy(scheme);
241 }
242 }
243
rws_socket_get_scheme(rws_socket socket)244 const char * rws_socket_get_scheme(rws_socket socket) {
245 return socket ? socket->scheme : NULL;
246 }
247
rws_socket_set_host(rws_socket socket,const char * host)248 void rws_socket_set_host(rws_socket socket, const char * host) {
249 if (socket) {
250 rws_string_delete(socket->host);
251 socket->host = rws_string_copy(host);
252 }
253 }
254
rws_socket_get_host(rws_socket socket)255 const char * rws_socket_get_host(rws_socket socket) {
256 return socket ? socket->host : NULL;
257 }
258
rws_socket_set_path(rws_socket socket,const char * path)259 void rws_socket_set_path(rws_socket socket, const char * path) {
260 if (socket) {
261 rws_string_delete(socket->path);
262 socket->path = rws_string_copy(path);
263 }
264 }
265
rws_socket_get_path(rws_socket socket)266 const char * rws_socket_get_path(rws_socket socket) {
267 return socket ? socket->path : NULL;
268 }
269
rws_socket_set_port(rws_socket socket,const int port)270 void rws_socket_set_port(rws_socket socket, const int port) {
271 if (socket) {
272 socket->port = port;
273 }
274 }
275
rws_socket_get_port(rws_socket socket)276 int rws_socket_get_port(rws_socket socket) {
277 return socket ? socket->port : -1;
278 }
279
rws_socket_set_protocol(rws_socket socket,const char * protocol)280 void rws_socket_set_protocol(rws_socket socket, const char * protocol) {
281 if (socket) {
282 rws_string_delete(socket->sec_ws_protocol);
283 socket->sec_ws_protocol = rws_string_copy(protocol);
284 }
285 }
286
287 /*
288 unsigned int _rws_socket_get_receive_buffer_size(rws_socket_t socket) {
289 unsigned int size = 0;
290 #if defined(RWS_OS_WINDOWS)
291 int len = sizeof(unsigned int);
292 if (getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&size, &len) == -1) {
293 size = 0;
294 }
295 #else
296 socklen_t len = sizeof(unsigned int);
297 if (getsockopt(socket, SOL_SOCKET, SO_RCVBUF, &size, &len) == -1) {
298 size = 0;
299 }
300 #endif
301 return size;
302 }
303
304 unsigned int rws_socket_get_receive_buffer_size(rws_socket socket) {
305 _rws_socket * s = (_rws_socket *)socket;
306 if (!s) {
307 return 0;
308 }
309 if (s->socket == RWS_INVALID_SOCKET) {
310 return 0;
311 }
312 return _rws_socket_get_receive_buffer_size(s->socket);
313 }
314 */
315
rws_socket_get_error(rws_socket socket)316 rws_error rws_socket_get_error(rws_socket socket) {
317 return socket ? socket->error : NULL;
318 }
319
rws_socket_set_user_object(rws_socket socket,void * user_object)320 void rws_socket_set_user_object(rws_socket socket, void * user_object) {
321 if (socket) {
322 socket->user_object = user_object;
323 }
324 }
325
rws_socket_get_user_object(rws_socket socket)326 void * rws_socket_get_user_object(rws_socket socket) {
327 return socket ? socket->user_object : NULL;
328 }
329
rws_socket_set_on_connected(rws_socket socket,rws_on_socket callback)330 void rws_socket_set_on_connected(rws_socket socket, rws_on_socket callback) {
331 if (socket) {
332 socket->on_connected = callback;
333 }
334 }
335
rws_socket_set_on_disconnected(rws_socket socket,rws_on_socket callback)336 void rws_socket_set_on_disconnected(rws_socket socket, rws_on_socket callback) {
337 if (socket) {
338 socket->on_disconnected = callback;
339 }
340 }
341
rws_socket_set_on_received_text(rws_socket socket,rws_on_socket_recvd_text callback)342 void rws_socket_set_on_received_text(rws_socket socket, rws_on_socket_recvd_text callback) {
343 if (socket) {
344 socket->on_recvd_text = callback;
345 }
346 }
347
rws_socket_set_on_received_bin(rws_socket socket,rws_on_socket_recvd_bin callback)348 void rws_socket_set_on_received_bin(rws_socket socket, rws_on_socket_recvd_bin callback) {
349 if (socket) {
350 socket->on_recvd_bin = callback;
351 }
352 }
353
rws_socket_is_connected(rws_socket socket)354 rws_bool rws_socket_is_connected(rws_socket socket) {
355 rws_bool r = rws_false;
356 if (socket) {
357 rws_mutex_lock(socket->send_mutex);
358 r = socket->is_connected;
359 rws_mutex_unlock(socket->send_mutex);
360 }
361 return r;
362 }
363
rws_socket_set_on_received_pong(rws_socket socket,rws_on_socket_recvd_pong callback)364 void rws_socket_set_on_received_pong(rws_socket socket, rws_on_socket_recvd_pong callback) {
365 if (socket) {
366 socket->on_recvd_pong = callback;
367 }
368 }
369
rws_socket_set_on_send_ping(rws_socket socket,rws_on_socket_send_ping callback)370 void rws_socket_set_on_send_ping(rws_socket socket, rws_on_socket_send_ping callback) {
371 if (socket) {
372 socket->on_send_ping = callback;
373 }
374 }
375
376 #ifdef WEBSOCKET_SSL_ENABLE
rws_socket_set_server_cert(rws_socket socket,const char * server_cert,int server_cert_len)377 void rws_socket_set_server_cert(rws_socket socket, const char *server_cert, int server_cert_len)
378 {
379 DBG("%s: server_cert[len:%d]: \n%s", __FUNCTION__, server_cert_len, server_cert);
380
381 rws_socket s = socket;
382 if (s) {
383 s->server_cert = server_cert;
384 s->server_cert_len = server_cert_len;
385 }
386 }
387 #endif
388
389