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 ******************************************************************/
20 #include "caethernetinterface.h"
22 #include <sys/types.h>
23 #include <sys/socket.h>
26 #include <sys/select.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
32 #include "caadapterutils.h"
34 #include "caadapternetdtls.h"
39 * @def ETHERNET_SERVER_TAG
40 * @brief Logging tag for module name
42 #define ETHERNET_SERVER_TAG "ETHERNET_SERVER"
45 * @def CA_UDP_BIND_RETRY_COUNT
46 * @brief Retry count in case of socket bind failure.
48 #define CA_UDP_BIND_RETRY_COUNT 10
52 * @brief max length for ip
57 * @var gUnicastServerSocketFD
58 * @brief Unicast server socket descriptor
60 static int32_t gUnicastServerSocketFD = -1;
63 * @var gMutexUnicastServer
64 * @brief Mutex to synchronize unicast server
66 static u_mutex gMutexUnicastServer = NULL;
70 * @brief Flag to control the Receive Unicast Data Thread
72 static bool gStopUnicast = false;
75 * @var gMulticastServerSocketFD
76 * @brief socket descriptor for multicast server
78 static int32_t gMulticastServerSocketFD = -1;
81 * @var gMutexMulticastServer
82 * @brief Mutex to synchronize secure multicast server
84 static u_mutex gMutexMulticastServer = NULL;
88 * @brief Flag to control the Receive Multicast Data Thread
90 static bool gStopMulticast = false;
94 * @var gSecureUnicastServerSocketFD
95 * @brief Secure unicast server socket descriptor
97 static int32_t gSecureUnicastServerSocketFD = -1;
100 * @var gMutexSecureUnicastServer
101 * @brief Mutex to synchronize secure unicast server
103 static u_mutex gMutexSecureUnicastServer = NULL;
106 * @var gStopSecureUnicast
107 * @brief Flag to control the unicast secure data receive thread
109 static bool gStopSecureUnicast = false;
114 * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
116 static u_thread_pool_t gThreadPool = NULL;
119 * @var gMulticastServerInterface
120 * @brief Local interface on which multicast server is running
122 static char gMulticastServerInterface[IPNAMESIZE];
125 * @var gMulticastMemberReq
126 * @brief ip_mreq structure passed to join a multicast group
128 static struct ip_mreq gMulticastMemberReq;
131 * @var gPacketReceivedCallback
132 * @brief Callback for notifying the upper layer on receival data from remote OIC device
134 static CAEthernetPacketReceivedCallback gPacketReceivedCallback = NULL;
137 * @var gExceptionCallback
138 * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
140 static CAEthernetExceptionCallback gExceptionCallback = NULL;
143 @brief Thread context information for unicast, multicast and secured unicast server
149 CAAdapterServerType_t type;
150 } CAAdapterReceiveThreadContext_t;
152 static void CAReceiveHandler(void *data)
154 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
157 VERIFY_NON_NULL_VOID(data, ETHERNET_SERVER_TAG, "Invalid thread context");
159 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data;
161 struct timeval timeout;
162 char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
164 while (true != *(ctx->stopFlag))
170 FD_SET(ctx->socket_fd, &reads);
172 int32_t ret = select(ctx->socket_fd + 1, &reads, NULL, NULL, &timeout);
173 if (*(ctx->stopFlag) == true)
175 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Stop request received for [%d] server", ctx->type);
181 OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
185 if (!FD_ISSET(ctx->socket_fd, &reads))
190 memset(recvBuffer, 0, sizeof(recvBuffer));
192 // Read data from socket
193 struct sockaddr_in srcSockAddress;
195 socklen_t srcAddressLen = sizeof(srcSockAddress);
196 if (-1 == (recvLen = recvfrom(ctx->socket_fd, recvBuffer,
197 sizeof(recvBuffer), 0, (struct sockaddr *) &srcSockAddress,
200 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
203 else if (0 == recvLen)
205 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Server socket shutdown [%d]!", ctx->type);
207 // Notify upper layer this exception
208 if (gExceptionCallback)
210 gExceptionCallback(ctx->type);
217 const char *srcIPAddress = NULL;
218 int32_t srcPort = -1;
220 srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
221 srcPort = ntohs(srcSockAddress.sin_port);
223 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
224 srcIPAddress, srcPort);
225 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
226 recvBuffer, recvLen);
228 char *netMask = NULL;
229 if (CA_STATUS_OK != CAEthernetGetInterfaceSubnetMask(&netMask))
231 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to get ethernet subnet");
235 if (!CAAdapterIsSameSubnet(gMulticastServerInterface, srcIPAddress, netMask))
237 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Packet received from different subnet, Ignore!");
249 case CA_UNICAST_SERVER:
250 case CA_MULTICAST_SERVER:
251 // Notify data to upper layer
252 if (gPacketReceivedCallback)
254 gPacketReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);
258 case CA_SECURED_UNICAST_SERVER:
260 CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,
262 (uint8_t *)recvBuffer,
263 recvLen, DTLS_ETHERNET);
264 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
267 #endif //__WITH_DTLS__
269 // Should never occur
270 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Invalid server type");
280 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
283 static CAResult_t CACreateSocket(int32_t *socketFD, const char *localIp, int16_t *port,
284 const bool forceStart)
287 // Create a UDP socket
288 if (-1 == (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
290 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to create Socket, Error code: %s",
292 return CA_STATUS_FAILED;
295 // Make the socket non-blocking
296 if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
298 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
302 return CA_STATUS_FAILED;
305 if (true == forceStart)
307 int32_t setOptionOn = 1;
308 if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
309 (char *) &setOptionOn,
310 sizeof(setOptionOn)))
312 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
316 return CA_STATUS_FAILED;
320 struct sockaddr_in sockAddr;
321 bool isBound = false;
322 int16_t serverPort = *port;
324 memset((char *) &sockAddr, 0, sizeof(sockAddr));
325 sockAddr.sin_family = AF_INET;
326 sockAddr.sin_port = htons(serverPort);
329 sockAddr.sin_addr.s_addr = inet_addr(localIp);
333 sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
337 for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
339 if (-1 == bind(sock, (struct sockaddr *) &sockAddr,
342 if (false == forceStart)
344 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
347 //Set the port to next one
349 sockAddr.sin_port = htons(serverPort);
354 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]!",
364 if (false == isBound)
367 return CA_STATUS_FAILED;
375 static CAResult_t CACloseSocket(int32_t *socketFD)
379 OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Server not running");
380 return CA_SERVER_NOT_STARTED;
384 if (-1 == close(*socketFD))
386 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
388 return CA_STATUS_FAILED;
395 static CAResult_t CAStartUnicastServer(const char *localAddress, int16_t *port,
396 const bool forceStart, bool isSecured, int32_t *serverFD)
398 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
400 CAResult_t ret = CACreateSocket(serverFD, localAddress, port, forceStart);
401 if (CA_STATUS_OK != ret)
403 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create unicast socket");
408 * The task to listen for data from unicast socket is added to the thread pool.
409 * This is a blocking call is made where we try to receive some data..
410 * We will keep waiting until some data is received.
411 * This task will be terminated when thread pool is freed on stopping the adapters.
412 * Thread context will be freed by thread on exit.
414 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
415 OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
418 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
420 return CA_MEMORY_ALLOC_FAILED;
423 ctx->stopFlag = &gStopUnicast;
424 ctx->socket_fd = *serverFD;
425 ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
426 if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))
428 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create read thread!");
429 OICFree((void *)ctx);
431 return CA_STATUS_FAILED;
434 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
438 static void CAEthernetServerDestroyMutex(void)
440 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
442 if (gMutexUnicastServer)
444 u_mutex_free(gMutexUnicastServer);
445 gMutexUnicastServer = NULL;
449 if (gMutexSecureUnicastServer)
451 u_mutex_free(gMutexSecureUnicastServer);
452 gMutexSecureUnicastServer = NULL;
456 if (gMutexMulticastServer)
458 u_mutex_free(gMutexMulticastServer);
459 gMutexMulticastServer = NULL;
462 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
465 static CAResult_t CAEthernetServerCreateMutex(void)
467 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
469 gMutexUnicastServer = u_mutex_new();
470 if (!gMutexUnicastServer)
472 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
473 return CA_STATUS_FAILED;
477 gMutexSecureUnicastServer = u_mutex_new();
478 if (!gMutexSecureUnicastServer)
480 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
482 CAEthernetServerDestroyMutex();
483 return CA_STATUS_FAILED;
487 gMutexMulticastServer = u_mutex_new();
488 if (!gMutexMulticastServer)
490 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
492 CAEthernetServerDestroyMutex();
493 return CA_STATUS_FAILED;
496 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
500 CAResult_t CAEthernetInitializeServer(const u_thread_pool_t threadPool)
502 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
505 VERIFY_NON_NULL(threadPool, ETHERNET_SERVER_TAG, "Thread pool handle is NULL");
508 if (CA_STATUS_OK != CAEthernetServerCreateMutex())
510 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create mutex!");
511 return CA_STATUS_FAILED;
514 gThreadPool = threadPool;
516 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
520 void CAEthernetTerminateServer(void)
522 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
527 CAEthernetServerDestroyMutex();
529 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
532 CAResult_t CAEthernetStartUnicastServer(const char *localAddress, int16_t *port,
533 const bool forceStart, const bool isSecured,
536 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
539 VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
540 VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port");
541 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
545 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: port is invalid!");
546 return CA_STATUS_INVALID_PARAM;
550 if (CA_FALSE == isSecured)
552 u_mutex_lock(gMutexUnicastServer);
553 if (-1 != gUnicastServerSocketFD)
555 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
556 CA_SERVER_STARTED_ALREADY);
558 *serverFD = gUnicastServerSocketFD;
559 u_mutex_unlock(gMutexUnicastServer);
560 return CA_SERVER_STARTED_ALREADY;
563 gStopUnicast = false;
564 if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
565 &gUnicastServerSocketFD))
567 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
568 gUnicastServerSocketFD = -1;
569 u_mutex_unlock(gMutexUnicastServer);
570 return CA_STATUS_FAILED;
573 *serverFD = gUnicastServerSocketFD;
574 u_mutex_unlock(gMutexUnicastServer);
577 else // Start unicast server for secured communication
579 u_mutex_lock(gMutexSecureUnicastServer);
580 if (-1 != gSecureUnicastServerSocketFD)
582 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
583 CA_SERVER_STARTED_ALREADY);
585 *serverFD = gSecureUnicastServerSocketFD;
586 u_mutex_unlock(gMutexSecureUnicastServer);
587 return CA_SERVER_STARTED_ALREADY;
590 gStopSecureUnicast = false;
591 if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
592 &gSecureUnicastServerSocketFD))
594 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
595 gSecureUnicastServerSocketFD = -1;
596 u_mutex_unlock(gMutexSecureUnicastServer);
597 return CA_STATUS_FAILED;
600 *serverFD = gSecureUnicastServerSocketFD;
601 u_mutex_unlock(gMutexSecureUnicastServer);
604 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
608 CAResult_t CAEthernetStartMulticastServer(const char *localAddress, const char *multicastAddress,
609 const int16_t multicastPort, int32_t *serverFD)
611 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
614 VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
615 VERIFY_NON_NULL(multicastAddress, ETHERNET_SERVER_TAG, "port");
616 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
618 int16_t port = multicastPort;
621 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: Multicast port is invalid!");
622 return CA_STATUS_INVALID_PARAM;
625 u_mutex_lock(gMutexMulticastServer);
627 if (gMulticastServerSocketFD != -1)
629 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server is already running!");
630 u_mutex_unlock(gMutexMulticastServer);
631 return CA_SERVER_STARTED_ALREADY;
634 CAResult_t ret = CACreateSocket(&gMulticastServerSocketFD, multicastAddress, &port, true);
635 if (ret != CA_STATUS_OK)
637 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create multicast socket");
638 u_mutex_unlock(gMutexMulticastServer);
642 // Add membership to receiving socket (join group)
643 memset(&gMulticastMemberReq, 0, sizeof(struct ip_mreq));
644 gMulticastMemberReq.imr_interface.s_addr = inet_addr(localAddress);
645 inet_aton(multicastAddress, &gMulticastMemberReq.imr_multiaddr);
647 if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
648 (char *) &gMulticastMemberReq,
649 sizeof(struct ip_mreq)))
651 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
653 close(gMulticastServerSocketFD);
654 gMulticastServerSocketFD = -1;
655 u_mutex_unlock(gMutexMulticastServer);
656 return CA_STATUS_FAILED;
660 * The task to listen to data from multicastcast socket is added to the thread pool.
661 * This is a blocking call is made where we try to receive some data.
662 * We will keep waiting until some data is received.
663 * This task will be terminated when thread pool is freed on stopping the adapters.
664 * Thread context will be freed by thread on exit.
666 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
667 OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
670 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
671 close(gMulticastServerSocketFD);
672 gMulticastServerSocketFD = -1;
673 return CA_MEMORY_ALLOC_FAILED;
676 ctx->stopFlag = &gStopMulticast;
677 ctx->socket_fd = gMulticastServerSocketFD;
678 ctx->type = CA_MULTICAST_SERVER;
680 gStopMulticast = false;
681 if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))
683 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "thread_pool_add_task failed!");
685 close(gMulticastServerSocketFD);
686 gMulticastServerSocketFD = -1;
687 gStopMulticast = true;
688 u_mutex_unlock(gMutexMulticastServer);
689 return CA_STATUS_FAILED;
692 *serverFD = gMulticastServerSocketFD;
693 strncpy(gMulticastServerInterface, localAddress, IPNAMESIZE);
694 u_mutex_unlock(gMutexMulticastServer);
696 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
700 CAResult_t CAEthernetStopUnicastServer()
702 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
704 u_mutex_lock(gMutexUnicastServer);
706 CAResult_t ret = CACloseSocket(&gUnicastServerSocketFD);
707 u_mutex_unlock(gMutexUnicastServer);
709 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Unicast server stopped [%d]", ret);
714 CAResult_t CAEthernetStopSecureUnicastServer()
716 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
718 u_mutex_lock(gMutexSecureUnicastServer);
719 gStopSecureUnicast = true;
720 CAResult_t ret = CACloseSocket(&gSecureUnicastServerSocketFD);
721 u_mutex_unlock(gMutexSecureUnicastServer);
723 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Secured unicast server stopped [%d]", ret);
728 CAResult_t CAEthernetStopMulticastServer(void)
730 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
732 u_mutex_lock(gMutexMulticastServer);
734 if (gMulticastServerSocketFD == -1)
736 OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast server is not yet started");
737 u_mutex_unlock(gMutexMulticastServer);
738 return CA_SERVER_NOT_STARTED;
741 gStopMulticast = true;
743 // leave the group after you are done
744 if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
745 (char *)&gMulticastMemberReq,
746 sizeof(struct ip_mreq)))
748 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",
752 CAResult_t ret = CACloseSocket(&gMulticastServerSocketFD);
753 u_mutex_unlock(gMutexMulticastServer);
755 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Multicast server stopped [%d]", ret);
759 CAResult_t CAEthernetGetUnicastServerInfo(const bool isSecured, char **ipAddress, int16_t *port,
762 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
765 VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "IP address");
766 VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "Port");
767 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "Server ID");
769 struct sockaddr_in sockAddr;
770 socklen_t len = sizeof(struct sockaddr_in);
771 if (-1 == getsockname(gUnicastServerSocketFD, (struct sockaddr *)&sockAddr, &len))
773 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));
774 return CA_STATUS_FAILED;
778 const char *serverAddress = inet_ntoa(sockAddr.sin_addr);
779 *ipAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) : NULL;
780 *port = ntohs(sockAddr.sin_port);
782 *serverFD = (CA_TRUE == isSecured) ? gSecureUnicastServerSocketFD : gUnicastServerSocketFD;
784 *serverFD = gUnicastServerSocketFD;
787 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
791 void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
793 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
794 gPacketReceivedCallback = callback;
797 void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
799 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
800 gExceptionCallback = callback;