GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/sockettools.c
Date: 2026-10-19 17:06:30
Exec Total Coverage
Lines: 755 994 76.0%
Functions: 69 85 81.2%
Branches: 247 481 51.4%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28 #include "gate/net/sockettools.h"
29 #include "gate/net/nameresolvers.h"
30 #include "gate/threading.h"
31 #include "gate/synchronization.h"
32 #include "gate/arrays.h"
33 #include "gate/debugging.h"
34 #include "gate/maps.h"
35 #include "gate/platforms.h"
36
37 #define GATE_SOCKETGROUP_LIMIT 512
38
39
40 #if !defined(GATE_SYS_POSIX)
41
42 gate_result_t gate_socketselector_create(gate_socketselector_t* selector)
43 {
44 gate_result_t ret;
45 gate_socket_t sock;
46 do
47 {
48 gate_mem_clear(selector, sizeof(gate_socketselector_t));
49 ret = gate_socket_create_ex(GATE_SOCKET_FAMILY_INET4, GATE_SOCKET_MSGTYPE_STREAM, GATE_SOCKET_PROTOCOL_TCP, &sock);
50 } while (0);
51 selector->handles[0] = (void*)sock;
52 return ret;
53 }
54 gate_result_t gate_socketselector_destroy(gate_socketselector_t* selector)
55 {
56 gate_result_t ret = GATE_RESULT_OK;
57 gate_socket_t sock = (gate_socket_t)(gate_intptr_t)selector->handles[0];
58 gate_socket_close(sock);
59 return ret;
60 }
61 gate_result_t gate_socketselector_interrupt(gate_socketselector_t* selector)
62 {
63 gate_result_t ret;
64 gate_socket_t oldsock = (gate_socket_t)(gate_intptr_t)selector->handles[0];
65 gate_socket_t newsock;
66 do
67 {
68 ret = gate_socket_create_ex(GATE_SOCKET_FAMILY_INET4, GATE_SOCKET_MSGTYPE_STREAM, GATE_SOCKET_PROTOCOL_TCP, &newsock);
69 GATE_BREAK_IF_FAILED(ret);
70
71 selector->handles[0] = (void*)newsock;
72 gate_socket_close(oldsock);
73 } while (0);
74 return ret;
75 }
76 gate_result_t gate_socketselector_select(gate_socketselector_t* selector, gate_socket_t const* socks, gate_size_t sockcount, gate_uint8_t* statusflags, gate_uint32_t timeout)
77 {
78 gate_result_t ret;
79 gate_socket_t local_sockets[GATE_SOCKETGROUP_LIMIT];
80 gate_uint8_t local_flags[GATE_SOCKETGROUP_LIMIT];
81 gate_size_t index;
82 gate_size_t local_sockcount = sockcount;
83 gate_socket_t interruptor = (gate_socket_t)(gate_intptr_t)selector->handles[0];
84
85 if (local_sockcount >= (GATE_SOCKETGROUP_LIMIT - 1))
86 {
87 local_sockcount = GATE_SOCKETGROUP_LIMIT - 2;
88 }
89
90 for (index = 0; index != local_sockcount; ++index)
91 {
92 local_sockets[index] = socks[index];
93 local_flags[index] = statusflags[index];
94 }
95 local_sockets[local_sockcount] = interruptor;
96 local_flags[local_sockcount] = GATE_SOCKET_SELECT_FLAG_ERROR;
97
98 ret = gate_socket_select(local_sockets, local_sockcount + 1, local_flags, timeout);
99
100 index = 0;
101 if (GATE_SUCCEEDED(ret))
102 {
103 for (; index != local_sockcount; ++index)
104 {
105 statusflags[index] = local_flags[index];
106 }
107 }
108
109 /* notify NO-ACTION on all non-processed sockets */
110 for (; index < sockcount; ++index)
111 {
112 statusflags[index] = 0;
113 }
114
115 return ret;
116 }
117
118 #else
119
120 #include <unistd.h>
121
122 7 gate_result_t gate_socketselector_create(gate_socketselector_t* selector)
123 {
124 int result;
125 7 gate_result_t ret = gate_socket_init();
126
127
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(GATE_SUCCEEDED(ret))
128 {
129 int pipe_fd[2];
130 7 result = pipe(pipe_fd);
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (result == -1)
132 {
133 ✗ ret = GATE_RESULT_FAILED;
134 }
135 else
136 {
137 7 selector->handles[0] = (void*)(gate_intptr_t)pipe_fd[0];
138 7 selector->handles[1] = (void*)(gate_intptr_t)pipe_fd[1];
139 7 ret = GATE_RESULT_OK;
140 }
141 }
142 7 return ret;
143
144 }
145 7 gate_result_t gate_socketselector_destroy(gate_socketselector_t* selector)
146 {
147 7 int read_pipe = (int)(gate_intptr_t)selector->handles[0];
148 7 int write_pipe = (int)(gate_intptr_t)selector->handles[1];
149 7 gate_posix_close(read_pipe);
150 7 gate_posix_close(write_pipe);
151 7 return GATE_RESULT_OK;
152 }
153 44 gate_result_t gate_socketselector_interrupt(gate_socketselector_t* selector)
154 {
155 44 int write_pipe = (int)(gate_intptr_t)selector->handles[1];
156 static char const ch = 'I';
157 44 gate_posix_write(write_pipe, &ch, 1);
158 44 return GATE_RESULT_OK;
159 }
160 48 gate_result_t gate_socketselector_select(gate_socketselector_t* selector, gate_socket_t const* socks, gate_size_t sockcount, gate_uint8_t* statusflags, gate_uint32_t timeout)
161 {
162 gate_result_t ret;
163 gate_socket_t local_sockets[GATE_SOCKETGROUP_LIMIT];
164 gate_uint8_t local_flags[GATE_SOCKETGROUP_LIMIT];
165 gate_size_t index;
166 48 gate_size_t local_sockcount = sockcount;
167 48 gate_socket_t interruptor = (gate_socket_t)(gate_intptr_t)selector->handles[0];
168
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (local_sockcount >= GATE_SOCKETGROUP_LIMIT)
170 {
171 ✗ local_sockcount = GATE_SOCKETGROUP_LIMIT - 1;
172 }
173
174
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 48 times.
125 for (index = 0; index != local_sockcount; ++index)
175 {
176 77 local_sockets[index] = socks[index];
177 77 local_flags[index] = statusflags[index];
178 }
179 48 local_sockets[local_sockcount] = interruptor;
180 48 local_flags[local_sockcount] = GATE_SOCKET_SELECT_FLAG_RECEIVE | GATE_SOCKET_SELECT_FLAG_ERROR;
181
182 48 ret = gate_socket_select(local_sockets, local_sockcount + 1, local_flags, timeout);
183
184 48 index = 0;
185
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (GATE_SUCCEEDED(ret))
186 {
187
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 10 times.
48 if (GATE_FLAG_ENABLED(local_flags[local_sockcount], GATE_SOCKET_SELECT_FLAG_RECEIVE))
188 {
189 char buf[1];
190 38 gate_posix_read((int)interruptor, buf, 1);
191 }
192
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 48 times.
125 for (; index != local_sockcount; ++index)
193 {
194 77 statusflags[index] = local_flags[index];
195 }
196 }
197
198 /* notify NO-ACTION on all non-processed sockets */
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 for (; index < sockcount; ++index)
200 {
201 ✗ statusflags[index] = 0;
202 }
203
204 48 return ret;
205 }
206
207
208 #endif
209
210
211
212 typedef struct gate_socketgroup_task
213 {
214 gate_socket_t sock;
215 int command;
216 gate_size_t length;
217 gate_size_t offset;
218 void* param;
219 gate_intptr_t info;
220 gate_bool_t completed;
221 char data[1];
222
223 } gate_socketgroup_task_t;
224
225 43 static gate_socketgroup_task_t* gate_socketgroup_task_create(int command, gate_size_t datalength, gate_size_t allocatelength, void* param)
226 {
227 43 gate_socketgroup_task_t* ret = (gate_socketgroup_task_t*)gate_mem_alloc(sizeof(gate_socketgroup_task_t) + allocatelength);
228
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (ret)
229 {
230 43 gate_mem_clear(ret, sizeof(gate_socketgroup_task_t) + allocatelength);
231 43 ret->command = command;
232 43 ret->offset = 0;
233 43 ret->length = datalength;
234 43 ret->param = param;
235 43 ret->completed = false;
236 }
237 43 return ret;
238 }
239
240 43 static void gate_socketgroup_task_destroy(gate_socketgroup_task_t* task)
241 {
242 43 gate_mem_dealloc(task);
243 43 }
244
245
246 6 gate_result_t gate_socketgroup_create(gate_socketgroup_t* group, void* user_tag)
247 {
248 6 gate_result_t ret = GATE_RESULT_OK;
249 do
250 {
251 6 gate_mem_clear(group, sizeof(gate_socketgroup_t));
252 6 gate_atomic_int_set(&group->running, 0);
253
254 6 ret = gate_socketselector_create(&group->selector);
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
256
257 6 group->tasks = gate_arraylist_create(sizeof(gate_socketgroup_task_t*), NULL, 0, NULL, NULL);
258
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (gate_arraylist_is_null(group->tasks))
259 {
260 ✗ gate_socketselector_destroy(&group->selector);
261 ✗ ret = GATE_RESULT_OUTOFMEMORY;
262 ✗ break;
263 }
264 6 ret = gate_mutex_create(&group->mutex);
265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (GATE_FAILED(ret))
266 {
267 ✗ gate_arraylist_release(&group->tasks);
268 ✗ gate_socketselector_destroy(&group->selector);
269 ✗ break;
270 }
271 6 group->interval_ms = 500;
272 6 group->user_tag = user_tag;
273 } while (0);
274 6 return ret;
275 }
276
277 6 gate_result_t gate_socketgroup_destroy(gate_socketgroup_t* group)
278 {
279 6 gate_result_t ret = GATE_RESULT_OK;
280 gate_result_t result;
281 6 gate_socketgroup_quit(group);
282
283 6 result = gate_socketgroup_clear(group);
284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (GATE_FAILED(result)) ret = result;
285
286 6 gate_arraylist_release(&group->tasks);
287 6 gate_socketselector_destroy(&group->selector);
288
289 6 result = gate_mutex_destroy(&group->mutex);
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (GATE_FAILED(result)) ret = result;
291
292 6 return ret;
293 }
294 11 gate_result_t gate_socketgroup_clear(gate_socketgroup_t* group)
295 {
296 11 gate_result_t ret = GATE_RESULT_FAILED;
297 gate_size_t index;
298 gate_size_t sockcount;
299 gate_socketgroup_task_t** ptr_task;
300 do
301 {
302 11 ret = gate_mutex_acquire(&group->mutex);
303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 GATE_BREAK_IF_FAILED(ret);
304
305 do
306 {
307 11 sockcount = gate_arraylist_length(group->tasks);
308
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 for (index = 0; index != sockcount; ++index)
309 {
310 1 ptr_task = (gate_socketgroup_task_t**)gate_arraylist_get(group->tasks, index);
311
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (ptr_task && *ptr_task)
312 {
313 1 gate_socketgroup_task_destroy(*ptr_task);
314 }
315 }
316 11 gate_arraylist_clear(group->tasks);
317
318 } while (0);
319 11 gate_mutex_release(&group->mutex);
320
321 } while (0);
322 11 return ret;
323 }
324
325 19 static gate_bool_t gate_socketgroup_remove_condition(void const* item, void* param)
326 {
327 19 gate_socketgroup_task_t* const* task = (gate_socketgroup_task_t* const*)item;
328 19 gate_socket_t* sock = (gate_socket_t*)param;
329
5/6
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 7 times.
19 if (task && (*task) && ((*task)->sock == *sock))
330 {
331 /* delete task pointer and return true to remove it from arraylist */
332 6 gate_socketgroup_task_destroy(*task);
333 6 return true;
334 }
335 13 return false;
336 }
337
338 43 static gate_bool_t gate_socketgroup_integrate_task(gate_socketgroup_t* group, gate_socketgroup_task_t* task)
339 {
340 43 gate_size_t len = gate_arraylist_length(group->tasks);
341
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4 times.
43 if (len != 0)
342 {
343 /* find empty slot to overwrite: */
344 39 gate_socketgroup_task_t** tasks = (gate_socketgroup_task_t**)gate_arraylist_get(group->tasks, 0);
345
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 19 times.
91 for (; len != 0; --len, ++tasks)
346 {
347
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 52 times.
72 if (*tasks == NULL)
348 {
349 20 *tasks = task;
350 20 return true;
351 }
352 }
353 }
354 /* add new entry */
355 23 return NULL != gate_arraylist_add(group->tasks, &task);
356 }
357
358 10 gate_result_t gate_socketgroup_remove(gate_socketgroup_t* group, gate_socket_t sock)
359 {
360 10 gate_result_t ret = GATE_RESULT_FAILED;
361 do
362 {
363 10 ret = gate_mutex_acquire(&group->mutex);
364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 GATE_BREAK_IF_FAILED(ret);
365
366 do
367 {
368 10 ret = gate_arraylist_remove_if(group->tasks, &gate_socketgroup_remove_condition, &sock);
369 } while (0);
370 10 gate_mutex_release(&group->mutex);
371
372 } while (0);
373 10 return ret;
374 }
375
376 4 gate_result_t gate_socketgroup_connect(gate_socketgroup_t* group, gate_socket_t sock, gate_socket_endpoint_t const* endpoint, void* param)
377 {
378 4 gate_result_t ret = GATE_RESULT_OK;
379 do
380 {
381 4 gate_socketgroup_task_t* task = gate_socketgroup_task_create(GATE_SOCKETGROUP_OPERATION_CONNECT, 0, 0, param);
382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!task)
383 {
384 ✗ ret = GATE_RESULT_OUTOFMEMORY;
385 ✗ break;
386 }
387 4 ret = gate_socket_connect(sock, endpoint);
388
389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(ret))
390 {
391 ✗ gate_socketgroup_task_destroy(task);
392 }
393 else
394 {
395 4 task->sock = sock;
396 4 ret = gate_mutex_acquire(&group->mutex);
397
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
398 {
399
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!gate_socketgroup_integrate_task(group, task))
400 {
401 ✗ gate_socketgroup_task_destroy(task);
402 ✗ ret = GATE_RESULT_OUTOFMEMORY;
403 }
404 4 gate_mutex_release(&group->mutex);
405 }
406 4 gate_socketselector_interrupt(&group->selector);
407 }
408 } while (0);
409 4 return ret;
410 }
411 10 gate_result_t gate_socketgroup_accept(gate_socketgroup_t* group, gate_socket_t sock, void* param)
412 {
413 10 gate_result_t ret = GATE_RESULT_OK;
414 do
415 {
416 10 gate_socketgroup_task_t* task = gate_socketgroup_task_create(GATE_SOCKETGROUP_OPERATION_ACCEPT, 0, 0, param);
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!task)
418 {
419 ✗ ret = GATE_RESULT_OUTOFMEMORY;
420 ✗ break;
421 }
422 10 task->sock = sock;
423 {
424 10 ret = gate_mutex_acquire(&group->mutex);
425
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (GATE_SUCCEEDED(ret))
426 {
427
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (!gate_socketgroup_integrate_task(group, task))
428 {
429 ✗ gate_socketgroup_task_destroy(task);
430 ✗ ret = GATE_RESULT_OUTOFMEMORY;
431 }
432 10 gate_mutex_release(&group->mutex);
433 }
434 10 gate_socketselector_interrupt(&group->selector);
435 }
436 } while (0);
437 10 return ret;
438 }
439 12 gate_result_t gate_socketgroup_read(gate_socketgroup_t* group, gate_socket_t sock, gate_size_t length, void* param)
440 {
441 12 gate_result_t ret = GATE_RESULT_OK;
442 do
443 {
444 12 gate_socketgroup_task_t* task = gate_socketgroup_task_create(GATE_SOCKETGROUP_OPERATION_READ, 0, 0, param);
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!task)
446 {
447 ✗ ret = GATE_RESULT_OUTOFMEMORY;
448 ✗ break;
449 }
450 12 task->length = length;
451 12 task->sock = sock;
452 {
453 12 ret = gate_mutex_acquire(&group->mutex);
454
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (GATE_SUCCEEDED(ret))
455 {
456
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if (!gate_socketgroup_integrate_task(group, task))
457 {
458 ✗ gate_socketgroup_task_destroy(task);
459 ✗ ret = GATE_RESULT_OUTOFMEMORY;
460 }
461 12 gate_mutex_release(&group->mutex);
462 }
463 12 gate_socketselector_interrupt(&group->selector);
464 }
465 } while (0);
466 12 return ret;
467 }
468 13 gate_result_t gate_socketgroup_write(gate_socketgroup_t* group, gate_socket_t sock, char const* data, gate_size_t length, void* param)
469 {
470 13 gate_result_t ret = GATE_RESULT_OK;
471 do
472 {
473 13 gate_socketgroup_task_t* task = gate_socketgroup_task_create(GATE_SOCKETGROUP_OPERATION_WRITE, length, length, param);
474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!task)
475 {
476 ✗ ret = GATE_RESULT_OUTOFMEMORY;
477 ✗ break;
478 }
479
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (length != 0)
480 {
481 13 gate_mem_copy(task->data, data, length);
482 }
483 13 task->sock = sock;
484 {
485 13 ret = gate_mutex_acquire(&group->mutex);
486
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (GATE_SUCCEEDED(ret))
487 {
488
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (!gate_socketgroup_integrate_task(group, task))
489 {
490 ✗ gate_socketgroup_task_destroy(task);
491 ✗ ret = GATE_RESULT_OUTOFMEMORY;
492 }
493 13 gate_mutex_release(&group->mutex);
494 }
495 13 gate_socketselector_interrupt(&group->selector);
496 }
497 } while (0);
498 13 return ret;
499 }
500 4 gate_result_t gate_socketgroup_shutdown_write(gate_socketgroup_t* group, gate_socket_t sock, void* param)
501 {
502 4 gate_result_t ret = GATE_RESULT_OK;
503 do
504 {
505 4 gate_socketgroup_task_t* task = gate_socketgroup_task_create(GATE_SOCKETGROUP_OPERATION_SHUTDOWN_WRITE, 0, 0, param);
506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!task)
507 {
508 ✗ ret = GATE_RESULT_OUTOFMEMORY;
509 ✗ break;
510 }
511 4 task->sock = sock;
512 {
513 4 ret = gate_mutex_acquire(&group->mutex);
514
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
515 {
516
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!gate_socketgroup_integrate_task(group, task))
517 {
518 ✗ gate_socketgroup_task_destroy(task);
519 ✗ ret = GATE_RESULT_OUTOFMEMORY;
520 }
521 4 gate_mutex_release(&group->mutex);
522 }
523 4 gate_socketselector_interrupt(&group->selector);
524 }
525 } while (0);
526 4 return ret;
527 }
528
529
530 95 static gate_size_t gate_socketgroup_find_socket(gate_socket_t* sockets, gate_size_t socketcount, gate_socket_t target)
531 {
532 95 gate_size_t sockindex = 0;
533
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 76 times.
137 while (socketcount-- != 0)
534 {
535
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 42 times.
61 if (*sockets == target)
536 {
537 19 return sockindex;
538 }
539 42 ++sockets;
540 42 ++sockindex;
541 }
542 76 return GATE_INVALID_SIZE;
543 }
544
545 44 static gate_size_t gate_socketgroup_load_sockets(gate_socketgroup_task_t* const* tasks, gate_size_t taskcount,
546 gate_socket_t* sockets, gate_uint8_t* flags, gate_size_t maxsockets)
547 {
548 44 gate_size_t sockets_used = 0;
549 gate_size_t sockindex;
550 gate_socketgroup_task_t* current_task;
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (taskcount > maxsockets)
552 {
553 ✗ taskcount = maxsockets;
554 }
555
556
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
139 while ((taskcount-- != 0) && (sockets_used < maxsockets))
557 {
558 95 current_task = *tasks;
559 95 ++tasks;
560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (current_task == NULL)
561 {
562 /* skip empty tasks */
563 ✗ continue;
564 }
565 95 sockindex = gate_socketgroup_find_socket(sockets, sockets_used, current_task->sock);
566
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 19 times.
95 if (sockindex == GATE_INVALID_SIZE)
567 {
568 76 sockindex = sockets_used++;
569 76 sockets[sockindex] = current_task->sock;
570 76 flags[sockindex] = GATE_SOCKET_SELECT_FLAG_ERROR;
571 }
572
573
3/4
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
95 switch (current_task->command)
574 {
575 63 case GATE_SOCKETGROUP_OPERATION_ACCEPT:
576 case GATE_SOCKETGROUP_OPERATION_READ:
577 {
578 63 flags[sockindex] |= GATE_SOCKET_SELECT_FLAG_RECEIVE;
579 63 break;
580 }
581 28 case GATE_SOCKETGROUP_OPERATION_WRITE:
582 case GATE_SOCKETGROUP_OPERATION_SHUTDOWN_WRITE:
583 {
584 28 flags[sockindex] |= GATE_SOCKET_SELECT_FLAG_SEND;
585 28 break;
586 }
587 4 case GATE_SOCKETGROUP_OPERATION_CONNECT:
588 {
589 4 flags[sockindex] |= GATE_SOCKET_SELECT_FLAG_SEND;
590 4 break;
591 }
592 }
593
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 44 times.
139 }
594 44 return sockets_used;
595 }
596
597 36 static gate_size_t gate_socketgroup_find_task(gate_socketgroup_task_t* const* tasks, gate_size_t taskcount,
598 gate_socket_t target, gate_uint8_t flag)
599 {
600 36 gate_size_t task_index = 0;
601
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 while (taskcount-- != 0)
602 {
603
4/4
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 14 times.
55 if ((*tasks) && (*tasks)->sock == target)
604 {
605
2/3
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
37 switch ((*tasks)->command)
606 {
607 19 case GATE_SOCKETGROUP_OPERATION_CONNECT:
608 case GATE_SOCKETGROUP_OPERATION_WRITE:
609 case GATE_SOCKETGROUP_OPERATION_SHUTDOWN_WRITE:
610 {
611
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (GATE_FLAG_ENABLED(flag, GATE_SOCKET_SELECT_FLAG_SEND))
612 {
613 19 return task_index;
614 }
615 ✗ break;
616 }
617 18 case GATE_SOCKETGROUP_OPERATION_ACCEPT:
618 case GATE_SOCKETGROUP_OPERATION_READ:
619 {
620
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
18 if (GATE_FLAG_ENABLED(flag, GATE_SOCKET_SELECT_FLAG_RECEIVE))
621 {
622 17 return task_index;
623 }
624 1 break;
625 }
626 }
627
628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FLAG_ENABLED(flag, GATE_SOCKET_SELECT_FLAG_ERROR))
629 {
630 /* errors are always communicated */
631 ✗ return task_index;
632 }
633 }
634 19 ++task_index;
635 19 ++tasks;
636 }
637 ✗ return GATE_INVALID_SIZE;
638 }
639
640 44 static gate_size_t gate_socketgroup_load_tasks(gate_socket_t const* sockets, gate_uint8_t* flags, gate_size_t socketcount,
641 gate_socketgroup_task_t** tasks, gate_size_t taskcount,
642 gate_socketgroup_task_t** localtasks, gate_size_t max_localtasks)
643 {
644 44 gate_size_t localtasks_used = 0;
645 gate_size_t taskindex;
646 gate_size_t sockindex;
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (taskcount > max_localtasks)
648 {
649 ✗ taskcount = max_localtasks;
650 }
651
652
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 44 times.
120 for (sockindex = 0; sockindex != socketcount; ++sockindex)
653 {
654
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 36 times.
76 if (flags[sockindex] == 0)
655 {
656 /* skip socket with no activity */
657 40 continue;
658 }
659
660 36 taskindex = gate_socketgroup_find_task(tasks, taskcount, sockets[sockindex], flags[sockindex]);
661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (taskindex == GATE_INVALID_SIZE)
662 {
663 /* skip sockets with no associated task */
664 ✗ continue;
665 }
666 /* put task into local-tasks buffer */
667
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (tasks[taskindex])
668 {
669 36 localtasks[localtasks_used] = tasks[taskindex];
670 36 localtasks[localtasks_used]->info = flags[sockindex];
671 36 tasks[taskindex] = NULL; /* remove task pointer from array */
672 36 ++localtasks_used;
673 }
674 }
675
676 44 return localtasks_used;
677 }
678 105 static gate_bool_t gate_socketgroup_remove_completed_task(void const* item, void* param)
679 {
680 105 gate_socketgroup_task_t* const* ptr_task = (gate_socketgroup_task_t* const*)item;
681 (void)param;
682
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 if (ptr_task != NULL)
683 {
684
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 16 times.
105 if (*ptr_task != NULL)
685 {
686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 if ((*ptr_task)->completed)
687 {
688 ✗ gate_socketgroup_task_destroy(*ptr_task);
689 ✗ return true;
690 }
691 else
692 {
693 89 return false;
694 }
695 }
696 16 return true;
697 }
698 ✗ GATE_DEBUG_BREAKPOINT;
699 ✗ return false;
700 }
701
702 5 gate_result_t gate_socketgroup_run(gate_socketgroup_t* group, gate_socketgroup_callback_t callback)
703 {
704 gate_result_t ret;
705 5 gate_int32_t prev_state = gate_atomic_int_xchg_if(&group->running, 0, 1);
706 gate_socket_t sockets[GATE_SOCKETGROUP_LIMIT];
707 gate_uint8_t flags[GATE_SOCKETGROUP_LIMIT];
708 gate_size_t sockets_used;
709 gate_socketgroup_task_t* localtasks[GATE_SOCKETGROUP_LIMIT];
710 gate_size_t localtasks_used;
711 gate_size_t localtask_index;
712
713 gate_socketgroup_task_t** tasks;
714 gate_size_t task_count;
715 gate_socketgroup_task_t* current_task;
716 gate_bool_t error_detected;
717 char buffer[1024 * 6 + 1];
718 gate_size_t buffer_len;
719 gate_size_t buffer_used;
720 gate_socket_t new_sock;
721
722 do
723 {
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (prev_state != 0)
725 {
726 ✗ ret = GATE_RESULT_INVALIDSTATE;
727 ✗ break;
728 }
729
730 5 ret = GATE_RESULT_OK;
731
732
2/2
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 5 times.
52 while (gate_atomic_int_get(&group->running) == 1)
733 {
734 {
735 /* idle event */
736 47 callback(group, GATE_SOCKETGROUP_OPERATION_PREPARE, GATE_SOCKET_INVALID, GATE_RESULT_OK, NULL, NULL, 0);
737 }
738
739 47 sockets_used = 0;
740 { /* mutex section */
741 47 ret = gate_mutex_acquire(&group->mutex);
742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 GATE_BREAK_IF_FAILED(ret);
743
744 47 task_count = gate_arraylist_length(group->tasks);
745
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 3 times.
47 if (task_count != 0)
746 {
747 44 tasks = (gate_socketgroup_task_t**)gate_arraylist_get(group->tasks, 0);
748
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (tasks != NULL)
749 {
750 44 sockets_used = gate_socketgroup_load_sockets(tasks, task_count, sockets, flags, GATE_SOCKETGROUP_LIMIT);
751 }
752 }
753 47 gate_mutex_release(&group->mutex);
754 }
755
756 47 ret = gate_socketselector_select(&group->selector, sockets, sockets_used, flags, group->interval_ms);
757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 GATE_BREAK_IF_FAILED(ret);
758
759 47 localtasks_used = 0;
760 { /* mutex section */
761 47 ret = gate_mutex_acquire(&group->mutex);
762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 GATE_BREAK_IF_FAILED(ret);
763
764 47 task_count = gate_arraylist_length(group->tasks);
765
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 3 times.
47 if (task_count != 0)
766 {
767 44 tasks = (gate_socketgroup_task_t**)gate_arraylist_get(group->tasks, 0);
768
769 44 localtasks_used = gate_socketgroup_load_tasks(sockets, flags, sockets_used, tasks, task_count, localtasks, GATE_SOCKETGROUP_LIMIT);
770 }
771
772 47 gate_mutex_release(&group->mutex);
773 }
774
775
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 47 times.
83 for (localtask_index = 0; localtask_index != localtasks_used; ++localtask_index)
776 {
777 36 current_task = localtasks[localtask_index];
778 36 error_detected = GATE_FLAG_ENABLED(current_task->info, GATE_SOCKET_SELECT_FLAG_ERROR);
779
780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (error_detected)
781 {
782 ✗ current_task->completed = true;
783 ✗ callback(group, current_task->command, current_task->sock, GATE_RESULT_CRITICALERROR, current_task->param, NULL, 0);
784 }
785 else
786 {
787
5/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
36 switch (current_task->command)
788 {
789 4 case GATE_SOCKETGROUP_OPERATION_CONNECT:
790 {
791 4 gate_bool_t error_flag = false;
792 4 gate_socket_has_error(current_task->sock, &error_flag);
793 4 current_task->completed = true;
794
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (error_flag)
795 {
796 1 callback(group, GATE_SOCKETGROUP_OPERATION_CONNECT, current_task->sock,
797 GATE_RESULT_NOTAVAILABLE, current_task->param, NULL, 0);
798 }
799 else
800 {
801 3 callback(group, GATE_SOCKETGROUP_OPERATION_CONNECT, current_task->sock,
802 GATE_RESULT_OK, current_task->param, NULL, 0);
803 }
804 4 break;
805 }
806 7 case GATE_SOCKETGROUP_OPERATION_ACCEPT:
807 {
808 7 current_task->completed = true;
809 7 ret = gate_socket_accept(current_task->sock, &new_sock);
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (GATE_FAILED(ret))
811 {
812 ✗ callback(group, GATE_SOCKETGROUP_OPERATION_ACCEPT, current_task->sock, ret, current_task->param,
813 NULL, 0);
814 }
815 else
816 {
817 7 callback(group, GATE_SOCKETGROUP_OPERATION_ACCEPT, new_sock, GATE_RESULT_OK, current_task->param,
818 7 (char const*)&current_task->sock, sizeof(current_task->sock));
819 }
820 7 break;
821 }
822 10 case GATE_SOCKETGROUP_OPERATION_READ:
823 {
824 10 current_task->completed = true;
825 10 buffer_len = sizeof(buffer) - 1;
826
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (buffer_len > current_task->length)
827 {
828 10 buffer_len = current_task->length;
829 }
830 10 ret = gate_socket_receive(current_task->sock, buffer, buffer_len, &buffer_used);
831
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (GATE_SUCCEEDED(ret))
832 {
833 10 buffer[buffer_used] = 0;
834 }
835
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 callback(group, GATE_SOCKETGROUP_OPERATION_READ, current_task->sock, ret, current_task->param,
836 GATE_FAILED(ret) ? NULL : buffer, GATE_FAILED(ret) ? 0 : buffer_used);
837 10 break;
838 }
839 12 case GATE_SOCKETGROUP_OPERATION_WRITE:
840 {
841
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (current_task->offset < current_task->length)
842 {
843 12 ret = gate_socket_send(current_task->sock, &current_task->data[current_task->offset],
844 12 current_task->length - current_task->offset, &buffer_used);
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (GATE_FAILED(ret))
846 {
847 ✗ current_task->completed = true;
848 ✗ callback(group, GATE_SOCKETGROUP_OPERATION_WRITE, current_task->sock, ret, current_task->param,
849 ✗ current_task->data, current_task->length);
850 ✗ break;
851 }
852 12 current_task->offset += buffer_used;
853 }
854
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (current_task->offset >= current_task->length)
855 {
856 12 current_task->completed = true;
857 24 callback(group, GATE_SOCKETGROUP_OPERATION_WRITE, current_task->sock, GATE_RESULT_OK, current_task->param,
858 12 current_task->data, current_task->length);
859 }
860
861 12 break;
862 }
863 3 case GATE_SOCKETGROUP_OPERATION_SHUTDOWN_WRITE:
864 {
865 3 ret = gate_socket_shutdown(current_task->sock, false, true);
866 3 current_task->completed = true;
867 3 callback(group, GATE_SOCKETGROUP_OPERATION_SHUTDOWN_WRITE, current_task->sock, ret, current_task->param,
868 NULL, 0);
869 3 break;
870 }
871 }
872 36 }
873
874 } /* for(all localtask */
875
876 { /* mutex section */
877 47 ret = gate_mutex_acquire(&group->mutex);
878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 GATE_BREAK_IF_FAILED(ret);
879
880
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 47 times.
83 for (localtask_index = 0; localtask_index != localtasks_used; ++localtask_index)
881 {
882 36 current_task = localtasks[localtask_index];
883
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (current_task->completed)
884 {
885 36 gate_socketgroup_task_destroy(current_task);
886 }
887 else
888 {
889 ✗ if (!gate_socketgroup_integrate_task(group, current_task))
890 {
891 ✗ GATE_DEBUG_BREAKPOINT;
892 }
893 }
894 }
895
896 47 ret = gate_arraylist_remove_if(group->tasks, &gate_socketgroup_remove_completed_task, NULL);
897
898 47 gate_mutex_release(&group->mutex);
899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 GATE_BREAK_IF_FAILED(ret);
900 }
901
902 } /* while running */
903
904 5 gate_atomic_int_set(&group->running, 0);
905
906 } while (0);
907
908 5 return ret;
909 }
910 11 gate_result_t gate_socketgroup_quit(gate_socketgroup_t* group)
911 {
912 11 gate_atomic_int_set(&group->running, 0);
913 11 return GATE_RESULT_OK;
914 }
915
916
917
918
919
920
921
922
923
924
925
926 /*
927 typedef struct gate_socket_request_class
928 {
929 gate_dataqueue_status_t callback;
930 gate_size_t length;
931 gate_size_t used;
932 char buffer[1];
933 } gate_socket_request_t;
934
935
936 static gate_socket_request_t* gate_socket_request_create(gate_dataqueue_status_t callback, gate_size_t length, char const* data)
937 {
938 gate_socket_request_t* ret = (gate_socket_request_t*)gate_mem_alloc(sizeof(gate_socket_request_t) + length);
939 if(ret != NULL)
940 {
941 ret->callback = callback;
942 ret->used = 0;
943 ret->length = length;
944 if(data != NULL)
945 {
946 gate_mem_copy(&ret->buffer[0], data, length);
947 ret->buffer[length] = 0;
948 }
949 else
950 {
951 ret->buffer[0] = 0;
952 }
953 }
954 return ret;
955 }
956 static void gate_socket_request_release(gate_socket_request_t* request)
957 {
958 gate_mem_dealloc(request);
959 }
960
961 typedef struct gate_socket_channel_class
962 {
963 gate_channel_id_t id;
964 gate_socket_t sock;
965 gate_arraylist_t read_requests;
966 gate_arraylist_t write_requests;
967
968 } gate_socket_channel_t;
969
970 static gate_socket_channel_t* gate_socket_channel_create()
971 {
972 gate_socket_channel_t* channel = gate_mem_alloc(sizeof(gate_socket_channel_t));
973 gate_mem_clear(channel, sizeof(gate_socket_channel_t));
974 channel->sock = GATE_SOCKET_INVALID;
975 return channel;
976 }
977 static void gate_socket_channel_release(gate_socket_channel_t* channel)
978 {
979 if(channel->sock != GATE_SOCKET_INVALID)
980 {
981 gate_socket_close(channel->sock);
982 }
983 gate_mem_dealloc(channel);
984 }
985 */
986
987 #define GATE_SOCKETQUEUE_STATE_OFFLINE 0
988 #define GATE_SOCKETQUEUE_STATE_STARTING 1
989 #define GATE_SOCKETQUEUE_STATE_ONLINE 2
990 #define GATE_SOCKETQUEUE_STATE_STOPPING 3
991
992 typedef struct gate_socketqueue_impl_class
993 {
994 GATE_INTERFACE_VTBL(gate_socketqueue) const* vtbl;
995
996 gate_atomic_int_t ref_counter;
997 gate_atomic_int_t state;
998 gate_atomic_int_t max_channel_id;
999 gate_thread_t thread;
1000 gate_mutex_t lock;
1001 gate_map_t channel_2_sock;
1002 gate_map_t sock_2_channel;
1003 gate_socketgroup_t sockets;
1004 gate_dataqueue_status_t next_callback;
1005 void* next_callback_data;
1006 gate_dataqueue_status_t callback;
1007 void* callback_data;
1008
1009 } gate_socketqueue_impl_t;
1010
1011 36 static gate_bool_t gate_socketqueue_impl_new_state(gate_socketqueue_impl_t* impl, gate_int32_t from_state, gate_int32_t to_state)
1012 {
1013 36 gate_int32_t old_state = gate_atomic_int_xchg_if(&impl->state, from_state, to_state);
1014 36 return old_state == from_state;
1015 }
1016 4 static gate_int32_t gate_socketqueue_impl_set_state(gate_socketqueue_impl_t* impl, gate_int32_t to_state)
1017 {
1018 4 gate_int32_t old_state = gate_atomic_int_set(&impl->state, to_state);
1019 4 return old_state;
1020 }
1021
1022 23 static gate_result_t gate_socketqueue_impl_resolve_socket(gate_socketqueue_impl_t* impl, gate_channel_id_t id, gate_socket_t* ptr_sock)
1023 {
1024 gate_result_t ret;
1025 gate_map_iterator_t iter;
1026 do
1027 {
1028 23 iter = gate_map_get(&impl->channel_2_sock, &id);
1029
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 if (gate_map_iterator_valid(iter))
1030 {
1031 23 *ptr_sock = GATE_MAP_ITER_VALUE(gate_socket_t, iter);
1032 23 ret = GATE_RESULT_OK;
1033 }
1034 else
1035 {
1036 ✗ ret = GATE_RESULT_NOMATCH;
1037 }
1038 } while (0);
1039 23 return ret;
1040 }
1041 32 static gate_result_t gate_socketqueue_impl_resolve_channel(gate_socketqueue_impl_t* impl, gate_socket_t sock, gate_channel_id_t* ptr_id)
1042 {
1043 gate_result_t ret;
1044 gate_map_iterator_t iter;
1045 do
1046 {
1047 32 iter = gate_map_get(&impl->sock_2_channel, &sock);
1048
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (gate_map_iterator_valid(iter))
1049 {
1050 32 *ptr_id = GATE_MAP_ITER_VALUE(gate_channel_id_t, iter);
1051 32 ret = GATE_RESULT_OK;
1052 }
1053 else
1054 {
1055 ✗ ret = GATE_RESULT_NOMATCH;
1056 }
1057 } while (0);
1058 32 return ret;
1059 }
1060 12 static gate_result_t gate_socketqueue_impl_register(gate_socketqueue_impl_t* impl, gate_socket_t sock, gate_channel_id_t channel_id)
1061 {
1062 gate_result_t ret;
1063 do
1064 {
1065
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!gate_map_iterator_valid(gate_map_add(&impl->sock_2_channel, &sock, &channel_id)))
1066 {
1067 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1068 ✗ break;
1069 }
1070
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!gate_map_iterator_valid(gate_map_add(&impl->channel_2_sock, &channel_id, &sock)))
1071 {
1072 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1073 ✗ gate_map_remove(&impl->sock_2_channel, &sock);
1074 ✗ break;
1075 }
1076 12 ret = GATE_RESULT_OK;
1077 } while (0);
1078 12 return ret;
1079 }
1080
1081 76 static void gate_socketqueue_group_callback(gate_socketgroup_t* group, gate_uint32_t operation, gate_socket_t sock,
1082 gate_result_t result, void* user_param, char const* data, gate_size_t data_len)
1083 {
1084 gate_result_t res;
1085 76 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)group->user_tag;
1086 76 gate_channel_id_t channel_id = GATE_QUEUE_INVALID_ID;
1087 76 gate_socket_t parent_socket = GATE_SOCKET_INVALID;
1088 gate_channel_id_t parent_channel_id;
1089
1090 {
1091
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
76 if (GATE_FAILED(res = gate_mutex_acquire(&impl->lock)))
1092 {
1093 ✗ gate_socket_close(sock);
1094 ✗ return;
1095 }
1096
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 70 times.
76 if (operation == GATE_SOCKETGROUP_OPERATION_ACCEPT)
1097 {
1098 6 channel_id = gate_atomic_int_inc(&impl->max_channel_id);
1099 6 res = gate_socketqueue_impl_register(impl, sock, channel_id);
1100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (GATE_FAILED(res))
1101 {
1102 ✗ gate_socket_close(sock);
1103 ✗ result = res;
1104 }
1105 else
1106 {
1107 6 parent_channel_id = 0;
1108 6 parent_socket = *(gate_socket_t const*)data;
1109 6 gate_socketqueue_impl_resolve_channel(impl, parent_socket, &parent_channel_id);
1110 }
1111 }
1112
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 44 times.
70 else if (operation != GATE_SOCKETGROUP_OPERATION_PREPARE)
1113 {
1114 26 res = gate_socketqueue_impl_resolve_channel(impl, sock, &channel_id);
1115 }
1116 76 gate_mutex_release(&impl->lock);
1117 }
1118
1119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (GATE_FAILED(res))
1120 {
1121 ✗ impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_ERROR, 0, res, NULL, 0, user_param);
1122 }
1123 else
1124 {
1125
6/8
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
76 switch (operation)
1126 {
1127 6 case GATE_SOCKETGROUP_OPERATION_ACCEPT:
1128 {
1129 6 impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_OPENNEW, channel_id, result,
1130 (char const*)&parent_channel_id, sizeof(parent_channel_id), user_param);
1131 6 gate_socketgroup_accept(&impl->sockets, parent_socket, user_param);
1132 6 break;
1133 /* accepts are automatically repeated until server socket is closed */
1134 }
1135 3 case GATE_SOCKETGROUP_OPERATION_CONNECT:
1136 {
1137 3 impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_OPEN, channel_id, result, NULL, 0, user_param);
1138 3 break;
1139 }
1140 10 case GATE_SOCKETGROUP_OPERATION_READ:
1141 {
1142
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 if (data_len == 0)
1143 {
1144 3 impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_CLOSE, channel_id, result, NULL, 0, user_param);
1145 }
1146 else
1147 {
1148 7 impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_READ, channel_id, result, data, data_len, user_param);
1149 }
1150 10 break;
1151 }
1152 11 case GATE_SOCKETGROUP_OPERATION_WRITE:
1153 {
1154 11 impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_WRITE, channel_id, result, data, data_len, user_param);
1155 11 break;
1156 }
1157 2 case GATE_SOCKETGROUP_OPERATION_SHUTDOWN_WRITE:
1158 {
1159 2 impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_WRITE, channel_id, result, NULL, 0, user_param);
1160 2 break;
1161 }
1162 ✗ case GATE_SOCKETGROUP_OPERATION_ERROR:
1163 {
1164 ✗ impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_ERROR, channel_id, result, data, data_len, user_param);
1165 ✗ break;
1166 }
1167 44 case GATE_SOCKETGROUP_OPERATION_PREPARE:
1168 {
1169 44 impl->callback(impl->callback_data, GATE_DATAQUEUE_RESULT_HEARTBEAT, GATE_QUEUE_INVALID_ID, result, NULL, 0, user_param);
1170 44 break;
1171 }
1172 }
1173 76 }
1174 }
1175
1176 4 static gate_result_t gate_socketqueue_impl_worker(void* data)
1177 {
1178 4 gate_result_t ret = GATE_RESULT_OK;
1179 4 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)data;
1180
1181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!gate_socketqueue_impl_new_state(impl, GATE_SOCKETQUEUE_STATE_STARTING, GATE_SOCKETQUEUE_STATE_ONLINE))
1182 {
1183 ✗ return GATE_RESULT_INVALIDSTATE;
1184 }
1185
1186 do
1187 {
1188 4 ret = gate_socketgroup_run(&impl->sockets, &gate_socketqueue_group_callback);
1189 if (GATE_FAILED(ret))
1190 {
1191 /* TODO */
1192 }
1193
1194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 } while (gate_socketqueue_impl_new_state(impl, GATE_SOCKETQUEUE_STATE_ONLINE, GATE_SOCKETQUEUE_STATE_ONLINE));
1195 4 return ret;
1196 }
1197
1198
1199 7 static int gate_socketqueue_impl_retain(void* obj)
1200 {
1201 7 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1202 7 return gate_atomic_int_inc(&impl->ref_counter);
1203 }
1204 1 static char const* gate_socketqueue_impl_get_interface_name(void* obj)
1205 {
1206 (void)obj;
1207 1 return GATE_INTERFACE_NAME_SOCKETQUEUE;
1208 }
1209
1210
1211 4 static gate_result_t gate_socketqueue_impl_start(void* obj)
1212 {
1213 4 gate_result_t ret = GATE_RESULT_FAILED;
1214 4 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1215
1216 do
1217 {
1218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!gate_socketqueue_impl_new_state(impl, GATE_SOCKETQUEUE_STATE_OFFLINE, GATE_SOCKETQUEUE_STATE_STARTING))
1219 {
1220 ✗ ret = GATE_RESULT_INVALIDSTATE;
1221 ✗ break;
1222 }
1223
1224 4 impl->callback = impl->next_callback;
1225 4 impl->callback_data = impl->next_callback_data;
1226
1227 4 ret = gate_thread_start_code(&gate_socketqueue_impl_worker, obj, &impl->thread, NULL);
1228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(ret))
1229 {
1230 ✗ gate_socketqueue_impl_new_state(impl, GATE_SOCKETQUEUE_STATE_STARTING, GATE_SOCKETQUEUE_STATE_OFFLINE);
1231 }
1232 } while (0);
1233
1234 4 return ret;
1235 }
1236 12 static gate_result_t gate_socketqueue_impl_stop(void* obj)
1237 {
1238 12 gate_result_t ret = GATE_RESULT_FAILED;
1239 12 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1240 gate_result_t thread_result;
1241 12 gate_bool_t is_current_thread = false;
1242 12 gate_bool_t join_thread = true;
1243
1244 do
1245 {
1246
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 if (!gate_socketqueue_impl_new_state(impl, GATE_SOCKETQUEUE_STATE_STARTING, GATE_SOCKETQUEUE_STATE_STOPPING))
1247 {
1248
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
12 if (!gate_socketqueue_impl_new_state(impl, GATE_SOCKETQUEUE_STATE_ONLINE, GATE_SOCKETQUEUE_STATE_STOPPING))
1249 {
1250 8 ret = GATE_RESULT_INVALIDSTATE;
1251 8 break;
1252 }
1253 }
1254
1255 4 ret = gate_socketgroup_quit(&impl->sockets);
1256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(GATE_SUCCEEDED(ret));
1257
1258 4 ret = gate_thread_is_current(&impl->thread, &is_current_thread);
1259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(GATE_SUCCEEDED(ret));
1260
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
1261 {
1262 4 join_thread = !is_current_thread;
1263 }
1264
1265
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (join_thread)
1266 {
1267 4 ret = gate_thread_join(&impl->thread, &thread_result);
1268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(GATE_SUCCEEDED(ret));
1269 }
1270 else
1271 {
1272 ✗ ret = gate_thread_detach(&impl->thread);
1273 ✗ GATE_DEBUG_ASSERT(GATE_SUCCEEDED(ret));
1274 }
1275
1276 4 gate_socketqueue_impl_set_state(impl, GATE_SOCKETQUEUE_STATE_OFFLINE);
1277 } while (0);
1278
1279 12 return ret;
1280 }
1281
1282
1283 1 static gate_enumint_t gate_socketqueue_impl_get_status(void* obj)
1284 {
1285 1 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1286 1 return (gate_enumint_t)gate_atomic_int_get(&impl->state);
1287 }
1288
1289 4 gate_result_t gate_socketqueue_impl_set_callback(void* obj, gate_dataqueue_status_t callback_func, void* callback_data)
1290 {
1291 4 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1292 4 impl->next_callback = callback_func;
1293 4 impl->next_callback_data = callback_data;
1294 4 return GATE_RESULT_OK;
1295 }
1296
1297
1298 6 static gate_result_t gate_socketqueue_impl_open(void* obj, gate_string_t const* address, gate_enumint_t flags, void* user_param, gate_channel_id_t* channel_id)
1299 {
1300 6 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1301 6 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1302 gate_socket_endpoint_t endpoint;
1303 6 gate_socket_t new_sock = GATE_SOCKET_INVALID;
1304 6 gate_channel_id_t new_channel = 0;
1305 6 gate_bool_t server_socket = GATE_FLAG_ENABLED(flags, GATE_SOCKETQUEUE_OPEN_SERVER);
1306
1307 do
1308 {
1309 6 ret = gate_socket_parse_endpoint(address, &endpoint);
1310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1311
1312
1/3
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
6 switch (endpoint.family)
1313 {
1314 6 case GATE_SOCKET_FAMILY_INET4:
1315 {
1316 6 ret = gate_socket_create_ex(endpoint.family, GATE_SOCKET_MSGTYPE_STREAM, GATE_SOCKET_PROTOCOL_IP, &new_sock);
1317 6 break;
1318 }
1319 ✗ case GATE_SOCKET_FAMILY_INET6:
1320 {
1321 ✗ ret = gate_socket_create_ex(endpoint.family, GATE_SOCKET_MSGTYPE_STREAM, GATE_SOCKET_PROTOCOL_IP6, &new_sock);
1322 ✗ break;
1323 }
1324 ✗ default:
1325 {
1326 ✗ ret = GATE_RESULT_NOTSUPPORTED;
1327 ✗ break;
1328 }
1329 }
1330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1331
1332
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (server_socket)
1333 {
1334 3 ret = gate_socket_bind(new_sock, &endpoint);
1335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED_TRACE(ret, "gate_socket_bind() failed");
1336 3 ret = gate_socket_listen(new_sock, 0);
1337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED_TRACE(ret, "gate_socket_listen() failed");
1338 3 ret = gate_socketgroup_accept(&impl->sockets, new_sock, user_param);
1339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED_TRACE(ret, "gate_socketgroup_accept() failed");
1340 }
1341 else
1342 {
1343 3 ret = gate_socket_set(new_sock, GATE_SOCKET_OPTION_BLOCKING, 0);
1344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED_TRACE(ret, "gate_socket_set() failed");
1345
1346 3 ret = gate_socketgroup_connect(&impl->sockets, new_sock, &endpoint, user_param);
1347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED_TRACE(ret, "gate_socketgroup_connect() failed");
1348
1349 3 ret = gate_socket_set(new_sock, GATE_SOCKET_OPTION_BLOCKING, 1);
1350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED_TRACE(ret, "gate_socket_set() failed");
1351 }
1352
1353
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 if (GATE_SUCCEEDED(ret = gate_mutex_acquire(&impl->lock)))
1354 {
1355 6 new_channel = gate_atomic_int_inc(&impl->max_channel_id);
1356 6 ret = gate_socketqueue_impl_register(impl, new_sock, new_channel);
1357 6 gate_mutex_release(&impl->lock);
1358 6 *channel_id = new_channel;
1359 }
1360
1361 } while (0);
1362
1363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (GATE_FAILED(ret))
1364 {
1365 ✗ gate_socket_close(new_sock);
1366 }
1367
1368 6 return ret;
1369 }
1370 22 static gate_result_t gate_socketqueue_impl_close(void* obj, gate_channel_id_t channel_id)
1371 {
1372 22 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1373 22 gate_result_t ret = GATE_RESULT_FAILED;
1374 gate_map_iterator_t iter;
1375 22 gate_socket_t sock = GATE_SOCKET_INVALID;
1376
1377
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 if (GATE_SUCCEEDED(ret = gate_mutex_acquire(&impl->lock)))
1378 {
1379 do
1380 {
1381
2/2
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 9 times.
22 if (!gate_map_iterator_valid(iter = gate_map_get(&impl->channel_2_sock, &channel_id)))
1382 {
1383 13 ret = GATE_RESULT_NOMATCH;
1384 13 break;
1385 }
1386 9 sock = GATE_MAP_ITER_VALUE(gate_socket_t, iter);
1387 9 gate_map_remove(&impl->sock_2_channel, &sock);
1388 9 gate_map_remove(&impl->channel_2_sock, &channel_id);
1389
1390 9 gate_socketgroup_remove(&impl->sockets, sock);
1391 9 gate_socket_close(sock);
1392
1393 9 ret = GATE_RESULT_OK;
1394 } while (0);
1395 22 gate_mutex_release(&impl->lock);
1396 }
1397 22 return ret;
1398 }
1399 10 static gate_result_t gate_socketqueue_impl_begin_read(void* obj, gate_channel_id_t channel_id, gate_size_t size, void* user_param)
1400 {
1401 10 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1402 gate_result_t ret;
1403 10 gate_socket_t sock = GATE_SOCKET_INVALID;
1404
1405
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 if (GATE_SUCCEEDED(ret = gate_mutex_acquire(&impl->lock)))
1406 {
1407 10 ret = gate_socketqueue_impl_resolve_socket(impl, channel_id, &sock);
1408 10 gate_mutex_release(&impl->lock);
1409 }
1410
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (GATE_SUCCEEDED(ret))
1411 {
1412 10 ret = gate_socketgroup_read(&impl->sockets, sock, size, user_param);
1413 }
1414
1415 10 return ret;
1416 }
1417 13 static gate_result_t gate_socketqueue_impl_begin_write(void* obj, gate_channel_id_t channel_id, char const* buffer, gate_size_t buffer_size, void* user_param)
1418 {
1419 13 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1420 gate_result_t ret;
1421 13 gate_socket_t sock = GATE_SOCKET_INVALID;
1422
1423
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 if (GATE_SUCCEEDED(ret = gate_mutex_acquire(&impl->lock)))
1424 {
1425 13 ret = gate_socketqueue_impl_resolve_socket(impl, channel_id, &sock);
1426 13 gate_mutex_release(&impl->lock);
1427 }
1428
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (GATE_SUCCEEDED(ret))
1429 {
1430
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
13 if ((buffer_size == 0) || (buffer == NULL))
1431 {
1432 /* sending empty buffers is interpreted as socket shutdown */
1433 2 ret = gate_socketgroup_shutdown_write(&impl->sockets, sock, user_param);
1434 }
1435 else
1436 {
1437 11 ret = gate_socketgroup_write(&impl->sockets, sock, buffer, buffer_size, user_param);
1438 }
1439 }
1440 13 return ret;
1441 }
1442
1443 4 static gate_result_t gate_socketqueue_impl_close_all(void* obj)
1444 {
1445 gate_result_t ret;
1446 4 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1447
1448
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (GATE_SUCCEEDED(ret = gate_mutex_acquire(&impl->lock)))
1449 {
1450 gate_map_iterator_t iter;
1451 4 ret = gate_socketgroup_clear(&impl->sockets);
1452 /* close all opened sockets */
1453
2/2
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
7 GATE_MAP_FOREACH(iter, &impl->sock_2_channel)
1454 {
1455 3 gate_socket_t const* ptr_sock = (gate_socket_t const*)gate_map_iterator_key(iter);
1456
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ptr_sock)
1457 {
1458 3 gate_socket_close(*ptr_sock);
1459 }
1460 }
1461 4 gate_map_clear(&impl->channel_2_sock);
1462 4 gate_map_clear(&impl->sock_2_channel);
1463 4 gate_mutex_release(&impl->lock);
1464 }
1465 4 return ret;
1466 }
1467
1468 12 static void gate_socketqueue_impl_release(void* obj)
1469 {
1470 12 gate_socketqueue_impl_t* impl = (gate_socketqueue_impl_t*)obj;
1471
1472
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 7 times.
12 if (gate_atomic_int_dec(&impl->ref_counter) == 0)
1473 {
1474 5 gate_socketqueue_impl_stop(impl);
1475
1476 5 gate_socketgroup_destroy(&impl->sockets);
1477 5 gate_map_destroy(&impl->sock_2_channel);
1478 5 gate_map_destroy(&impl->channel_2_sock);
1479 5 gate_mutex_destroy(&impl->lock);
1480 5 gate_mem_dealloc(impl);
1481 }
1482 12 }
1483
1484 static GATE_INTERFACE_VTBL(gate_socketqueue) gate_socketqueue_vtbl;
1485 5 static void gate_init_socketqueue_vtbl()
1486 {
1487
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!gate_socketqueue_vtbl.get_interface_name)
1488 {
1489 GATE_INTERFACE_VTBL(gate_socketqueue) const local_vtbl =
1490 {
1491 &gate_socketqueue_impl_get_interface_name,
1492 &gate_socketqueue_impl_release,
1493 &gate_socketqueue_impl_retain,
1494
1495 &gate_socketqueue_impl_start,
1496 &gate_socketqueue_impl_stop,
1497 &gate_socketqueue_impl_get_status,
1498
1499 &gate_socketqueue_impl_set_callback,
1500 &gate_socketqueue_impl_open,
1501 &gate_socketqueue_impl_close,
1502 &gate_socketqueue_impl_begin_read,
1503 &gate_socketqueue_impl_begin_write,
1504
1505 &gate_socketqueue_impl_close_all
1506 };
1507 3 gate_socketqueue_vtbl = local_vtbl;
1508 }
1509 5 }
1510
1511 5 gate_result_t gate_socketqueue_create(gate_socketqueue_t** ptr_queue, gate_uint32_t idle_interval_ms)
1512 {
1513 5 gate_result_t ret = GATE_RESULT_FAILED;
1514 gate_socketqueue_impl_t* impl;
1515
1516 do
1517 {
1518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (idle_interval_ms < 1)
1519 {
1520 ✗ idle_interval_ms = 1;
1521 }
1522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 else if (idle_interval_ms > 60000)
1523 {
1524 ✗ idle_interval_ms = 60000;
1525 }
1526
1527 5 impl = gate_mem_alloc(sizeof(gate_socketqueue_impl_t));
1528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (impl == NULL)
1529 {
1530 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1531 ✗ break;
1532 }
1533 5 gate_mem_clear(impl, sizeof(gate_socketqueue_impl_t));
1534 5 gate_init_socketqueue_vtbl();
1535 5 impl->vtbl = &gate_socketqueue_vtbl;
1536 5 gate_atomic_int_init(&impl->ref_counter, 1);
1537 5 gate_atomic_int_init(&impl->state, GATE_SOCKETQUEUE_STATE_OFFLINE);
1538 5 gate_atomic_int_init(&impl->max_channel_id, 0);
1539
1540 5 ret = gate_mutex_create(&impl->lock);
1541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_BREAK_IF_FAILED(ret);
1542
1543
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (NULL == gate_map_create(&impl->sock_2_channel, &gate_compare_socket, sizeof(gate_socket_t), NULL, NULL, sizeof(gate_channel_id_t), NULL, NULL))
1544 {
1545 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1546 ✗ break;
1547 }
1548
1549
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (NULL == gate_map_create(&impl->channel_2_sock, &gate_compare_channel_id, sizeof(gate_channel_id_t), NULL, NULL, sizeof(gate_socket_t), NULL, NULL))
1550 {
1551 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1552 ✗ break;
1553 }
1554
1555 5 ret = gate_socketgroup_create(&impl->sockets, impl);
1556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_BREAK_IF_FAILED(ret);
1557 5 impl->sockets.interval_ms = idle_interval_ms;
1558
1559 5 ret = GATE_RESULT_OK;
1560 5 *ptr_queue = (gate_socketqueue_t*)impl;
1561 5 impl = NULL;
1562 } while (0);
1563
1564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (GATE_FAILED(ret))
1565 {
1566 ✗ if (impl)
1567 {
1568 ✗ gate_map_destroy(&impl->sock_2_channel);
1569 ✗ gate_map_destroy(&impl->channel_2_sock);
1570 ✗ gate_mutex_destroy(&impl->lock);
1571 ✗ gate_mem_dealloc(impl);
1572 }
1573 }
1574
1575 5 return ret;
1576 }
1577
1578
1579
1580 /**********************************
1581 * SOCKET STREAM implementation *
1582 **********************************/
1583
1584 typedef struct gate_socketstream_class
1585 {
1586 GATE_INTERFACE_VTBL(gate_controlstream) const* vtbl;
1587
1588 gate_atomic_int_t ref_counter;
1589 gate_socket_t sock;
1590 gate_bool_t connected;
1591 gate_socket_endpoint_t ep;
1592 gate_uint64_t bytes_received;
1593 gate_uint64_t bytes_sent;
1594 } gate_socketstream_t;
1595
1596 5 static gate_result_t socketstream_create_socket(gate_socket_endpoint_t const* ptr_ep, gate_socket_t* ptr_sock)
1597 {
1598 gate_int16_t socktype;
1599
1/3
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
5 switch (ptr_ep->family)
1600 {
1601 5 case GATE_SOCKET_FAMILY_INET4: socktype = GATE_SOCKET_TYPE_TCP4; break;
1602 ✗ case GATE_SOCKET_FAMILY_INET6: socktype = GATE_SOCKET_TYPE_TCP6; break;
1603 ✗ default: socktype = 0;
1604 }
1605
1606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (socktype == 0)
1607 {
1608 ✗ return GATE_RESULT_INVALIDARG;
1609 }
1610
1611 5 return gate_socket_create(socktype, ptr_sock);
1612 }
1613
1614 4 static gate_result_t socketstream_connect_socket(gate_socketstream_t* ptr_sockstream)
1615 {
1616 4 gate_result_t ret = gate_socket_connect(ptr_sockstream->sock, &ptr_sockstream->ep);
1617
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
1618 {
1619 4 ptr_sockstream->connected = true;
1620 }
1621 4 return ret;
1622 }
1623
1624
1625 1 static char const* socketstream_get_interface_name(void* obj)
1626 {
1627 GATE_UNUSED_ARG(obj);
1628 1 return GATE_INTERFACE_NAME_CONTROLSTREAM;
1629 }
1630 9 static void socketstream_release(void* obj)
1631 {
1632 9 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1633
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 5 times.
9 if (0 == gate_atomic_int_dec(&self->ref_counter))
1634 {
1635 4 gate_socket_close(self->sock);
1636 4 gate_mem_dealloc(self);
1637 }
1638 9 }
1639 5 static int socketstream_retain(void* obj)
1640 {
1641 5 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1642 5 return gate_atomic_int_inc(&self->ref_counter);
1643 }
1644
1645 140 static gate_result_t socketstream_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1646 {
1647 gate_result_t ret;
1648 140 gate_size_t received = 0;
1649 140 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1650
1651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!self->connected)
1652 {
1653 ✗ ret = socketstream_connect_socket(self);
1654 ✗ GATE_RETURN_IF_FAILED(ret);
1655 }
1656
1657 140 ret = gate_socket_receive(self->sock, buffer, bufferlength, &received);
1658
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (GATE_SUCCEEDED(ret))
1659 {
1660
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (returned)
1661 {
1662 140 *returned = received;
1663 }
1664 140 self->bytes_received += received;
1665 }
1666 140 return ret;
1667 }
1668 ✗ static gate_result_t socketstream_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1669 {
1670 ✗ gate_socketstream_t* self = (gate_socketstream_t*)obj;
1671 gate_result_t ret;
1672 ✗ gate_uint8_t sel_states = GATE_SOCKET_SELECT_FLAG_RECEIVE;
1673
1674 do
1675 {
1676 ✗ if (!self->connected)
1677 {
1678 ✗ ret = socketstream_connect_socket(self);
1679 ✗ GATE_BREAK_IF_FAILED(ret);
1680 }
1681
1682 ✗ ret = gate_socket_select(&self->sock, 1, &sel_states, 0);
1683 ✗ GATE_BREAK_IF_FAILED(ret);
1684
1685 ✗ if (GATE_FLAG_ENABLED(sel_states, GATE_SOCKET_SELECT_FLAG_RECEIVE))
1686 {
1687 /* there are bytes in receive buffer: */
1688 ✗ ret = gate_socket_receive_from(self->sock, NULL, buffer, bufferlength, returned, GATE_SOCKET_FLAG_PEEK);
1689 }
1690 else
1691 {
1692 /* no bytes in receive buffer */
1693 ✗ if (returned)
1694 {
1695 ✗ *returned = 0;
1696 }
1697 ✗ ret = GATE_RESULT_OK;
1698 }
1699 } while (0);
1700
1701 ✗ return ret;
1702 }
1703 4 static gate_result_t socketstream_write(void* obj, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1704 {
1705 gate_result_t ret;
1706 4 gate_size_t sent = 0;
1707 4 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1708
1709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!self->connected)
1710 {
1711 ✗ ret = socketstream_connect_socket(self);
1712 ✗ GATE_RETURN_IF_FAILED(ret);
1713 }
1714
1715 4 ret = gate_socket_send(self->sock, buffer, bufferlength, &sent);
1716
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
1717 {
1718
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (written)
1719 {
1720 4 *written = sent;
1721 }
1722 4 self->bytes_sent += sent;
1723 }
1724 4 return ret;
1725 }
1726 1 static gate_result_t socketstream_flush(void* obj)
1727 {
1728 1 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!self->connected)
1730 {
1731 ✗ return socketstream_connect_socket(self);
1732 }
1733 1 return GATE_RESULT_OK;
1734 }
1735
1736 1 static gate_result_t socketstream_get_resource(void* obj, gate_enumint_t resource_type, gate_uintptr_t* resource)
1737 {
1738 1 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1739
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 switch (resource_type)
1740 {
1741 1 case GATE_STREAM_RESOURCE_DEFAULT:
1742 case GATE_STREAM_RESOURCE_INPUT:
1743 case GATE_STREAM_RESOURCE_OUTPUT:
1744
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (resource)
1745 {
1746 1 *resource = (gate_uintptr_t)self->sock;
1747 }
1748 1 return GATE_RESULT_OK;
1749 ✗ default:
1750 ✗ return GATE_RESULT_NOTSUPPORTED;
1751 }
1752 }
1753
1754 1 static gate_result_t socketstream_can_read(void* obj, gate_bool_t* return_value)
1755 {
1756 1 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1757 1 gate_uint8_t status = GATE_SOCKET_SELECT_FLAG_RECEIVE;
1758 gate_result_t ret;
1759
1760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!self->connected)
1761 {
1762 ✗ ret = socketstream_connect_socket(self);
1763 ✗ GATE_RETURN_IF_FAILED(ret);
1764 }
1765
1766 1 ret = gate_socket_select(&self->sock, 1, &status, 10);
1767
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
1768 {
1769 1 *return_value = GATE_FLAG_ENABLED(status, GATE_SOCKET_SELECT_FLAG_RECEIVE);
1770 }
1771 1 return ret;
1772 }
1773
1774 1 static gate_result_t socketstream_can_write(void* obj, gate_bool_t* return_value)
1775 {
1776 1 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1777 1 gate_uint8_t status = GATE_SOCKET_SELECT_FLAG_SEND;
1778 gate_result_t ret;
1779
1780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!self->connected)
1781 {
1782 ✗ ret = socketstream_connect_socket(self);
1783 ✗ GATE_RETURN_IF_FAILED(ret);
1784 }
1785
1786 1 ret = gate_socket_select(&self->sock, 1, &status, 10);
1787
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
1788 {
1789 1 *return_value = GATE_FLAG_ENABLED(status, GATE_SOCKET_SELECT_FLAG_SEND);
1790 }
1791 1 return ret;
1792 }
1793
1794 ✗ static gate_result_t socketstream_get_size(void* obj, gate_int64_t* return_value)
1795 {
1796 ✗ gate_socketstream_t* self = (gate_socketstream_t*)obj;
1797 ✗ if (return_value)
1798 {
1799 ✗ *return_value = (gate_int64_t)self->bytes_received;
1800 }
1801 ✗ return GATE_RESULT_NOTAVAILABLE;
1802 }
1803
1804 ✗ static gate_result_t socketstream_get_available(void* obj, gate_int64_t* return_value)
1805 {
1806 ✗ gate_socketstream_t* self = (gate_socketstream_t*)obj;
1807 ✗ gate_uint8_t status = GATE_SOCKET_SELECT_FLAG_RECEIVE;
1808 ✗ gate_result_t ret = gate_socket_select(&self->sock, 1, &status, 0);
1809 ✗ if (return_value)
1810 {
1811 ✗ *return_value = GATE_FLAG_ENABLED(status, GATE_SOCKET_SELECT_FLAG_RECEIVE) ? 1 : 0;
1812 }
1813 ✗ return ret;
1814 }
1815
1816 ✗ static gate_result_t socketstream_seek(void* obj, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position)
1817 {
1818 ✗ gate_socketstream_t* self = (gate_socketstream_t*)obj;
1819 ✗ if (((origin == GATE_STREAM_SEEK_CURRENT) || (origin == GATE_STREAM_SEEK_END)) && (position == 0))
1820 {
1821 /* just return current 'write' position */
1822 ✗ if (final_position)
1823 {
1824 ✗ *final_position = (gate_int64_t)self->bytes_sent;
1825 }
1826 ✗ return GATE_RESULT_OK;
1827 }
1828 ✗ return GATE_RESULT_NOTSUPPORTED;
1829 }
1830 ✗ static gate_result_t socketstream_reset(void* obj)
1831 {
1832 ✗ gate_socketstream_t* self = (gate_socketstream_t*)obj;
1833
1834 ✗ if (self->connected)
1835 {
1836 ✗ gate_socket_close(self->sock);
1837 ✗ self->connected = false;
1838 }
1839
1840 ✗ return socketstream_connect_socket(self);
1841 }
1842 3 static gate_result_t socketstream_close(void* obj, gate_enumint_t close_type)
1843 {
1844 3 gate_socketstream_t* self = (gate_socketstream_t*)obj;
1845
1846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!self->connected)
1847 {
1848 ✗ return GATE_RESULT_OK;
1849 }
1850
1851
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 switch (close_type)
1852 {
1853 ✗ case GATE_STREAM_CLOSE_INPUT:
1854 ✗ return gate_socket_shutdown(self->sock, true, false);
1855 3 case GATE_STREAM_CLOSE_OUTPUT:
1856 3 return gate_socket_shutdown(self->sock, false, true);
1857 }
1858 ✗ return GATE_RESULT_NOTSUPPORTED;
1859 }
1860
1861 static GATE_INTERFACE_VTBL(gate_controlstream) sockstream_vtbl;
1862
1863 4 static void gate_init_socketstream_vtbl()
1864 {
1865
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!sockstream_vtbl.get_interface_name)
1866 {
1867 2 GATE_INTERFACE_VTBL(gate_controlstream) local_vtbl =
1868 {
1869 &socketstream_get_interface_name,
1870 &socketstream_release,
1871 &socketstream_retain,
1872
1873 &socketstream_read,
1874 &socketstream_peek,
1875 &socketstream_write,
1876 &socketstream_flush,
1877
1878 &socketstream_get_resource,
1879
1880 &socketstream_can_read,
1881 &socketstream_can_write,
1882 &socketstream_get_size,
1883 &socketstream_get_available,
1884 &socketstream_seek,
1885 &socketstream_reset,
1886 &socketstream_close
1887 };
1888 2 sockstream_vtbl = local_vtbl;
1889 }
1890 4 }
1891
1892
1893 4 static gate_result_t gate_socketstream_create_internal(
1894 gate_socket_t sock, gate_socket_endpoint_t const* ep, gate_bool_t delay_connect, gate_controlstream_t** ptr_stream)
1895 {
1896 4 gate_result_t ret = GATE_RESULT_FAILED;
1897 4 gate_socketstream_t* ptr_sockstream = NULL;
1898 do
1899 {
1900 4 ptr_sockstream = (gate_socketstream_t*)gate_mem_alloc(sizeof(gate_socketstream_t));
1901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (NULL == ptr_sockstream)
1902 {
1903 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1904 ✗ break;
1905 }
1906 4 gate_atomic_int_init(&ptr_sockstream->ref_counter, 1);
1907 4 gate_init_socketstream_vtbl();
1908 4 ptr_sockstream->vtbl = &sockstream_vtbl;
1909 4 ptr_sockstream->bytes_sent = 0;
1910 4 ptr_sockstream->bytes_received = 0;
1911 4 ptr_sockstream->sock = sock;
1912
1913
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (sock == GATE_SOCKET_INVALID)
1914 {
1915 4 ptr_sockstream->sock = GATE_SOCKET_INVALID;
1916 4 ptr_sockstream->connected = false;
1917 4 gate_mem_copy(&ptr_sockstream->ep, ep, sizeof(ptr_sockstream->ep));
1918
1919 4 ret = socketstream_create_socket(&ptr_sockstream->ep, &ptr_sockstream->sock);
1920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1921
1922
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!delay_connect)
1923 {
1924 4 ret = socketstream_connect_socket(ptr_sockstream);
1925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1926 }
1927 }
1928 else
1929 {
1930 ✗ ptr_sockstream->connected = true;
1931 ✗ gate_mem_clear(&ptr_sockstream->ep, sizeof(ptr_sockstream->ep));
1932 }
1933
1934
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ptr_stream)
1935 {
1936 4 *ptr_stream = (gate_controlstream_t*)ptr_sockstream;
1937 4 ptr_sockstream = NULL;
1938 }
1939 4 ret = GATE_RESULT_OK;
1940 } while (0);
1941
1942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ptr_sockstream)
1943 {
1944 ✗ gate_object_release(ptr_sockstream);
1945 }
1946
1947 4 return ret;
1948 }
1949
1950 ✗ gate_result_t gate_socketstream_create(gate_socket_t sock, gate_controlstream_t** ptr_stream)
1951 {
1952 ✗ return gate_socketstream_create_internal(sock, NULL, false, ptr_stream);
1953 }
1954
1955 2 gate_result_t gate_socketstream_create_endpoint(gate_socket_endpoint_t const* ep, gate_controlstream_t** ptr_stream, gate_bool_t delay_connect)
1956 {
1957 2 return gate_socketstream_create_internal(GATE_SOCKET_INVALID, ep, delay_connect, ptr_stream);
1958 }
1959
1960 2 gate_result_t gate_socketstream_create_address(gate_string_t const* addr, gate_controlstream_t** ptr_stream, gate_bool_t delay_connect)
1961 {
1962 gate_result_t ret;
1963 gate_socket_endpoint_t ep;
1964 do
1965 {
1966 2 ret = gate_socket_parse_endpoint(addr, &ep);
1967
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (GATE_FAILED(ret))
1968 {
1969 1 gate_string_t host = GATE_STRING_INIT_EMPTY;
1970 1 gate_uint16_t port = 0;
1971 1 gate_int16_t family = 0;
1972 1 gate_size_t ep_count = 1;
1973 do
1974 {
1975 1 ret = gate_socket_parse_address(addr, &host, &port, &family);
1976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1977
1978 1 ret = gate_net_resolve_host(&host, family, &ep, &ep_count);
1979
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (ep.family)
1980 {
1981 1 case GATE_SOCKET_FAMILY_INET4: ep.ip4.port = port; break;
1982 ✗ case GATE_SOCKET_FAMILY_INET6: ep.ip6.port = port; break;
1983 }
1984 1 } while (0);
1985 1 gate_string_release(&host);
1986 }
1987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1988
1989 2 ret = gate_socketstream_create_internal(GATE_SOCKET_INVALID, &ep, delay_connect, ptr_stream);
1990 } while (0);
1991 2 return ret;
1992 }
1993
1994
1995
1996 typedef struct gate_socketserverstream_class
1997 {
1998 GATE_INTERFACE_VTBL(gate_controlstream) const* vtbl;
1999
2000 gate_atomic_int_t ref_counter;
2001 gate_socket_t server_sock;
2002 gate_socket_endpoint_t ep;
2003 gate_socket_t connection_sock;
2004 gate_bool_t connected;
2005 gate_uint64_t bytes_received;
2006 gate_uint64_t bytes_sent;
2007 } gate_socketserverstream_t;
2008
2009
2010 ✗ static char const* socketserverstream_get_interface_name(void* obj)
2011 {
2012 GATE_UNUSED_ARG(obj);
2013 ✗ return GATE_INTERFACE_NAME_CONTROLSTREAM;
2014 }
2015 1 static void socketserverstream_release(void* obj)
2016 {
2017 1 gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2018
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (0 == gate_atomic_int_dec(&self->ref_counter))
2019 {
2020
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (self->connection_sock != GATE_SOCKET_INVALID)
2021 {
2022 1 gate_socket_close(self->connection_sock);
2023 }
2024
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (self->server_sock != GATE_SOCKET_INVALID)
2025 {
2026 1 gate_socket_close(self->server_sock);
2027 }
2028 1 gate_mem_dealloc(self);
2029 }
2030 1 }
2031 ✗ static int socketserverstream_retain(void* obj)
2032 {
2033 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2034 ✗ return gate_atomic_int_inc(&self->ref_counter);
2035 }
2036
2037 4 static gate_result_t socketserverstream_accept(gate_socketserverstream_t* self)
2038 {
2039 4 gate_result_t ret = GATE_RESULT_OK;
2040
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (!self->connected)
2041 {
2042 1 ret = gate_socket_accept(self->server_sock, &self->connection_sock);
2043
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
2044 {
2045 1 self->connected = true;
2046 }
2047 }
2048 4 return ret;
2049 }
2050
2051 2 static gate_result_t socketserverstream_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2052 {
2053 gate_result_t ret;
2054 2 gate_size_t received = 0;
2055 2 gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2056
2057 2 ret = socketserverstream_accept(self);
2058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_RETURN_IF_FAILED(ret);
2059
2060 2 ret = gate_socket_receive(self->connection_sock, buffer, bufferlength, &received);
2061
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
2062 {
2063
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (returned)
2064 {
2065 2 *returned = received;
2066 }
2067 2 self->bytes_received += received;
2068 }
2069 2 return ret;
2070 }
2071
2072 ✗ static gate_result_t socketserverstream_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2073 {
2074 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2075 gate_result_t ret;
2076
2077 ✗ ret = socketserverstream_accept(self);
2078 ✗ GATE_RETURN_IF_FAILED(ret);
2079
2080 ✗ return gate_socket_receive_from(self->connection_sock, NULL, buffer, bufferlength, returned, GATE_SOCKET_FLAG_PEEK);
2081 }
2082
2083 1 static gate_result_t socketserverstream_write(void* obj, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2084 {
2085 gate_result_t ret;
2086 1 gate_size_t sent = 0;
2087 1 gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2088
2089 1 ret = socketserverstream_accept(self);
2090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_RETURN_IF_FAILED(ret);
2091
2092 1 ret = gate_socket_send(self->connection_sock, buffer, bufferlength, &sent);
2093
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
2094 {
2095
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (written)
2096 {
2097 1 *written = sent;
2098 }
2099 1 self->bytes_sent += sent;
2100 }
2101 1 return ret;
2102 }
2103 1 static gate_result_t socketserverstream_flush(void* obj)
2104 {
2105 1 gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2106
2107 1 return socketserverstream_accept(self);
2108 }
2109
2110 ✗ static gate_result_t socketserverstream_get_resource(void* obj, gate_enumint_t resource_type, gate_uintptr_t* resource)
2111 {
2112 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2113 ✗ switch (resource_type)
2114 {
2115 ✗ case GATE_STREAM_RESOURCE_DEFAULT:
2116 ✗ if (resource)
2117 {
2118 ✗ *resource = (gate_uintptr_t)self->server_sock;
2119 }
2120 ✗ return GATE_RESULT_OK;
2121
2122 ✗ case GATE_STREAM_RESOURCE_INPUT:
2123 case GATE_STREAM_RESOURCE_OUTPUT:
2124 ✗ if (resource)
2125 {
2126 ✗ *resource = (gate_uintptr_t)self->connection_sock;
2127 }
2128 ✗ return GATE_RESULT_OK;
2129 ✗ default:
2130 ✗ return GATE_RESULT_NOTSUPPORTED;
2131 }
2132 }
2133
2134 ✗ static gate_result_t socketserverstream_can_read(void* obj, gate_bool_t* return_value)
2135 {
2136 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2137 ✗ gate_uint8_t status = GATE_SOCKET_SELECT_FLAG_RECEIVE;
2138 gate_result_t ret;
2139 ✗ gate_bool_t can_read = false;
2140
2141 ✗ if (self->connected)
2142 {
2143 ✗ ret = gate_socket_select(&self->connection_sock, 1, &status, 10);
2144 ✗ can_read = GATE_FLAG_ENABLED(status, GATE_SOCKET_SELECT_FLAG_RECEIVE);
2145 }
2146
2147 ✗ if (return_value)
2148 {
2149 ✗ *return_value = can_read;
2150 }
2151
2152 ✗ return ret;
2153 }
2154
2155 ✗ static gate_result_t socketserverstream_can_write(void* obj, gate_bool_t* return_value)
2156 {
2157 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2158 ✗ gate_uint8_t status = GATE_SOCKET_SELECT_FLAG_SEND;
2159 gate_result_t ret;
2160 ✗ gate_bool_t can_read = false;
2161
2162 ✗ if (self->connected)
2163 {
2164 ✗ ret = gate_socket_select(&self->connection_sock, 1, &status, 10);
2165 ✗ can_read = GATE_FLAG_ENABLED(status, GATE_SOCKET_SELECT_FLAG_SEND);
2166 }
2167
2168 ✗ if (return_value)
2169 {
2170 ✗ *return_value = can_read;
2171 }
2172
2173 ✗ return ret;
2174 }
2175
2176 ✗ static gate_result_t socketserverstream_get_size(void* obj, gate_int64_t* return_value)
2177 {
2178 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2179 ✗ if (return_value)
2180 {
2181 ✗ *return_value = (gate_int64_t)self->bytes_received;
2182 }
2183 ✗ return GATE_RESULT_NOTAVAILABLE;
2184 }
2185
2186 ✗ static gate_result_t socketserverstream_get_available(void* obj, gate_int64_t* return_value)
2187 {
2188 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2189 ✗ gate_uint8_t status = GATE_SOCKET_SELECT_FLAG_RECEIVE;
2190 ✗ gate_result_t ret = GATE_RESULT_OK;
2191 ✗ unsigned available = 0;
2192
2193 ✗ if (self->connected)
2194 {
2195 ✗ ret = gate_socket_select(&self->connection_sock, 1, &status, 0);
2196 ✗ available = GATE_FLAG_ENABLED(status, GATE_SOCKET_SELECT_FLAG_RECEIVE) ? 1 : 0;
2197 }
2198
2199 ✗ if (return_value)
2200 {
2201 ✗ *return_value = (gate_int64_t)available;
2202 }
2203 ✗ return ret;
2204 }
2205
2206 ✗ static gate_result_t socketserverstream_seek(void* obj, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position)
2207 {
2208 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2209 ✗ if (((origin == GATE_STREAM_SEEK_CURRENT) || (origin == GATE_STREAM_SEEK_END)) && (position == 0))
2210 {
2211 /* just return current 'write' position */
2212 ✗ if (final_position)
2213 {
2214 ✗ *final_position = (gate_int64_t)self->bytes_sent;
2215 }
2216 ✗ return GATE_RESULT_OK;
2217 }
2218 ✗ return GATE_RESULT_NOTSUPPORTED;
2219 }
2220 ✗ static gate_result_t socketserverstream_reset(void* obj)
2221 {
2222 ✗ gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2223
2224 ✗ if (self->connected)
2225 {
2226 ✗ gate_socket_close(self->connection_sock);
2227 ✗ self->connected = false;
2228 }
2229
2230 ✗ return socketserverstream_accept(self);
2231 }
2232
2233 1 static gate_result_t socketserverstream_close(void* obj, gate_enumint_t close_type)
2234 {
2235 1 gate_socketserverstream_t* self = (gate_socketserverstream_t*)obj;
2236
2237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!self->connected)
2238 {
2239 ✗ return GATE_RESULT_OK;
2240 }
2241
2242
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (close_type)
2243 {
2244 ✗ case GATE_STREAM_CLOSE_INPUT:
2245 ✗ return gate_socket_shutdown(self->connected, true, false);
2246 1 case GATE_STREAM_CLOSE_OUTPUT:
2247 1 return gate_socket_shutdown(self->connection_sock, false, true);
2248 }
2249 ✗ return GATE_RESULT_NOTSUPPORTED;
2250 }
2251
2252 static GATE_INTERFACE_VTBL(gate_controlstream) socketserverstream_vtbl;
2253
2254 1 static void gate_init_socketserverstream_vtbl()
2255 {
2256
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!sockstream_vtbl.get_interface_name)
2257 {
2258 1 GATE_INTERFACE_VTBL(gate_controlstream) local_vtbl =
2259 {
2260 &socketserverstream_get_interface_name,
2261 &socketserverstream_release,
2262 &socketserverstream_retain,
2263
2264 &socketserverstream_read,
2265 &socketserverstream_peek,
2266 &socketserverstream_write,
2267 &socketserverstream_flush,
2268
2269 &socketserverstream_get_resource,
2270
2271 &socketserverstream_can_read,
2272 &socketserverstream_can_write,
2273 &socketserverstream_get_size,
2274 &socketserverstream_get_available,
2275 &socketserverstream_seek,
2276 &socketserverstream_reset,
2277 &socketserverstream_close
2278 };
2279 1 socketserverstream_vtbl = local_vtbl;
2280 }
2281 1 }
2282
2283
2284 1 gate_result_t gate_socketstream_create_server(gate_socket_endpoint_t const* bind_ep, gate_controlstream_t** ptr_stream)
2285 {
2286 1 gate_result_t ret = GATE_RESULT_FAILED;
2287 1 gate_socketserverstream_t* ptr_sockstream = NULL;
2288
2289 do
2290 {
2291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (bind_ep == NULL)
2292 {
2293 ✗ ret = GATE_RESULT_INVALIDARG;
2294 ✗ break;
2295 }
2296 1 ptr_sockstream = (gate_socketserverstream_t*)gate_mem_alloc(sizeof(gate_socketserverstream_t));
2297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == ptr_sockstream)
2298 {
2299 ✗ ret = GATE_RESULT_OUTOFMEMORY;
2300 ✗ break;
2301 }
2302 1 gate_atomic_int_init(&ptr_sockstream->ref_counter, 1);
2303 1 gate_init_socketserverstream_vtbl();
2304 1 ptr_sockstream->vtbl = &socketserverstream_vtbl;
2305 1 ptr_sockstream->bytes_sent = 0;
2306 1 ptr_sockstream->bytes_received = 0;
2307 1 ptr_sockstream->server_sock = GATE_SOCKET_INVALID;
2308 1 ptr_sockstream->connection_sock = GATE_SOCKET_INVALID;
2309 1 ptr_sockstream->connected = false;
2310
2311 1 gate_mem_copy(&ptr_sockstream->ep, bind_ep, sizeof(ptr_sockstream->ep));
2312
2313 1 ret = socketstream_create_socket(&ptr_sockstream->ep, &ptr_sockstream->server_sock);
2314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
2315
2316 1 ret = gate_socket_bind(ptr_sockstream->server_sock, &ptr_sockstream->ep);
2317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
2318
2319 1 ret = gate_socket_listen(ptr_sockstream->server_sock, 1);
2320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
2321
2322
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_stream)
2323 {
2324 1 *ptr_stream = (gate_controlstream_t*)ptr_sockstream;
2325 1 ptr_sockstream = NULL;
2326 }
2327 1 ret = GATE_RESULT_OK;
2328 } while (0);
2329
2330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_sockstream)
2331 {
2332 ✗ gate_object_release(ptr_sockstream);
2333 }
2334
2335 1 return ret;
2336 }
2337
2338