source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/adapters/socketio_lwip.c@ 473

Last change on this file since 473 was 473, checked in by coas-nagasima, 3 years ago

lwipとESP ATの両方使えるよう変更

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 38.8 KB
RevLine 
[457]1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#ifndef _BSD_SOURCE
5#define _BSD_SOURCE
6#define SOCKETIO_BERKELEY_UNDEF_BSD_SOURCE
7#endif
8
9#define _DEFAULT_SOURCE
10#include <net/if.h>
11#undef _DEFAULT_SOURCE
12
13#ifdef SOCKETIO_BERKELEY_UNDEF_BSD_SOURCE
14#undef _BSD_SOURCE
15#undef SOCKETIO_BERKELEY_UNDEF_BSD_SOURCE
16#endif
17
[468]18#ifndef MSG_NOSIGNAL
19#define MSG_NOSIGNAL 0
20#endif
21
[457]22#include <signal.h>
23#include <stdlib.h>
24#include <stddef.h>
25#include <stdio.h>
26#include <string.h>
27#include <ctype.h>
28#include "azure_c_shared_utility/socketio.h"
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/select.h>
32#ifdef TIZENRT
33#include <net/lwip/tcp.h>
34#else
35#include <lwip/tcp.h>
36#endif
37#include <netdb.h>
38#include <unistd.h>
[468]39//#include <fcntl.h>
[457]40#include <errno.h>
41#include "azure_c_shared_utility/singlylinkedlist.h"
42#include "azure_c_shared_utility/gballoc.h"
43#include "azure_c_shared_utility/gbnetwork.h"
44#include "azure_c_shared_utility/optimize_size.h"
45#include "azure_c_shared_utility/optionhandler.h"
46#include "azure_c_shared_utility/shared_util_options.h"
47#include "azure_c_shared_utility/xlogging.h"
48#include "azure_c_shared_utility/const_defines.h"
49#include "azure_c_shared_utility/dns_resolver.h"
50//#include <sys/ioctl.h>
51//#include <netinet/in.h>
52//#include <arpa/inet.h>
53//#include <sys/un.h>
54
55#define SOCKET_SUCCESS 0
56#define INVALID_SOCKET -1
57#define SOCKET_SEND_FAILURE -1
58#define MAC_ADDRESS_STRING_LENGTH 18
59
60#ifndef IFREQ_BUFFER_SIZE
61#define IFREQ_BUFFER_SIZE 1024
62#endif
63
64// connect timeout in seconds
65#define CONNECT_TIMEOUT 10
66
67typedef enum IO_STATE_TAG
68{
69 IO_STATE_CLOSED,
70 IO_STATE_OPENING,
71 IO_STATE_OPEN,
72 IO_STATE_CLOSING,
73 IO_STATE_ERROR
74} IO_STATE;
75
76typedef struct PENDING_SOCKET_IO_TAG
77{
78 unsigned char* bytes;
79 size_t size;
80 ON_SEND_COMPLETE on_send_complete;
81 void* callback_context;
82 SINGLYLINKEDLIST_HANDLE pending_io_list;
83} PENDING_SOCKET_IO;
84
85typedef struct SOCKET_IO_INSTANCE_TAG
86{
87 int socket;
88 SOCKETIO_ADDRESS_TYPE address_type;
89 ON_BYTES_RECEIVED on_bytes_received;
90 ON_IO_ERROR on_io_error;
91 ON_IO_OPEN_COMPLETE on_io_open_complete;
92 void* on_bytes_received_context;
93 void* on_io_error_context;
94 void* on_io_open_complete_context;
95 char* hostname;
96 int port;
97 char* target_mac_address;
98 IO_STATE io_state;
99 SINGLYLINKEDLIST_HANDLE pending_io_list;
[468]100 unsigned char recv_bytes[XIO_RECEIVE_BUFFER_SIZE];
[457]101 DNSRESOLVER_HANDLE dns_resolver;
102} SOCKET_IO_INSTANCE;
103
104typedef struct NETWORK_INTERFACE_DESCRIPTION_TAG
105{
106 char* name;
107 char* mac_address;
108 char* ip_address;
109 struct NETWORK_INTERFACE_DESCRIPTION_TAG* next;
110} NETWORK_INTERFACE_DESCRIPTION;
111
112/*this function will clone an option given by name and value*/
[473]113static void* socketio_lwip_CloneOption(const char* name, const void* value)
[457]114{
115 void* result;
116
117 if (name != NULL)
118 {
119 result = NULL;
120
121 if (strcmp(name, OPTION_NET_INT_MAC_ADDRESS) == 0)
122 {
123 if (value == NULL)
124 {
125 LogError("Failed cloning option %s (value is NULL)", name);
126 }
127 else
128 {
129 if ((result = malloc(sizeof(char) * (strlen((char*)value) + 1))) == NULL)
130 {
131 LogError("Failed cloning option %s (malloc failed)", name);
132 }
133 else if (strcpy((char*)result, (char*)value) == NULL)
134 {
135 LogError("Failed cloning option %s (strcpy failed)", name);
136 free(result);
137 result = NULL;
138 }
139 }
140 }
141 else
142 {
143 LogError("Cannot clone option %s (not suppported)", name);
144 }
145 }
146 else
147 {
148 result = NULL;
149 }
150 return result;
151}
152
153/*this function destroys an option previously created*/
[473]154static void socketio_lwip_DestroyOption(const char* name, const void* value)
[457]155{
156 if (name != NULL)
157 {
158 if (strcmp(name, OPTION_NET_INT_MAC_ADDRESS) == 0 && value != NULL)
159 {
160 free((void*)value);
161 }
162 }
163}
164
[473]165CONCRETE_IO_HANDLE socketio_lwip_create(void* io_create_parameters);
166void socketio_lwip_destroy(CONCRETE_IO_HANDLE socket_io);
167int socketio_lwip_open(CONCRETE_IO_HANDLE socket_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context);
168int socketio_lwip_close(CONCRETE_IO_HANDLE socket_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context);
169int socketio_lwip_send(CONCRETE_IO_HANDLE socket_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context);
170void socketio_lwip_dowork(CONCRETE_IO_HANDLE socket_io);
171int socketio_lwip_setoption(CONCRETE_IO_HANDLE socket_io, const char* optionName, const void* value);
172
173static OPTIONHANDLER_HANDLE socketio_lwip_retrieveoptions(CONCRETE_IO_HANDLE handle)
[457]174{
175 OPTIONHANDLER_HANDLE result;
176
177 if (handle == NULL)
178 {
179 LogError("failed retrieving options (handle is NULL)");
180 result = NULL;
181 }
182 else
183 {
184 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)handle;
185
[473]186 result = OptionHandler_Create(socketio_lwip_CloneOption, socketio_lwip_DestroyOption, socketio_lwip_setoption);
[457]187 if (result == NULL)
188 {
189 LogError("unable to OptionHandler_Create");
190 }
191 else if (socket_io_instance->target_mac_address != NULL &&
192 OptionHandler_AddOption(result, OPTION_NET_INT_MAC_ADDRESS, socket_io_instance->target_mac_address) != OPTIONHANDLER_OK)
193 {
194 LogError("failed retrieving options (failed adding net_interface_mac_address)");
195 OptionHandler_Destroy(result);
196 result = NULL;
197 }
198 }
199
200 return result;
201}
202
203static const IO_INTERFACE_DESCRIPTION socket_io_interface_description =
204{
[473]205 socketio_lwip_retrieveoptions,
206 socketio_lwip_create,
207 socketio_lwip_destroy,
208 socketio_lwip_open,
209 socketio_lwip_close,
210 socketio_lwip_send,
211 socketio_lwip_dowork,
212 socketio_lwip_setoption
[457]213};
214
215static void indicate_error(SOCKET_IO_INSTANCE* socket_io_instance)
216{
217 socket_io_instance->io_state = IO_STATE_ERROR;
218 if (socket_io_instance->on_io_error != NULL)
219 {
220 socket_io_instance->on_io_error(socket_io_instance->on_io_error_context);
221 }
222}
223
224static int add_pending_io(SOCKET_IO_INSTANCE* socket_io_instance, const unsigned char* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
225{
226 int result;
227 PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)malloc(sizeof(PENDING_SOCKET_IO));
228 if (pending_socket_io == NULL)
229 {
230 result = MU_FAILURE;
231 }
232 else
233 {
234 pending_socket_io->bytes = (unsigned char*)malloc(size);
235 if (pending_socket_io->bytes == NULL)
236 {
237 LogError("Allocation Failure: Unable to allocate pending list.");
238 free(pending_socket_io);
239 result = MU_FAILURE;
240 }
241 else
242 {
243 pending_socket_io->size = size;
244 pending_socket_io->on_send_complete = on_send_complete;
245 pending_socket_io->callback_context = callback_context;
246 pending_socket_io->pending_io_list = socket_io_instance->pending_io_list;
247 (void)memcpy(pending_socket_io->bytes, buffer, size);
248
249 if (singlylinkedlist_add(socket_io_instance->pending_io_list, pending_socket_io) == NULL)
250 {
251 LogError("Failure: Unable to add socket to pending list.");
252 free(pending_socket_io->bytes);
253 free(pending_socket_io);
254 result = MU_FAILURE;
255 }
256 else
257 {
258 result = 0;
259 }
260 }
261 }
262 return result;
263}
264
265static STATIC_VAR_UNUSED void signal_callback(int signum)
266{
267 AZURE_UNREFERENCED_PARAMETER(signum);
268 LogError("Socket received signal %d.", signum);
269}
270
271static int lookup_address(SOCKET_IO_INSTANCE* socket_io_instance)
272{
273 int result = 0;
274
275 if (socket_io_instance->address_type == ADDRESS_TYPE_IP)
276 {
277 if (!dns_resolver_is_lookup_complete(socket_io_instance->dns_resolver))
278 {
279 socket_io_instance->io_state = IO_STATE_OPENING;
280 }
281 else
282 {
283 socket_io_instance->io_state = IO_STATE_OPEN;
284 }
285 }
286 else //ADDRESS_TYPE_DOMAIN_SOCKET
287 {
288 socket_io_instance->io_state = IO_STATE_OPEN;
289 }
290
291 return result;
292}
293
294static int initiate_socket_connection(SOCKET_IO_INSTANCE* socket_io_instance)
295{
296 int result;
297 int flags;
298 struct addrinfo* addr = NULL;
299 struct sockaddr* connect_addr = NULL;
300 struct sockaddr_un addrInfoUn;
301 socklen_t connect_addr_len;
302
303 if (socket_io_instance->address_type == ADDRESS_TYPE_IP)
304 {
305 if(!dns_resolver_is_lookup_complete(socket_io_instance->dns_resolver))
306 {
307 LogError("DNS did not resolve IP address");
308 result = MU_FAILURE;
309 }
310 else
311 {
312 addr = dns_resolver_get_addrInfo(socket_io_instance->dns_resolver);
313
314 if (addr == NULL)
315 {
316 LogError("DNS resolution failed");
317 result = MU_FAILURE;
318 }
319 else
320 {
321 connect_addr = addr->ai_addr;
322 connect_addr_len = sizeof(*addr->ai_addr);
323 result = 0;
324 }
325 }
326 }
327 else
328 {
329 size_t hostname_len = strlen(socket_io_instance->hostname);
330 if (hostname_len + 1 > sizeof(addrInfoUn.sun_path))
331 {
332 LogError("Hostname %s is too long for a unix socket (max len = %lu)", socket_io_instance->hostname, (unsigned long)sizeof(addrInfoUn.sun_path));
333 result = MU_FAILURE;
334 }
335 else
336 {
337 memset(&addrInfoUn, 0, sizeof(addrInfoUn));
338 addrInfoUn.sun_family = AF_UNIX;
339 // No need to add NULL terminator due to the above memset
340 (void)memcpy(addrInfoUn.sun_path, socket_io_instance->hostname, hostname_len);
341
342 connect_addr = (struct sockaddr*)&addrInfoUn;
343 connect_addr_len = sizeof(addrInfoUn);
344 result = 0;
345 }
346 }
347
348 if (result == 0)
349 {
350 if ((-1 == (flags = fcntl(socket_io_instance->socket, F_GETFL, 0))) ||
351 (fcntl(socket_io_instance->socket, F_SETFL, flags | O_NONBLOCK) == -1))
352 {
353 LogError("Failure: fcntl failure.");
354 result = MU_FAILURE;
355 }
356 else
357 {
358 result = connect(socket_io_instance->socket, connect_addr, connect_addr_len);
359 if ((result != 0) && (errno != EINPROGRESS))
360 {
361 LogError("Failure: connect failure %d.", errno);
362 result = MU_FAILURE;
363 }
364 else
365 {
366 // Async connect will return -1.
367 result = 0;
368 if (socket_io_instance->on_io_open_complete != NULL)
369 {
370 socket_io_instance->on_io_open_complete(socket_io_instance->on_io_open_complete_context, IO_OPEN_OK /*: IO_OPEN_ERROR*/);
371 }
372 }
373 }
374 }
375
376 return result;
377}
378
379static int lookup_address_and_initiate_socket_connection(SOCKET_IO_INSTANCE* socket_io_instance)
380{
381 int result;
382
383 result = lookup_address(socket_io_instance);
384
385 if(socket_io_instance->io_state == IO_STATE_OPEN)
386 {
387 if (result == 0)
388 {
389 result = initiate_socket_connection(socket_io_instance);
390 }
391 }
392
393 return result;
394}
395
396static int wait_for_connection(SOCKET_IO_INSTANCE* socket_io_instance)
397{
398 int result;
399 int err;
400 int retval;
401 int select_errno = 0;
402
403 fd_set fdset;
404 struct timeval tv;
405
406 FD_ZERO(&fdset);
407 FD_SET(socket_io_instance->socket, &fdset);
408 tv.tv_sec = CONNECT_TIMEOUT;
409 tv.tv_usec = 0;
410
411 do
412 {
413 retval = select(socket_io_instance->socket + 1, NULL, &fdset, NULL, &tv);
414
415 if (retval < 0)
416 {
417 select_errno = errno;
418 }
419 } while (retval < 0 && select_errno == EINTR);
420
421 if (retval != 1)
422 {
423 LogError("Failure: select failure.");
424 result = MU_FAILURE;
425 }
426 else
427 {
428 int so_error = 0;
429 socklen_t len = sizeof(so_error);
430 err = getsockopt(socket_io_instance->socket, SOL_SOCKET, SO_ERROR, &so_error, &len);
431 if (err != 0)
432 {
433 LogError("Failure: getsockopt failure %d.", errno);
434 result = MU_FAILURE;
435 }
436 else if (so_error != 0)
437 {
438 err = so_error;
439 LogError("Failure: connect failure %d.", so_error);
440 result = MU_FAILURE;
441 }
442 else
443 {
444 result = 0;
445 }
446 }
447
448 return result;
449}
450
451
452
453#ifndef __APPLE__
454static void destroy_network_interface_descriptions(NETWORK_INTERFACE_DESCRIPTION* nid)
455{
456 if (nid != NULL)
457 {
458 if (nid->next != NULL)
459 {
460 destroy_network_interface_descriptions(nid->next);
461 }
462
463 if (nid->name != NULL)
464 {
465 free(nid->name);
466 }
467
468 if (nid->mac_address != NULL)
469 {
470 free(nid->mac_address);
471 }
472
473 if (nid->ip_address != NULL)
474 {
475 free(nid->ip_address);
476 }
477
478 free(nid);
479 }
480}
481
482static NETWORK_INTERFACE_DESCRIPTION* create_network_interface_description(struct ifreq *ifr, NETWORK_INTERFACE_DESCRIPTION* previous_nid)
483{
484 NETWORK_INTERFACE_DESCRIPTION* result;
485
486 if ((result = (NETWORK_INTERFACE_DESCRIPTION*)malloc(sizeof(NETWORK_INTERFACE_DESCRIPTION))) == NULL)
487 {
488 LogError("Failed allocating NETWORK_INTERFACE_DESCRIPTION");
489 }
490 else if ((result->name = (char*)malloc(sizeof(char) * (strlen(ifr->ifr_name) + 1))) == NULL)
491 {
492 LogError("failed setting interface description name (malloc failed)");
493 destroy_network_interface_descriptions(result);
494 result = NULL;
495 }
496 else if (strcpy(result->name, ifr->ifr_name) == NULL)
497 {
498 LogError("failed setting interface description name (strcpy failed)");
499 destroy_network_interface_descriptions(result);
500 result = NULL;
501 }
502 else
503 {
504 char* ip_address;
505 unsigned char* mac = (unsigned char*)ifr->ifr_hwaddr.sa_data;
506
507 if ((result->mac_address = (char*)malloc(sizeof(char) * MAC_ADDRESS_STRING_LENGTH)) == NULL)
508 {
509 LogError("failed formatting mac address (malloc failed)");
510 destroy_network_interface_descriptions(result);
511 result = NULL;
512 }
513 else if (sprintf(result->mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]) <= 0)
514 {
515 LogError("failed formatting mac address (sprintf failed)");
516 destroy_network_interface_descriptions(result);
517 result = NULL;
518 }
519 else if ((ip_address = inet_ntoa(((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr)) == NULL)
520 {
521 LogError("failed setting the ip address (inet_ntoa failed)");
522 destroy_network_interface_descriptions(result);
523 result = NULL;
524 }
525 else if ((result->ip_address = (char*)malloc(sizeof(char) * (strlen(ip_address) + 1))) == NULL)
526 {
527 LogError("failed setting the ip address (malloc failed)");
528 destroy_network_interface_descriptions(result);
529 result = NULL;
530 }
531 else if (strcpy(result->ip_address, ip_address) == NULL)
532 {
533 LogError("failed setting the ip address (strcpy failed)");
534 destroy_network_interface_descriptions(result);
535 result = NULL;
536 }
537 else
538 {
539 result->next = NULL;
540
541 if (previous_nid != NULL)
542 {
543 previous_nid->next = result;
544 }
545 }
546 }
547
548 return result;
549}
550
551static int get_network_interface_descriptions(int socket, NETWORK_INTERFACE_DESCRIPTION** nid)
552{
553 int result;
554
555 struct ifreq ifr;
556 struct ifconf ifc;
557 char buf[IFREQ_BUFFER_SIZE];
558
559 ifc.ifc_len = sizeof(buf);
560 ifc.ifc_buf = buf;
561
562 if (ioctl(socket, SIOCGIFCONF, &ifc) == -1)
563 {
564 LogError("ioctl failed querying socket (SIOCGIFCONF, errno=%d)", errno);
565 result = MU_FAILURE;
566 }
567 else
568 {
569 NETWORK_INTERFACE_DESCRIPTION* root_nid = NULL;
570 NETWORK_INTERFACE_DESCRIPTION* new_nid = NULL;
571
572 struct ifreq* it = ifc.ifc_req;
573 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
574
575 result = 0;
576
577 for (; it != end; ++it)
578 {
579 strcpy(ifr.ifr_name, it->ifr_name);
580
581 if (ioctl(socket, SIOCGIFFLAGS, &ifr) != 0)
582 {
583 LogError("ioctl failed querying socket (SIOCGIFFLAGS, errno=%d)", errno);
584 result = MU_FAILURE;
585 break;
586 }
587 else if (ioctl(socket, SIOCGIFHWADDR, &ifr) != 0)
588 {
589 LogError("ioctl failed querying socket (SIOCGIFHWADDR, errno=%d)", errno);
590 result = MU_FAILURE;
591 break;
592 }
593 else if (ioctl(socket, SIOCGIFADDR, &ifr) != 0)
594 {
595 LogError("ioctl failed querying socket (SIOCGIFADDR, errno=%d)", errno);
596 result = MU_FAILURE;
597 break;
598 }
599 else if ((new_nid = create_network_interface_description(&ifr, new_nid)) == NULL)
600 {
601 LogError("Failed creating network interface description");
602 result = MU_FAILURE;
603 break;
604 }
605 else if (root_nid == NULL)
606 {
607 root_nid = new_nid;
608 }
609 }
610
611 if (result == 0)
612 {
613 *nid = root_nid;
614 }
615 else
616 {
617 destroy_network_interface_descriptions(root_nid);
618 }
619 }
620
621 return result;
622}
623
624static int set_target_network_interface(int socket, char* mac_address)
625{
626 int result;
627 NETWORK_INTERFACE_DESCRIPTION* nid;
628
629 if (get_network_interface_descriptions(socket, &nid) != 0)
630 {
631 LogError("Failed getting network interface descriptions");
632 result = MU_FAILURE;
633 }
634 else
635 {
636 NETWORK_INTERFACE_DESCRIPTION* current_nid = nid;
637
638 while(current_nid != NULL)
639 {
640 if (strcmp(mac_address, current_nid->mac_address) == 0)
641 {
642 break;
643 }
644
645 current_nid = current_nid->next;
646 }
647
648 if (current_nid == NULL)
649 {
650 LogError("Did not find a network interface matching MAC ADDRESS");
651 result = MU_FAILURE;
652 }
653 else if (setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, current_nid->name, strlen(current_nid->name)) != 0)
654 {
655 LogError("setsockopt failed (%d)", errno);
656 result = MU_FAILURE;
657 }
658 else
659 {
660 result = 0;
661 }
662
663 destroy_network_interface_descriptions(nid);
664 }
665
666 return result;
667}
668#endif //__APPLE__
669
670static void destroy_socket_io_instance(SOCKET_IO_INSTANCE* instance)
671{
672 if (instance->dns_resolver != NULL)
673 {
674 dns_resolver_destroy(instance->dns_resolver);
675 }
676
677 free(instance->hostname);
678 free(instance->target_mac_address);
679
680 if (instance->pending_io_list != NULL)
681 {
682 singlylinkedlist_destroy(instance->pending_io_list);
683 }
684
685 free(instance);
686}
687
[473]688CONCRETE_IO_HANDLE socketio_lwip_create(void* io_create_parameters)
[457]689{
690 SOCKETIO_CONFIG* socket_io_config = io_create_parameters;
691 SOCKET_IO_INSTANCE* result;
692
693 if (socket_io_config == NULL)
694 {
695 LogError("Invalid argument: socket_io_config is NULL");
696 result = NULL;
697 }
698 else
699 {
700 result = malloc(sizeof(SOCKET_IO_INSTANCE));
701 if (result != NULL)
702 {
703 (void)memset(result, 0, sizeof(SOCKET_IO_INSTANCE));
704
705 result->address_type = ADDRESS_TYPE_IP;
706 result->pending_io_list = singlylinkedlist_create();
707 if (result->pending_io_list == NULL)
708 {
709 LogError("Failure: singlylinkedlist_create unable to create pending list.");
710 destroy_socket_io_instance(result);
711 result = NULL;
712 }
713 else
714 {
715 if (socket_io_config->hostname != NULL)
716 {
717 result->hostname = (char*)malloc(strlen(socket_io_config->hostname) + 1);
718 if (result->hostname != NULL)
719 {
720 (void)strcpy(result->hostname, socket_io_config->hostname);
721 }
722
723 result->socket = INVALID_SOCKET;
724 }
725 else
726 {
727 result->hostname = NULL;
728 result->socket = *((int*)socket_io_config->accepted_socket);
729 }
730
731 if ((result->hostname == NULL) && (result->socket == INVALID_SOCKET))
732 {
733 LogError("Failure: hostname == NULL and socket is invalid.");
734 destroy_socket_io_instance(result);
735 result = NULL;
736 }
737 else
738 {
739 result->port = socket_io_config->port;
740 result->on_io_open_complete = NULL;
741 result->dns_resolver = dns_resolver_create(result->hostname, socket_io_config->port, NULL);
742 result->target_mac_address = NULL;
743 result->on_bytes_received = NULL;
744 result->on_io_error = NULL;
745 result->on_bytes_received_context = NULL;
746 result->on_io_error_context = NULL;
747 result->io_state = IO_STATE_CLOSED;
748 }
749 }
750 }
751 else
752 {
753 LogError("Allocation Failure: SOCKET_IO_INSTANCE");
754 }
755 }
756
757 return result;
758}
759
[473]760void socketio_lwip_destroy(CONCRETE_IO_HANDLE socket_io)
[457]761{
762 if (socket_io != NULL)
763 {
764 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
765 /* we cannot do much if the close fails, so just ignore the result */
766 if (socket_io_instance->socket != INVALID_SOCKET)
767 {
768 close(socket_io_instance->socket);
769 }
770
771 /* clear allpending IOs */
772 LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
773 while (first_pending_io != NULL)
774 {
775 PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io);
776 if (pending_socket_io != NULL)
777 {
778 free(pending_socket_io->bytes);
779 free(pending_socket_io);
780 }
781
782 (void)singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io);
783 first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
784 }
785
786 destroy_socket_io_instance(socket_io_instance);
787 }
788}
789
[473]790int socketio_lwip_open(CONCRETE_IO_HANDLE socket_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
[457]791{
792 int result;
793
794 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
795 if (socket_io == NULL)
796 {
797 LogError("Invalid argument: SOCKET_IO_INSTANCE is NULL");
798 result = MU_FAILURE;
799 }
800 else
801 {
802 if (socket_io_instance->io_state != IO_STATE_CLOSED)
803 {
804 LogError("Failure: socket state is not closed.");
805 result = MU_FAILURE;
806 }
807 else if (socket_io_instance->socket != INVALID_SOCKET)
808 {
809 // Opening an accepted socket
810 socket_io_instance->on_bytes_received_context = on_bytes_received_context;
811 socket_io_instance->on_bytes_received = on_bytes_received;
812 socket_io_instance->on_io_error = on_io_error;
813 socket_io_instance->on_io_error_context = on_io_error_context;
814
815 socket_io_instance->io_state = IO_STATE_OPEN;
816
817 result = 0;
818 }
819 else
820 {
821 socket_io_instance->socket = socket (socket_io_instance->address_type == ADDRESS_TYPE_IP ? AF_INET : AF_UNIX, SOCK_STREAM, 0);
822 if (socket_io_instance->socket < SOCKET_SUCCESS)
823 {
824 LogError("Failure: socket create failure %d.", socket_io_instance->socket);
825 result = MU_FAILURE;
826 }
827#ifndef __APPLE__
828 else if (socket_io_instance->target_mac_address != NULL &&
829 set_target_network_interface(socket_io_instance->socket, socket_io_instance->target_mac_address) != 0)
830 {
831 LogError("Failure: failed selecting target network interface (MACADDR=%s).", socket_io_instance->target_mac_address);
832 result = MU_FAILURE;
833 }
834#endif //__APPLE__
835 else if ((result = lookup_address_and_initiate_socket_connection(socket_io_instance)) != 0)
836 {
837 LogError("lookup_address_and_connect_socket failed");
838 }
839 else if ((result = wait_for_connection(socket_io_instance)) != 0)
840 {
841 LogError("wait_for_connection failed");
842 }
843
844 if (result == 0)
845 {
846 socket_io_instance->on_bytes_received = on_bytes_received;
847 socket_io_instance->on_bytes_received_context = on_bytes_received_context;
848
849 socket_io_instance->on_io_error = on_io_error;
850 socket_io_instance->on_io_error_context = on_io_error_context;
851
852 socket_io_instance->on_io_open_complete = on_io_open_complete;
853 socket_io_instance->on_io_open_complete_context = on_io_open_complete_context;
854 }
855 else
856 {
857 if (socket_io_instance->socket >= SOCKET_SUCCESS)
858 {
859 close(socket_io_instance->socket);
860 }
861 socket_io_instance->socket = INVALID_SOCKET;
862 }
863 }
864 }
865
866 if (socket_io_instance->io_state != IO_STATE_OPENING)
867 {
868 if (on_io_open_complete != NULL)
869 {
870 on_io_open_complete(on_io_open_complete_context, result == 0 ? IO_OPEN_OK : IO_OPEN_ERROR);
871 }
872 }
873
874 return result;
875}
876
[473]877int socketio_lwip_close(CONCRETE_IO_HANDLE socket_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
[457]878{
879 int result = 0;
880
881 if (socket_io == NULL)
882 {
883 result = MU_FAILURE;
884 }
885 else
886 {
887 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
888 if ((socket_io_instance->io_state != IO_STATE_CLOSED) && (socket_io_instance->io_state != IO_STATE_CLOSING))
889 {
890 // Only close if the socket isn't already in the closed or closing state
891 (void)shutdown(socket_io_instance->socket, SHUT_RDWR);
892 close(socket_io_instance->socket);
893 socket_io_instance->socket = INVALID_SOCKET;
894 socket_io_instance->io_state = IO_STATE_CLOSED;
895 }
896
897 if (on_io_close_complete != NULL)
898 {
899 on_io_close_complete(callback_context);
900 }
901
902 result = 0;
903 }
904
905 return result;
906}
907
[473]908int socketio_lwip_send(CONCRETE_IO_HANDLE socket_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
[457]909{
910 int result;
911
912 if ((socket_io == NULL) ||
913 (buffer == NULL) ||
914 (size == 0))
915 {
916 /* Invalid arguments */
917 LogError("Invalid argument: send given invalid parameter");
918 result = MU_FAILURE;
919 }
920 else
921 {
922 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
923 if (socket_io_instance->io_state != IO_STATE_OPEN)
924 {
925 LogError("Failure: socket state is not opened.");
926 result = MU_FAILURE;
927 }
928 else
929 {
930 LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
931 if (first_pending_io != NULL)
932 {
933 if (add_pending_io(socket_io_instance, buffer, size, on_send_complete, callback_context) != 0)
934 {
935 LogError("Failure: add_pending_io failed.");
936 result = MU_FAILURE;
937 }
938 else
939 {
940 result = 0;
941 }
942 }
943 else
944 {
945 signal(SIGPIPE, SIG_IGN);
946
[468]947 ssize_t send_result = send(socket_io_instance->socket, buffer, size, MSG_NOSIGNAL);
[457]948 if ((size_t)send_result != size)
949 {
950 if (send_result == SOCKET_SEND_FAILURE && errno != EAGAIN)
951 {
952 LogError("Failure: sending socket failed. errno=%d (%s).", errno, strerror(errno));
953 result = MU_FAILURE;
954 }
955 else
956 {
957 /*send says "come back later" with EAGAIN - likely the socket buffer cannot accept more data*/
958 /* queue data */
959 size_t bytes_sent = (send_result < 0 ? 0 : send_result);
960
[468]961 if (add_pending_io(socket_io_instance, (const unsigned char*)buffer + bytes_sent, size - bytes_sent, on_send_complete, callback_context) != 0)
[457]962 {
963 LogError("Failure: add_pending_io failed.");
964 result = MU_FAILURE;
965 }
966 else
967 {
968 result = 0;
969 }
970 }
971 }
972 else
973 {
974 if (on_send_complete != NULL)
975 {
976 on_send_complete(callback_context, IO_SEND_OK);
977 }
978
979 result = 0;
980 }
981 }
982 }
983 }
984
985 return result;
986}
987
[473]988void socketio_lwip_dowork(CONCRETE_IO_HANDLE socket_io)
[457]989{
990 if (socket_io != NULL)
991 {
992 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
993 signal(SIGPIPE, SIG_IGN);
994
995 if (socket_io_instance->io_state == IO_STATE_OPEN)
996 {
997 LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
998 while (first_pending_io != NULL)
999 {
1000 PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io);
1001 if (pending_socket_io == NULL)
1002 {
1003 indicate_error(socket_io_instance);
1004 LogError("Failure: retrieving socket from list");
1005 break;
1006 }
1007
[468]1008 ssize_t send_result = send(socket_io_instance->socket, pending_socket_io->bytes, pending_socket_io->size, MSG_NOSIGNAL);
[457]1009 if ((send_result < 0) || ((size_t)send_result != pending_socket_io->size))
1010 {
1011 if (send_result == INVALID_SOCKET)
1012 {
1013 if (errno == EAGAIN) /*send says "come back later" with EAGAIN - likely the socket buffer cannot accept more data*/
1014 {
1015 /*do nothing until next dowork */
1016 break;
1017 }
1018 else
1019 {
1020 free(pending_socket_io->bytes);
1021 free(pending_socket_io);
1022 (void)singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io);
1023
1024 LogError("Failure: sending Socket information. errno=%d (%s).", errno, strerror(errno));
1025 indicate_error(socket_io_instance);
1026 }
1027 }
1028 else
1029 {
1030 /* simply wait until next dowork */
1031 (void)memmove(pending_socket_io->bytes, pending_socket_io->bytes + send_result, pending_socket_io->size - send_result);
1032 pending_socket_io->size -= send_result;
1033 break;
1034 }
1035 }
1036 else
1037 {
1038 if (pending_socket_io->on_send_complete != NULL)
1039 {
1040 pending_socket_io->on_send_complete(pending_socket_io->callback_context, IO_SEND_OK);
1041 }
1042
1043 free(pending_socket_io->bytes);
1044 free(pending_socket_io);
1045 if (singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io) != 0)
1046 {
1047 indicate_error(socket_io_instance);
1048 LogError("Failure: unable to remove socket from list");
1049 }
1050 }
1051
1052 first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
1053 }
1054
1055 if (socket_io_instance->io_state == IO_STATE_OPEN)
1056 {
1057 ssize_t received = 0;
1058 do
1059 {
[468]1060 received = recv(socket_io_instance->socket, socket_io_instance->recv_bytes, XIO_RECEIVE_BUFFER_SIZE, MSG_NOSIGNAL);
[457]1061 if (received > 0)
1062 {
1063 if (socket_io_instance->on_bytes_received != NULL)
1064 {
1065 /* Explicitly ignoring here the result of the callback */
1066 (void)socket_io_instance->on_bytes_received(socket_io_instance->on_bytes_received_context, socket_io_instance->recv_bytes, received);
1067 }
1068 }
1069 else if (received == 0)
1070 {
1071 // Do not log error here due to this is probably the socket being closed on the other end
1072 indicate_error(socket_io_instance);
1073 }
1074 else if (received < 0 && errno != EAGAIN)
1075 {
1076 LogError("Socketio_Failure: Receiving data from endpoint: errno=%d.", errno);
1077 indicate_error(socket_io_instance);
1078 }
1079
1080 } while (received > 0 && socket_io_instance->io_state == IO_STATE_OPEN);
1081 }
1082 }
1083 else
1084 {
1085 if (socket_io_instance->io_state == IO_STATE_OPENING)
1086 {
1087 if(lookup_address(socket_io_instance) != 0)
1088 {
1089 LogError("Socketio_Failure: lookup address failed");
1090 indicate_error(socket_io_instance);
1091 }
1092 else
1093 {
1094 if(socket_io_instance->io_state == IO_STATE_OPEN)
1095 {
1096 initiate_socket_connection(socket_io_instance);
1097 }
1098 }
1099
1100 }
1101 }
1102 }
1103}
1104
1105// Edison is missing this from netinet/tcp.h, but this code still works if we manually define it.
1106#ifndef SOL_TCP
1107#define SOL_TCP 6
1108#endif
1109
1110#ifndef __APPLE__
1111static void strtoup(char* str)
1112{
1113 if (str != NULL)
1114 {
1115 while (*str != '\0')
1116 {
1117 if (isalpha((int)*str) && islower((int)*str))
1118 {
1119 *str = (char)toupper((int)*str);
1120 }
1121 str++;
1122 }
1123 }
1124}
1125#endif // __APPLE__
1126
[473]1127static int socketio_lwip_setaddresstype_option(SOCKET_IO_INSTANCE* socket_io_instance, const char* addressType)
[457]1128{
1129 int result;
1130
1131 if (socket_io_instance->io_state != IO_STATE_CLOSED)
1132 {
1133 LogError("Socket's type can only be changed when in state 'IO_STATE_CLOSED'. Current state=%d", socket_io_instance->io_state);
1134 result = MU_FAILURE;
1135 }
1136 else if (strcmp(addressType, OPTION_ADDRESS_TYPE_DOMAIN_SOCKET) == 0)
1137 {
1138 socket_io_instance->address_type = ADDRESS_TYPE_DOMAIN_SOCKET;
1139 result = 0;
1140 }
1141 else if (strcmp(addressType, OPTION_ADDRESS_TYPE_IP_SOCKET) == 0)
1142 {
1143 socket_io_instance->address_type = ADDRESS_TYPE_IP;
1144 result = 0;
1145 }
1146 else
1147 {
1148 LogError("Address type %s is not supported", addressType);
1149 result = MU_FAILURE;
1150 }
1151
1152 return result;
1153}
1154
[473]1155int socketio_lwip_setoption(CONCRETE_IO_HANDLE socket_io, const char* optionName, const void* value)
[457]1156{
1157 int result;
1158
1159 if (socket_io == NULL ||
1160 optionName == NULL ||
1161 value == NULL)
1162 {
1163 result = MU_FAILURE;
1164 }
1165 else
1166 {
1167 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
1168
1169 if (strcmp(optionName, "tcp_keepalive") == 0)
1170 {
1171 result = setsockopt(socket_io_instance->socket, SOL_SOCKET, SO_KEEPALIVE, value, sizeof(int));
1172 if (result == -1) result = errno;
1173 }
1174 else if (strcmp(optionName, "tcp_keepalive_time") == 0)
1175 {
1176#ifdef __APPLE__
1177 result = setsockopt(socket_io_instance->socket, IPPROTO_TCP, TCP_KEEPALIVE, value, sizeof(int));
1178#else
1179 result = setsockopt(socket_io_instance->socket, SOL_TCP, TCP_KEEPIDLE, value, sizeof(int));
1180#endif
1181 if (result == -1) result = errno;
1182 }
1183 else if (strcmp(optionName, "tcp_keepalive_interval") == 0)
1184 {
1185 result = setsockopt(socket_io_instance->socket, SOL_TCP, TCP_KEEPINTVL, value, sizeof(int));
1186 if (result == -1) result = errno;
1187 }
1188 else if (strcmp(optionName, OPTION_NET_INT_MAC_ADDRESS) == 0)
1189 {
1190#ifdef __APPLE__
1191 LogError("option not supported.");
1192 result = MU_FAILURE;
1193#else
1194 if (strlen(value) == 0)
1195 {
1196 LogError("option value must be a valid mac address");
1197 result = MU_FAILURE;
1198 }
1199 else if ((socket_io_instance->target_mac_address = (char*)malloc(sizeof(char) * (strlen(value) + 1))) == NULL)
1200 {
1201 LogError("failed setting net_interface_mac_address option (malloc failed)");
1202 result = MU_FAILURE;
1203 }
1204 else if (strcpy(socket_io_instance->target_mac_address, value) == NULL)
1205 {
1206 LogError("failed setting net_interface_mac_address option (strcpy failed)");
1207 free(socket_io_instance->target_mac_address);
1208 socket_io_instance->target_mac_address = NULL;
1209 result = MU_FAILURE;
1210 }
1211 else
1212 {
1213 strtoup(socket_io_instance->target_mac_address);
1214 result = 0;
1215 }
1216#endif
1217 }
1218 else if (strcmp(optionName, OPTION_ADDRESS_TYPE) == 0)
1219 {
[473]1220 result = socketio_lwip_setaddresstype_option(socket_io_instance, (const char*)value);
[457]1221 }
1222 else
1223 {
1224 result = MU_FAILURE;
1225 }
1226 }
1227
1228 return result;
1229}
1230
[473]1231const IO_INTERFACE_DESCRIPTION* socketio_lwip_get_interface_description(void)
[457]1232{
1233 return &socket_io_interface_description;
1234}
1235
Note: See TracBrowser for help on using the repository browser.