GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/platform/socket_api.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 44 46 95.7%
Functions: 9 10 90.0%
Branches: 0 0 -%

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
29 #include "gate/net/platform/socket_api.h"
30 #include "gate/results.h"
31 #include "gate/memalloc.h"
32
33 #if defined(GATE_SYS_WIN)
34 # define GATE_NET_PLATFORM_SOCKET_API_WINSOCK 1
35 #elif defined(GATE_SYS_DOS)
36 # define GATE_NET_PLATFORM_SOCKET_API_SOCOP 1
37 #elif defined(GATE_SYS_POSIX)
38 # define GATE_NET_PLATFORM_SOCKET_API_LINKED 1
39 #elif defined(GATE_SYS_NDS)
40 # define GATE_NET_PLATFORM_SOCKET_API_LINKED 1
41 # define GATE_NET_PLATFORM_SOCKET_API_SIMULATE_GETADDRINFO 1
42 # define GATE_NET_PLATFORM_SOCKET_API_NO_IOCTL 1
43 #else
44 # define GATE_NET_PLATFORM_SOCKET_API_NOIMPL 1
45 #endif
46
47
48
49 #if defined(GATE_NET_PLATFORM_SOCKET_API_WINSOCK)
50
51 #if defined(GATE_SYS_WIN16)
52 # include <tchar.h>
53 #endif
54
55 static HMODULE hmod_winsock = (HMODULE)NULL;
56
57 struct hostent* (SOCK_API* gethostbyname_func)(const char* name);
58
59 #if (defined(GATE_COMPILER_MSVC98) || defined(GATE_WIN32_ANSI)) && !defined(GATE_COMPILER_TCC)
60 struct sockaddr_storage
61 {
62 char buffer[128];
63 };
64
65 #endif
66
67 struct addrinfo_buffer
68 {
69 struct addrinfo ai;
70 struct sockaddr_storage addr;
71 };
72
73 #ifndef ERROR_NOT_ENOUGH_MEMORY
74 #define ERROR_NOT_ENOUGH_MEMORY 0x8
75 #endif
76
77 static int WINAPI getaddrinfo_hbn(const char* nodename, const char* servname, const struct addrinfo* hints, struct addrinfo** res)
78 {
79 struct hostent* h;
80 struct addrinfo_buffer* ptr_info;
81 struct addrinfo* ptr_ai;
82 struct sockaddr_in* ptr_addr_in = NULL;
83 gate_size_t info_len;
84
85 GATE_UNUSED_ARG(servname);
86 GATE_UNUSED_ARG(hints);
87
88 if (!nodename || !res)
89 {
90 gate_win32_setlasterror(ERROR_INVALID_PARAMETER);
91 return -1;
92 }
93
94 *res = NULL;
95
96 h = gethostbyname_func(nodename);
97 if (NULL == h)
98 {
99 return -1;
100 }
101
102 info_len = sizeof(struct addrinfo_buffer);
103 ptr_info = (struct addrinfo_buffer*)gate_mem_alloc(info_len);
104 if (!ptr_info)
105 {
106 gate_win32_setlasterror(ERROR_NOT_ENOUGH_MEMORY);
107 return -1;
108 }
109
110 ptr_ai = &ptr_info->ai;
111
112 ptr_ai->ai_flags = AI_CANONNAME;
113 ptr_ai->ai_family = AF_INET;
114 ptr_ai->ai_socktype = SOCK_STREAM;
115 ptr_ai->ai_protocol = IPPROTO_TCP;
116 ptr_ai->ai_addrlen = 0;
117 ptr_ai->ai_canonname = NULL;
118 if (h->h_addrtype == AF_INET)
119 {
120 ptr_addr_in = (struct sockaddr_in*)&ptr_info->addr;
121 ptr_addr_in->sin_family = AF_INET;
122 ptr_addr_in->sin_port = 0;
123 ptr_addr_in->sin_addr.S_un.S_un_b.s_b1 = h->h_addr_list[0][0];
124 ptr_addr_in->sin_addr.S_un.S_un_b.s_b2 = h->h_addr_list[0][1];
125 ptr_addr_in->sin_addr.S_un.S_un_b.s_b3 = h->h_addr_list[0][2];
126 ptr_addr_in->sin_addr.S_un.S_un_b.s_b4 = h->h_addr_list[0][3];
127 }
128 ptr_ai->ai_addr = (struct sockaddr*)ptr_addr_in;
129 ptr_ai->ai_next = NULL;
130
131 *res = ptr_ai;
132 return 0;
133 }
134 static void WINAPI freeaddrinfo_hbn(struct addrinfo* ai)
135 {
136 if (ai)
137 {
138 gate_mem_dealloc(ai);
139 }
140 }
141
142 gate_result_t gate_socket_api_load(gate_net_platform_socket_api_t* ptr)
143 {
144
145 if (!hmod_winsock)
146 {
147 hmod_winsock = gate_win32_load_library(_T("ws2_32"), 0);
148 if (!hmod_winsock)
149 {
150 hmod_winsock = gate_win32_load_library(_T("wsock32"), 0);
151 }
152 }
153
154 if (!hmod_winsock)
155 {
156 return GATE_RESULT_NOTAVAILABLE;
157 }
158
159 if (ptr)
160 {
161 gate_win32_get_proc_address(hmod_winsock, "socket", &ptr->sock_socket);
162 gate_win32_get_proc_address(hmod_winsock, "closesocket", &ptr->sock_close);
163 gate_win32_get_proc_address(hmod_winsock, "connect", &ptr->sock_connect);
164 gate_win32_get_proc_address(hmod_winsock, "accept", &ptr->sock_accept);
165 gate_win32_get_proc_address(hmod_winsock, "bind", &ptr->sock_bind);
166 gate_win32_get_proc_address(hmod_winsock, "listen", &ptr->sock_listen);
167 gate_win32_get_proc_address(hmod_winsock, "recv", &ptr->sock_recv);
168 gate_win32_get_proc_address(hmod_winsock, "recvfrom", &ptr->sock_recvfrom);
169 gate_win32_get_proc_address(hmod_winsock, "send", &ptr->sock_send);
170 gate_win32_get_proc_address(hmod_winsock, "sendto", &ptr->sock_sendto);
171 gate_win32_get_proc_address(hmod_winsock, "shutdown", &ptr->sock_shutdown);
172 gate_win32_get_proc_address(hmod_winsock, "getsockopt", &ptr->sock_getsockopt);
173 gate_win32_get_proc_address(hmod_winsock, "setsockopt", &ptr->sock_setsockopt);
174 gate_win32_get_proc_address(hmod_winsock, "getsockname", &ptr->sock_getsockname);
175 gate_win32_get_proc_address(hmod_winsock, "getpeername", &ptr->sock_getpeername);
176 gate_win32_get_proc_address(hmod_winsock, "ioctlsocket", &ptr->sock_ioctl);
177 gate_win32_get_proc_address(hmod_winsock, "select", &ptr->sock_select);
178 gate_win32_get_proc_address(hmod_winsock, "__WSAFDIsSet", &ptr->sock_isset);
179
180 gate_win32_get_proc_address(hmod_winsock, "htonl", &ptr->sock_htonl);
181 gate_win32_get_proc_address(hmod_winsock, "htons", &ptr->sock_htons);
182 gate_win32_get_proc_address(hmod_winsock, "ntohl", &ptr->sock_ntohl);
183 gate_win32_get_proc_address(hmod_winsock, "ntohs", &ptr->sock_ntohs);
184 gate_win32_get_proc_address(hmod_winsock, "WSAGetLastError", &ptr->sock_errno);
185
186 gate_win32_get_proc_address(hmod_winsock, "gethostbyname", &ptr->sock_gethostbyname);
187 gate_win32_get_proc_address(hmod_winsock, "getaddrinfo", &ptr->sock_getaddrinfo);
188 gate_win32_get_proc_address(hmod_winsock, "freeaddrinfo", &ptr->sock_freeaddrinfo);
189
190 if (!ptr->sock_getaddrinfo && ptr->sock_gethostbyname)
191 {
192 gethostbyname_func = ptr->sock_gethostbyname;
193 ptr->sock_getaddrinfo = &getaddrinfo_hbn;
194 ptr->sock_freeaddrinfo = &freeaddrinfo_hbn;
195 }
196 }
197
198 return GATE_RESULT_OK;
199 }
200
201 gate_result_t gate_socket_session_init()
202 {
203 static int(WINAPI * startup)(WORD version_requested, LPWSADATA ptr_wsa_data) = NULL;
204 static WORD versions[] = {
205 MAKEWORD(2,2),
206 MAKEWORD(2,0),
207 MAKEWORD(1,1),
208 MAKEWORD(1,0)
209 };
210 static unsigned const versions_count = sizeof(versions) / sizeof(versions[0]);
211 unsigned ndx;
212 gate_result_t ret;
213
214 gate_socket_api_load(NULL);
215
216 if (!startup)
217 {
218 if (!hmod_winsock)
219 {
220 return GATE_RESULT_NOTAVAILABLE;
221 }
222 gate_win32_get_proc_address(hmod_winsock, "WSAStartup", &startup);
223 if (!startup)
224 {
225 return GATE_RESULT_NOTAVAILABLE;
226 }
227 }
228
229 for (ndx = 0; ndx != versions_count; ++ndx)
230 {
231 WSADATA wsa_data;
232 int result = startup(versions[ndx], &wsa_data);
233 if (result == 0)
234 {
235 /* WINSOCK initialized */
236 return GATE_RESULT_OK;
237 }
238 }
239 gate_win32_print_lasterror(&ret, NULL, 0);
240 return ret;
241 }
242
243 gate_result_t gate_socket_session_uninit()
244 {
245 static int(WINAPI * cleanup)(void) = NULL;
246
247 int result;
248 gate_result_t ret = GATE_RESULT_OK;
249
250 if (!cleanup)
251 {
252 if (!hmod_winsock)
253 {
254 return GATE_RESULT_NOTAVAILABLE;
255 }
256
257 gate_win32_get_proc_address(hmod_winsock, "WSACleanup", &cleanup);
258 if (!cleanup)
259 {
260 return GATE_RESULT_NOTAVAILABLE;
261 }
262 }
263
264 result = cleanup();
265 if (result != 0)
266 {
267 gate_win32_print_lasterror(&ret, NULL, 0);
268 }
269 return ret;
270 }
271
272 #endif /* GATE_NET_PLATFORM_SOCKET_API_WINSOCK */
273
274
275
276
277 #if defined(GATE_NET_PLATFORM_SOCKET_API_LINKED)
278
279 5 static int sock_errno_impl(void)
280 {
281 5 return errno;
282 }
283 270 static int sock_isset_impl(sock_fd_t fd, fd_set* set)
284 {
285 270 return FD_ISSET(fd, set);
286 }
287 static int sock_ioctl_impl(sock_fd_t fd, unsigned long request, void* argp)
288 {
289 #if defined(GATE_NET_PLATFORM_SOCKET_API_NO_IOCTL)
290 return -1;
291 #else
292 return ioctl(fd, request, argp);
293 #endif
294 }
295
296 26 gate_result_t gate_socket_session_init()
297 {
298 26 return GATE_RESULT_OK;
299 }
300 5 gate_result_t gate_socket_session_uninit()
301 {
302 5 return GATE_RESULT_OK;
303 }
304
305 /* some platforms use macros for htoX and ntoX (e.g android) */
306 17 static sock_ulong_t disp_htonl(sock_ulong_t hostlong)
307 {
308 17 return htonl(hostlong);
309 }
310 22 static sock_ushort_t disp_htons(sock_ushort_t hostshort)
311 {
312 22 return htons(hostshort);
313 }
314 9 static sock_ulong_t disp_ntohl(sock_ulong_t netlong)
315 {
316 9 return ntohl(netlong);
317 }
318 12 static sock_ushort_t disp_ntohs(sock_ushort_t netshort)
319 {
320 12 return ntohs(netshort);
321 }
322
323 #if defined(GATE_NET_PLATFORM_SOCKET_API_NO_IOCTL)
324
325 #endif
326
327 #if defined(GATE_NET_PLATFORM_SOCKET_API_SIMULATE_GETADDRINFO)
328
329 static int gethostbyname_getaddrinfo(const char *node, const char *service,
330 const struct addrinfo *hints,
331 struct addrinfo **res)
332 {
333 int ret = -1;
334 do
335 {
336 struct addrinfo* ai = NULL;
337 struct hostent* he = gethostbyname(node);
338 struct sockaddr_in* addr;
339 if (!he) break;
340
341 ai = gate_mem_alloc(sizeof(struct addrinfo));
342 if (NULL == ai) break;
343
344 addr = gate_mem_alloc(sizeof(struct sockaddr_in));
345 if (NULL == addr)
346 {
347 gate_mem_dealloc(ai);
348 break;
349 }
350
351 ai->ai_family = AF_INET;
352 ai->ai_socktype = hints ? hints->ai_socktype : SOCK_STREAM;
353 ai->ai_protocol = 0;
354 ai->ai_addrlen = sizeof(struct sockaddr_in);
355
356 addr->sin_family = AF_INET;
357 addr->sin_port = htons(atoi(service));
358 gate_mem_copy(&addr->sin_addr, he->h_addr_list[0], he->h_length);
359
360 ai->ai_addr = (struct sockaddr *)addr;
361 ai->ai_next = NULL;
362
363 /* success: */
364 *res = ai;
365 ret = 0;
366
367 } while (0);
368
369 return ret;
370 }
371
372 static void gethostbyname_freeaddrinfo(struct addrinfo* ai)
373 {
374 if (ai != NULL)
375 {
376 gate_mem_dealloc(ai->ai_addr);
377 gate_mem_dealloc(ai);
378 }
379 }
380
381 #endif /* GATE_NET_PLATFORM_SOCKET_API_SIMULATE_GETADDRINFO */
382
383 38 gate_result_t gate_socket_api_load(gate_net_platform_socket_api_t* ptr)
384 {
385 38 ptr->sock_socket = &socket;
386 38 ptr->sock_close = &close;
387 38 ptr->sock_connect = &connect;
388 38 ptr->sock_accept = &accept;
389 38 ptr->sock_bind = &bind;
390 38 ptr->sock_listen = &listen;
391 38 ptr->sock_recv = &recv;
392 38 ptr->sock_recvfrom = &recvfrom;
393 38 ptr->sock_send = &send;
394 38 ptr->sock_sendto = &sendto;
395 38 ptr->sock_shutdown = &shutdown;
396 38 ptr->sock_getsockopt = &getsockopt;
397 38 ptr->sock_setsockopt = &setsockopt;
398 38 ptr->sock_getsockname = &getsockname;
399 38 ptr->sock_getpeername = &getpeername;
400 38 ptr->sock_ioctl = &sock_ioctl_impl;
401 38 ptr->sock_select = &select;
402 38 ptr->sock_isset = &sock_isset_impl;
403
404 38 ptr->sock_htonl = &disp_htonl;
405 38 ptr->sock_htons = &disp_htons;
406 38 ptr->sock_ntohl = &disp_ntohl;
407 38 ptr->sock_ntohs = &disp_ntohs;
408 38 ptr->sock_errno = &sock_errno_impl;
409
410 38 ptr->sock_gethostbyname = &gethostbyname;
411 #if defined(GATE_NET_PLATFORM_SOCKET_API_SIMULATE_GETADDRINFO)
412 ptr->sock_getaddrinfo = &gethostbyname_getaddrinfo;
413 ptr->sock_freeaddrinfo = &gethostbyname_freeaddrinfo;
414 #else
415 38 ptr->sock_getaddrinfo = &getaddrinfo;
416 38 ptr->sock_freeaddrinfo = &freeaddrinfo;
417 #endif /* GATE_NET_PLATFORM_SOCKET_API_SIMULATE_GETADDRINFO */
418
419 38 return GATE_RESULT_OK;
420 }
421
422 #endif /* GATE_NET_PLATFORM_SOCKET_API_LINKED */
423
424
425
426
427 #if defined(GATE_NET_PLATFORM_SOCKET_API_SOCOP)
428
429 #include "gate/interfaces/socop.h"
430 #include "gate/interfaces/socop_impl.c"
431
432 #include "gate/atomics.h"
433 #include "gate/environments.h"
434 #include "gate/streams.h"
435 #include "gate/io/serialports.h"
436
437 typedef struct socl_class
438 {
439 int sockfd;
440 socop_socket_t sockhandle;
441 } socl_t;
442
443 static socl_t socl_pool[64];
444 static unsigned const socl_pool_length = 64;
445 static int volatile socl_next_fd = 0;
446
447 static socop_client_t global_socop_client;
448 static gate_atomic_int_t global_socop_client_used;
449
450 static gate_stream_t* global_socop_stream = NULL;
451
452 static int gate_socop_read_byte(unsigned char* num, unsigned want_more, void* user_param)
453 {
454 gate_size_t retrieved = 0;
455 gate_result_t result;
456 GATE_UNUSED_ARG(want_more);
457 GATE_UNUSED_ARG(user_param);
458 if (!global_socop_stream)
459 {
460 return SOCOP_ERROR_IO;
461 }
462 result = gate_stream_read(global_socop_stream, (char*)&num, 1, &retrieved);
463 if (GATE_FAILED(result))
464 {
465 return SOCOP_ERROR_IO;
466 }
467 if (retrieved == 0)
468 {
469 return SOCOP_ERROR_TIMEOUT;
470 }
471 return SOCOP_OK;
472 }
473 static int gate_socop_write_byte(unsigned char num, unsigned send_more, void* user_param)
474 {
475 gate_size_t written = 0;
476 gate_result_t result;
477 GATE_UNUSED_ARG(send_more);
478 GATE_UNUSED_ARG(user_param);
479 if (!global_socop_stream)
480 {
481 return SOCOP_ERROR_IO;
482 }
483 result = gate_stream_write(global_socop_stream, (char const*)&num, 1, &written);
484 if (GATE_FAILED(result))
485 {
486 return SOCOP_ERROR_IO;
487 }
488 if (written == 0)
489 {
490 return SOCOP_ERROR_TIMEOUT;
491 }
492 return SOCOP_OK;
493 }
494
495 static sock_fd_t get_next_sock_fd()
496 {
497 /* TODO: ensure unique fd */
498 return (sock_fd_t)++socl_next_fd;
499 }
500
501 static socl_t* allocate_socket()
502 {
503 socl_t* ret = NULL;
504 unsigned ndx;
505 for (ndx = 0; ndx != socl_pool_length; ++ndx)
506 {
507 if (socl_pool[ndx].sockfd == 0)
508 {
509 ret = &socl_pool[ndx];
510 ret->sockfd = get_next_sock_fd();
511 ret->sockhandle = 0;
512 break;
513 }
514 }
515 return ret;
516 }
517 static void deallocate_socket(socl_t* ptr_socl)
518 {
519 ptr_socl->sockfd = 0;
520 ptr_socl->sockhandle = 0;
521 }
522 static socl_t* resolve_fd(int fd)
523 {
524 socl_t* ret = NULL;
525 unsigned ndx;
526 for (ndx = 0; ndx != socl_pool_length; ++ndx)
527 {
528 if (socl_pool[ndx].sockfd == fd)
529 {
530 ret = &socl_pool[ndx];
531 break;
532 }
533 }
534 return ret;
535 }
536
537 static socop_client_t* get_session()
538 {
539 return &global_socop_client;
540 }
541
542 static sock_fd_t SOCK_API socl_socket(int domain, int type, int protocol)
543 {
544 socl_t* ptr_socl;
545
546 switch (domain)
547 {
548 case AF_INET:
549 case AF_INET6: break; /* OK */
550 default: return -1;
551 }
552 switch (type)
553 {
554 case SOCK_STREAM:
555 case SOCK_DGRAM: break; /* OK */
556 default: return -1;
557 }
558 switch (protocol)
559 {
560 case IPPROTO_TCP:
561 case IPPROTO_UDP: break; /* OK */
562 default: return -1;
563 }
564
565 ptr_socl = allocate_socket();
566 if (!ptr_socl)
567 {
568 return -1;
569 }
570 return ptr_socl->sockfd;
571 }
572 static int SOCK_API socl_close(sock_fd_t fd)
573 {
574 socop_client_t* session = get_session();
575 socl_t* socl = resolve_fd(fd);
576 if (!session || !socl) return -1;
577
578 socl->sockfd = 0;
579 if (socl->sockhandle)
580 {
581 int result = socop_client_close(session, socl->sockhandle);
582 socl->sockhandle = 0;
583 return (result == SOCOP_OK) ? 0 : -1;
584 }
585 return 0;
586 }
587
588 static void SOCK_API sockaddr_2_socop_addr(const struct sockaddr* ptr_src, sock_socklen_t srclen, socop_addr_t* ptr_target)
589 {
590 struct sockaddr_in const* const addr_in = (struct sockaddr_in const*)ptr_src;
591 GATE_UNUSED_ARG(srclen);
592 ptr_target->port = addr_in->sin_port;
593 ptr_target->ip[0] = (unsigned char)((addr_in->sin_addr.s_addr & 0xff000000) >> 24);
594 ptr_target->ip[1] = (unsigned char)((addr_in->sin_addr.s_addr & 0x00ff0000) >> 16);
595 ptr_target->ip[2] = (unsigned char)((addr_in->sin_addr.s_addr & 0x0000ff00) >> 8);
596 ptr_target->ip[3] = (unsigned char)((addr_in->sin_addr.s_addr & 0x000000ff));
597 }
598
599 static int SOCK_API socl_connect(sock_fd_t fd, const struct sockaddr* addr, sock_socklen_t addrlen)
600 {
601 socop_addr_t socop_addr;
602 int result;
603 socop_client_t* session = get_session();
604 socl_t* socl = resolve_fd(fd);
605 if (!session || !socl) return -1;
606
607 sockaddr_2_socop_addr(addr, addrlen, &socop_addr);
608 result = socop_client_connect(session, &socop_addr, &socl->sockhandle);
609 if (SOCOP_OK == result)
610 {
611 return 0;
612 }
613 return -1;
614 }
615 static sock_fd_t SOCK_API socl_accept(sock_fd_t fd, struct sockaddr* addr, sock_socklen_t* addrlen)
616 {
617 socop_client_t* session = get_session();
618 socl_t* socl = resolve_fd(fd);
619 socl_t* new_socl = NULL;
620 socop_socket_t new_sock;
621 int result;
622
623 GATE_UNUSED_ARG(addrlen);
624 if (!session || !socl) return -1;
625
626 result = socop_client_accept(session, socl->sockhandle, &new_sock);
627 if (SOCOP_OK == result)
628 {
629 new_socl = allocate_socket();
630 if (new_socl == NULL)
631 {
632 socop_client_close(session, new_sock);
633 }
634 else
635 {
636 /* success case */
637 /* TODO: fill peer addr */
638 new_socl->sockhandle = new_sock;
639 return (sock_fd_t)new_socl->sockfd;
640 }
641 }
642 return -1;
643 }
644 static int SOCK_API socl_bind(sock_fd_t fd, const struct sockaddr* addr, sock_socklen_t addrlen)
645 {
646 socop_client_t* session = get_session();
647 socl_t* socl = resolve_fd(fd);
648 socop_addr_t socop_addr;
649 int result;
650 if (!session || !socl) return -1;
651
652 sockaddr_2_socop_addr(addr, addrlen, &socop_addr);
653 result = socop_client_bind(session, &socop_addr, &socl->sockhandle);
654 if (SOCOP_OK == result)
655 {
656 return 0;
657 }
658 return -1;
659 }
660 static int SOCK_API socl_listen(sock_fd_t fd, int backlog)
661 {
662 socop_client_t* session = get_session();
663 socl_t* socl = resolve_fd(fd);
664 if (!session || !socl) return -1;
665 /* TODO */
666 return -1;
667 }
668 static sock_ssize_t SOCK_API socl_recv(sock_fd_t fd, void* buf, size_t len, int flags)
669 {
670 unsigned int buf_used = 0;
671 int result;
672
673 socop_client_t* session = get_session();
674 socl_t* socl = resolve_fd(fd);
675 if (!session || !socl) return -1;
676
677 result = socop_client_receive(session, socl->sockhandle, buf, len, &buf_used);
678 if (SOCOP_OK == result)
679 {
680 return (sock_ssize_t)buf_used;
681 }
682 return -1;
683 }
684 static sock_ssize_t SOCK_API socl_recvfrom(sock_fd_t fd, void* buf, size_t len, int flags, struct sockaddr* src_addr, sock_socklen_t* addrlen)
685 {
686 socop_client_t* session = get_session();
687 socl_t* socl = resolve_fd(fd);
688 if (!session || !socl) return -1;
689 /* TODO */
690 return -1;
691 }
692 static sock_ssize_t SOCK_API socl_send(sock_fd_t fd, const void* buf, size_t len, int flags)
693 {
694 unsigned int buf_used = 0;
695 int result;
696
697 socop_client_t* session = get_session();
698 socl_t* socl = resolve_fd(fd);
699 if (!session || !socl) return -1;
700
701 result = socop_client_send(session, socl->sockhandle, buf, len, &buf_used);
702 if (SOCOP_OK == result)
703 {
704 return (sock_ssize_t)buf_used;
705 }
706 return -1;
707 }
708 static sock_ssize_t SOCK_API socl_sendto(sock_fd_t fd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, sock_socklen_t addrlen)
709 {
710 socop_client_t* session = get_session();
711 socl_t* socl = resolve_fd(fd);
712 if (!session || !socl) return -1;
713 /* TODO */
714 return -1;
715 }
716 static int SOCK_API socl_shutdown(sock_fd_t fd, int how)
717 {
718 socop_client_t* session = get_session();
719 socl_t* socl = resolve_fd(fd);
720 int result;
721 if (!session || !socl) return -1;
722 /* TODO */
723 result = socop_client_shutdown(session, socl->sockhandle, SOCOP_MSG_FLAG_RECV | SOCOP_MSG_FLAG_SEND);
724 if (SOCOP_OK == result)
725 {
726 return 0;
727 }
728 return -1;
729 }
730 static int SOCK_API socl_getsockopt(sock_fd_t fd, int level, int optname, void* optval, sock_socklen_t* optlen)
731 {
732 socop_client_t* session = get_session();
733 socl_t* socl = resolve_fd(fd);
734 if (!session || !socl) return -1;
735 /* TODO */
736 return -1;
737 }
738 static int SOCK_API socl_setsockopt(sock_fd_t fd, int level, int optname, const void* optval, sock_socklen_t optlen)
739 {
740 socop_client_t* session = get_session();
741 socl_t* socl = resolve_fd(fd);
742 if (!session || !socl) return -1;
743 /* TODO */
744 return -1;
745 }
746 static int SOCK_API socl_getsockname(sock_fd_t fd, struct sockaddr* addr, sock_socklen_t* addrlen)
747 {
748 socop_client_t* session = get_session();
749 socl_t* socl = resolve_fd(fd);
750 if (!session || !socl) return -1;
751 /* TODO */
752 return -1;
753 }
754 static int SOCK_API socl_getpeername(sock_fd_t fd, struct sockaddr* addr, sock_socklen_t* addrlen)
755 {
756 socop_client_t* session = get_session();
757 socl_t* socl = resolve_fd(fd);
758 if (!session || !socl) return -1;
759 /* TODO */
760 return -1;
761 }
762 static int SOCK_API socl_ioctl(sock_fd_t fd, unsigned long request, void* argp)
763 {
764 socop_client_t* session = get_session();
765 socl_t* socl = resolve_fd(fd);
766 if (!session || !socl) return -1;
767 /* TODO */
768 return -1;
769 }
770 static int SOCK_API socl_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, sock_timeval_t* timeout)
771 {
772 socop_client_t* session = get_session();
773 if (!session) return -1;
774 /* TODO */
775 return -1;
776
777 }
778 static int SOCK_API socl_isset(sock_fd_t fd, fd_set* set)
779 {
780 socop_client_t* session = get_session();
781 socl_t* socl = resolve_fd(fd);
782 if (!session || !socl) return -1;
783 /* TODO */
784 return -1;
785 }
786
787 union host_types
788 {
789 sock_ulong_t l;
790 sock_ushort_t s;
791 unsigned char c[sizeof(unsigned long)];
792 };
793
794 static sock_ulong_t SOCK_API socl_htonl(sock_ulong_t hostlong)
795 {
796 unsigned ndx;
797 union host_types a, b;
798 a.l = hostlong;
799 for (ndx = 0; ndx != sizeof(sock_ulong_t); ++ndx)
800 {
801 b.c[ndx] = a.c[sizeof(sock_ulong_t) - 1 - ndx];
802 }
803 return b.l;
804 }
805 static sock_ushort_t SOCK_API socl_htons(sock_ushort_t hostshort)
806 {
807 unsigned ndx;
808 union host_types a, b;
809 a.s = hostshort;
810 for (ndx = 0; ndx != sizeof(sock_ushort_t); ++ndx)
811 {
812 b.c[ndx] = a.c[sizeof(sock_ushort_t) - 1 - ndx];
813 }
814 return b.s;
815 }
816 static sock_ulong_t SOCK_API socl_ntohl(sock_ulong_t netlong)
817 {
818 return socl_htonl(netlong);
819 }
820 static sock_ushort_t SOCK_API socl_ntohs(sock_ushort_t netshort)
821 {
822 return socl_htons(netshort);
823 }
824 static int SOCK_API socl_errno(void)
825 {
826 /* TODO */
827 return -1;
828 }
829
830 static struct hostent* SOCK_API socl_gethostbyname(const char* name)
831 {
832 socop_client_t* session = get_session();
833 if (!session) return NULL;
834 /* TODO */
835 return NULL;
836 }
837 static int SOCK_API socl_getaddrinfo(const char* nodename, const char* servname, const struct addrinfo* hints, struct addrinfo** res)
838 {
839 socop_client_t* session = get_session();
840 if (!session) return -1;
841 /* TODO */
842 return -1;
843 }
844 static void SOCK_API socl_freeaddrinfo(struct addrinfo* ai)
845 {
846 if (ai)
847 {
848 gate_mem_dealloc(ai);
849 }
850 }
851
852
853 gate_result_t gate_socket_api_load(gate_net_platform_socket_api_t* ptr)
854 {
855 gate_result_t ret = GATE_RESULT_OK;
856
857 ptr->sock_socket = &socl_socket;
858 ptr->sock_close = &socl_close;
859 ptr->sock_connect = &socl_connect;
860 ptr->sock_accept = &socl_accept;
861 ptr->sock_bind = &socl_bind;
862 ptr->sock_listen = &socl_listen;
863 ptr->sock_recv = &socl_recv;
864 ptr->sock_recvfrom = &socl_recvfrom;
865 ptr->sock_send = &socl_send;
866 ptr->sock_sendto = &socl_sendto;
867 ptr->sock_shutdown = &socl_shutdown;
868 ptr->sock_getsockopt = &socl_getsockopt;
869 ptr->sock_setsockopt = &socl_setsockopt;
870 ptr->sock_getsockname = &socl_getsockname;
871 ptr->sock_getpeername = &socl_getpeername;
872 ptr->sock_ioctl = &socl_ioctl;
873 ptr->sock_select = &socl_select;
874 ptr->sock_isset = &socl_isset;
875
876 ptr->sock_htonl = &socl_htonl;
877 ptr->sock_htons = &socl_htons;
878 ptr->sock_ntohl = &socl_ntohl;
879 ptr->sock_ntohs = &socl_ntohs;
880 ptr->sock_errno = &socl_errno;
881
882 ptr->sock_gethostbyname = &socl_gethostbyname;
883 ptr->sock_getaddrinfo = &socl_getaddrinfo;
884 ptr->sock_freeaddrinfo = &socl_freeaddrinfo;
885
886 return ret;
887 }
888
889 static gate_result_t open_socop_com_port()
890 {
891 static gate_string_t const var_socop_port = GATE_STRING_INIT_STATIC("SOCOP_PORT");
892 static gate_string_t const var_socop_baud = GATE_STRING_INIT_STATIC("SOCOP_BAUD");
893 static gate_string_t const default_port = GATE_STRING_INIT_STATIC("COM1");
894 static gate_string_t const default_baud = GATE_STRING_INIT_STATIC("9600");
895
896 gate_result_t result;
897 gate_string_t com_port_name = GATE_STRING_INIT_EMPTY;
898 gate_string_t com_port_baud = GATE_STRING_INIT_EMPTY;
899 gate_int64_t baud_value = 0;
900 gate_stream_t* ptr_strm = NULL;
901
902 result = gate_env_get_var(&var_socop_port, &com_port_name);
903 if (GATE_FAILED(result))
904 {
905 gate_string_duplicate(&com_port_name, &default_port);
906 }
907
908 result = gate_env_get_var(&var_socop_baud, &com_port_baud);
909 if (GATE_FAILED(result))
910 {
911 gate_string_duplicate(&com_port_baud, &default_baud);
912 }
913
914 gate_string_parse_int(&com_port_baud, &baud_value);
915 result = gate_serialport_openstream(&com_port_name, (gate_uint32_t)baud_value,
916 8, GATE_SERIALPORT_PARITY_NONE, GATE_SERIALPORT_STOPBITS_1_0, GATE_SERIALPORT_FLOWCTRL_NONE,
917 &ptr_strm
918 );
919 if (GATE_SUCCEEDED(result) && (ptr_strm != NULL))
920 {
921 if (ptr_strm != NULL)
922 {
923 global_socop_stream = ptr_strm;
924 }
925 else
926 {
927 result = GATE_RESULT_NULLPOINTER;
928 }
929 }
930 return result;
931 }
932
933 gate_result_t gate_socket_session_init()
934 {
935 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
936 gate_int32_t use_count = gate_atomic_int_inc(&global_socop_client_used);
937 if (use_count == 1)
938 {
939 int result = socop_client_init(
940 &global_socop_client,
941 &gate_socop_read_byte, NULL,
942 &gate_socop_write_byte, NULL);
943 if (SOCOP_OK != result)
944 {
945 gate_atomic_int_dec(&global_socop_client_used);
946 ret = GATE_RESULT_FAILED;
947 }
948 else
949 {
950 ret = open_socop_com_port();
951 if (GATE_FAILED(ret))
952 {
953 gate_atomic_int_dec(&global_socop_client_used);
954 }
955 }
956 }
957 else
958 {
959 ret = GATE_RESULT_OK;
960 }
961 return ret;
962 }
963
964 gate_result_t gate_socket_session_uninit()
965 {
966 gate_result_t ret = GATE_RESULT_OK;
967 gate_uint32_t use_count = gate_atomic_int_dec(&global_socop_client_used);
968 if (use_count == 0)
969 {
970 unsigned ndx;
971 if (global_socop_stream != NULL)
972 {
973 gate_object_release(global_socop_stream);
974 global_socop_stream = NULL;
975 }
976
977 socop_client_reset(&global_socop_client);
978 for (ndx = 0; ndx != sizeof(socl_pool) / sizeof(socl_pool[0]); ++ndx)
979 {
980 socl_pool[ndx].sockfd = 0;
981 socl_pool[ndx].sockhandle = 0;
982 }
983 }
984 return ret;
985 }
986
987 #endif /* GATE_NET_PLATFORM_SOCKET_API_SOCOP */
988
989
990
991
992 #if defined(GATE_NET_PLATFORM_SOCKET_API_NOIMPL)
993
994 gate_result_t gate_socket_api_load(gate_net_platform_socket_api_t* ptr)
995 {
996 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
997 GATE_UNUSED_ARG(ptr);
998 return ret;
999 }
1000
1001 gate_result_t gate_socket_session_init()
1002 {
1003 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1004 return ret;
1005 }
1006
1007 gate_result_t gate_socket_session_uninit()
1008 {
1009 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1010 return ret;
1011 }
1012
1013 #endif /* GATE_NET_PLATFORM_SOCKET_API_NOIMPL */
1014