GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/platform/socket_api.c
Date: 2025-09-22 22:57:09
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 3 static int sock_errno_impl(void)
273 {
274 3 return errno;
275 }
276 222 static int sock_isset_impl(sock_fd_t fd, fd_set* set)
277 {
278 222 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 23 gate_result_t gate_socket_session_init()
286 {
287 23 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 14 static sock_ulong_t disp_htonl(sock_ulong_t hostlong)
296 {
297 14 return htonl(hostlong);
298 }
299 19 static sock_ushort_t disp_htons(sock_ushort_t hostshort)
300 {
301 19 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 30 gate_result_t gate_socket_api_load(gate_net_platform_socket_api_t* ptr)
313 {
314 30 ptr->sock_socket = &socket;
315 30 ptr->sock_close = &close;
316 30 ptr->sock_connect = &connect;
317 30 ptr->sock_accept = &accept;
318 30 ptr->sock_bind = &bind;
319 30 ptr->sock_listen = &listen;
320 30 ptr->sock_recv = &recv;
321 30 ptr->sock_recvfrom = &recvfrom;
322 30 ptr->sock_send = &send;
323 30 ptr->sock_sendto = &sendto;
324 30 ptr->sock_shutdown = &shutdown;
325 30 ptr->sock_getsockopt = &getsockopt;
326 30 ptr->sock_setsockopt = &setsockopt;
327 30 ptr->sock_getsockname = &getsockname;
328 30 ptr->sock_getpeername = &getpeername;
329 30 ptr->sock_ioctl = &sock_ioctl_impl;
330 30 ptr->sock_select = &select;
331 30 ptr->sock_isset = &sock_isset_impl;
332
333 30 ptr->sock_htonl = &disp_htonl;
334 30 ptr->sock_htons = &disp_htons;
335 30 ptr->sock_ntohl = &disp_ntohl;
336 30 ptr->sock_ntohs = &disp_ntohs;
337 30 ptr->sock_errno = &sock_errno_impl;
338
339 30 ptr->sock_gethostbyname = &gethostbyname;
340 30 ptr->sock_getaddrinfo = &getaddrinfo;
341 30 ptr->sock_freeaddrinfo = &freeaddrinfo;
342
343 30 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 GATE_UNUSED_ARG(want_more);
381 GATE_UNUSED_ARG(user_param);
382 if (!global_socop_stream)
383 {
384 return SOCOP_ERROR_IO;
385 }
386 result = gate_stream_read(global_socop_stream, (char*)&num, 1, &retrieved);
387 if (GATE_FAILED(result))
388 {
389 return SOCOP_ERROR_IO;
390 }
391 if (retrieved == 0)
392 {
393 return SOCOP_ERROR_TIMEOUT;
394 }
395 return SOCOP_OK;
396 }
397 static int gate_socop_write_byte(unsigned char num, unsigned send_more, void* user_param)
398 {
399 gate_size_t written = 0;
400 gate_result_t result;
401 GATE_UNUSED_ARG(send_more);
402 GATE_UNUSED_ARG(user_param);
403 if (!global_socop_stream)
404 {
405 return SOCOP_ERROR_IO;
406 }
407 result = gate_stream_write(global_socop_stream, (char const*)&num, 1, &written);
408 if (GATE_FAILED(result))
409 {
410 return SOCOP_ERROR_IO;
411 }
412 if (written == 0)
413 {
414 return SOCOP_ERROR_TIMEOUT;
415 }
416 return SOCOP_OK;
417 }
418
419 static sock_fd_t get_next_sock_fd()
420 {
421 /* TODO: ensure unique fd */
422 return (sock_fd_t)++socl_next_fd;
423 }
424
425 static socl_t* allocate_socket()
426 {
427 socl_t* ret = NULL;
428 unsigned ndx;
429 for (ndx = 0; ndx != socl_pool_length; ++ndx)
430 {
431 if (socl_pool[ndx].sockfd == 0)
432 {
433 ret = &socl_pool[ndx];
434 ret->sockfd = get_next_sock_fd();
435 ret->sockhandle = 0;
436 break;
437 }
438 }
439 return ret;
440 }
441 static void deallocate_socket(socl_t* ptr_socl)
442 {
443 ptr_socl->sockfd = 0;
444 ptr_socl->sockhandle = 0;
445 }
446 static socl_t* resolve_fd(int fd)
447 {
448 socl_t* ret = NULL;
449 unsigned ndx;
450 for (ndx = 0; ndx != socl_pool_length; ++ndx)
451 {
452 if (socl_pool[ndx].sockfd == fd)
453 {
454 ret = &socl_pool[ndx];
455 break;
456 }
457 }
458 return ret;
459 }
460
461 static socop_client_t* get_session()
462 {
463 return &global_socop_client;
464 }
465
466 static sock_fd_t SOCK_API socl_socket(int domain, int type, int protocol)
467 {
468 socl_t* ptr_socl;
469
470 switch (domain)
471 {
472 case AF_INET:
473 case AF_INET6: break; /* OK */
474 default: return -1;
475 }
476 switch (type)
477 {
478 case SOCK_STREAM:
479 case SOCK_DGRAM: break; /* OK */
480 default: return -1;
481 }
482 switch (protocol)
483 {
484 case IPPROTO_TCP:
485 case IPPROTO_UDP: break; /* OK */
486 default: return -1;
487 }
488
489 ptr_socl = allocate_socket();
490 if (!ptr_socl)
491 {
492 return -1;
493 }
494 return ptr_socl->sockfd;
495 }
496 static int SOCK_API socl_close(sock_fd_t fd)
497 {
498 int result;
499 socop_client_t* session = get_session();
500 socl_t* socl = resolve_fd(fd);
501 if (!session || !socl) return -1;
502
503 socl->sockfd = 0;
504 if (socl->sockhandle)
505 {
506 result = socop_client_close(session, socl->sockhandle);
507 socl->sockhandle = 0;
508 return (result == SOCOP_OK) ? 0 : -1;
509 }
510 return 0;
511 }
512
513 static void SOCK_API sockaddr_2_socop_addr(const struct sockaddr* ptr_src, sock_socklen_t srclen, socop_addr_t* ptr_target)
514 {
515 struct sockaddr_in const* const addr_in = (struct sockaddr_in const*)ptr_src;
516 GATE_UNUSED_ARG(srclen);
517 ptr_target->port = addr_in->sin_port;
518 ptr_target->ip[0] = (unsigned char)((addr_in->sin_addr.s_addr & 0xff000000) >> 24);
519 ptr_target->ip[1] = (unsigned char)((addr_in->sin_addr.s_addr & 0x00ff0000) >> 16);
520 ptr_target->ip[2] = (unsigned char)((addr_in->sin_addr.s_addr & 0x0000ff00) >> 8);
521 ptr_target->ip[3] = (unsigned char)((addr_in->sin_addr.s_addr & 0x000000ff));
522 }
523
524 static int SOCK_API socl_connect(sock_fd_t fd, const struct sockaddr* addr, sock_socklen_t addrlen)
525 {
526 socop_addr_t socop_addr;
527 int result;
528 socop_client_t* session = get_session();
529 socl_t* socl = resolve_fd(fd);
530 if (!session || !socl) return -1;
531
532 sockaddr_2_socop_addr(addr, addrlen, &socop_addr);
533 result = socop_client_connect(session, &socop_addr, &socl->sockhandle);
534 if (SOCOP_OK == result)
535 {
536 return 0;
537 }
538 return -1;
539 }
540 static sock_fd_t SOCK_API socl_accept(sock_fd_t fd, struct sockaddr* addr, sock_socklen_t* addrlen)
541 {
542 socop_client_t* session = get_session();
543 socl_t* socl = resolve_fd(fd);
544 socl_t* new_socl = NULL;
545 socop_socket_t new_sock;
546 int result;
547
548 GATE_UNUSED_ARG(addrlen);
549 if (!session || !socl) return -1;
550
551 result = socop_client_accept(session, socl->sockhandle, &new_sock);
552 if (SOCOP_OK == result)
553 {
554 new_socl = allocate_socket();
555 if (new_socl == NULL)
556 {
557 socop_client_close(session, new_sock);
558 }
559 else
560 {
561 /* success case */
562 /* TODO: fill peer addr */
563 new_socl->sockhandle = new_sock;
564 return (sock_fd_t)new_socl->sockfd;
565 }
566 }
567 return -1;
568 }
569 static int SOCK_API socl_bind(sock_fd_t fd, const struct sockaddr* addr, sock_socklen_t addrlen)
570 {
571 socop_client_t* session = get_session();
572 socl_t* socl = resolve_fd(fd);
573 socop_addr_t socop_addr;
574 int result;
575 if (!session || !socl) return -1;
576
577 sockaddr_2_socop_addr(addr, addrlen, &socop_addr);
578 result = socop_client_bind(session, &socop_addr, &socl->sockhandle);
579 if (SOCOP_OK == result)
580 {
581 return 0;
582 }
583 return -1;
584 }
585 static int SOCK_API socl_listen(sock_fd_t fd, int backlog)
586 {
587 socop_client_t* session = get_session();
588 socl_t* socl = resolve_fd(fd);
589 if (!session || !socl) return -1;
590 /* TODO */
591 return -1;
592 }
593 static sock_ssize_t SOCK_API socl_recv(sock_fd_t fd, void* buf, size_t len, int flags)
594 {
595 unsigned int buf_used = 0;
596 int result;
597
598 socop_client_t* session = get_session();
599 socl_t* socl = resolve_fd(fd);
600 if (!session || !socl) return -1;
601
602 result = socop_client_receive(session, socl->sockhandle, buf, len, &buf_used);
603 if (SOCOP_OK == result)
604 {
605 return (sock_ssize_t)buf_used;
606 }
607 return -1;
608 }
609 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)
610 {
611 socop_client_t* session = get_session();
612 socl_t* socl = resolve_fd(fd);
613 if (!session || !socl) return -1;
614 /* TODO */
615 return -1;
616 }
617 static sock_ssize_t SOCK_API socl_send(sock_fd_t fd, const void* buf, size_t len, int flags)
618 {
619 unsigned int buf_used = 0;
620 int result;
621
622 socop_client_t* session = get_session();
623 socl_t* socl = resolve_fd(fd);
624 if (!session || !socl) return -1;
625
626 result = socop_client_send(session, socl->sockhandle, buf, len, &buf_used);
627 if (SOCOP_OK == result)
628 {
629 return (sock_ssize_t)buf_used;
630 }
631 return -1;
632 }
633 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)
634 {
635 socop_client_t* session = get_session();
636 socl_t* socl = resolve_fd(fd);
637 if (!session || !socl) return -1;
638 /* TODO */
639 return -1;
640 }
641 static int SOCK_API socl_shutdown(sock_fd_t fd, int how)
642 {
643 socop_client_t* session = get_session();
644 socl_t* socl = resolve_fd(fd);
645 int result;
646 if (!session || !socl) return -1;
647 /* TODO */
648 result = socop_client_shutdown(session, socl->sockhandle, SOCOP_MSG_FLAG_RECV | SOCOP_MSG_FLAG_SEND);
649 if (SOCOP_OK == result)
650 {
651 return 0;
652 }
653 return -1;
654 }
655 static int SOCK_API socl_getsockopt(sock_fd_t fd, int level, int optname, void* optval, sock_socklen_t* optlen)
656 {
657 socop_client_t* session = get_session();
658 socl_t* socl = resolve_fd(fd);
659 if (!session || !socl) return -1;
660 /* TODO */
661 return -1;
662 }
663 static int SOCK_API socl_setsockopt(sock_fd_t fd, int level, int optname, const void* optval, sock_socklen_t optlen)
664 {
665 socop_client_t* session = get_session();
666 socl_t* socl = resolve_fd(fd);
667 if (!session || !socl) return -1;
668 /* TODO */
669 return -1;
670 }
671 static int SOCK_API socl_getsockname(sock_fd_t fd, struct sockaddr* addr, sock_socklen_t* addrlen)
672 {
673 socop_client_t* session = get_session();
674 socl_t* socl = resolve_fd(fd);
675 if (!session || !socl) return -1;
676 /* TODO */
677 return -1;
678 }
679 static int SOCK_API socl_getpeername(sock_fd_t fd, struct sockaddr* addr, sock_socklen_t* addrlen)
680 {
681 socop_client_t* session = get_session();
682 socl_t* socl = resolve_fd(fd);
683 if (!session || !socl) return -1;
684 /* TODO */
685 return -1;
686 }
687 static int SOCK_API socl_ioctl(sock_fd_t fd, unsigned long request, void* argp)
688 {
689 socop_client_t* session = get_session();
690 socl_t* socl = resolve_fd(fd);
691 if (!session || !socl) return -1;
692 /* TODO */
693 return -1;
694 }
695 static int SOCK_API socl_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, sock_timeval_t* timeout)
696 {
697 socop_client_t* session = get_session();
698 if (!session) return -1;
699 /* TODO */
700 return -1;
701
702 }
703 static int SOCK_API socl_isset(sock_fd_t fd, fd_set* set)
704 {
705 socop_client_t* session = get_session();
706 socl_t* socl = resolve_fd(fd);
707 if (!session || !socl) return -1;
708 /* TODO */
709 return -1;
710 }
711
712 union host_types
713 {
714 sock_ulong_t l;
715 sock_ushort_t s;
716 unsigned char c[sizeof(unsigned long)];
717 };
718
719 static sock_ulong_t SOCK_API socl_htonl(sock_ulong_t hostlong)
720 {
721 unsigned ndx;
722 union host_types a, b;
723 a.l = hostlong;
724 for (ndx = 0; ndx != sizeof(sock_ulong_t); ++ndx)
725 {
726 b.c[ndx] = a.c[sizeof(sock_ulong_t) - 1 - ndx];
727 }
728 return b.l;
729 }
730 static sock_ushort_t SOCK_API socl_htons(sock_ushort_t hostshort)
731 {
732 unsigned ndx;
733 union host_types a, b;
734 a.s = hostshort;
735 for (ndx = 0; ndx != sizeof(sock_ushort_t); ++ndx)
736 {
737 b.c[ndx] = a.c[sizeof(sock_ushort_t) - 1 - ndx];
738 }
739 return b.s;
740 }
741 static sock_ulong_t SOCK_API socl_ntohl(sock_ulong_t netlong)
742 {
743 return socl_htonl(netlong);
744 }
745 static sock_ushort_t SOCK_API socl_ntohs(sock_ushort_t netshort)
746 {
747 return socl_htons(netshort);
748 }
749 static int SOCK_API socl_errno(void)
750 {
751 /* TODO */
752 return -1;
753 }
754
755 static struct hostent* SOCK_API socl_gethostbyname(const char* name)
756 {
757 socop_client_t* session = get_session();
758 if (!session) return NULL;
759 /* TODO */
760 return NULL;
761 }
762 static int SOCK_API socl_getaddrinfo(const char* nodename, const char* servname, const struct addrinfo* hints, struct addrinfo** res)
763 {
764 socop_client_t* session = get_session();
765 if (!session) return -1;
766 /* TODO */
767 return -1;
768 }
769 static void SOCK_API socl_freeaddrinfo(struct addrinfo* ai)
770 {
771 if (ai)
772 {
773 gate_mem_dealloc(ai);
774 }
775 }
776
777
778 gate_result_t gate_socket_api_load(gate_net_platform_socket_api_t* ptr)
779 {
780 gate_result_t ret = GATE_RESULT_OK;
781
782 ptr->sock_socket = &socl_socket;
783 ptr->sock_close = &socl_close;
784 ptr->sock_connect = &socl_connect;
785 ptr->sock_accept = &socl_accept;
786 ptr->sock_bind = &socl_bind;
787 ptr->sock_listen = &socl_listen;
788 ptr->sock_recv = &socl_recv;
789 ptr->sock_recvfrom = &socl_recvfrom;
790 ptr->sock_send = &socl_send;
791 ptr->sock_sendto = &socl_sendto;
792 ptr->sock_shutdown = &socl_shutdown;
793 ptr->sock_getsockopt = &socl_getsockopt;
794 ptr->sock_setsockopt = &socl_setsockopt;
795 ptr->sock_getsockname = &socl_getsockname;
796 ptr->sock_getpeername = &socl_getpeername;
797 ptr->sock_ioctl = &socl_ioctl;
798 ptr->sock_select = &socl_select;
799 ptr->sock_isset = &socl_isset;
800
801 ptr->sock_htonl = &socl_htonl;
802 ptr->sock_htons = &socl_htons;
803 ptr->sock_ntohl = &socl_ntohl;
804 ptr->sock_ntohs = &socl_ntohs;
805 ptr->sock_errno = &socl_errno;
806
807 ptr->sock_gethostbyname = &socl_gethostbyname;
808 ptr->sock_getaddrinfo = &socl_getaddrinfo;
809 ptr->sock_freeaddrinfo = &socl_freeaddrinfo;
810
811 return ret;
812 }
813
814 static gate_result_t open_socop_com_port()
815 {
816 static gate_string_t const var_socop_port = GATE_STRING_INIT_STATIC("SOCOP_PORT");
817 static gate_string_t const var_socop_baud = GATE_STRING_INIT_STATIC("SOCOP_BAUD");
818 static gate_string_t const default_port = GATE_STRING_INIT_STATIC("COM1");
819 static gate_string_t const default_baud = GATE_STRING_INIT_STATIC("9600");
820
821 gate_result_t result;
822 gate_string_t com_port_name = GATE_STRING_INIT_EMPTY;
823 gate_string_t com_port_baud = GATE_STRING_INIT_EMPTY;
824 gate_int64_t baud_value = 0;
825 gate_stream_t* ptr_strm = NULL;
826
827 result = gate_env_get_var(&var_socop_port, &com_port_name);
828 if (GATE_FAILED(result))
829 {
830 gate_string_duplicate(&com_port_name, &default_port);
831 }
832
833 result = gate_env_get_var(&var_socop_baud, &com_port_baud);
834 if (GATE_FAILED(result))
835 {
836 gate_string_duplicate(&com_port_baud, &default_baud);
837 }
838
839 gate_string_parse_int(&com_port_baud, &baud_value);
840 result = gate_serialport_openstream(&com_port_name, (gate_uint32_t)baud_value,
841 8, GATE_SERIALPORT_PARITY_NONE, GATE_SERIALPORT_STOPBITS_1_0, GATE_SERIALPORT_FLOWCTRL_NONE,
842 &ptr_strm
843 );
844 if (GATE_SUCCEEDED(result) && (ptr_strm != NULL))
845 {
846 if (ptr_strm != NULL)
847 {
848 global_socop_stream = ptr_strm;
849 }
850 else
851 {
852 result = GATE_RESULT_NULLPOINTER;
853 }
854 }
855 return result;
856 }
857
858 gate_result_t gate_socket_session_init()
859 {
860 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
861 int result;
862 gate_int32_t use_count = gate_atomic_int_inc(&global_socop_client_used);
863 if (use_count == 1)
864 {
865 result = socop_client_init(
866 &global_socop_client,
867 &gate_socop_read_byte, NULL,
868 &gate_socop_write_byte, NULL);
869 if (SOCOP_OK != result)
870 {
871 gate_atomic_int_dec(&global_socop_client_used);
872 ret = GATE_RESULT_FAILED;
873 }
874 else
875 {
876 ret = open_socop_com_port();
877 if (GATE_FAILED(ret))
878 {
879 gate_atomic_int_dec(&global_socop_client_used);
880 }
881 }
882 }
883 else
884 {
885 ret = GATE_RESULT_OK;
886 }
887 return ret;
888 }
889
890 gate_result_t gate_socket_session_uninit()
891 {
892 gate_result_t ret = GATE_RESULT_OK;
893 gate_uint32_t use_count = gate_atomic_int_dec(&global_socop_client_used);
894 unsigned ndx;
895 if (use_count == 0)
896 {
897 if (global_socop_stream != NULL)
898 {
899 gate_object_release(global_socop_stream);
900 global_socop_stream = NULL;
901 }
902
903 socop_client_reset(&global_socop_client);
904 for (ndx = 0; ndx != sizeof(socl_pool) / sizeof(socl_pool[0]); ++ndx)
905 {
906 socl_pool[ndx].sockfd = 0;
907 socl_pool[ndx].sockhandle = 0;
908 }
909 }
910 return ret;
911 }
912
913 #endif /* GATE_NET_PLATFORM_SOCKET_API_SOCOP */
914
915
916
917
918 #if defined(GATE_NET_PLATFORM_SOCKET_API_NOIMPL)
919
920 gate_result_t gate_socket_api_load(gate_net_platform_socket_api_t* ptr)
921 {
922 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
923 GATE_UNUSED_ARG(ptr);
924 return ret;
925 }
926
927 gate_result_t gate_socket_session_init()
928 {
929 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
930 return ret;
931 }
932
933 gate_result_t gate_socket_session_uninit()
934 {
935 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
936 return ret;
937 }
938
939 #endif /* GATE_NET_PLATFORM_SOCKET_API_NOIMPL */
940