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