GCC Code Coverage Report


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