Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
net_cc3220/CC32xxSocket.cxx
Go to the documentation of this file.
1
34#define SUPPORT_SL_R1_API
35
36#include "CC32xxSocket.hxx"
37#include "CC32xxWiFi.hxx"
38#include "CC32xxHelper.hxx"
39
40#include <memory>
41#include <fcntl.h>
42#include <unistd.h>
43#include <netdb.h>
44#include <netinet/in.h>
45#include <netinet/tcp.h>
46#include <ifaddrs.h>
47#include <sys/socket.h>
48
49// Simplelink includes
50#include <ti/drivers/net/wifi/simplelink.h>
51
53#include "utils/logging.h"
54
63
65static CC32xxSocket *cc32xxSockets[SL_MAX_SOCKETS];
66
68static volatile uint8_t reservedPtr;
69
71#define CC32XX_SOCKET_RESERVED ((CC32xxSocket *)(&reservedPtr))
72
73/*
74 * CC32xxSocket::socket()
75 */
76int CC32xxSocket::socket(int domain, int type, int protocol)
77{
78 int reserved = reserve_socket();
79 if (reserved < 0)
80 {
81 return -1;
82 }
83
84 mutex.lock();
85 int fd = fd_alloc();
86 mutex.unlock();
87 if (fd < 0)
88 {
89 cc32xxSockets[reserved] = nullptr;
90 errno = EMFILE;
91 return -1;
92 }
93
94 std::unique_ptr<CC32xxSocket> new_socket(new CC32xxSocket());
95 if (new_socket.get() == nullptr)
96 {
97 cc32xxSockets[reserved] = nullptr;
98 fd_free(fd);
99 errno = ENOMEM;
100 return -1;
101 }
102
103 switch (domain)
104 {
105 case AF_INET:
106 domain = SL_AF_INET;
107 break;
108 case AF_INET6:
109 domain = SL_AF_INET6;
110 break;
111 case AF_PACKET:
112 domain = SL_AF_PACKET;
113 break;
114 default:
115 cc32xxSockets[reserved] = nullptr;
116 fd_free(fd);
117 errno = EAFNOSUPPORT;
118 return -1;
119 }
120
121 switch (type)
122 {
123 case SOCK_STREAM:
124 type = SL_SOCK_STREAM;
125 break;
126 case SOCK_DGRAM:
127 type = SL_SOCK_DGRAM;
128 break;
129 case SOCK_RAW:
130 type = SL_SOCK_RAW;
131 break;
132 default:
133 cc32xxSockets[reserved] = nullptr;
134 fd_free(fd);
135 errno = EINVAL;
136 return -1;
137 }
138
139 switch (protocol)
140 {
141 case 0:
142 break;
143 case IPPROTO_TCP:
144 protocol = SL_IPPROTO_TCP;
145 break;
146 case IPPROTO_UDP:
147 protocol = SL_IPPROTO_UDP;
148 break;
149 case IPPROTO_RAW:
150 protocol = SL_IPPROTO_RAW;
151 break;
153 protocol = SL_SEC_SOCKET;
154 break;
155 default:
156 cc32xxSockets[reserved] = nullptr;
157 fd_free(fd);
158 errno = EINVAL;
159 return -1;
160 }
161
162 int result = sl_Socket(domain, type, protocol);
163
164 if (result < 0)
165 {
166 switch (result)
167 {
168 default:
169 SlCheckResult(result);
170 break;
171 case SL_ERROR_BSD_EAFNOSUPPORT:
172 errno = EAFNOSUPPORT;
173 break;
174 case SL_ERROR_BSD_EPROTOTYPE:
175 errno = EPROTOTYPE;
176 break;
177 case SL_ERROR_BSD_EACCES:
178 errno = EACCES;
179 break;
180 case SL_ERROR_BSD_ENSOCK:
181 errno = EMFILE;
182 break;
183 case SL_ERROR_BSD_ENOMEM:
184 errno = ENOMEM;
185 break;
186 case SL_ERROR_BSD_EINVAL:
187 errno = EINVAL;
188 break;
189 case SL_ERROR_BSD_EPROTONOSUPPORT:
190 errno = EPROTONOSUPPORT;
191 break;
192 case SL_ERROR_BSD_EOPNOTSUPP:
193 errno = EOPNOTSUPP;
194 break;
195 }
196
197 cc32xxSockets[reserved] = nullptr;
198 fd_free(fd);
199 return -1;
200 }
201
202
203 File *file = file_lookup(fd);
204
205 file->dev = new_socket.get();
206 file->flags = O_RDWR;
207 file->priv = new_socket.get();
208
209 new_socket->sd = result;
210 new_socket->references_ = 1;
211
212 cc32xxSockets[reserved] = new_socket.release();
213
214 return fd;
215}
216
217/*
218 * CC32xxSocket::bind()
219 */
220int CC32xxSocket::bind(int socket, const struct sockaddr *address,
221 socklen_t address_len)
222{
224 if (s == nullptr)
225 {
226 /* get_instance_from_fd() sets the errno appropriately */
227 return -1;
228 }
229
230 SlSockAddr_t sl_address;
231 sl_address.sa_family = address->sa_family;
232 memcpy(sl_address.sa_data, address->sa_data, sizeof(sl_address.sa_data));
233
234 int result = sl_Bind(s->sd, &sl_address, address_len);
235
236 if (result < 0)
237 {
238 switch (result)
239 {
240 default:
241 SlCheckResult(result);
242 break;
243 }
244 return -1;
245 }
246 return result;
247}
248
249/*
250 * CC32xxSocket::listen()
251 */
252int CC32xxSocket::listen(int socket, int backlog)
253{
255 if (s == nullptr)
256 {
257 /* get_instance_from_fd() sets the errno appropriately */
258 return -1;
259 }
260
261 int result = sl_Listen(s->sd, backlog);
262
263 if (result < 0)
264 {
265 switch (result)
266 {
267 default:
268 SlCheckResult(result);
269 break;
270 }
271 return -1;
272 }
273
274 s->readActive = false;
275 s->listenActive = true;
276 return result;
277}
278
279/*
280 * CC32xxSocket::accpet()
281 */
282int CC32xxSocket::accept(int socket, struct sockaddr *address,
283 socklen_t *address_len)
284{
286 if (s == nullptr)
287 {
288 /* get_instance_from_fd() sets the errno appropriately */
289 return -1;
290 }
291
292 if (!s->listenActive)
293 {
294 errno = EINVAL;
295 return -1;
296 }
297
298 s->readActive = false;
299
300 SlSockAddr_t sl_address;
301 SlSocklen_t sl_address_len;
302
303 int result = sl_Accept(s->sd, &sl_address, &sl_address_len);
304
305 if (address && address_len)
306 {
307 memcpy(address, &sl_address, *address_len);
308 }
309
310 if (result < 0)
311 {
312 switch (result)
313 {
314 default:
315 SlCheckResult(result);
316 break;
317 case SL_ERROR_BSD_ENSOCK:
318 errno = EMFILE;
319 break;
320 case SL_POOL_IS_EMPTY:
321 usleep(10000);
322 /* fall through */
323 case SL_ERROR_BSD_EAGAIN:
324 errno = EAGAIN;
325 break;
326 case SL_RET_CODE_STOP_IN_PROGRESS:
327 errno = ECONNABORTED;
328 break;
329 }
330 return -1;
331 }
332
333 int reserved = reserve_socket();
334 if (reserved < 0)
335 {
336 sl_Close(result);
337 return -1;
338 }
339
340 mutex.lock();
341 int fd = fd_alloc();
342 mutex.unlock();
343 if (fd < 0)
344 {
345 cc32xxSockets[reserved] = nullptr;
346 sl_Close(result);
347 errno = EMFILE;
348 return -1;
349 }
350
351 std::unique_ptr<CC32xxSocket> new_socket(new CC32xxSocket());
352 if (new_socket.get() == nullptr)
353 {
354 cc32xxSockets[reserved] = nullptr;
355 sl_Close(result);
356 fd_free(fd);
357 errno = ENOMEM;
358 return -1;
359 }
360
361 File *file = file_lookup(fd);
362
363 file->dev = new_socket.get();
364 file->flags = O_RDWR;
365 file->priv = new_socket.get();
366
367 new_socket->sd = result;
368 new_socket->references_ = 1;
369
370 cc32xxSockets[reserved] = new_socket.release();
371
372 return fd;
373}
374
375/*
376 * CC32xxSocket::connect()
377 */
378int CC32xxSocket::connect(int socket, const struct sockaddr *address,
379 socklen_t address_len)
380{
382 if (s == nullptr)
383 {
384 /* get_instance_from_fd() sets the errno appropriately */
385 return -1;
386 }
387
388 SlSockAddr_t sl_address;
389 sl_address.sa_family = address->sa_family;
390 memcpy(sl_address.sa_data, address->sa_data, sizeof(sl_address.sa_data));
391
392 int result = sl_Connect(s->sd, &sl_address, address_len);
393
394 if (result < 0)
395 {
396 switch (result)
397 {
398 default:
399 {
400 SlCheckResult(result);
401 break;
402 }
403 case SL_RET_CODE_STOP_IN_PROGRESS:
404 errno = ENETUNREACH;
405 break;
406 case SL_ERROR_BSD_EISCONN:
407 errno = EISCONN;
408 break;
409 case SL_ERROR_BSD_ECONNREFUSED:
410 errno = ECONNREFUSED;
411 break;
412 case SL_ERROR_BSD_EALREADY:
417 errno = EINPROGRESS;
418 break;
419 case SL_POOL_IS_EMPTY:
420 usleep(10000);
421 /* fall through */
422 case SL_ERROR_BSD_EAGAIN:
423 errno = EAGAIN;
424 break;
425 }
426 return -1;
427 }
428
429 return result;
430}
431
432/*
433 * CC32xxSocket::recv()
434 */
435ssize_t CC32xxSocket::recv(int socket, void *buffer, size_t length, int flags)
436{
437 /* flags are not supported on the CC32xx */
438 HASSERT(flags == 0);
439
441 if (s == nullptr)
442 {
443 /* get_instance_from_fd() sets the errno appropriately */
444 return -1;
445 }
446
447 int result = sl_Recv(s->sd, buffer, length, flags);
448
449 if (result < 0)
450 {
451 switch (result)
452 {
453 default:
454 SlCheckResult(result);
455 break;
456 case SL_POOL_IS_EMPTY:
457 usleep(10000);
458 /* fall through */
459 case SL_ERROR_BSD_EAGAIN:
460 errno = EAGAIN;
461 s->readActive = false;
462 break;
463 case SL_ERROR_BSD_ECONNREFUSED:
464 s->readActive = true;
465 return 0;
466 case SL_ERROR_BSD_EBADF:
467 errno = EBADF;
468 break;
469 case SL_RET_CODE_STOP_IN_PROGRESS:
470 errno = ECONNRESET;
471 break;
472 }
473 return -1;
474 }
475
476 return result;
477}
478
479/*
480 * CC32xxSocket::send()
481 */
482ssize_t CC32xxSocket::send(int socket, const void *buffer, size_t length, int flags)
483{
484 /* flags are not supported on the CC32xx */
485 HASSERT(flags == 0);
486
488 if (s == nullptr)
489 {
490 /* get_instance_from_fd() sets the errno appropriately */
491 return -1;
492 }
493
494 if (s->writeActive == false)
495 {
496 /* typically we would never get here as callers usually go to select()
497 * before attempting a send again. */
498 HASSERT(s->mode_ & O_NONBLOCK);
499 errno = EAGAIN;
500 return -1;
501 }
502
503 int result = sl_Send(s->sd, buffer, length, flags);
504
505 if (result < 0)
506 {
507 LOG_ERROR("sl socket write return error %d", result);
508 switch (result)
509 {
510 case SL_ERROR_BSD_SOC_ERROR:
512 errno = ECONNRESET;
513 break;
514 case SL_ERROR_BSD_EAGAIN:
515 errno = EAGAIN;
516 s->writeActive = false;
517 break;
518 case SL_ERROR_BSD_EBADF:
519 errno = EBADF;
520 break;
521 default:
523 SlCheckResult(result);
524 break;
525 }
526 return -1;
527 }
528
529 return result;
530}
531
532/*
533 * CC32xxSocket::setsockopt()
534 */
535int CC32xxSocket::setsockopt(int socket, int level, int option_name,
536 const void *option_value, socklen_t option_len)
537{
539 if (s == nullptr)
540 {
541 /* get_instance_from_fd() sets the errno appropriately */
542 return -1;
543 }
544
545 int result;
546
547 switch (level)
548 {
549 default:
550 errno = EINVAL;
551 return -1;
552 case SOL_SOCKET:
553 switch (option_name)
554 {
555 default:
556 errno = EINVAL;
557 return -1;
558 case SO_REUSEADDR:
559 /* CC32xx does not care about SO_REUSEADDR, ignore it */
560 result = 0;
561 break;
562 case SO_RCVTIMEO:
563 {
564 const struct timeval *tm;
565 struct SlTimeval_t timeval;
566
567 tm = static_cast<const struct timeval *>(option_value);
568 timeval.tv_sec = tm->tv_sec;
569 timeval.tv_usec = tm->tv_usec;
570 result = sl_SetSockOpt(s->sd, SL_SOL_SOCKET,
571 SL_SO_RCVTIMEO, &timeval,
572 sizeof(timeval));
573 break;
574 }
575 case SO_RCVBUF:
576 {
577 SlSocklen_t sl_option_len = option_len;
578
579 result = sl_SetSockOpt(s->sd, SL_SOL_SOCKET, SL_SO_RCVBUF,
580 option_value, sl_option_len);
581 break;
582 }
583 case SO_KEEPALIVETIME:
584 {
585 SlSocklen_t sl_option_len = option_len;
586
587 result = sl_SetSockOpt(s->sd, SL_SOL_SOCKET,
588 SL_SO_KEEPALIVETIME, option_value, sl_option_len);
589 break;
590 }
591 }
592 break;
593 case IPPROTO_TCP:
594 switch (option_name)
595 {
596 default:
597 errno = EINVAL;
598 return -1;
599 case TCP_NODELAY:
600 /* CC32xx does not care about Nagle algorithm, ignore it */
601 result = 0;
602 break;
603 }
604 break;
605 }
606
607 if (result < 0)
608 {
609 switch (result)
610 {
611 default:
612 SlCheckResult(result);
613 break;
614 }
615 return -1;
616 }
617
618 return result;
619}
620
621/*
622 * CC32xxSocket::getsockopt()
623 */
624int CC32xxSocket::getsockopt(int socket, int level, int option_name,
625 void *option_value, socklen_t *option_len)
626{
628 if (s == nullptr)
629 {
630 /* get_instance_from_fd() sets the errno appropriately */
631 return -1;
632 }
633
634 int result;
635
636 switch (level)
637 {
638 default:
639 errno = EINVAL;
640 return -1;
641 case SOL_SOCKET:
642 switch (option_name)
643 {
644 default:
645 errno = EINVAL;
646 return -1;
647 case SO_REUSEADDR:
648 {
649 /* CC32xx does not care about SO_REUSEADDR,
650 * we assume it is on by default
651 */
652 int *so_reuseaddr = static_cast<int *>(option_value);
653 *so_reuseaddr = 1;
654 *option_len = sizeof(int);
655 result = 0;
656 break;
657 }
658 case SO_RCVTIMEO:
659 {
660 struct timeval *tm;
661 struct SlTimeval_t timeval;
662 SlSocklen_t sl_option_len = sizeof(timeval);
663
664 tm = static_cast<struct timeval *>(option_value);
665 result = sl_GetSockOpt(s->sd, SL_SOL_SOCKET,
666 SL_SO_RCVTIMEO, &timeval,
667 &sl_option_len);
668 tm->tv_sec = timeval.tv_sec;
669 tm->tv_usec = timeval.tv_usec;
670 *option_len = sizeof(struct timeval);
671 break;
672 }
673 case SO_RCVBUF:
674 {
675 SlSocklen_t sl_option_len = *option_len;
676
677 result = sl_GetSockOpt(s->sd, SL_SOL_SOCKET, SL_SO_RCVBUF,
678 option_value, &sl_option_len);
679 *option_len = sl_option_len;
680 break;
681 }
682 case SO_KEEPALIVETIME:
683 {
684 SlSocklen_t sl_option_len = *option_len;
685
686 result = sl_GetSockOpt(s->sd, SL_SOL_SOCKET,
687 SL_SO_KEEPALIVETIME, option_value, &sl_option_len);
688 *option_len = sl_option_len;
689 break;
690 }
691 }
692 break;
693 case IPPROTO_TCP:
694 switch (option_name)
695 {
696 default:
697 errno = EINVAL;
698 return -1;
699 case TCP_NODELAY:
700 {
701 /* CC32xx does not care about Nagel algorithm,
702 * we assume it is off by default
703 */
704 int *tcp_nodelay = static_cast<int *>(option_value);
705 *tcp_nodelay = 1;
706 *option_len = sizeof(int);
707 result = 0;
708 break;
709 }
710 }
711 break;
713 switch (option_name)
714 {
715 default:
716 errno = EINVAL;
717 return -1;
719 int *opt_sd = static_cast<int *>(option_value);
720 *opt_sd = s->sd;
721 *option_len = sizeof(int);
722 result = 0;
723 break;
724 }
725 }
726
727 if (result < 0)
728 {
729 switch (result)
730 {
731 default:
732 SlCheckResult(result);
733 break;
734 }
735 return -1;
736 }
737
738 return result;
739}
740
741/*
742 * CC32xxSocket::close()
743 */
745{
746 CC32xxSocket *s = static_cast<CC32xxSocket *>(file->priv);
747
748 mutex.lock();
749 if (--references_ == 0)
750 {
751 mutex.unlock();
752 /* request that the socket be removed from managment */
753 int16_t sd = s->sd;
755 portENTER_CRITICAL();
757 portEXIT_CRITICAL();
758 sl_Close(sd);
759 delete this;
760 }
761 else
762 {
763 mutex.unlock();
764 }
765
766 return 0;
767}
768
775bool CC32xxSocket::select(File* file, int mode)
776{
777 CC32xxSocket *s = static_cast<CC32xxSocket *>(file->priv);
778 bool retval = false;
779
780 switch (mode)
781 {
782 case FREAD:
783 portENTER_CRITICAL();
784 if (readActive)
785 {
786 retval = true;
787 portEXIT_CRITICAL();
788 }
789 else
790 {
792 portEXIT_CRITICAL();
794 }
795 break;
796 case FWRITE:
797 portENTER_CRITICAL();
798 HASSERT(listenActive == false);
799 if (writeActive)
800 {
801 retval = true;
802 portEXIT_CRITICAL();
803 }
804 else
805 {
807 portEXIT_CRITICAL();
809 }
810 break;
811 default:
812 case 0:
813 /* we don't support any exceptions */
814 break;
815 }
816 return retval;
817}
818
819/*
820 * CC32xxSocket::get_instance_from_sd()
821 */
823{
824 for (int i = 0; i < SL_MAX_SOCKETS; ++i)
825 {
826 if (cc32xxSockets[i] != nullptr &&
828 {
829 if (sd == cc32xxSockets[i]->sd)
830 {
831 return cc32xxSockets[i];
832 }
833 }
834 }
835 return nullptr;
836}
837
838/*
839 * CC32xxSocket::get_instance_from_fd(int fd)
840 */
842{
843 File* f = file_lookup(fd);
844 if (!f)
845 {
846 errno = EBADF;
847 return nullptr;
848 }
849
850 struct stat stat;
851 ::fstat(fd, &stat);
852
853 if (!S_ISSOCK(stat.st_mode))
854 {
855 errno = ENOTSOCK;
856 return nullptr;
857 }
858
859 return static_cast<CC32xxSocket *>(f->priv);
860}
861
862/*
863 * CC32xxSocket::remove_instance_from_sd()
864 */
866{
867 for (int i = 0; i < SL_MAX_SOCKETS; ++i)
868 {
869 if (cc32xxSockets[i] != nullptr &&
871 {
872 if (sd == cc32xxSockets[i]->sd)
873 {
874 cc32xxSockets[i] = nullptr;
875 break;
876 }
877 }
878 }
879}
880
881/*
882 * CC32xxSocket::reserve_socket()
883 */
885{
886 int i;
887 portENTER_CRITICAL();
888 for (i = 0; i < SL_MAX_SOCKETS; ++i)
889 {
890 if (cc32xxSockets[i] == nullptr)
891 {
892 /* mark the socket reserved */
894 break;
895 }
896 }
897 portEXIT_CRITICAL();
898 if (i == SL_MAX_SOCKETS)
899 {
900 /* out of free sockets */
901 errno = EMFILE;
902 return -1;
903 }
904
905 return i;
906}
907
908/*
909 * CC32xxSocket::fcntl()
910 */
911int CC32xxSocket::fcntl(File *file, int cmd, unsigned long data)
912{
913 CC32xxSocket *s = static_cast<CC32xxSocket *>(file->priv);
914 if (!S_ISSOCK(s->mode_))
915 {
916 return -ENOTSOCK;
917 }
918
919 switch (cmd)
920 {
921 default:
922 {
923 return -EINVAL;
924 }
925 case F_SETFL:
926 {
927 SlSockNonblocking_t sl_option_value;
928 sl_option_value.NonBlockingEnabled = data & O_NONBLOCK ? 1 : 0;
929 int result = sl_SetSockOpt(s->sd, SL_SOL_SOCKET,
930 SL_SO_NONBLOCKING, &sl_option_value,
931 sizeof(sl_option_value));
932 SlCheckResult(result, 0);
933 if (data & O_NONBLOCK)
934 {
935 mode_ |= O_NONBLOCK;
936 }
937 else
938 {
939 mode_ &= ~O_NONBLOCK;
940 }
941 return 0;
942 }
943 }
944}
945
946extern "C"
947{
960int socket(int domain, int type, int protocol)
961{
962 return CC32xxSocket::socket(domain, type, protocol);
963}
964
974int bind(int socket, const struct sockaddr *address, socklen_t address_len)
975{
976 return CC32xxSocket::bind(socket, address, address_len);
977}
978
988int listen(int socket, int backlog)
989{
990 return CC32xxSocket::listen(socket, backlog);
991}
992
1007int accept(int socket, struct sockaddr *address, socklen_t *address_len)
1008{
1009 return CC32xxSocket::accept(socket, address, address_len);
1010}
1011
1020int connect(int socket, const struct sockaddr *address, socklen_t address_len)
1021{
1022 return CC32xxSocket::connect(socket, address, address_len);
1023}
1024
1036ssize_t recv(int socket, void *buffer, size_t length, int flags)
1037{
1038 return CC32xxSocket::recv(socket, buffer, length, flags);
1039}
1040
1049ssize_t send(int socket, const void *buffer, size_t length, int flags)
1050{
1051 return CC32xxSocket::send(socket, buffer, length, flags);
1052}
1053
1064int setsockopt(int socket, int level, int option_name,
1065 const void *option_value, socklen_t option_len)
1066{
1067 return CC32xxSocket::setsockopt(socket, level, option_name,
1068 option_value, option_len);
1069}
1070
1081int getsockopt(int socket, int level, int option_name,
1082 void *option_value, socklen_t *option_len)
1083{
1084 return CC32xxSocket::getsockopt(socket, level, option_name,
1085 option_value, option_len);
1086}
1087
1093const char *gai_strerror (int __ecode)
1094{
1095 switch (__ecode)
1096 {
1097 default:
1098 return "gai_strerror unkown";
1099 case EAI_AGAIN:
1100 return "temporary failure";
1101 case EAI_FAIL:
1102 return "non-recoverable failure";
1103 case EAI_MEMORY:
1104 return "memory allocation failure";
1105 }
1106}
1107
1112void freeaddrinfo(struct addrinfo *ai)
1113{
1114 delete ai->ai_addr;
1115 if (ai->ai_canonname)
1116 {
1117 delete ai->ai_canonname;
1118 }
1119 delete ai;
1120}
1121
1131int getaddrinfo(const char *nodename, const char *servname,
1132 const struct addrinfo *hints,
1133 struct addrinfo **res)
1134{
1135 uint32_t ip_addr[4];
1136 uint32_t port;
1137 uint8_t domain;
1138 int8_t text[120];
1139 uint16_t text_len = 120;
1140
1141 std::unique_ptr<struct addrinfo> ai(new struct addrinfo);
1142 if (ai.get() == nullptr)
1143 {
1144 return EAI_MEMORY;
1145 }
1146 memset(ai.get(), 0, sizeof(struct addrinfo));
1147
1148 std::unique_ptr<struct sockaddr> sa(new struct sockaddr);
1149 if (sa.get() == nullptr)
1150 {
1151 return EAI_MEMORY;
1152 }
1153 memset(sa.get(), 0, sizeof(struct sockaddr));
1154
1155 switch (hints->ai_family)
1156 {
1157 case AF_INET:
1158 domain = SL_AF_INET;
1159 break;
1160 case AF_INET6:
1161 domain = SL_AF_INET6;
1162 break;
1163 case AF_PACKET:
1164 domain = SL_AF_PACKET;
1165 break;
1166 default:
1167 errno = EAFNOSUPPORT;
1168 return -1;
1169 }
1170
1171 int result;
1172
1173 if (nodename)
1174 {
1175 result = sl_NetAppDnsGetHostByName((int8_t*)nodename, strlen(nodename),
1176 ip_addr, domain);
1177 }
1178 else
1179 {
1180 result = sl_NetAppDnsGetHostByService((int8_t*)servname,
1181 strlen(servname), domain, ip_addr,
1182 &port, &text_len, text);
1183 }
1184
1185 if (result != 0)
1186 {
1187 switch (result)
1188 {
1189 default:
1190 case SL_POOL_IS_EMPTY:
1191 return EAI_AGAIN;
1192 case SL_ERROR_NET_APP_DNS_QUERY_NO_RESPONSE:
1193 case SL_ERROR_NET_APP_DNS_NO_SERVER:
1194 case SL_ERROR_NET_APP_DNS_QUERY_FAILED:
1195 case SL_ERROR_NET_APP_DNS_MALFORMED_PACKET:
1196 case SL_ERROR_NET_APP_DNS_MISMATCHED_RESPONSE:
1197 return EAI_FAIL;
1198 }
1199 }
1200
1201 switch (hints->ai_family)
1202 {
1203 case AF_INET:
1204 {
1205 struct sockaddr_in *sa_in = (struct sockaddr_in*)sa.get();
1206 ai->ai_flags = 0;
1207 ai->ai_family = hints->ai_family;
1208 ai->ai_socktype = hints->ai_socktype;
1209 ai->ai_protocol = hints->ai_protocol;
1210 ai->ai_addrlen = sizeof(struct sockaddr_in);
1211 sa_in->sin_family = hints->ai_family;
1212 long port_name = strtol(servname, nullptr, 0);
1213 /* the newlib implementation of strtol does not properly implement
1214 * errno == EINVAL. We would normally want the if statement to be:
1215 * if (port_name == 0 && errno == EINVAL)
1216 */
1217 if (port_name == 0 && (servname[0] < '0' || servname[0] > '9') &&
1218 servname[0] != '+' && servname[0] != '-')
1219 {
1220 sa_in->sin_port = htons((uint16_t)port);
1221 }
1222 else
1223 {
1224 sa_in->sin_port = htons((uint16_t)port_name);
1225 }
1226 sa_in->sin_addr.s_addr = htonl(ip_addr[0]);
1227 break;
1228 }
1229 case AF_INET6:
1230 case AF_PACKET:
1231 default:
1232 errno = EAFNOSUPPORT;
1233 return -1;
1234 }
1235
1236 *res = ai.release();
1237 (*res)->ai_addr = sa.release();
1238 return 0;
1239}
1240
1241/*
1242 * ::inet_ntop()
1243 */
1244const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
1245{
1246 char *org = dst;
1247
1248 switch (af)
1249 {
1250 default:
1251 errno = EAFNOSUPPORT;
1252 return nullptr;
1253 case AF_INET6:
1254 HASSERT(0);
1255 case AF_INET:
1256 {
1257 socklen_t count = 0;
1258 uint8_t *ip = (uint8_t*)src;
1259 for (int i = 0; i < 4; ++i)
1260 {
1261 char string[5];
1262 char *end = integer_to_buffer(ip[i], string);
1263 count += (end - string) + 1;
1264 if (count > size)
1265 {
1266 errno = ENOSPC;
1267 return nullptr;
1268 }
1269 strcpy(dst, string);
1270 dst += (end - string);
1271 *dst++ = '.';
1272 }
1273 *--dst = '\0';
1274 break;
1275 }
1276 }
1277
1278 return org;
1279}
1280
1281/*
1282 * ::getifaddrs()
1283 */
1284int getifaddrs(struct ifaddrs **ifap)
1285{
1286 /* start with something "safe" in case we bail out early */
1287 *ifap = nullptr;
1288
1289 /* allocate all the structure memory */
1290 std::unique_ptr<struct ifaddrs> ia(new struct ifaddrs);
1291 if (ia.get() == nullptr)
1292 {
1293 errno = ENOMEM;
1294 return -1;
1295 }
1296 memset(ia.get(), 0, sizeof(struct ifaddrs));
1297
1298 std::unique_ptr<char[]> ifa_name(new char[6]);
1299 if (ifa_name.get() == nullptr)
1300 {
1301 errno = ENOMEM;
1302 return -1;
1303 }
1304
1305 std::unique_ptr<struct sockaddr> ifa_addr(new struct sockaddr);
1306 if (ifa_addr == nullptr)
1307 {
1308 errno = ENOMEM;
1309 return -1;
1310 }
1311 memset(ifa_addr.get(), 0, sizeof(struct sockaddr));
1312
1314#if 0
1315 std::unique_ptr<struct sockaddr> ifa_netmask(new struct sockaddr);
1316 if (ifa_netmask == nullptr)
1317 {
1318 errno = ENOMEM;
1319 return -1;
1320 }
1321 memset(ifa_netmask.get(), 0, sizeof(struct sockaddr));
1322
1323 std::unique_ptr<struct sockaddr> ifa_broadaddr(new struct sockaddr);
1324 if (ifa_broadaddr == nullptr)
1325 {
1326 errno = ENOMEM;
1327 return -1;
1328 }
1329 memset(ifa_broadaddr.get(), 0, sizeof(struct sockaddr));
1330#endif
1331
1332 /* setup interface address data */
1333 strcpy(ifa_name.get(), "wlan0");
1334
1335 struct sockaddr_in *addr_in = (struct sockaddr_in*)ifa_addr.get();
1336 addr_in->sin_family = AF_INET;
1337 addr_in->sin_addr.s_addr = htonl(CC32xxWiFi::instance()->wlan_ip());
1338
1339 /* build up meta structure */
1340 ia.get()->ifa_next = nullptr;
1341 ia.get()->ifa_name = ifa_name.release();
1342 ia.get()->ifa_flags = 0;
1343 ia.get()->ifa_addr = ifa_addr.release();
1344 ia.get()->ifa_netmask = nullptr;
1345 ia.get()->ifa_ifu.ifu_broadaddr = nullptr;
1346 ia.get()->ifa_data = nullptr;
1347
1348 /* report results */
1349 *ifap = ia.release();
1350 return 0;
1351}
1352
1353/*
1354 * ::getifaddrs()
1355 */
1356void freeifaddrs(struct ifaddrs *ifa)
1357{
1358 while (ifa)
1359 {
1360 struct ifaddrs *next = ifa->ifa_next;
1361
1362 HASSERT(ifa->ifa_data == nullptr);
1363 HASSERT(ifa->ifa_ifu.ifu_broadaddr == nullptr);
1364 HASSERT(ifa->ifa_netmask == nullptr);
1365
1366 if (ifa->ifa_addr)
1367 {
1368 delete ifa->ifa_addr;
1369 }
1370 if (ifa->ifa_name)
1371 {
1372 delete[] ifa->ifa_name;
1373 }
1374 delete ifa;
1375
1376 ifa = next;
1377 }
1378}
1379
1380} /* extern "C" */
void SlCheckResult(int result, int expected)
Tests that a SimpleLink request has succeeded.
Socket implementation for the CC32xx class WiFi devices.
int16_t sd
CC32xx socket descriptor.
static int reserve_socket()
Reserve a location in the cc32xxSockets pool.
bool select(File *file, int mode) override
Device select method.
static CC32xxSocket * get_instance_from_fd(int fd)
Get the CC32xxSocket instance given a file descriptor.
static int connect(int socket, const struct sockaddr *address, socklen_t address_len)
Connect a socket.
uint8_t readActive
indicates our "best guess" at current socket's read active status
static int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len)
Set the socket options.
static int getsockopt(int socket, int level, int option_name, void *option_value, socklen_t *option_len)
Get the socket options.
uint8_t listenActive
This is a listen socket.
int fcntl(File *file, int cmd, unsigned long data) override
Manipulate a file descriptor.
static int bind(int socket, const struct sockaddr *address, socklen_t address_len)
Bind a name to a socket.
static CC32xxSocket * get_instance_from_sd(int sd)
Get the CC32xxSocket instance given a specific CC32xx socket descriptor.
static int listen(int socket, int backlog)
Mark a connection-mode socket, specified by the socket argument, as accepting connections.
static void remove_instance_from_sd(int sd)
Remove the CC32xxSocket instance from the active CC32xxSocket list.
static int socket(int domain, int type, int protocol)
Create an unbound socket in a communications domain.
int close(File *file) override
Close method.
static int accept(int socket, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
static ssize_t send(int socket, const void *buffer, size_t length, int flags)
Initiate transmission of a message from the specified socket.
uint8_t writeActive
indicates our "best guess" at current socket's write active status
static ssize_t recv(int socket, void *buffer, size_t length, int flags)
Receive a message from a connection-mode or connectionless-mode socket.
void fd_remove(int16_t sd)
Remove a socket from the known sockets that might be part of the sl_Select fdset.
void fd_set_read(int16_t sd)
Add socket to the read fd set.
void fd_set_write(int16_t sd)
Add socket to the write fd set.
static constexpr unsigned IPPROTO_TCP_TLS
Pass this option as protocol to socket to create a secure socket.
static constexpr unsigned SO_SIMPLELINK_SD
Retrieves the socket descriptor for setting TLS parameters.
static void fd_free(int fd)
Free up a file descriptor.
Definition Fileio.cxx:71
static File * file_lookup(int fd)
Looks up a reference to a File corresponding to a given file descriptor.
Definition Fileio.cxx:82
static int fd_alloc(void)
Allocate a free file descriptor.
Definition Fileio.cxx:47
static OSMutex mutex
mutual exclusion for fileio
Definition Devtab.hxx:264
virtual int fstat(File *file, struct stat *stat) override
Get the status information of a file or device.
unsigned int references_
number of open references
Definition Devtab.hxx:592
mode_t mode_
File open mode, such as O_NONBLOCK.
Definition Devtab.hxx:590
void lock()
Lock a mutex.
Definition OS.hxx:446
void unlock()
Unlock a mutex.
Definition OS.hxx:453
static CC32xxWiFi * instance()
Definition Singleton.hxx:77
SelectInfo selInfoRd
select wakeup metadata for read active
Definition Socket.hxx:79
SelectInfo selInfoWr
select wakeup metadata for write active
Definition Socket.hxx:80
#define FWRITE
Workaround for missing header defines on some newlib versions.
Definition fcntl.h:58
#define FREAD
Workaround for missing header defines on some newlib versions.
Definition fcntl.h:53
#define IPPROTO_RAW
Raw Socket.
Definition in.h:76
#define htons(x)
Converts a host endian short value to network endian.
Definition in.h:93
#define IPPROTO_TCP
TCP Raw Socket.
Definition in.h:70
#define IPPROTO_UDP
UDP Raw Socket.
Definition in.h:73
#define htonl(x)
Converts a host endian long value to network endian.
Definition in.h:91
#define LOG_ERROR(message...)
Shorthand for LOG(LEVEL_ERROR, message...). See LOG.
Definition logging.h:124
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
ssize_t recv(int socket, void *buffer, size_t length, int flags)
Receive a message from a connection-mode or connectionless-mode socket.
int accept(int socket, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len)
Set the socket options.
int bind(int socket, const struct sockaddr *address, socklen_t address_len)
Bind a name to a socket.
void freeaddrinfo(struct addrinfo *ai)
see 'man freeaddrinfo'
ssize_t send(int socket, const void *buffer, size_t length, int flags)
Initiate transmission of a message from the specified socket.
#define CC32XX_SOCKET_RESERVED
Guard value indivating a reserved socket that is currently being allocated.
const char * gai_strerror(int __ecode)
see 'man gai_strerror'
int getifaddrs(struct ifaddrs **ifap)
Create a linked list of structures describing the network interfaces of the local system.
int getsockopt(int socket, int level, int option_name, void *option_value, socklen_t *option_len)
Get the socket options.
int listen(int socket, int backlog)
Mark a connection-mode socket, specified by the socket argument, as accepting connections.
int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
see 'man getaddrinfo'
const char * inet_ntop(int af, const void *src, char *dst, socklen_t size)
Convert the network address in src to a character string in src.
static volatile uint8_t reservedPtr
Dummy pointer address that can be used as a reserved indicator.
static CC32xxSocket * cc32xxSockets[SL_MAX_SOCKETS]
Existing (allocated) sockets.
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
Connect a socket.
void freeifaddrs(struct ifaddrs *ifa)
Free a previously generated linked list of structures describing the network interfaces of the local ...
int socket(int domain, int type, int protocol)
Create an unbound socket in a communications domain.
#define EAI_MEMORY
Memory allocation failure.
Definition netdb.h:69
#define EAI_AGAIN
Temporary failure in name resolution.
Definition netdb.h:67
#define EAI_FAIL
, Non-recoverable failure in name res
Definition netdb.h:68
#define SO_RCVBUF
socket option for receive buffer size
Definition socket.h:76
#define SOCK_STREAM
TCP Socket.
Definition socket.h:45
#define SOCK_RAW
Raw Socket.
Definition socket.h:51
uint32_t socklen_t
type of sockaddr lenth
Definition socket.h:89
#define SO_KEEPALIVETIME
socket option to set TCP keepalive timeout
Definition socket.h:79
#define SOCK_DGRAM
UDP Socket.
Definition socket.h:48
#define SO_REUSEADDR
socket option to reuse address
Definition socket.h:67
#define SOL_SOCKET
socket option category
Definition socket.h:64
#define AF_INET
IPv4 Socket (UDP, TCP, etc...)
Definition socket.h:54
#define AF_INET6
IPv6 Socket (UDP, TCP, etc...)
Definition socket.h:57
#define SO_RCVTIMEO
socket option receive timout
Definition socket.h:70
static void select_insert(SelectInfo *info)
Add client to list of clients needing woken.
Definition Select.cxx:197
static int stat(struct _reent *reent, const char *path, struct stat *stat)
Get the status information of a file or device.
Definition Device.cxx:165
File information.
Definition Devtab.hxx:52
int flags
open flags
Definition Devtab.hxx:63
void * priv
file reference specific data "pointer"
Definition Devtab.hxx:57
FileIO * dev
file operations
Definition Devtab.hxx:53
Structure to contain information about address of a service provider.
Definition netdb.h:48
struct sockaddr * ai_addr
Socket address for socket.
Definition netdb.h:54
char * ai_canonname
Canonical name for service location.
Definition netdb.h:55
int ai_socktype
Socket type.
Definition netdb.h:51
int ai_protocol
Protocol for socket.
Definition netdb.h:52
int ai_family
Protocol family for socket.
Definition netdb.h:50
network interface address list member
char * ifa_name
name of interface.
struct sockaddr * ifa_netmask
netmask of interface
void * ifa_data
address-specific data
struct ifaddrs * ifa_next
next item in list
struct sockaddr * ifu_broadaddr
broadcast address of interface
struct sockaddr * ifa_addr
address of interface
in_addr_t s_addr
Address.
Definition in.h:51
Structure describing an Internet socket address.
Definition in.h:56
uint16_t sin_family
protocol family (AF_INET)
Definition in.h:57
uint16_t sin_port
port number
Definition in.h:58
struct in_addr sin_addr
internet address
Definition in.h:59
IPv4 socket address.
Definition socket.h:83
uint16_t sa_family
address family (e.g.
Definition socket.h:84
uint8_t sa_data[14]
protocol specific address information
Definition socket.h:85
#define TCP_NODELAY
don't delay send to coalesce packets
Definition tcp.h:42