* limitations under the License.
*
******************************************************************/
+
+// Defining _POSIX_C_SOURCE macro with 200809L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1-2008 base
+// specification (excluding the XSI extension).
+// For POSIX.1-2008 base specification,
+// Refer http://pubs.opengroup.org/stage7tc1/
+//
+// For this specific file, see use of strndup,
+// Refer http://man7.org/linux/man-pages/man3/strdup.3.html
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+// Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
+// definitions that may otherwise be skipped. Skipping can cause implicit
+// declaration warnings and/or bugs and subtle problems in code execution.
+// For glibc information on feature test macros,
+// Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
+//
+// This file requires #define use due to struct ip_mreq
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE
+#include <netinet/in.h>
+
#include "caethernetinterface.h"
#include <sys/types.h>
#include <fcntl.h>
#include <sys/select.h>
#include <arpa/inet.h>
-#include <netinet/in.h>
+#include <string.h>
+
#include <errno.h>
#include "pdu.h"
#include "caadapterutils.h"
+#ifdef __WITH_DTLS__
+#include "caadapternetdtls.h"
+#endif
#include "umutex.h"
+#include "oic_malloc.h"
/**
* @def ETHERNET_SERVER_TAG
#define CA_UDP_BIND_RETRY_COUNT 10
/**
- * @var gUnicastServerSocketDescriptor
- * @brief socket descriptor for unicast server
+ * @def IPNAMESIZE
+ * @brief max length for ip
*/
-static int32_t gUnicastServerSocketDescriptor = -1;
+#define IPNAMESIZE 16
/**
- * @var gUnicastServerSocketDescriptor
- * @brief socket descriptor for unicast server
+ * @var g_unicastServerSocketFD
+ * @brief Unicast server socket descriptor
*/
-static char *gUnicastServerAddress = NULL;
+static int32_t g_unicastServerSocketFD = -1;
/**
- * @var gUnicastServerSocketDescriptor
- * @brief socket descriptor for unicast server
+ * @var g_mutexUnicastServer
+ * @brief Mutex to synchronize unicast server
*/
-static int16_t gUnicastServerPort = -1;
+static u_mutex g_mutexUnicastServer = NULL;
/**
- * @var gMutexUnicastServerSocketDescriptor
- * @brief Mutex for socket descriptor for unicast server
- */
-static u_mutex gMutexUnicastServerSocketDescriptor = NULL;
-/**
- * @var gMulticastServerSocketDescriptor
- * @brief socket descriptor for multicast server
- */
-static int32_t gMulticastServerSocketDescriptor = -1;
-
-/**
- * @var gMutexMulticastServerSocketDescriptor
- * @brief Mutex for socket descriptor for Multicast server
- */
-static u_mutex gMutexMulticastServerSocketDescriptor = NULL;
-
-/**
- * @var gThreadPool
- * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
- */
-static u_thread_pool_t gThreadPool = NULL;
-
-/**
- * @var gMReq
- * @brief ip_mreq structure passed to join a multicast group
+ * @var g_stopUnicast
+ * @brief Flag to control the Receive Unicast Data Thread
*/
-static struct ip_mreq gMReq;
+static bool g_stopUnicast = false;
/**
- * @var gStopUnicast
- * @brief Flag to control the Receive Unicast Data Thread
+ * @var g_multicastServerSocketFD
+ * @brief socket descriptor for multicast server
*/
-static bool gStopUnicast = false;
+static int32_t g_multicastServerSocketFD = -1;
/**
- * @var gMutexStopUnicast
- * @brief Mutex for gStopUnicast
+ * @var g_mutexMulticastServer
+ * @brief Mutex to synchronize secure multicast server
*/
-static u_mutex gMutexStopUnicast = NULL;
+static u_mutex g_mutexMulticastServer = NULL;
/**
- * @var gStopMulticast
+ * @var g_stopMulticast
* @brief Flag to control the Receive Multicast Data Thread
*/
-static bool gStopMulticast = false;
+static bool g_stopMulticast = false;
+#ifdef __WITH_DTLS__
/**
- * @var gMutexStopMulticast
- * @brief Mutex for gStopMulticast
+ * @var g_secureUnicastServerSocketFD
+ * @brief Secure unicast server socket descriptor
*/
-static u_mutex gMutexStopMulticast = NULL;
+static int32_t g_secureUnicastServerSocketFD = -1;
/**
- * @var gPacketReceivedCallback
- * @brief Callback for notifying the upper layer on receival data from remote OIC device
+ * @var g_mutexSecureUnicastServer
+ * @brief Mutex to synchronize secure unicast server
*/
-static CAEthernetPacketReceivedCallback gPacketReceivedCallback = NULL;
+static u_mutex g_mutexSecureUnicastServer = NULL;
/**
- * @var gExceptionCallback
- * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
+ * @var g_stopSecureUnicast
+ * @brief Flag to control the unicast secure data receive thread
*/
-static CAEthernetExceptionCallback gExceptionCallback = NULL;
+static bool g_stopSecureUnicast = false;
+#endif
/**
- * @var gUnicastRecvBuffer
- * @brief Character buffer used for receiving unicast data from network
+ * @var g_threadPool
+ * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
*/
-static char gUnicastRecvBuffer[COAP_MAX_PDU_SIZE] = {0};
+static u_thread_pool_t g_threadPool = NULL;
/**
- * @var gMulticastRecvBuffer
- * @brief Character buffer used for receiving multicast data from network
+ * @var g_multicastServerInterface
+ * @brief Local interface on which multicast server is running
*/
-static char gMulticastRecvBuffer[COAP_MAX_PDU_SIZE] = {0};
+static char g_multicastServerInterface[IPNAMESIZE];
/**
- * @fn CAEthernetServerCreateMutex
- * @brief Creates and initializes mutex
+ * @var g_multicastMemberReq
+ * @brief ip_mreq structure passed to join a multicast group
*/
-static CAResult_t CAEthernetServerCreateMutex(void);
+static struct ip_mreq g_multicastMemberReq;
/**
- * @fn CAEthernetServerDestroyMutex
- * @brief Releases all created mutex
+ * @var g_packetReceivedCallback
+ * @brief Callback for notifying the upper layer on receival data from remote OIC device
*/
-static void CAEthernetServerDestroyMutex(void);
+static CAEthernetPacketReceivedCallback g_packetReceivedCallback = NULL;
/**
- * @fn CAReceiveThreadForMulticast
- * @brief Handler thread for receiving data on multicast server
+ * @var g_exceptionCallback
+ * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
*/
-static void *CAReceiveThreadForMulticast(void *data);
+static CAEthernetExceptionCallback g_exceptionCallback = NULL;
/**
- * @fn CAEthernetReceiveThreadForUnicast
- * @brief Handler thread for receiving data on unicast server
+ @brief Thread context information for unicast, multicast and secured unicast server
*/
-static void *CAEthernetReceiveThreadForUnicast(void *data);
-
-CAResult_t CAEthernetInitializeServer(const u_thread_pool_t threadPool)
+typedef struct
{
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
-
- //Input validation
- VERIFY_NON_NULL(threadPool, ETHERNET_SERVER_TAG, "Thread pool handle is NULL");
-
- //Initialize mutex
- if (CA_STATUS_OK != CAEthernetServerCreateMutex())
- {
- OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create mutex!");
- return CA_STATUS_FAILED;
- }
-
- gThreadPool = threadPool;
-
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-void CAEthernetTerminateServer(void)
-{
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
-
- gThreadPool = NULL;
-
- //Destroy mutex
- CAEthernetServerDestroyMutex();
-
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
-}
+ bool *stopFlag;
+ int32_t socket_fd;
+ CAAdapterServerType_t type;
+} CAAdapterReceiveThreadContext_t;
-CAResult_t CAEthernetStartMulticastServer(const char *localAddress, const char *multicastAddress,
- const int16_t multicastPort, int32_t *serverFD)
+static void CAReceiveHandler(void *data)
{
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- if (gMulticastServerSocketDescriptor != -1)
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server is already running!");
- return CA_SERVER_STARTED_ALREADY;
- }
+ // Input validation
+ VERIFY_NON_NULL_VOID(data, ETHERNET_SERVER_TAG, "Invalid thread context");
- VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "Local address is NULL");
- VERIFY_NON_NULL(multicastAddress, ETHERNET_SERVER_TAG, "Multicast address is NULL");
+ CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data;
+ fd_set reads;
+ struct timeval timeout;
+ char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
- if (0 >= multicastPort)
+ while (true != *(ctx->stopFlag))
{
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: Multicast port is invalid!");
- return CA_STATUS_INVALID_PARAM;
- }
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
- // Create a datagram socket on which to recv/send.
- u_mutex_lock(gMutexStopMulticast);
- gStopMulticast = false;
- u_mutex_unlock(gMutexStopMulticast);
+ FD_ZERO(&reads);
+ FD_SET(ctx->socket_fd, &reads);
- u_mutex_lock(gMutexMulticastServerSocketDescriptor);
+ int32_t ret = select(ctx->socket_fd + 1, &reads, NULL, NULL, &timeout);
+ if (*(ctx->stopFlag) == true)
+ {
+ OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG,
+ "Stop request received for [%d] server", ctx->type);
+ break;
+ }
- // create a UDP socket
- if ((gMulticastServerSocketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to Create Socket, Error code: %s",
- strerror(errno));
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- return CA_SOCKET_OPERATION_FAILED;
- }
+ if (ret < 0)
+ {
+ OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
+ continue;
+ }
- // Make the socket non-blocking
- if (-1 == fcntl(gMulticastServerSocketDescriptor, F_SETFL, O_NONBLOCK))
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
- strerror(errno));
- close(gMulticastServerSocketDescriptor);
- gMulticastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- return CA_STATUS_FAILED;
- }
+ if (!FD_ISSET(ctx->socket_fd, &reads))
+ {
+ continue;
+ }
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket creation success");
+ memset(recvBuffer, 0, sizeof(recvBuffer));
- int32_t setOptionOn = 1;
- if (-1 == setsockopt(gMulticastServerSocketDescriptor, SOL_SOCKET, SO_REUSEADDR,
- (char *) &setOptionOn,
- sizeof(setOptionOn)))
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to setsockopt for SO_REUSEADDR, Error code: %s",
- strerror(errno));
- close(gMulticastServerSocketDescriptor);
- gMulticastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- return CA_SOCKET_OPERATION_FAILED;
- }
+ // Read data from socket
+ struct sockaddr_in srcSockAddress;
+ int32_t recvLen;
+ socklen_t srcAddressLen = sizeof(srcSockAddress);
- struct sockaddr_in sockAddr;
- memset((char *) &sockAddr, 0, sizeof(sockAddr));
+ recvLen = recvfrom(ctx->socket_fd, recvBuffer,
+ sizeof(recvBuffer), 0, (struct sockaddr *) &srcSockAddress,
+ &srcAddressLen);
- sockAddr.sin_family = AF_INET;
- sockAddr.sin_port = htons(multicastPort);
- sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (-1 == recvLen)
+ {
+ OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
+ continue;
+ }
+ else if (0 == recvLen)
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Server socket shutdown [%d]!", ctx->type);
- //bind socket to multicast port
- if (-1 == bind(gMulticastServerSocketDescriptor, (struct sockaddr *) &sockAddr,
- sizeof(sockAddr)))
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to Bind Socket! Return Code[%d]",
- CA_SOCKET_OPERATION_FAILED);
- close(gMulticastServerSocketDescriptor);
- gMulticastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- return CA_SOCKET_OPERATION_FAILED;
- }
+ // Notify upper layer this exception
+ if (g_exceptionCallback)
+ {
+ g_exceptionCallback(ctx->type);
+ }
+ OICFree(ctx);
+ ctx = NULL;
+ return;
+ }
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket bind success");
+ char srcIPAddress[CA_IPADDR_SIZE] = {0};
+ inet_ntop(AF_INET, &srcSockAddress.sin_addr.s_addr, srcIPAddress, sizeof(srcIPAddress));
+ uint16_t srcPort = 0;
+ srcPort = ntohs(srcSockAddress.sin_port);
- //Add membership to receiving socket (join group)
- memset(&gMReq, 0, sizeof(struct ip_mreq));
- gMReq.imr_interface.s_addr = htonl(INADDR_ANY);
- inet_aton(multicastAddress, &gMReq.imr_multiaddr);
+ OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
+ srcIPAddress, srcPort);
+ OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
+ recvBuffer, recvLen);
- if (-1 == setsockopt(gMulticastServerSocketDescriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *) &gMReq,
- sizeof(struct ip_mreq)))
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
- strerror(errno));
- close(gMulticastServerSocketDescriptor);
- gMulticastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- return CA_SOCKET_OPERATION_FAILED;
- }
+ char *netMask = NULL;
+ if (CA_STATUS_OK != CAEthernetGetInterfaceSubnetMask(&netMask))
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to get ethernet subnet");
+ continue;
+ }
- /**
- * The task to listen to data from multicastcast socket is added to the thread pool.
- * This is a blocking call is made where we try to receive some data.. We will keep waiting until some data is received.
- * This task will be terminated when thread pool is freed on stopping the adapters.
- */
- if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CAReceiveThreadForMulticast,
- (void *)NULL))
- {
- OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "[testThreadPool] thread_pool_add_task failed!");
+ if (!CAAdapterIsSameSubnet(g_multicastServerInterface, srcIPAddress, netMask))
+ {
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Packet received from different subnet, Ignore!");
+ if (NULL != netMask)
+ {
+ OICFree(netMask);
+ }
+ netMask = NULL;
+ continue;
+ }
- close(gMulticastServerSocketDescriptor);
- gMulticastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- return CA_STATUS_FAILED;
+ OICFree(netMask);
+ switch (ctx->type)
+ {
+ case CA_UNICAST_SERVER:
+ case CA_MULTICAST_SERVER:
+ // Notify data to upper layer
+ if (g_packetReceivedCallback)
+ {
+ g_packetReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);
+ }
+ break;
+#ifdef __WITH_DTLS__
+ case CA_SECURED_UNICAST_SERVER:
+ {
+ CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,
+ srcPort,
+ (uint8_t *)recvBuffer,
+ recvLen, DTLS_ETHERNET);
+ OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG,
+ "CAAdapterNetDtlsDecrypt returns [%d]", ret);
+ }
+ break;
+#endif //__WITH_DTLS__
+ default:
+ // Should never occur
+ OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Invalid server type");
+ OICFree(ctx);
+ ctx = NULL;
+ return;
+ }
}
+ OICFree(ctx);
+ ctx = NULL;
- *serverFD = gMulticastServerSocketDescriptor;
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
-
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "thread_pool_add_task done");
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast Server Started Successfully");
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
- return CA_STATUS_OK;
-
}
-CAResult_t CAEthernetStartUnicastServer(const char *localAddress, int16_t *port,
- const bool forceStart, int32_t *serverFD)
+static CAResult_t CACreateSocket(int32_t *socketFD, const char *localIp, uint16_t *port,
+ bool forceStart)
{
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
-
- if (gUnicastServerSocketDescriptor != -1)
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already! Return Code[%d]",
- CA_SERVER_STARTED_ALREADY);
- return CA_SERVER_STARTED_ALREADY;
- }
-
- VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "Invalid argument : localAddress is NULL");
- VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "Invalid argument : port is NULL");
-
- if (*port < 0)
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: port is invalid!");
- return CA_STATUS_INVALID_PARAM;
- }
-
- u_mutex_lock(gMutexStopUnicast);
- gStopUnicast = false;
- u_mutex_unlock(gMutexStopUnicast);
-
- u_mutex_lock(gMutexUnicastServerSocketDescriptor);
+ int32_t sock = -1;
// Create a UDP socket
- if ((gUnicastServerSocketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (-1 == sock)
{
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to Create Socket, Error code: %s",
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to create Socket, Error code: %s",
strerror(errno));
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
- return CA_SOCKET_OPERATION_FAILED;
+ return CA_STATUS_FAILED;
}
// Make the socket non-blocking
- if (-1 == fcntl(gUnicastServerSocketDescriptor, F_SETFL, O_NONBLOCK))
+ if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
{
OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
strerror(errno));
- close(gUnicastServerSocketDescriptor);
- gUnicastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+
+ close(sock);
return CA_STATUS_FAILED;
}
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket creation success");
-
if (true == forceStart)
{
int32_t setOptionOn = 1;
- if (-1 == setsockopt(gUnicastServerSocketDescriptor, SOL_SOCKET, SO_REUSEADDR,
+ if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *) &setOptionOn,
sizeof(setOptionOn)))
{
OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
strerror(errno));
- close(gUnicastServerSocketDescriptor);
- gUnicastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
- return CA_SOCKET_OPERATION_FAILED;
+
+ close(sock);
+ return CA_STATUS_FAILED;
}
}
struct sockaddr_in sockAddr;
bool isBound = false;
- int16_t serverPort = *port;
+ uint16_t serverPort = *port;
- memset((char *) &sockAddr, 0, sizeof(sockAddr));
+ memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(serverPort);
- sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (localIp)
+ {
+ sockAddr.sin_addr.s_addr = inet_addr(localIp);
+ }
+ else
+ {
+ sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
- //Trying for bind in a loop
int16_t i;
for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
{
- if (-1 == bind(gUnicastServerSocketDescriptor, (struct sockaddr *) &sockAddr,
+ if (-1 == bind(sock, (struct sockaddr *) &sockAddr,
sizeof(sockAddr)))
{
if (false == forceStart)
{
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]. Trying again... ",
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
strerror(errno));
//Set the port to next one
if (false == isBound)
{
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind Socket! Return code[%d]",
- CA_SOCKET_OPERATION_FAILED);
- close(gUnicastServerSocketDescriptor);
- gUnicastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
- return CA_SOCKET_OPERATION_FAILED;
- }
-
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket bind success");
-
- socklen_t len = 0;
- char *serverAddress = NULL;
- if (-1 != getsockname(gUnicastServerSocketDescriptor, (struct sockaddr *)&sockAddr, &len))
- {
- serverPort = ntohs(sockAddr.sin_port);
- serverAddress = inet_ntoa(sockAddr.sin_addr);
- }
-
- /**
- * The task to listen for data from unicast socket is added to the thread pool.
- * This is a blocking call is made where we try to receive some data..
- * We will keep waiting until some data is received.
- * This task will be terminated when thread pool is freed on stopping the adapters.
- */
- if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CAEthernetReceiveThreadForUnicast,
- (void *) NULL))
- {
- OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "[testThreadPool] thread_pool_add_task failed!");
-
- close(gUnicastServerSocketDescriptor);
- gUnicastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ close(sock);
return CA_STATUS_FAILED;
}
- //Free the server address previously stored
- OICFree(gUnicastServerAddress);
- gUnicastServerAddress = NULL;
- gUnicastServerPort = serverPort;
- gUnicastServerAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) :
- NULL;
*port = serverPort;
- *serverFD = gUnicastServerSocketDescriptor;
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
-
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Unicast Server Started Successfully");
+ *socketFD = sock;
return CA_STATUS_OK;
}
-CAResult_t CAEthernetStopMulticastServer(void)
+static CAResult_t CACloseSocket(int32_t *socketFD)
{
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
-
- u_mutex_lock(gMutexMulticastServerSocketDescriptor);
-
- if (gMulticastServerSocketDescriptor == -1)
+ if (socketFD == NULL)
{
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast Server is not yet Started");
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- return CA_SERVER_NOT_STARTED;
+ return CA_STATUS_INVALID_PARAM;
}
- u_mutex_lock(gMutexStopMulticast);
- gStopMulticast = true;
-
- // leave the group after you are done
- if (-1 == setsockopt(gMulticastServerSocketDescriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (char *)&gMReq,
- sizeof(struct ip_mreq)))
+ if (-1 == *socketFD)
{
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "cannot leave multicast group, Error code: %s\n",
- strerror(errno));
+ OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Server not running");
+ return CA_SERVER_NOT_STARTED;
}
// close the socket
- if (-1 == close(gMulticastServerSocketDescriptor))
+ if (-1 == close(*socketFD))
{
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server socket close failed, Error code: %s\n",
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
strerror(errno));
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
- u_mutex_unlock(gMutexStopMulticast);
- return CA_SOCKET_OPERATION_FAILED;
+ return CA_STATUS_FAILED;
}
- u_mutex_unlock(gMutexStopMulticast);
-
- gMulticastServerSocketDescriptor = -1;
- u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
-
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast Server Stopped Successfully");
-
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
+ *socketFD = -1;
return CA_STATUS_OK;
-
}
-CAResult_t CAEthernetStopUnicastServer()
+static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port,
+ const bool forceStart, bool isSecured, int32_t *serverFD)
{
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- u_mutex_lock(gMutexUnicastServerSocketDescriptor);
- if (gUnicastServerSocketDescriptor == -1)
+ if (serverFD == NULL)
{
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Unicast Server is not yet Started");
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
- return CA_SERVER_NOT_STARTED;
+ return CA_STATUS_INVALID_PARAM;
}
- u_mutex_lock(gMutexStopUnicast);
- gStopUnicast = true;
- // close the socket
- if (-1 == close(gUnicastServerSocketDescriptor))
+ CAResult_t ret = CACreateSocket(serverFD, localAddress, port, forceStart);
+ if (CA_STATUS_OK != ret)
{
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server socket close failed, Error code: %s\n",
- strerror(errno));
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
- u_mutex_unlock(gMutexStopUnicast);
- return CA_SOCKET_OPERATION_FAILED;
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create unicast socket");
+ return ret;
}
- u_mutex_unlock(gMutexStopUnicast);
- gUnicastServerSocketDescriptor = -1;
+ /**
+ * The task to listen for data from unicast socket is added to the thread pool.
+ * This is a blocking call is made where we try to receive some data..
+ * We will keep waiting until some data is received.
+ * This task will be terminated when thread pool is freed on stopping the adapters.
+ * Thread context will be freed by thread on exit.
+ */
+ CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
+ OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
+ if (!ctx)
+ {
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
+ close(*serverFD);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
- u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ ctx->stopFlag = &g_stopUnicast;
+ ctx->socket_fd = *serverFD;
+ ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
+ if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *)ctx))
+ {
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create read thread!");
+ OICFree(ctx);
+ close(*serverFD);
+ *serverFD = -1;
+ return CA_STATUS_FAILED;
+ }
- OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Unicast Server Stopped Successfully");
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
return CA_STATUS_OK;
}
-CAResult_t CAEthernetGetUnicastServerInfo(char **ipAddress, int16_t *port, int32_t *serverFD)
+static void CAEthernetServerDestroyMutex(void)
{
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- //Input validation
- VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "ipAddress holder is NULL");
- VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port holder is NULL");
- VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "serverID holder is NULL");
-
- *ipAddress = gUnicastServerAddress;
- *port = gUnicastServerPort;
- *serverFD = gUnicastServerSocketDescriptor;
+ if (g_mutexUnicastServer)
+ {
+ u_mutex_free(g_mutexUnicastServer);
+ g_mutexUnicastServer = NULL;
+ }
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
- return CA_STATUS_OK;
-}
+#ifdef __WITH_DTLS__
+ if (g_mutexSecureUnicastServer)
+ {
+ u_mutex_free(g_mutexSecureUnicastServer);
+ g_mutexSecureUnicastServer = NULL;
+ }
+#endif
-void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
-{
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
+ if (g_mutexMulticastServer)
+ {
+ u_mutex_free(g_mutexMulticastServer);
+ g_mutexMulticastServer = NULL;
+ }
- gPacketReceivedCallback = callback;
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
}
-void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
+static CAResult_t CAEthernetServerCreateMutex(void)
{
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- gExceptionCallback = callback;
-}
-
-CAResult_t CAEthernetServerCreateMutex(void)
-{
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
+ if(g_mutexUnicastServer) {
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "mutex is already created!");
- gMutexUnicastServerSocketDescriptor = u_mutex_new();
- if (!gMutexUnicastServerSocketDescriptor)
- {
- OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
return CA_STATUS_FAILED;
}
- gMutexMulticastServerSocketDescriptor = u_mutex_new();
- if (!gMutexMulticastServerSocketDescriptor)
+ g_mutexUnicastServer = u_mutex_new();
+ if (!g_mutexUnicastServer)
{
OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
-
- CAEthernetServerDestroyMutex();
return CA_STATUS_FAILED;
}
- gMutexStopUnicast = u_mutex_new();
- if (!gMutexStopUnicast)
+#ifdef __WITH_DTLS__
+ g_mutexSecureUnicastServer = u_mutex_new();
+ if (!g_mutexSecureUnicastServer)
{
OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
CAEthernetServerDestroyMutex();
return CA_STATUS_FAILED;
}
+#endif
- gMutexStopMulticast = u_mutex_new();
- if (!gMutexStopMulticast)
+ g_mutexMulticastServer = u_mutex_new();
+ if (!g_mutexMulticastServer)
{
OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
return CA_STATUS_OK;
}
-void CAEthernetServerDestroyMutex(void)
+CAResult_t CAEthernetInitializeServer(const u_thread_pool_t threadPool)
{
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- if (gMutexUnicastServerSocketDescriptor)
- {
- u_mutex_free(gMutexUnicastServerSocketDescriptor);
- gMutexUnicastServerSocketDescriptor = NULL;
- }
+ // Input validation
+ VERIFY_NON_NULL(threadPool, ETHERNET_SERVER_TAG, "Thread pool handle is NULL");
- if (gMutexMulticastServerSocketDescriptor)
+ // Initialize mutex
+ if (CA_STATUS_OK != CAEthernetServerCreateMutex())
{
- u_mutex_free(gMutexMulticastServerSocketDescriptor);
- gMutexMulticastServerSocketDescriptor = NULL;
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create mutex!");
+ return CA_STATUS_FAILED;
}
- if (gMutexStopUnicast)
- {
- u_mutex_free(gMutexStopUnicast);
- gMutexStopUnicast = NULL;
- }
+ g_threadPool = threadPool;
- if (gMutexStopMulticast)
- {
- u_mutex_free(gMutexStopMulticast);
- gMutexStopMulticast = NULL;
- }
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CAEthernetTerminateServer(void)
+{
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
+
+ g_threadPool = NULL;
+
+ // Destroy mutex
+ CAEthernetServerDestroyMutex();
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
}
-void *CAEthernetReceiveThreadForUnicast(void *data)
+CAResult_t CAEthernetStartUnicastServer(const char *localAddress, uint16_t *port,
+ bool forceStart, bool isSecured, int32_t *serverFD)
{
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- fd_set reads;
- struct timeval timeout;
+ // Input validation
+ VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
+ VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port");
+ VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
- //keep listening for data
- while (!gStopUnicast)
+ if (0 >= *port)
{
- //OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Waiting for data..");
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: port is invalid!");
+ return CA_STATUS_INVALID_PARAM;
+ }
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ *serverFD = -1;
+ if (false == isSecured)
+ {
+ u_mutex_lock(g_mutexUnicastServer);
+ if (-1 != g_unicastServerSocketFD)
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
+ CA_SERVER_STARTED_ALREADY);
- FD_ZERO(&reads);
- FD_SET(gUnicastServerSocketDescriptor, &reads);
+ *serverFD = g_unicastServerSocketFD;
+ u_mutex_unlock(g_mutexUnicastServer);
+ return CA_SERVER_STARTED_ALREADY;
+ }
- int32_t ret = select(gUnicastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
- if (gStopUnicast)
+ g_stopUnicast = false;
+ if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
+ &g_unicastServerSocketFD))
{
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Stop Unicast is called");
- break;
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
+ g_unicastServerSocketFD = -1;
+ u_mutex_unlock(g_mutexUnicastServer);
+ return CA_STATUS_FAILED;
}
- if (ret < 0)
+
+ *serverFD = g_unicastServerSocketFD;
+ u_mutex_unlock(g_mutexUnicastServer);
+ }
+#ifdef __WITH_DTLS__
+ else // Start unicast server for secured communication
+ {
+ u_mutex_lock(g_mutexSecureUnicastServer);
+ if (-1 != g_secureUnicastServerSocketFD)
{
- OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
- continue;
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
+ CA_SERVER_STARTED_ALREADY);
+
+ *serverFD = g_secureUnicastServerSocketFD;
+ u_mutex_unlock(g_mutexSecureUnicastServer);
+ return CA_SERVER_STARTED_ALREADY;
}
- if (!FD_ISSET(gUnicastServerSocketDescriptor, &reads))
+
+ g_stopSecureUnicast = false;
+ if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
+ &g_secureUnicastServerSocketFD))
{
- //OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "No data to read");
- continue;
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
+ g_secureUnicastServerSocketFD = -1;
+ u_mutex_unlock(g_mutexSecureUnicastServer);
+ return CA_STATUS_FAILED;
}
- memset(gUnicastRecvBuffer, 0, sizeof(char)*COAP_MAX_PDU_SIZE);
+ *serverFD = g_secureUnicastServerSocketFD;
+ u_mutex_unlock(g_mutexSecureUnicastServer);
+ }
+#endif
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
- //Read data from socket
- struct sockaddr_in srcSockAddress;
- int32_t recvLen;
- socklen_t srcAddressLen = sizeof(srcSockAddress);
- if (-1 == (recvLen = recvfrom(gUnicastServerSocketDescriptor, gUnicastRecvBuffer,
- COAP_MAX_PDU_SIZE, 0, (struct sockaddr *) &srcSockAddress,
- &srcAddressLen)))
- {
- OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
- continue;
- }
- else if (0 == recvLen)
- {
- OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Unicast server socket is shutdown !");
+CAResult_t CAEthernetStartMulticastServer(const char *localAddress,
+ const char *multicastAddress, const uint16_t multicastPort, int32_t *serverFD)
+{
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- //Notify upper layer this exception
- if (gExceptionCallback)
- {
- gExceptionCallback(CA_UNICAST_SERVER);
- }
- return NULL;
- }
+ // Input validation
+ VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
+ VERIFY_NON_NULL(multicastAddress, ETHERNET_SERVER_TAG, "port");
+ VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
- const char *srcIPAddress = NULL;
- int32_t srcPort = -1;
+ uint16_t port = multicastPort;
+ if (0 >= port)
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: Multicast port is invalid!");
+ return CA_STATUS_INVALID_PARAM;
+ }
- srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
- srcPort = ntohs(srcSockAddress.sin_port);
+ u_mutex_lock(g_mutexMulticastServer);
- OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
- srcIPAddress, srcPort);
- OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
- gUnicastRecvBuffer, recvLen);
+ if (g_multicastServerSocketFD != -1)
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server is already running!");
+ u_mutex_unlock(g_mutexMulticastServer);
+ return CA_SERVER_STARTED_ALREADY;
+ }
- //Notify data to upper layer
- if (gPacketReceivedCallback)
- {
- gPacketReceivedCallback(srcIPAddress, srcPort, gUnicastRecvBuffer, recvLen);
- }
+ CAResult_t ret = CACreateSocket(&g_multicastServerSocketFD, multicastAddress, &port, true);
+ if (ret != CA_STATUS_OK)
+ {
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create multicast socket");
+ u_mutex_unlock(g_mutexMulticastServer);
+ return ret;
+ }
+
+ // Add membership to receiving socket (join group)
+ memset(&g_multicastMemberReq, 0, sizeof(struct ip_mreq));
+ g_multicastMemberReq.imr_interface.s_addr = inet_addr(localAddress);
+ inet_aton(multicastAddress, &g_multicastMemberReq.imr_multiaddr);
+
+ if (-1 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *) &g_multicastMemberReq,
+ sizeof(struct ip_mreq)))
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
+ strerror(errno));
+ close(g_multicastServerSocketFD);
+ g_multicastServerSocketFD = -1;
+ u_mutex_unlock(g_mutexMulticastServer);
+ return CA_STATUS_FAILED;
+ }
+
+ /**
+ * The task to listen to data from multicastcast socket is added to the thread pool.
+ * This is a blocking call is made where we try to receive some data.
+ * We will keep waiting until some data is received.
+ * This task will be terminated when thread pool is freed on stopping the adapters.
+ * Thread context will be freed by thread on exit.
+ */
+ CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
+ OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
+ if (!ctx)
+ {
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
+ close(g_multicastServerSocketFD);
+ g_multicastServerSocketFD = -1;
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ ctx->stopFlag = &g_stopMulticast;
+ ctx->socket_fd = g_multicastServerSocketFD;
+ ctx->type = CA_MULTICAST_SERVER;
+
+ g_stopMulticast = false;
+ if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *)ctx))
+ {
+ OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "thread_pool_add_task failed!");
+
+ close(g_multicastServerSocketFD);
+ g_multicastServerSocketFD = -1;
+ g_stopMulticast = true;
+ u_mutex_unlock(g_mutexMulticastServer);
+ return CA_STATUS_FAILED;
}
+ *serverFD = g_multicastServerSocketFD;
+ strncpy(g_multicastServerInterface, localAddress, IPNAMESIZE);
+ u_mutex_unlock(g_mutexMulticastServer);
+
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
- return NULL;
+ return CA_STATUS_OK;
}
-void *CAReceiveThreadForMulticast(void *data)
+CAResult_t CAEthernetStopUnicastServer()
{
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- fd_set reads;
- struct timeval timeout;
+ u_mutex_lock(g_mutexUnicastServer);
+ g_stopUnicast = true;
+ CAResult_t ret = CACloseSocket(&g_unicastServerSocketFD);
+ u_mutex_unlock(g_mutexUnicastServer);
- //keep listening for data
- while (!gStopMulticast)
- {
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Unicast server stopped [%d]", ret);
+ return ret;
+}
- FD_ZERO(&reads);
- FD_SET(gMulticastServerSocketDescriptor, &reads);
+#ifdef __WITH_DTLS__
+CAResult_t CAEthernetStopSecureUnicastServer()
+{
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- int32_t ret = select(gMulticastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
- if (gStopMulticast)
- {
- OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Stop Multicast is called");
- break;
- }
- if ( ret < 0)
- {
- OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
- continue;
- }
- if (!FD_ISSET(gMulticastServerSocketDescriptor, &reads))
- {
- continue;
- }
+ u_mutex_lock(g_mutexSecureUnicastServer);
+ g_stopSecureUnicast = true;
+ CAResult_t ret = CACloseSocket(&g_secureUnicastServerSocketFD);
+ u_mutex_unlock(g_mutexSecureUnicastServer);
- memset(gMulticastRecvBuffer, 0, sizeof(char)*COAP_MAX_PDU_SIZE);
+ OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Secured unicast server stopped [%d]", ret);
+ return ret;
+}
+#endif
- //Read data from socket
- struct sockaddr_in srcSockAddress;
- int32_t recvLen;
- socklen_t srcAddressLen = sizeof(srcSockAddress);
- if (-1 == (recvLen = recvfrom(gMulticastServerSocketDescriptor, gMulticastRecvBuffer,
- COAP_MAX_PDU_SIZE, 0, (struct sockaddr *) &srcSockAddress,
- &srcAddressLen)))
- {
- OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
- continue;
- }
- else if (0 == recvLen)
- {
- OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast socket is shutdown, returning from \
- thread\n");
+CAResult_t CAEthernetStopMulticastServer(void)
+{
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
- //Notify upper layer this exception
- if (gExceptionCallback)
- {
- gExceptionCallback(CA_MULTICAST_SERVER);
- }
- return NULL;
- }
+ u_mutex_lock(g_mutexMulticastServer);
- const char *srcIPAddress = NULL;
- int32_t srcPort = -1;
+ if (g_multicastServerSocketFD == -1)
+ {
+ OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast server is not yet started");
+ u_mutex_unlock(g_mutexMulticastServer);
+ return CA_SERVER_NOT_STARTED;
+ }
- srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
- srcPort = ntohs(srcSockAddress.sin_port);
+ g_stopMulticast = true;
- OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
- srcIPAddress, srcPort);
- OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
- gMulticastRecvBuffer, recvLen);
+ // leave the group after you are done
+ if (-1 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (char *)&g_multicastMemberReq,
+ sizeof(struct ip_mreq)))
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",
+ strerror(errno));
+ }
+ CAResult_t ret = CACloseSocket(&g_multicastServerSocketFD);
+ u_mutex_unlock(g_mutexMulticastServer);
- //Notify data to upper layer
- if (gPacketReceivedCallback)
- {
- gPacketReceivedCallback(srcIPAddress, srcPort, gMulticastRecvBuffer, recvLen);
- }
+ OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Multicast server stopped [%d]", ret);
+ return ret;
+}
+
+CAResult_t CAEthernetGetUnicastServerInfo(bool isSecured,
+ char **ipAddress, uint16_t *port, int32_t *serverFD)
+{
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
+
+ // Input validation
+ VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "IP address");
+ VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "Port");
+ VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "Server ID");
+
+ struct sockaddr_in sockAddr;
+ socklen_t len = sizeof(struct sockaddr_in);
+ if (-1 == getsockname(g_unicastServerSocketFD, (struct sockaddr *)&sockAddr, &len))
+ {
+ OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));
+ return CA_STATUS_FAILED;
}
+
+ const char *serverAddress = inet_ntoa(sockAddr.sin_addr);
+ *ipAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) : NULL;
+ *port = ntohs(sockAddr.sin_port);
+#ifdef __WITH_DTLS__
+ *serverFD = (true == isSecured) ? g_secureUnicastServerSocketFD : g_unicastServerSocketFD;
+#else
+ *serverFD = g_unicastServerSocketFD;
+#endif
+
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
+{
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
+ g_packetReceivedCallback = callback;
OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
- return NULL;
}
+void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
+{
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
+ g_exceptionCallback = callback;
+ OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
+}