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);
216 const char *srcIPAddress = NULL;
217 int32_t srcPort = -1;
219 srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
220 srcPort = ntohs(srcSockAddress.sin_port);
222 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
223 srcIPAddress, srcPort);
224 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
225 recvBuffer, recvLen);
227 char *netMask = NULL;
228 if (CA_STATUS_OK != CAEthernetGetInterfaceSubnetMask(&netMask))
230 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to get ethernet subnet");
234 if(!CAAdapterIsSameSubnet(gMulticastServerInterface, srcIPAddress, netMask))
236 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Packet received from different subnet, Ignore!");
243 case CA_UNICAST_SERVER:
244 case CA_MULTICAST_SERVER:
245 // Notify data to upper layer
246 if (gPacketReceivedCallback)
248 gPacketReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);
252 case CA_SECURED_UNICAST_SERVER:
254 CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,
256 (uint8_t *)recvBuffer,
257 recvLen, DTLS_ETHERNET);
258 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
261 #endif //__WITH_DTLS__
263 // Should never occur
264 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Invalid server type");
270 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
273 static CAResult_t CACreateSocket(int32_t* socketFD, const char *localIp, int16_t *port,
274 const bool forceStart)
277 // Create a UDP socket
278 if (-1 == (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
280 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to create Socket, Error code: %s",
282 return CA_STATUS_FAILED;
285 // Make the socket non-blocking
286 if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
288 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
292 return CA_STATUS_FAILED;
295 if (true == forceStart)
297 int32_t setOptionOn = 1;
298 if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
299 (char *) &setOptionOn,
300 sizeof(setOptionOn)))
302 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
306 return CA_STATUS_FAILED;
310 struct sockaddr_in sockAddr;
311 bool isBound = false;
312 int16_t serverPort = *port;
314 memset((char *) &sockAddr, 0, sizeof(sockAddr));
315 sockAddr.sin_family = AF_INET;
316 sockAddr.sin_port = htons(serverPort);
319 sockAddr.sin_addr.s_addr = inet_addr(localIp);
323 sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
327 for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
329 if (-1 == bind(sock, (struct sockaddr *) &sockAddr,
332 if (false == forceStart)
334 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
337 //Set the port to next one
339 sockAddr.sin_port = htons(serverPort);
344 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]!",
354 if (false == isBound)
357 return CA_STATUS_FAILED;
365 static CAResult_t CACloseSocket(int32_t *socketFD)
369 OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Server not running");
370 return CA_SERVER_NOT_STARTED;
374 if (-1 == close(*socketFD))
376 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
378 return CA_STATUS_FAILED;
385 static CAResult_t CAStartUnicastServer(const char *localAddress, int16_t *port,
386 const bool forceStart, bool isSecured, int32_t *serverFD)
388 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
390 CAResult_t ret = CACreateSocket(serverFD, localAddress, port, forceStart);
391 if(CA_STATUS_OK != ret)
393 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create unicast socket");
398 * The task to listen for data from unicast socket is added to the thread pool.
399 * This is a blocking call is made where we try to receive some data..
400 * We will keep waiting until some data is received.
401 * This task will be terminated when thread pool is freed on stopping the adapters.
402 * Thread context will be freed by thread on exit.
404 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
405 OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
408 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
410 return CA_MEMORY_ALLOC_FAILED;
413 ctx->stopFlag = &gStopUnicast;
414 ctx->socket_fd = *serverFD;
415 ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER:CA_UNICAST_SERVER;
416 if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))
418 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create read thread!");
419 OICFree((void *)ctx);
421 return CA_STATUS_FAILED;
424 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
428 static void CAEthernetServerDestroyMutex(void)
430 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
432 if (gMutexUnicastServer)
434 u_mutex_free(gMutexUnicastServer);
435 gMutexUnicastServer = NULL;
439 if (gMutexSecureUnicastServer)
441 u_mutex_free(gMutexSecureUnicastServer);
442 gMutexSecureUnicastServer = NULL;
446 if (gMutexMulticastServer)
448 u_mutex_free(gMutexMulticastServer);
449 gMutexMulticastServer = NULL;
452 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
455 static CAResult_t CAEthernetServerCreateMutex(void)
457 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
459 gMutexUnicastServer = u_mutex_new();
460 if (!gMutexUnicastServer)
462 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
463 return CA_STATUS_FAILED;
467 gMutexSecureUnicastServer = u_mutex_new();
468 if (!gMutexSecureUnicastServer)
470 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
472 CAEthernetServerDestroyMutex();
473 return CA_STATUS_FAILED;
477 gMutexMulticastServer = u_mutex_new();
478 if (!gMutexMulticastServer)
480 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
482 CAEthernetServerDestroyMutex();
483 return CA_STATUS_FAILED;
486 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
490 CAResult_t CAEthernetInitializeServer(const u_thread_pool_t threadPool)
492 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
495 VERIFY_NON_NULL(threadPool, ETHERNET_SERVER_TAG, "Thread pool handle is NULL");
498 if (CA_STATUS_OK != CAEthernetServerCreateMutex())
500 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create mutex!");
501 return CA_STATUS_FAILED;
504 gThreadPool = threadPool;
506 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
510 void CAEthernetTerminateServer(void)
512 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
517 CAEthernetServerDestroyMutex();
519 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
522 CAResult_t CAEthernetStartUnicastServer(const char *localAddress, int16_t *port,
523 const bool forceStart, const bool isSecured,
526 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
529 VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
530 VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port");
531 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
535 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: port is invalid!");
536 return CA_STATUS_INVALID_PARAM;
540 if (CA_FALSE == isSecured)
542 u_mutex_lock(gMutexUnicastServer);
543 if (-1 != gUnicastServerSocketFD)
545 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
546 CA_SERVER_STARTED_ALREADY);
548 *serverFD = gUnicastServerSocketFD;
549 u_mutex_unlock(gMutexUnicastServer);
550 return CA_SERVER_STARTED_ALREADY;
553 gStopUnicast = false;
554 if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
555 &gUnicastServerSocketFD))
557 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
558 gUnicastServerSocketFD = -1;
559 u_mutex_unlock(gMutexUnicastServer);
560 return CA_STATUS_FAILED;
563 *serverFD = gUnicastServerSocketFD;
564 u_mutex_unlock(gMutexUnicastServer);
567 else // Start unicast server for secured communication
569 u_mutex_lock(gMutexSecureUnicastServer);
570 if (-1 != gSecureUnicastServerSocketFD)
572 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
573 CA_SERVER_STARTED_ALREADY);
575 *serverFD = gSecureUnicastServerSocketFD;
576 u_mutex_unlock(gMutexSecureUnicastServer);
577 return CA_SERVER_STARTED_ALREADY;
580 gStopSecureUnicast = false;
581 if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
582 &gSecureUnicastServerSocketFD))
584 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
585 gSecureUnicastServerSocketFD = -1;
586 u_mutex_unlock(gMutexSecureUnicastServer);
587 return CA_STATUS_FAILED;
590 *serverFD = gSecureUnicastServerSocketFD;
591 u_mutex_unlock(gMutexSecureUnicastServer);
594 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
598 CAResult_t CAEthernetStartMulticastServer(const char *localAddress, const char *multicastAddress,
599 const int16_t multicastPort, int32_t *serverFD)
601 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
604 VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "Local address is NULL");
605 VERIFY_NON_NULL(multicastAddress, ETHERNET_SERVER_TAG, "Multicast address is NULL");
607 int16_t port = multicastPort;
610 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: Multicast port is invalid!");
611 return CA_STATUS_INVALID_PARAM;
614 u_mutex_lock(gMutexMulticastServer);
616 if (gMulticastServerSocketFD != -1)
618 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server is already running!");
619 u_mutex_unlock(gMutexMulticastServer);
620 return CA_SERVER_STARTED_ALREADY;
623 CAResult_t ret = CACreateSocket(&gMulticastServerSocketFD, multicastAddress, &port, true);
624 if(ret != CA_STATUS_OK)
626 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create multicast socket");
627 u_mutex_unlock(gMutexMulticastServer);
631 // Add membership to receiving socket (join group)
632 memset(&gMulticastMemberReq, 0, sizeof(struct ip_mreq));
633 gMulticastMemberReq.imr_interface.s_addr = inet_addr(localAddress);
634 inet_aton(multicastAddress, &gMulticastMemberReq.imr_multiaddr);
636 if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
637 (char *) &gMulticastMemberReq,
638 sizeof(struct ip_mreq)))
640 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
642 close(gMulticastServerSocketFD);
643 gMulticastServerSocketFD = -1;
644 u_mutex_unlock(gMutexMulticastServer);
645 return CA_STATUS_FAILED;
649 * The task to listen to data from multicastcast socket is added to the thread pool.
650 * This is a blocking call is made where we try to receive some data.
651 * We will keep waiting until some data is received.
652 * This task will be terminated when thread pool is freed on stopping the adapters.
653 * Thread context will be freed by thread on exit.
655 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
656 OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
659 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
660 close(gMulticastServerSocketFD);
661 gMulticastServerSocketFD = -1;
662 return CA_MEMORY_ALLOC_FAILED;
665 ctx->stopFlag = &gStopMulticast;
666 ctx->socket_fd = gMulticastServerSocketFD;
667 ctx->type = CA_MULTICAST_SERVER;
669 gStopMulticast = false;
670 if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))
672 OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "thread_pool_add_task failed!");
674 close(gMulticastServerSocketFD);
675 gMulticastServerSocketFD = -1;
676 gStopMulticast = true;
677 u_mutex_unlock(gMutexMulticastServer);
678 return CA_STATUS_FAILED;
681 *serverFD = gMulticastServerSocketFD;
682 strncpy(gMulticastServerInterface, localAddress, sizeof(gMulticastServerInterface));
683 u_mutex_unlock(gMutexMulticastServer);
685 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
689 CAResult_t CAEthernetStopUnicastServer()
691 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
693 u_mutex_lock(gMutexUnicastServer);
695 CAResult_t ret = CACloseSocket(&gUnicastServerSocketFD);
696 u_mutex_unlock(gMutexUnicastServer);
698 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Unicast server stopped [%d]", ret);
703 CAResult_t CAEthernetStopSecureUnicastServer()
705 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
707 u_mutex_lock(gMutexSecureUnicastServer);
708 gStopSecureUnicast = true;
709 CAResult_t ret = CACloseSocket(&gSecureUnicastServerSocketFD);
710 u_mutex_unlock(gMutexSecureUnicastServer);
712 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Secured unicast server stopped [%d]", ret);
717 CAResult_t CAEthernetStopMulticastServer(void)
719 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
721 u_mutex_lock(gMutexMulticastServer);
723 if (gMulticastServerSocketFD == -1)
725 OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast server is not yet started");
726 u_mutex_unlock(gMutexMulticastServer);
727 return CA_SERVER_NOT_STARTED;
730 gStopMulticast = true;
732 // leave the group after you are done
733 if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
734 (char *)&gMulticastMemberReq,
735 sizeof(struct ip_mreq)))
737 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",
741 CAResult_t ret = CACloseSocket(&gMulticastServerSocketFD);
742 u_mutex_unlock(gMutexMulticastServer);
744 OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Multicast server stopped [%d]", ret);
748 CAResult_t CAEthernetGetUnicastServerInfo(const bool isSecured, char **ipAddress, int16_t *port,
751 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
754 VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "IP address");
755 VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "Port");
756 VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "Server ID");
758 struct sockaddr_in sockAddr;
759 socklen_t len = sizeof(struct sockaddr_in);
760 if (-1 == getsockname(gUnicastServerSocketFD, (struct sockaddr *)&sockAddr, &len))
762 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));
763 return CA_STATUS_FAILED;
767 const char *serverAddress = inet_ntoa(sockAddr.sin_addr);
768 *ipAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) : NULL;
769 *port = ntohs(sockAddr.sin_port);
771 *serverFD = (CA_TRUE == isSecured) ? gSecureUnicastServerSocketFD : gUnicastServerSocketFD;
773 *serverFD = gUnicastServerSocketFD;
776 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
780 void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
782 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
783 gPacketReceivedCallback = callback;
786 void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
788 OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
789 gExceptionCallback = callback;