GCC Code Coverage Report


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