1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
21 // Defining _POSIX_C_SOURCE macro with 200809L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2008 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2008 base specification,
26 // Refer http://pubs.opengroup.org/stage7tc1/
28 // For this specific file, see use of strndup,
29 // Refer http://man7.org/linux/man-pages/man3/strdup.3.html
30 #ifndef _POSIX_C_SOURCE
31 #define _POSIX_C_SOURCE 200809L
34 // Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
35 // definitions that may otherwise be skipped. Skipping can cause implicit
36 // declaration warnings and/or bugs and subtle problems in code execution.
37 // For glibc information on feature test macros,
38 // Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
40 // This file requires #define use due to struct ip_mreq
41 #define _DEFAULT_SOURCE
43 #include <netinet/in.h>
45 #include "caethernetinterface.h"
47 #include <sys/types.h>
48 #include <sys/socket.h>
51 #include <sys/select.h>
52 #include <arpa/inet.h>
58 #include "caadapterutils.h"
60 #include "caadapternetdtls.h"
63 #include "oic_malloc.h"
65 // TODO g_stopSecureUnicast is set but never used. The three groups of
66 // globals should be combined into three instances of a common struct.
68 #define PIPE_READ_FD 0
70 #define PIPE_WRITE_FD 1
73 * @def ETHERNET_SERVER_TAG
74 * @brief Logging tag for module name
76 #define ETHERNET_SERVER_TAG "ETHERNET_SERVER"
79 * @def CA_UDP_BIND_RETRY_COUNT
80 * @brief Retry count in case of socket bind failure.
82 #define CA_UDP_BIND_RETRY_COUNT 10
86 * @brief max length for ip
91 * @var g_unicastServerSocketFD
92 * @brief Unicast server socket descriptor
94 static int32_t g_unicastServerSocketFD = -1;
97 * @var g_mutexUnicastServer
98 * @brief Mutex to synchronize unicast server
100 static ca_mutex g_mutexUnicastServer = NULL;
104 * @brief Flag to control the Receive Unicast Data Thread
106 static bool g_stopUnicast = false;
109 * Handle to interrupt unicast server for stopping, etc.
111 static int g_unicastTriggerFD = -1;
114 * @var g_multicastServerSocketFD
115 * @brief socket descriptor for multicast server
117 static int32_t g_multicastServerSocketFD = -1;
120 * @var g_mutexMulticastServer
121 * @brief Mutex to synchronize secure multicast server
123 static ca_mutex g_mutexMulticastServer = NULL;
126 * @var g_stopMulticast
127 * @brief Flag to control the Receive Multicast Data Thread
129 static bool g_stopMulticast = false;
132 * Handle to interrupt multicast server for stopping, etc.
134 static int g_multicastTriggerFD = -1;
138 * @var g_secureUnicastServerSocketFD
139 * @brief Secure unicast server socket descriptor
141 static int32_t g_secureUnicastServerSocketFD = -1;
144 * @var g_mutexSecureUnicastServer
145 * @brief Mutex to synchronize secure unicast server
147 static ca_mutex g_mutexSecureUnicastServer = NULL;
150 * @var g_stopSecureUnicast
151 * @brief Flag to control the unicast secure data receive thread
153 static bool g_stopSecureUnicast = false;
158 * @brief ThreadPool for storing ca_thread_pool_t handle passed from adapter
160 static ca_thread_pool_t g_threadPool = NULL;
163 * @var g_multicastServerInterface
164 * @brief Local interface on which multicast server is running
166 static char g_multicastServerInterface[IPNAMESIZE];
169 * @var g_multicastMemberReq
170 * @brief ip_mreq structure passed to join a multicast group
172 static struct ip_mreq g_multicastMemberReq;
175 * @var g_packetReceivedCallback
176 * @brief Callback for notifying the upper layer on receival data from remote OIC device
178 static CAEthernetPacketReceivedCallback g_packetReceivedCallback = NULL;
181 * @var g_exceptionCallback
182 * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
184 static CAEthernetExceptionCallback g_exceptionCallback = NULL;
187 @brief Thread context information for unicast, multicast and secured unicast server
194 CAAdapterServerType_t type;
195 } CAAdapterReceiveThreadContext_t;
198 * Creates a non-blocking pipe.
200 * Creates a pipe with two file descriptors then sets both to be
201 * non-blocking. If an error occurs setting flags, any created handles
202 * will be closed and set to -1.
204 * @param pipefd array of two ints to store the pipe handles in.
206 * @return 0 on success, -1 otherwise.
208 static int createNonblockingPipe(int pipefd[2]);
211 * Sets the given file descriptor to be non-blocking.
213 * @param fd the file descriptor to make non-blocking.
215 * @return 0 on success, -1 otherwise.
217 static int setNonblocking(int fd);
219 static void CAReceiveHandler(void *data)
221 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
224 VERIFY_NON_NULL_VOID(data, ETHERNET_SERVER_TAG, "Invalid thread context");
226 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data;
228 struct timeval timeout;
229 char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
231 while (true != *(ctx->stopFlag))
233 // safe to set longer value as select can be interrupted.
238 FD_SET(ctx->socket_fd, &reads);
239 int highest = (ctx->stopFd > ctx->socket_fd) ? ctx->stopFd : ctx->socket_fd;
240 if (ctx->stopFd != -1)
242 FD_SET(ctx->stopFd, &reads);
245 int32_t ret = select(highest + 1, &reads, NULL, NULL, &timeout);
246 if (*(ctx->stopFlag) == true)
248 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG,
249 "Stop request received for [%d] server", ctx->type);
255 OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
259 if ((ctx->stopFd != -1) && FD_ISSET(ctx->stopFd, &reads))
261 // Doesn't matter at this point what happens (errors can be
262 // ignored). Just drain some data if this code ever gets hit.
263 recv(ctx->stopFd, recvBuffer, sizeof(recvBuffer), MSG_DONTWAIT);
266 if (!FD_ISSET(ctx->socket_fd, &reads))
271 memset(recvBuffer, 0, sizeof(recvBuffer));
273 // Read data from socket
274 struct sockaddr_in srcSockAddress;
276 socklen_t srcAddressLen = sizeof(srcSockAddress);
278 recvLen = recvfrom(ctx->socket_fd, recvBuffer,
279 sizeof(recvBuffer), 0, (struct sockaddr *) &srcSockAddress,
284 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
287 else if (0 == recvLen)
289 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Server socket shutdown [%d]!", ctx->type);
291 // Notify upper layer this exception
292 if (g_exceptionCallback)
294 g_exceptionCallback(ctx->type);
296 if (ctx->stopFd != -1)
305 char srcIPAddress[CA_IPADDR_SIZE] = {0};
306 inet_ntop(AF_INET, &srcSockAddress.sin_addr.s_addr, srcIPAddress, sizeof(srcIPAddress));
307 uint16_t srcPort = 0;
308 srcPort = ntohs(srcSockAddress.sin_port);
310 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
311 srcIPAddress, srcPort);
312 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
313 recvBuffer, recvLen);
315 char *netMask = NULL;
316 if (CA_STATUS_OK != CAEthernetGetInterfaceSubnetMask(&netMask))
318 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to get ethernet subnet");
322 if (!CAAdapterIsSameSubnet(g_multicastServerInterface, srcIPAddress, netMask))
324 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Packet received from different subnet, Ignore!");
336 case CA_UNICAST_SERVER:
337 case CA_MULTICAST_SERVER:
338 // Notify data to upper layer
339 if (g_packetReceivedCallback)
341 g_packetReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);
345 case CA_SECURED_UNICAST_SERVER:
347 CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,
349 (uint8_t *)recvBuffer,
350 recvLen, DTLS_ETHERNET);
351 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG,
352 "CAAdapterNetDtlsDecrypt returns [%d]", ret);
355 #endif //__WITH_DTLS__
357 // Should never occur
358 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Invalid server type");
359 if (ctx->stopFd != -1)
369 if (ctx->stopFd != -1)
377 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
380 static CAResult_t CACreateSocket(int32_t *socketFD, const char *localIp, uint16_t *port,
384 // Create a UDP socket
385 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
388 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to create Socket, Error code: %s",
390 return CA_STATUS_FAILED;
393 // Make the socket non-blocking
394 if (-1 == setNonblocking(sock))
397 return CA_STATUS_FAILED;
400 if (true == forceStart)
402 int32_t setOptionOn = 1;
403 if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
404 (char *) &setOptionOn,
405 sizeof(setOptionOn)))
407 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
411 return CA_STATUS_FAILED;
415 struct sockaddr_in sockAddr;
416 bool isBound = false;
417 uint16_t serverPort = *port;
419 memset(&sockAddr, 0, sizeof(sockAddr));
420 sockAddr.sin_family = AF_INET;
421 sockAddr.sin_port = htons(serverPort);
424 sockAddr.sin_addr.s_addr = inet_addr(localIp);
428 sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
432 for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
434 if (-1 == bind(sock, (struct sockaddr *) &sockAddr,
437 if (false == forceStart)
439 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
442 //Set the port to next one
444 sockAddr.sin_port = htons(serverPort);
449 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]!",
459 if (false == isBound)
462 return CA_STATUS_FAILED;
470 static CAResult_t CACloseSocket(int32_t *socketFD)
472 if (socketFD == NULL)
474 return CA_STATUS_INVALID_PARAM;
479 OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Server not running");
480 return CA_SERVER_NOT_STARTED;
484 if (-1 == close(*socketFD))
486 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
488 return CA_STATUS_FAILED;
495 static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port,
496 const bool forceStart, bool isSecured, int32_t *serverFD)
498 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
500 if (serverFD == NULL)
502 return CA_STATUS_INVALID_PARAM;
505 CAResult_t ret = CACreateSocket(serverFD, localAddress, port, forceStart);
506 if (CA_STATUS_OK != ret)
508 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create unicast socket");
513 * The task to listen for data from unicast socket is added to the thread pool.
514 * This is a blocking call is made where we try to receive some data..
515 * We will keep waiting until some data is received.
516 * This task will be terminated when thread pool is freed on stopping the adapters.
517 * Thread context will be freed by thread on exit.
519 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
520 OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
523 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
525 return CA_MEMORY_ALLOC_FAILED;
528 int pipefd[2] = {-1, -1};
529 if (createNonblockingPipe(pipefd) != 0)
531 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create pipe");
535 return CA_STATUS_FAILED;
538 g_unicastTriggerFD = pipefd[PIPE_WRITE_FD]; // The write end of the pipe
540 ctx->stopFlag = &g_stopUnicast;
541 ctx->stopFd = pipefd[PIPE_READ_FD]; // The read end of the pipe
542 ctx->socket_fd = *serverFD;
543 ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
544 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *)ctx))
546 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create read thread!");
548 close(g_unicastTriggerFD);
549 g_unicastTriggerFD = -1;
556 return CA_STATUS_FAILED;
559 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
563 static void CAEthernetServerDestroyMutex(void)
565 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
567 if (g_mutexUnicastServer)
569 ca_mutex_free(g_mutexUnicastServer);
570 g_mutexUnicastServer = NULL;
574 if (g_mutexSecureUnicastServer)
576 ca_mutex_free(g_mutexSecureUnicastServer);
577 g_mutexSecureUnicastServer = NULL;
581 if (g_mutexMulticastServer)
583 ca_mutex_free(g_mutexMulticastServer);
584 g_mutexMulticastServer = NULL;
587 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
590 static CAResult_t CAEthernetServerCreateMutex(void)
592 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
594 if(g_mutexUnicastServer) {
595 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "mutex is already created!");
597 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
598 return CA_STATUS_FAILED;
601 g_mutexUnicastServer = ca_mutex_new();
602 if (!g_mutexUnicastServer)
604 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
605 return CA_STATUS_FAILED;
609 g_mutexSecureUnicastServer = ca_mutex_new();
610 if (!g_mutexSecureUnicastServer)
612 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
614 CAEthernetServerDestroyMutex();
615 return CA_STATUS_FAILED;
619 g_mutexMulticastServer = ca_mutex_new();
620 if (!g_mutexMulticastServer)
622 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
624 CAEthernetServerDestroyMutex();
625 return CA_STATUS_FAILED;
628 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
632 CAResult_t CAEthernetInitializeServer(const ca_thread_pool_t threadPool)
634 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
637 VERIFY_NON_NULL(threadPool, ETHERNET_SERVER_TAG, "Thread pool handle is NULL");
640 if (CA_STATUS_OK != CAEthernetServerCreateMutex())
642 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create mutex!");
643 return CA_STATUS_FAILED;
646 g_threadPool = threadPool;
648 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
652 void CAEthernetTerminateServer(void)
654 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
659 CAEthernetServerDestroyMutex();
661 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
664 CAResult_t CAEthernetStartUnicastServer(const char *localAddress, uint16_t *port,
665 bool forceStart, bool isSecured, int32_t *serverFD)
667 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
670 VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
671 VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port");
672 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
676 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Invalid input: port is invalid!");
677 return CA_STATUS_INVALID_PARAM;
681 if (false == isSecured)
683 ca_mutex_lock(g_mutexUnicastServer);
684 if (-1 != g_unicastServerSocketFD)
686 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
687 CA_SERVER_STARTED_ALREADY);
689 *serverFD = g_unicastServerSocketFD;
690 ca_mutex_unlock(g_mutexUnicastServer);
691 return CA_SERVER_STARTED_ALREADY;
694 g_stopUnicast = false;
695 if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
696 &g_unicastServerSocketFD))
698 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
699 g_unicastServerSocketFD = -1;
700 ca_mutex_unlock(g_mutexUnicastServer);
701 return CA_STATUS_FAILED;
704 *serverFD = g_unicastServerSocketFD;
705 ca_mutex_unlock(g_mutexUnicastServer);
708 else // Start unicast server for secured communication
710 ca_mutex_lock(g_mutexSecureUnicastServer);
711 if (-1 != g_secureUnicastServerSocketFD)
713 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
714 CA_SERVER_STARTED_ALREADY);
716 *serverFD = g_secureUnicastServerSocketFD;
717 ca_mutex_unlock(g_mutexSecureUnicastServer);
718 return CA_SERVER_STARTED_ALREADY;
721 g_stopSecureUnicast = false;
722 if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
723 &g_secureUnicastServerSocketFD))
725 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
726 g_secureUnicastServerSocketFD = -1;
727 ca_mutex_unlock(g_mutexSecureUnicastServer);
728 return CA_STATUS_FAILED;
731 *serverFD = g_secureUnicastServerSocketFD;
732 ca_mutex_unlock(g_mutexSecureUnicastServer);
735 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
739 CAResult_t CAEthernetStartMulticastServer(const char *localAddress,
740 const char *multicastAddress, const uint16_t multicastPort, int32_t *serverFD)
742 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
745 VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
746 VERIFY_NON_NULL(multicastAddress, ETHERNET_SERVER_TAG, "port");
747 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
749 uint16_t port = multicastPort;
752 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Invalid input: Multicast port is invalid!");
753 return CA_STATUS_INVALID_PARAM;
756 ca_mutex_lock(g_mutexMulticastServer);
758 if (g_multicastServerSocketFD != -1)
760 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Multicast Server is already running!");
761 ca_mutex_unlock(g_mutexMulticastServer);
762 return CA_SERVER_STARTED_ALREADY;
765 CAResult_t ret = CACreateSocket(&g_multicastServerSocketFD, multicastAddress, &port, true);
766 if (ret != CA_STATUS_OK)
768 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create multicast socket");
769 ca_mutex_unlock(g_mutexMulticastServer);
773 // Add membership to receiving socket (join group)
774 memset(&g_multicastMemberReq, 0, sizeof(struct ip_mreq));
775 g_multicastMemberReq.imr_interface.s_addr = inet_addr(localAddress);
776 inet_aton(multicastAddress, &g_multicastMemberReq.imr_multiaddr);
778 if (-1 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
779 (char *) &g_multicastMemberReq,
780 sizeof(struct ip_mreq)))
782 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
784 close(g_multicastServerSocketFD);
785 g_multicastServerSocketFD = -1;
786 ca_mutex_unlock(g_mutexMulticastServer);
787 return CA_STATUS_FAILED;
791 * The task to listen to data from multicastcast socket is added to the thread pool.
792 * This is a blocking call is made where we try to receive some data.
793 * We will keep waiting until some data is received.
794 * This task will be terminated when thread pool is freed on stopping the adapters.
795 * Thread context will be freed by thread on exit.
797 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
798 OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
801 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
802 close(g_multicastServerSocketFD);
803 g_multicastServerSocketFD = -1;
804 return CA_MEMORY_ALLOC_FAILED;
807 int pipefd[2] = {-1, -1};
808 if (createNonblockingPipe(pipefd) != 0)
810 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create pipe");
812 close(g_multicastServerSocketFD);
813 g_multicastServerSocketFD = -1;
814 return CA_STATUS_FAILED;
817 g_multicastTriggerFD = pipefd[PIPE_WRITE_FD]; // The write end of the pipe
819 ctx->stopFlag = &g_stopMulticast;
820 ctx->stopFd = pipefd[PIPE_READ_FD]; // The read end of the pipe
821 ctx->socket_fd = g_multicastServerSocketFD;
822 ctx->type = CA_MULTICAST_SERVER;
824 g_stopMulticast = false;
825 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *)ctx))
827 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "thread_pool_add_task failed!");
829 close(g_multicastTriggerFD);
830 g_multicastTriggerFD = -1;
834 close(g_multicastServerSocketFD);
835 g_multicastServerSocketFD = -1;
836 g_stopMulticast = true;
837 ca_mutex_unlock(g_mutexMulticastServer);
838 return CA_STATUS_FAILED;
841 *serverFD = g_multicastServerSocketFD;
842 strncpy(g_multicastServerInterface, localAddress, IPNAMESIZE);
843 ca_mutex_unlock(g_mutexMulticastServer);
845 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
849 CAResult_t CAEthernetStopUnicastServer()
851 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
853 ca_mutex_lock(g_mutexUnicastServer);
854 g_stopUnicast = true;
855 if (g_unicastTriggerFD != -1)
857 if (write(g_unicastTriggerFD, "X", 1) == -1)
859 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG,
860 "Failed to write to trigger, Error code: %s",
863 close(g_unicastTriggerFD);
864 g_unicastTriggerFD = -1;
866 CAResult_t ret = CACloseSocket(&g_unicastServerSocketFD);
867 g_unicastServerSocketFD = -1;
868 ca_mutex_unlock(g_mutexUnicastServer);
870 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Unicast server stopped [%d]", ret);
875 CAResult_t CAEthernetStopSecureUnicastServer()
877 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
879 ca_mutex_lock(g_mutexSecureUnicastServer);
880 g_stopSecureUnicast = true;
881 if (g_unicastTriggerFD != -1)
883 if (write(g_unicastTriggerFD, "X", 1) == -1)
885 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG,
886 "Failed to write to trigger, Error code: %s",
889 close(g_unicastTriggerFD);
890 g_unicastTriggerFD = -1;
892 CAResult_t ret = CACloseSocket(&g_secureUnicastServerSocketFD);
893 ca_mutex_unlock(g_mutexSecureUnicastServer);
895 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Secured unicast server stopped [%d]", ret);
900 CAResult_t CAEthernetStopMulticastServer(void)
902 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
904 ca_mutex_lock(g_mutexMulticastServer);
906 if (g_multicastServerSocketFD == -1)
908 OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast server is not yet started");
909 ca_mutex_unlock(g_mutexMulticastServer);
910 return CA_SERVER_NOT_STARTED;
913 g_stopMulticast = true;
914 if (g_multicastTriggerFD != -1)
916 if (write(g_multicastTriggerFD, "X", 1) == -1)
918 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG,
919 "Failed to write to trigger, Error code: %s",
922 close(g_multicastTriggerFD);
923 g_multicastTriggerFD = -1;
926 // leave the group after you are done
927 if (-1 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
928 (char *)&g_multicastMemberReq,
929 sizeof(struct ip_mreq)))
931 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",
935 CAResult_t ret = CACloseSocket(&g_multicastServerSocketFD);
936 ca_mutex_unlock(g_mutexMulticastServer);
938 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Multicast server stopped [%d]", ret);
942 CAResult_t CAEthernetGetUnicastServerInfo(bool isSecured,
943 char **ipAddress, uint16_t *port, int32_t *serverFD)
945 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
948 VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "IP address");
949 VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "Port");
950 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "Server ID");
952 struct sockaddr_in sockAddr;
953 socklen_t len = sizeof(struct sockaddr_in);
954 if (-1 == getsockname(g_unicastServerSocketFD, (struct sockaddr *)&sockAddr, &len))
956 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));
957 return CA_STATUS_FAILED;
961 const char *serverAddress = inet_ntoa(sockAddr.sin_addr);
962 *ipAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) : NULL;
963 *port = ntohs(sockAddr.sin_port);
965 *serverFD = (true == isSecured) ? g_secureUnicastServerSocketFD : g_unicastServerSocketFD;
967 *serverFD = g_unicastServerSocketFD;
970 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
974 void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
976 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
977 g_packetReceivedCallback = callback;
978 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
981 void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
983 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
984 g_exceptionCallback = callback;
985 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
988 int setNonblocking(int fd)
990 int rc = fcntl(fd, F_GETFL);
993 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG,
994 "Failed to get existing flags, Error code: %s",
999 rc = fcntl(fd, F_SETFL, rc | O_NONBLOCK);
1002 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG,
1003 "Failed to set non-blocking mode, Error code: %s",
1011 int createNonblockingPipe(int pipefd[2])
1016 pipefd[PIPE_READ_FD] = -1;
1017 pipefd[PIPE_WRITE_FD] = -1;
1022 rc = setNonblocking(pipefd[PIPE_READ_FD]);
1027 rc = setNonblocking(pipefd[PIPE_WRITE_FD]);
1032 if (pipefd[PIPE_READ_FD] != -1)
1034 close(pipefd[PIPE_READ_FD]);
1035 pipefd[PIPE_READ_FD] = -1;
1037 if (pipefd[PIPE_WRITE_FD] != -1)
1039 close(pipefd[PIPE_WRITE_FD]);
1040 pipefd[PIPE_WRITE_FD]= -1;