GCC Code Coverage Report


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