From 59ef2f1d5ce57a8e9115da4c79c10d493aaeb7fc Mon Sep 17 00:00:00 2001 From: John Light Date: Sat, 20 Jun 2015 16:48:52 -0700 Subject: [PATCH] New IP Adapter supports IPv6 builds on Linux tested on Linux IPv6 is now experimental missing: testing on Android, build and test on Tizen Change-Id: I4912317111dcc26712aec036715925905bd35eb9 Signed-off-by: John Light Reviewed-on: https://gerrit.iotivity.org/gerrit/1724 Tested-by: jenkins-iotivity Reviewed-by: Erich Keane --- auto_build.sh | 4 +- resource/csdk/connectivity/api/cacommon.h | 43 +- resource/csdk/connectivity/api/cainterface.h | 4 +- resource/csdk/connectivity/common/inc/uarraylist.h | 7 + resource/csdk/connectivity/common/src/uarraylist.c | 15 +- resource/csdk/connectivity/inc/caadapternetdtls.h | 2 +- resource/csdk/connectivity/inc/caadapterutils.h | 4 +- resource/csdk/connectivity/inc/caipinterface.h | 224 +--- resource/csdk/connectivity/inc/ifaddrs.h | 54 + .../csdk/connectivity/samples/arduino/casample.cpp | 2 +- resource/csdk/connectivity/src/SConscript | 3 +- .../src/adapter_util/caadapternetdtls.c | 8 +- .../connectivity/src/adapter_util/caadapterutils.c | 241 +--- .../csdk/connectivity/src/adapter_util/ifaddrs.c | 723 +++++++++++ .../src/bt_le_adapter/caleadapter_singlethread.c | 427 ++++++ .../csdk/connectivity/src/caconnectivitymanager.c | 6 +- resource/csdk/connectivity/src/camessagehandler.c | 47 + .../csdk/connectivity/src/ip_adapter/SConscript | 3 - .../src/ip_adapter/android/caipnwmonitor.c | 923 +------------ .../src/ip_adapter/arduino/caipclient_eth.cpp | 21 +- .../src/ip_adapter/arduino/caipclient_wifi.cpp | 16 +- .../src/ip_adapter/arduino/caipnwmonitor_eth.cpp | 106 +- .../src/ip_adapter/arduino/caipnwmonitor_wifi.cpp | 105 +- .../src/ip_adapter/arduino/caipserver_eth.cpp | 75 +- .../src/ip_adapter/arduino/caipserver_wifi.cpp | 75 +- .../csdk/connectivity/src/ip_adapter/caipadapter.c | 821 ++++-------- .../csdk/connectivity/src/ip_adapter/caipclient.c | 145 --- .../csdk/connectivity/src/ip_adapter/caipserver.c | 1358 +++++++++----------- .../src/ip_adapter/linux/caipnwmonitor.c | 631 +-------- .../src/ip_adapter/tizen/caipnwmonitor.c | 636 +-------- .../csdk/connectivity/test/ca_api_unittest.cpp | 6 +- .../stack/include/internal/ocresourcehandler.h | 2 +- .../csdk/stack/include/internal/ocserverrequest.h | 20 +- resource/csdk/stack/include/octypes.h | 5 + resource/csdk/stack/src/occollection.c | 11 +- resource/csdk/stack/src/ocobserve.c | 15 +- resource/csdk/stack/src/ocresource.c | 86 +- resource/csdk/stack/src/ocserverrequest.c | 2 + resource/csdk/stack/src/ocstack.c | 95 +- 39 files changed, 2745 insertions(+), 4226 deletions(-) create mode 100644 resource/csdk/connectivity/inc/ifaddrs.h create mode 100644 resource/csdk/connectivity/src/adapter_util/ifaddrs.c create mode 100644 resource/csdk/connectivity/src/bt_le_adapter/caleadapter_singlethread.c delete mode 100644 resource/csdk/connectivity/src/ip_adapter/caipclient.c diff --git a/auto_build.sh b/auto_build.sh index 3b73da1..adb514d 100755 --- a/auto_build.sh +++ b/auto_build.sh @@ -48,10 +48,10 @@ function build() scons resource TARGET_OS=arduino UPLOAD=false BOARD=arduino_due_x TARGET_ARCH=arm TARGET_TRANSPORT=IP SHIELD=WIFI RELEASE=$3 echo "*********** Build for Tizen CA lib and sample *************" - scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true RELEASE=$3 + #scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true RELEASE=$3 echo "*********** Build for Tizen CA lib and sample with Security *************" - scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true SECURED=1 RELEASE=$3 + #scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true SECURED=1 RELEASE=$3 if [ $(uname -s) = "Darwin" ] then diff --git a/resource/csdk/connectivity/api/cacommon.h b/resource/csdk/connectivity/api/cacommon.h index 3970fc5..e8a59e2 100644 --- a/resource/csdk/connectivity/api/cacommon.h +++ b/resource/csdk/connectivity/api/cacommon.h @@ -134,6 +134,8 @@ typedef enum // IPv4 & IPv6 autoselection is the default CA_IPV6 = (1 << 5), // IP adapter only CA_IPV4 = (1 << 6), // IP adapter only + // Indication that a message was received by multicast. + CA_MULTICAST = (1 << 7), // Link-Local multicast is the default multicast scope for IPv6. // These correspond in both value and position to the IPv6 address bits. CA_SCOPE_INTERFACE = 0x1, // IPv6 Interface-Local scope @@ -145,6 +147,9 @@ typedef enum CA_SCOPE_GLOBAL = 0xE, // IPv6 Global scope } CATransportFlags_t; +#define CA_IPFAMILY_MASK (CA_IPV6|CA_IPV4) +#define CA_SCOPE_MASK 0xf // mask scope bits above + /** * @enum CANetworkStatus_t * @brief Information about the network status. @@ -348,8 +353,44 @@ typedef struct */ typedef struct { - CATransportFlags_t serverFlags; + int fd; + uint16_t port; +} CASocket_t; + +typedef struct +{ CATransportFlags_t clientFlags; + CATransportFlags_t serverFlags; + bool client; + bool server; + + struct sockets + { + void *threadpool; // threadpool between Initialize and Start + CASocket_t u6; // unicast IPv6 + CASocket_t u6s; // unicast IPv6 secure + CASocket_t u4; // unicast IPv4 + CASocket_t u4s; // unicast IPv4 secure + CASocket_t m6; // multicast IPv6 + CASocket_t m6s; // multicast IPv6 secure + CASocket_t m4; // multicast IPv4 + CASocket_t m4s; // multicast IPv4 secure + int netlinkFd; // netlink + int shutdownFds[2]; // shutdown pipe + int selectTimeout; // in seconds + int maxfd; // highest fd (for select) + int numInterfaces; // number of active interfaces + bool started; // the IP adapter has started + bool terminate; // the IP adapter needs to stop + bool ipv6enabled; // IPv6 enabled by OCInit flags + bool ipv4enabled; // IPv4 enabled by OCInit flags + } ip; + + struct calayer + { + CATransportFlags_t previousRequestFlags; // address family filtering + uint16_t previousRequestMessageId; // address family filtering + } ca; } CAGlobals_t; extern CAGlobals_t caglobals; diff --git a/resource/csdk/connectivity/api/cainterface.h b/resource/csdk/connectivity/api/cainterface.h index 90aeb67..5a65ee0 100644 --- a/resource/csdk/connectivity/api/cainterface.h +++ b/resource/csdk/connectivity/api/cainterface.h @@ -220,14 +220,14 @@ CAResult_t CASendNotification(const CAEndpoint_t *object, * @param interestedNetwork [IN] Connectivity Type enum * @return #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED or #CA_NOT_SUPPORTED */ -CAResult_t CASelectNetwork(const uint32_t interestedNetwork); +CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork); /** * @brief Select network to unuse * @param nonInterestedNetwork [IN] Connectivity Type enum * @return #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED */ -CAResult_t CAUnSelectNetwork(const uint32_t nonInterestedNetwork); +CAResult_t CAUnSelectNetwork(CATransportAdapter_t nonInterestedNetwork); /** * @brief Get network information diff --git a/resource/csdk/connectivity/common/inc/uarraylist.h b/resource/csdk/connectivity/common/inc/uarraylist.h index 17edead..7fa6200 100644 --- a/resource/csdk/connectivity/common/inc/uarraylist.h +++ b/resource/csdk/connectivity/common/inc/uarraylist.h @@ -105,6 +105,13 @@ uint32_t u_arraylist_length(const u_arraylist_t *list); */ bool u_arraylist_contains(const u_arraylist_t *list,const void *data); +/** + * @brief Destroys array list and elements (assuming elements are shallow) + * @param list + * [IN] pointer of array list + */ +void u_arraylist_destroy(u_arraylist_t *list); + #ifdef __cplusplus } #endif diff --git a/resource/csdk/connectivity/common/src/uarraylist.c b/resource/csdk/connectivity/common/src/uarraylist.c index 7c569d4..be897be 100644 --- a/resource/csdk/connectivity/common/src/uarraylist.c +++ b/resource/csdk/connectivity/common/src/uarraylist.c @@ -178,4 +178,17 @@ bool u_arraylist_contains(const u_arraylist_t *list,const void *data) return false; } - +// Assumes elements are shallow (have no pointers to allocated memory) +void u_arraylist_destroy(u_arraylist_t *list) +{ + if (!list) + { + return; + } + uint32_t len = u_arraylist_length(list); + for (uint32_t i = 0; i < len; i++) + { + OICFree(u_arraylist_get(list, i)); + } + (void)u_arraylist_free(&list); +} diff --git a/resource/csdk/connectivity/inc/caadapternetdtls.h b/resource/csdk/connectivity/inc/caadapternetdtls.h index 402c746..c1d5349 100644 --- a/resource/csdk/connectivity/inc/caadapternetdtls.h +++ b/resource/csdk/connectivity/inc/caadapternetdtls.h @@ -41,7 +41,7 @@ extern void OCGetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo); typedef void (*CAPacketReceivedCallback)(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength); -typedef uint32_t (*CAPacketSendCallback)(const CAEndpoint_t *endpoint, +typedef void (*CAPacketSendCallback)(CAEndpoint_t *endpoint, const void *data, uint32_t dataLength); /** diff --git a/resource/csdk/connectivity/inc/caadapterutils.h b/resource/csdk/connectivity/inc/caadapterutils.h index 9d7a587..197cc97 100644 --- a/resource/csdk/connectivity/inc/caadapterutils.h +++ b/resource/csdk/connectivity/inc/caadapterutils.h @@ -87,8 +87,9 @@ extern "C" */ #define IPV4_ADDR_ONE_OCTECT_LEN 4 +#ifdef SINGLE_THREAD /** - * @brief Network Interface Information. + * @brief Network Interface Information. Only needed for Arduino. */ typedef struct { @@ -96,6 +97,7 @@ typedef struct char subnetMask[CA_IPADDR_SIZE]; /**< Maintains interface subnetmask **/ char interfaceName[CA_INTERFACE_NAME_SIZE]; /**< Interface name**/ } CANetInfo_t; +#endif /** * @brief unicast and multicast server information. diff --git a/resource/csdk/connectivity/inc/caipinterface.h b/resource/csdk/connectivity/inc/caipinterface.h index 085169f..a7afbd9 100644 --- a/resource/csdk/connectivity/inc/caipinterface.h +++ b/resource/csdk/connectivity/inc/caipinterface.h @@ -84,7 +84,7 @@ typedef void (*CAIPErrorHandleCallback)(const CAEndpoint_t *endpoint, const void typedef void (*CAIPExceptionCallback)(CAAdapterServerType_t type); /** - * @brief Initialize IP server + * @brief Start IP server * * @param threadPool [IN] Thread pool for managing Unicast/Multicast server threads. * @@ -93,118 +93,17 @@ typedef void (*CAIPExceptionCallback)(CAAdapterServerType_t type); * @retval #CA_STATUS_INVALID_PARAM Invalid input data * @retval #CA_STATUS_FAILED Initialization failed */ -CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool); +#ifdef SINGLE_THREAD +CAResult_t CAIPStartServer(); +#else +CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool); +#endif /** - * @brief Terminate IP server + * @brief Stop IP server * @return NONE */ -void CAIPTerminateServer(); - -/** - * @brief Start multicast server for specified multicast address and port - * - * @param localAddress [IN] Local adapter address to which server to be binded. - * @param multicastAddress [IN] Multicast group address. - * @param multicastPort [IN,OUT] Port number on which server will be running. If binding - * the port failed, server starts in the next available port. - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_INVALID_PARAM Invalid input data - * @retval #CA_SERVER_STARTED_ALREADY Multicast server is already started and running. - * @retval #CA_STATUS_FAILED Operation failed - */ -CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress, - uint16_t multicastPort); - -/** - * @brief Start unicast server for specified local address and port - * - * @param localAddress [IN] Local adapter address to which server to be binded. - * @param port [IN,OUT] Port number on which server will be running. If binding - * the port failed, server starts in the next available port. - * @param secured [IN] True if the secure server to be started, otherwise false. - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_INVALID_PARAM Invalid input data - * @retval #CA_SERVER_STARTED_ALREADY Unicast server is already started and running. - * @retval #CA_STATUS_FAILED Operation failed - */ -CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port, bool secured); - -/** - * @brief Stop servers that are running in particular interface address. - * - * @param interfaceAddress [IN] interface address in which servers are running. - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_FAILED Operation failed - */ -CAResult_t CAIPStopServer(const char *interfaceAddress); - -/** - * @brief Used to stop all unicast and multicast servers. - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_FAILED Operation failed - */ -CAResult_t CAIPStopAllServers(); - -/** - * @brief Used to get the socket fd based on index value of server info list. - * - * @param index [IN] Index where we need socket fd value. - * @param isSecured [IN] For secured unicast server or normal server. - * - * @return positive value on success and -1 on error. - */ -int CAGetSocketFdFromUnicastIPServerbyIndex(int16_t index, bool isSecured); - -/** - * @brief Used to get the number of unicast server currently running. - * - * @param isSecured [IN] To identify whether its secured unicast server or normal server. - * - * @return positive value on success and -1 on error. - */ -int16_t CAGetNumberOfUnicastIPServers(bool isSecured); - -/** - * @brief Used to get the stored socket fd for corresponding ipAddress. - * - * @param ipAddress [IN] IpAddress of server. - * @param isSecured [IN] Used to check the server is secured or not. - * @param isMulticast [IN] To identify whether its for multicast or unicast. - * - * @return socket fd on success and -1 on error. - */ -int CAGetSocketFdFromUnicastIPServer(const char *ipAddress, bool isSecured, bool isMulticast); - -/** - * @brief Used to get the port number to the corresponding ip for giving interface info. - * - * @param ipAddress [IN] IpAddress of server. - * @param isSecured [IN] Used to check the server is secured or not. - * - * @return port number on success and -1 on error. - */ -uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured); - -/** - * @brief Used to get the port number for corresponding ipAddress. - * - * @param serverInfoList [OUT] ServerInfoList holds unicast and multicast server informations. - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_INVALID_PARAM Invalid input data - * @retval #CA_STATUS_FAILED Initialization failed - */ -CAResult_t CAGetIPServerInfoList(u_arraylist_t **serverInfoList); +void CAIPStopServer(); /** * @brief Set this callback for receiving data packets from peer devices. @@ -247,61 +146,18 @@ void CAIPSetUnicastPort(uint16_t port); * @param data [IN] Data to be send. * @param dataLength [IN] Length of data in bytes * @param isMulticast [IN] Whether data needs to be sent to multicast ip - * - * @return The number of bytes sent on the network. Returns 0 on error. - * @remarks isSecure will be ignored when isMulticast is true. - */ -uint32_t CAIPSendData(const CAEndpoint_t *endpoint, - const void *data, - uint32_t dataLength, - bool isMulticast); - -/** - * @brief Callback to be notified when IP adapter connection state changes. - * - * @param ipAddress [IN] IP address of remote OIC device. - * @param status [IN] Connection status either #CA_INTERFACE_UP or #CA_INTERFACE_DOWN. - * @return NONE - * @pre Callback must be registered using CAIPSetConnectionStateChangeCallback() - */ -typedef void (*CAIPConnectionStateChangeCallback)(const char *ipAddress, - CANetworkStatus_t status); - -/** - * @brief Initialize IP network monitor - * - * @param threadPool [IN] Thread pool for managing network monitor thread. - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_INVALID_PARAM Invalid input data - * @retval #CA_STATUS_FAILED Initialization failed - */ -CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool); - -/** - * @brief Terminate IP network monitor by removing interface list. - * @return NONE */ -void CAIPTerminateNetworkMonitor(); +void CAIPSendData(CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLength, + bool isMulticast); /** - * @brief Start network monitoring process. It will start the monitor thread. - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_FAILED Operation failed - */ -CAResult_t CAIPStartNetworkMonitor(); - -/** - * @brief Stop network monitoring process. It will stop the monitor thread. + * @brief Get IP adapter connection state. * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_FAILED Operation failed + * @return True if IP adapter is connected, otherwise false */ -CAResult_t CAIPStopNetworkMonitor(); +bool CAIPIsConnected(); /** * @brief Pull the Received Data @@ -309,47 +165,25 @@ CAResult_t CAIPStopNetworkMonitor(); */ void CAIPPullData(); -/** - * @brief Get local adapter network information. - * - * @param netInterfaceList [OUT] network interface information list - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_INVALID_PARAM Invalid input data - * @retval #CA_STATUS_FAILED Operation failed - * @remarks interfaceName and ipAddress must be freed using free(). - */ -CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList); +#define CA_COAP 5683 +#define CA_SECURE_COAP 5684 +#define INTERFACE_NAME_MAX 16 -/** - * @brief Get local adapter network subnet mask. - * - * @param ipAddress [IN] IpAddress which is used for getting subnet mask. - * @param subnetMask [OUT] Local adapter interface subnet mask - * - * @return #CA_STATUS_OK or Appropriate error code - * @retval #CA_STATUS_OK Successful - * @retval #CA_STATUS_INVALID_PARAM Invalid input data - * @retval #CA_STATUS_FAILED Operation failed - * @remarks subnetMask must be freed using free(). - */ -CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask); - -/** - * @brief Get IP adapter connection state. - * - * @return True if IP adapter is connected, otherwise false - */ - bool CAIPIsConnected(); +typedef struct +{ + char name[INTERFACE_NAME_MAX]; + uint32_t index; + uint32_t flags; + uint16_t family; + uint32_t ipv4addr; // used for IPv4 only +} CAInterface_t; /** - * @brief Set callback for receiving local IP adapter connection status. + * @brief Get a list of CAInterface_t items * - * @param callback [IN] Callback to be notified when IP adapter connection state changes. - * @return NONE + * @return List of CAInterface_t items */ -void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback); +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex); /** * @brief Set callback for error handling diff --git a/resource/csdk/connectivity/inc/ifaddrs.h b/resource/csdk/connectivity/inc/ifaddrs.h new file mode 100644 index 0000000..9cd19fe --- /dev/null +++ b/resource/csdk/connectivity/inc/ifaddrs.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1995, 1999 + * Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp + */ + +#ifndef _IFADDRS_H_ +#define _IFADDRS_H_ + +struct ifaddrs { + struct ifaddrs *ifa_next; + char *ifa_name; + unsigned int ifa_flags; + struct sockaddr *ifa_addr; + struct sockaddr *ifa_netmask; + struct sockaddr *ifa_dstaddr; + void *ifa_data; +}; + +/* + * This may have been defined in . Note that if is + * to be included it must be included before this header file. + */ +#ifndef ifa_broadaddr +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ +#endif + +#include + +__BEGIN_DECLS +extern int getifaddrs(struct ifaddrs **ifap); +extern void freeifaddrs(struct ifaddrs *ifa); +__END_DECLS + +#endif diff --git a/resource/csdk/connectivity/samples/arduino/casample.cpp b/resource/csdk/connectivity/samples/arduino/casample.cpp index a254ec4..165796e 100644 --- a/resource/csdk/connectivity/samples/arduino/casample.cpp +++ b/resource/csdk/connectivity/samples/arduino/casample.cpp @@ -622,7 +622,7 @@ void UnselectNetwork() { g_isLeSelected = false; } - CAUnSelectNetwork(1 << number); + CAUnSelectNetwork((CATransportAdapter_t)(1 << number)); Serial.println("Terminate"); CATerminate(); Serial.println("============"); diff --git a/resource/csdk/connectivity/src/SConscript b/resource/csdk/connectivity/src/SConscript index 31ba920..f1ca463 100755 --- a/resource/csdk/connectivity/src/SConscript +++ b/resource/csdk/connectivity/src/SConscript @@ -45,7 +45,8 @@ env.AppendUnique(CA_SRC = [os.path.join(ca_path, 'adapter_util/caadapterutils.c')]) env.AppendUnique(CA_SRC = [os.path.join(ca_path, 'adapter_util/cafragmentation.c')]) - +if ca_os in ['android', 'tizen']: + env.AppendUnique(CA_SRC=[os.path.join(ca_path, 'adapter_util/ifaddrs.c')]) if env.get('SECURED') == '1': env.AppendUnique(CA_SRC = [os.path.join(ca_path, 'adapter_util/caadapternetdtls.c')]) diff --git a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c index f49e3d5..92b40c2 100644 --- a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c +++ b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c @@ -436,24 +436,20 @@ static int32_t CASendSecureData(dtls_context_t *dtlsContext, int type = 0; //Mutex is not required for g_caDtlsContext. It will be called in same thread. - int32_t sentLen = 0; if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) && (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback)) { - sentLen = g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen); + g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen); } else { OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type ); } - OIC_LOG_V(DEBUG, NET_DTLS_TAG, "sent buffer length [%d]", sentLen); - OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT"); - return sentLen; + return bufLen; } - static int32_t CAHandleSecureEvent(dtls_context_t *dtlsContext, session_t *session, dtls_alert_level_t level, diff --git a/resource/csdk/connectivity/src/adapter_util/caadapterutils.c b/resource/csdk/connectivity/src/adapter_util/caadapterutils.c index 80ac0cc..2094a6e 100644 --- a/resource/csdk/connectivity/src/adapter_util/caadapterutils.c +++ b/resource/csdk/connectivity/src/adapter_util/caadapterutils.c @@ -66,6 +66,7 @@ void CALogPDUData(coap_pdu_t *pdu) OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - token : %s", pdu->hdr->token); } +#ifdef WITH_ARDUINO CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr, size_t ipAddrLen, uint16_t *port) { @@ -130,243 +131,7 @@ CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr, return CA_STATUS_FAILED; } -bool CAAdapterIsSameSubnet(const char *ipAddress1, const char *ipAddress2, const char *netMask) -{ - VERIFY_NON_NULL_RET(ipAddress1, CA_ADAPTER_UTILS_TAG, "First address", false); - VERIFY_NON_NULL_RET(ipAddress2, CA_ADAPTER_UTILS_TAG, "Second address", false); - VERIFY_NON_NULL_RET(netMask, CA_ADAPTER_UTILS_TAG, "netMask", false); - - uint8_t ipList1[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 }; - uint8_t ipList2[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 }; - uint8_t maskList[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 }; - CAResult_t ret = CA_STATUS_OK; - - /* Local Loopback Address */ - if (0 == strncmp(ipAddress1, "127.", 4) || 0 == strncmp(ipAddress2, "127.", 4)) - { - return true; - } - - uint16_t parsedPort = 0; - ret = CAParseIPv4AddressInternal(ipAddress1, ipList1, sizeof(ipList1), &parsedPort); - if (ret != CA_STATUS_OK) - { - OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "First ip address parse fail %d", ret); - return false; - } - - ret = CAParseIPv4AddressInternal(ipAddress2, ipList2, sizeof(ipList2), &parsedPort); - if (ret != CA_STATUS_OK) - { - OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Second ip address parse fail %d", ret); - return false; - } - - ret = CAParseIPv4AddressInternal(netMask, maskList, sizeof(maskList), &parsedPort); - if (ret != CA_STATUS_OK) - { - OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Net mask parse fail %d", ret); - return false; - } - - return ((ipList1[0] & maskList[0]) == (ipList2[0] & maskList[0])) && ((ipList1[1] & maskList[1]) - == (ipList2[1] & maskList[1])) - && ((ipList1[2] & maskList[2]) == (ipList2[2] & maskList[2])) - && ((ipList1[3] & maskList[3]) == (ipList2[3] & maskList[3])); -} - -bool CAIsMulticastServerStarted(const u_arraylist_t *serverInfoList, const char *ipAddress, - const char *multicastAddress, uint16_t port) -{ - VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", false); - VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", false); - VERIFY_NON_NULL_RET(multicastAddress, CA_ADAPTER_UTILS_TAG, "multicastAddress is null", false); - - uint32_t listLength = u_arraylist_length(serverInfoList); - for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex); - if (!info) - { - OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Info is NULL"); - return false; - } - - if (info->isMulticastServer && (strncmp(info->endpoint.addr, multicastAddress, - strlen(multicastAddress)) == 0) - && (info->endpoint.port == port) && (strncmp(info->ifAddr, ipAddress, strlen(ipAddress)) == 0)) - { - return info->isServerStarted; - } - } - return false; -} - -bool CAIsUnicastServerStarted(const u_arraylist_t *serverInfoList, const char *ipAddress, - uint16_t port) -{ - VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", false); - VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", false); - - uint32_t listLength = u_arraylist_length(serverInfoList); - for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex); - if (!info) - { - continue; - } - - if (!info->isMulticastServer && (strncmp(info->endpoint.addr, ipAddress, - strlen(ipAddress)) == 0) - && (info->endpoint.port == port)) - { - return info->isServerStarted; - } - } - return false; -} - -uint16_t CAGetServerPort(const u_arraylist_t *serverInfoList, const char *ipAddress, bool isSecured) -{ - VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", 0); - VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", 0); - - uint32_t listLength = u_arraylist_length(serverInfoList); - for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex); - if (!info) - { - continue; - } - bool ifSecured = info->endpoint.flags & CA_SECURE; - if ((strncmp(info->endpoint.addr, ipAddress, strlen(ipAddress)) == 0) && - (ifSecured == isSecured)) - { - return info->endpoint.port; - } - } - - return 0; -} - -int CAGetSocketFdForUnicastServer(const u_arraylist_t *serverInfoList, - bool isMulticast, const CAEndpoint_t *endpoint) -{ - VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", -1); - VERIFY_NON_NULL_RET(endpoint, CA_ADAPTER_UTILS_TAG, "endpoint is null", -1); - - bool isSecured = (endpoint->flags & CA_SECURE) != 0; - - uint32_t listLength = u_arraylist_length(serverInfoList); - - for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex); - if (!info) - { - continue; - } - - if (!CAAdapterIsSameSubnet(info->endpoint.addr, endpoint->addr, info->subNetMask)) - { - continue; - } - - bool ifSecured = info->endpoint.flags & CA_SECURE; - if (!info->isMulticastServer && (ifSecured == isSecured)) - { - OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, - "CAGetSocketFdForServer found socket [%d]", info->socketFd); - return info->socketFd; - } - - } - - OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, - "CAGetSocketFdForServer socket fd is not found"); - return -1; -} - -CAResult_t CAAddServerInfo(u_arraylist_t *serverInfoList, CAServerInfo_t *info) -{ - VERIFY_NON_NULL(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null"); - VERIFY_NON_NULL(info, CA_ADAPTER_UTILS_TAG, "info is null"); - - CAResult_t result = u_arraylist_add(serverInfoList, (void *) info); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "u_arraylist_add failed!"); - } - return result; -} - -void CARemoveServerInfo(u_arraylist_t *serverInfoList, int sockFd) -{ - VERIFY_NON_NULL_VOID(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null"); - - uint32_t listLength = u_arraylist_length(serverInfoList); - for (uint32_t listIndex = 0; listIndex < listLength;) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex); - if (!info) - { - listIndex++; - continue; - } - - if (info->socketFd == sockFd) - { - if (u_arraylist_remove(serverInfoList, listIndex)) - { - OICFree(info); - listLength--; - } - else - { - OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "u_arraylist_remove failed!"); - break; - } - } - else - { - listIndex++; - } - } -} - -void CAClearNetInterfaceInfoList(u_arraylist_t *infoList) -{ - uint32_t listLength = u_arraylist_length(infoList); - for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) - { - CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(infoList, listIndex); - if (!netInfo) - { - continue; - } - OICFree(netInfo); - } - u_arraylist_free(&infoList); -} - -void CAClearServerInfoList(u_arraylist_t *serverInfoList) -{ - uint32_t listLength = u_arraylist_length(serverInfoList); - for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *serverInfo = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex); - if (!serverInfo) - { - continue; - } - OICFree(serverInfo); - } - u_arraylist_free(&serverInfoList); -} - -#ifndef WITH_ARDUINO +#else // not with_arduino /* * These two conversion functions return void because errors can't happen * (because of NI_NUMERIC), and there's nothing to do if they do happen. @@ -379,7 +144,7 @@ void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, char *host, ui int r = getnameinfo((struct sockaddr *)sockAddr, sizeof (struct sockaddr_storage), - host, CA_IPADDR_SIZE, + host, MAX_ADDR_STR_SIZE_CA, NULL, 0, NI_NUMERICHOST|NI_NUMERICSERV); if (r) diff --git a/resource/csdk/connectivity/src/adapter_util/ifaddrs.c b/resource/csdk/connectivity/src/adapter_util/ifaddrs.c new file mode 100644 index 0000000..9176a32 --- /dev/null +++ b/resource/csdk/connectivity/src/adapter_util/ifaddrs.c @@ -0,0 +1,723 @@ +/* +Copyright (c) 2013, Kenneth MacKay +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "ifaddrs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct NetlinkList +{ + struct NetlinkList *m_next; + struct nlmsghdr *m_data; + unsigned int m_size; +} NetlinkList; + +static int netlink_socket(void) +{ + int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if(l_socket < 0) + { + return -1; + } + + struct sockaddr_nl l_addr; + memset(&l_addr, 0, sizeof(l_addr)); + l_addr.nl_family = AF_NETLINK; + if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) + { + close(l_socket); + return -1; + } + + return l_socket; +} + +static int netlink_send(int p_socket, int p_request) +{ + struct + { + struct nlmsghdr m_hdr; + struct rtgenmsg m_msg; + } l_data; + + memset(&l_data, 0, sizeof(l_data)); + + l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); + l_data.m_hdr.nlmsg_type = p_request; + l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + l_data.m_hdr.nlmsg_pid = 0; + l_data.m_hdr.nlmsg_seq = p_socket; + l_data.m_msg.rtgen_family = AF_UNSPEC; + + struct sockaddr_nl l_addr; + memset(&l_addr, 0, sizeof(l_addr)); + l_addr.nl_family = AF_NETLINK; + return (sendto(p_socket, &l_data.m_hdr, l_data.m_hdr.nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); +} + +static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) +{ + struct msghdr l_msg; + struct iovec l_iov = { p_buffer, p_len }; + struct sockaddr_nl l_addr; + + for(;;) + { + l_msg.msg_name = (void *)&l_addr; + l_msg.msg_namelen = sizeof(l_addr); + l_msg.msg_iov = &l_iov; + l_msg.msg_iovlen = 1; + l_msg.msg_control = NULL; + l_msg.msg_controllen = 0; + l_msg.msg_flags = 0; + int l_result = recvmsg(p_socket, &l_msg, 0); + + if(l_result < 0) + { + if(errno == EINTR) + { + continue; + } + return -2; + } + + if(l_msg.msg_flags & MSG_TRUNC) + { // buffer was too small + return -1; + } + return l_result; + } +} + +static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) +{ + size_t l_size = 4096; + void *l_buffer = NULL; + + for(;;) + { + free(l_buffer); + l_buffer = malloc(l_size); + if (l_buffer == NULL) + { + return NULL; + } + + int l_read = netlink_recv(p_socket, l_buffer, l_size); + *p_size = l_read; + if(l_read == -2) + { + free(l_buffer); + return NULL; + } + if(l_read >= 0) + { + pid_t l_pid = getpid(); + struct nlmsghdr *l_hdr; + for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) + { + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + { + continue; + } + + if(l_hdr->nlmsg_type == NLMSG_DONE) + { + *p_done = 1; + break; + } + + if(l_hdr->nlmsg_type == NLMSG_ERROR) + { + free(l_buffer); + return NULL; + } + } + return l_buffer; + } + + l_size *= 2; + } +} + +static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) +{ + NetlinkList *l_item = malloc(sizeof(NetlinkList)); + if (l_item == NULL) + { + return NULL; + } + + l_item->m_next = NULL; + l_item->m_data = p_data; + l_item->m_size = p_size; + return l_item; +} + +static void freeResultList(NetlinkList *p_list) +{ + NetlinkList *l_cur; + while(p_list) + { + l_cur = p_list; + p_list = p_list->m_next; + free(l_cur->m_data); + free(l_cur); + } +} + +static NetlinkList *getResultList(int p_socket, int p_request) +{ + if(netlink_send(p_socket, p_request) < 0) + { + return NULL; + } + + NetlinkList *l_list = NULL; + NetlinkList *l_end = NULL; + int l_size; + int l_done = 0; + while(!l_done) + { + struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); + if(!l_hdr) + { // error + freeResultList(l_list); + return NULL; + } + + NetlinkList *l_item = newListItem(l_hdr, l_size); + if (!l_item) + { + freeResultList(l_list); + return NULL; + } + if(!l_list) + { + l_list = l_item; + } + else + { + l_end->m_next = l_item; + } + l_end = l_item; + } + return l_list; +} + +static size_t maxSize(size_t a, size_t b) +{ + return (a > b ? a : b); +} + +static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) +{ + switch(p_family) + { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + case AF_PACKET: + return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); + default: + return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); + } +} + +static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) +{ + switch(p_family) + { + case AF_INET: + memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); + break; + case AF_INET6: + memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); + break; + case AF_PACKET: + memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); + ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; + break; + default: + memcpy(p_dest->sa_data, p_data, p_size); + break; + } + p_dest->sa_family = p_family; +} + +static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) +{ + if(!*p_resultList) + { + *p_resultList = p_entry; + } + else + { + struct ifaddrs *l_cur = *p_resultList; + while(l_cur->ifa_next) + { + l_cur = l_cur->ifa_next; + } + l_cur->ifa_next = p_entry; + } +} + +static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) +{ + struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); + + size_t l_nameSize = 0; + size_t l_addrSize = 0; + size_t l_dataSize = 0; + + size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); + struct rtattr *l_rta; + for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + //void *l_rtaData = RTA_DATA(l_rta); + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + switch(l_rta->rta_type) + { + case IFLA_ADDRESS: + case IFLA_BROADCAST: + l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); + break; + case IFLA_IFNAME: + l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); + break; + case IFLA_STATS: + l_dataSize += NLMSG_ALIGN(l_rtaSize); + break; + default: + break; + } + } + + struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize); + if (l_entry == NULL) + { + return -1; + } + memset(l_entry, 0, sizeof(struct ifaddrs)); + l_entry->ifa_name = ""; + + char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs); + char *l_name = l_index + sizeof(int); + char *l_addr = l_name + l_nameSize; + char *l_data = l_addr + l_addrSize; + + // save the interface index so we can look it up when handling the addresses. + memcpy(l_index, &l_info->ifi_index, sizeof(int)); + + l_entry->ifa_flags = l_info->ifi_flags; + + l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); + for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + void *l_rtaData = RTA_DATA(l_rta); + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + switch(l_rta->rta_type) + { + case IFLA_ADDRESS: + case IFLA_BROADCAST: + { + size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); + makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); + ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; + ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; + if(l_rta->rta_type == IFLA_ADDRESS) + { + l_entry->ifa_addr = (struct sockaddr *)l_addr; + } + else + { + l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; + } + l_addr += NLMSG_ALIGN(l_addrLen); + break; + } + case IFLA_IFNAME: + strncpy(l_name, l_rtaData, l_rtaDataSize); + l_name[l_rtaDataSize] = '\0'; + l_entry->ifa_name = l_name; + break; + case IFLA_STATS: + memcpy(l_data, l_rtaData, l_rtaDataSize); + l_entry->ifa_data = l_data; + break; + default: + break; + } + } + + addToEnd(p_resultList, l_entry); + return 0; +} + +static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) +{ + int l_num = 0; + struct ifaddrs *l_cur = *p_links; + while(l_cur && l_num < p_numLinks) + { + char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); + int l_index; + memcpy(&l_index, l_indexPtr, sizeof(int)); + if(l_index == p_index) + { + return l_cur; + } + + l_cur = l_cur->ifa_next; + ++l_num; + } + return NULL; +} + +static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks) +{ + struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); + struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks); + + if(l_info->ifa_family == AF_PACKET) + { + return 0; + } + + size_t l_nameSize = 0; + size_t l_addrSize = 0; + + int l_addedNetmask = 0; + + size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); + struct rtattr *l_rta; + for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + //void *l_rtaData = RTA_DATA(l_rta); + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + + switch(l_rta->rta_type) + { + case IFA_ADDRESS: + case IFA_LOCAL: + if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) + { // make room for netmask + l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); + l_addedNetmask = 1; + } + case IFA_BROADCAST: + l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); + break; + case IFA_LABEL: + l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); + break; + default: + break; + } + } + + struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); + if (l_entry == NULL) + { + return -1; + } + memset(l_entry, 0, sizeof(struct ifaddrs)); + l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); + + char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); + char *l_addr = l_name + l_nameSize; + + l_entry->ifa_flags = l_info->ifa_flags; + if(l_interface) + { + l_entry->ifa_flags |= l_interface->ifa_flags; + } + + l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); + for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + void *l_rtaData = RTA_DATA(l_rta); + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + switch(l_rta->rta_type) + { + case IFA_ADDRESS: + case IFA_BROADCAST: + case IFA_LOCAL: + { + size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); + makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); + if(l_info->ifa_family == AF_INET6) + { + if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) + { + ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; + } + } + + if(l_rta->rta_type == IFA_ADDRESS) + { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address + if(l_entry->ifa_addr) + { + l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; + } + else + { + l_entry->ifa_addr = (struct sockaddr *)l_addr; + } + } + else if(l_rta->rta_type == IFA_LOCAL) + { + if(l_entry->ifa_addr) + { + l_entry->ifa_dstaddr = l_entry->ifa_addr; + } + l_entry->ifa_addr = (struct sockaddr *)l_addr; + } + else + { + l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; + } + l_addr += NLMSG_ALIGN(l_addrLen); + break; + } + case IFA_LABEL: + strncpy(l_name, l_rtaData, l_rtaDataSize); + l_name[l_rtaDataSize] = '\0'; + l_entry->ifa_name = l_name; + break; + default: + break; + } + } + + if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) + { + unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); + unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); + char l_mask[16] = {0}; + unsigned i; + for(i=0; i<(l_prefix/8); ++i) + { + l_mask[i] = 0xff; + } + if(l_prefix % 8) + { + l_mask[i] = 0xff << (8 - (l_prefix % 8)); + } + + makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); + l_entry->ifa_netmask = (struct sockaddr *)l_addr; + } + + addToEnd(p_resultList, l_entry); + return 0; +} + +static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) +{ + int l_numLinks = 0; + pid_t l_pid = getpid(); + for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) + { + unsigned int l_nlsize = p_netlinkList->m_size; + struct nlmsghdr *l_hdr; + for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) + { + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + { + continue; + } + + if(l_hdr->nlmsg_type == NLMSG_DONE) + { + break; + } + + if(l_hdr->nlmsg_type == RTM_NEWLINK) + { + if(interpretLink(l_hdr, p_resultList) == -1) + { + return -1; + } + ++l_numLinks; + } + } + } + return l_numLinks; +} + +static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) +{ + pid_t l_pid = getpid(); + for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) + { + unsigned int l_nlsize = p_netlinkList->m_size; + struct nlmsghdr *l_hdr; + for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) + { + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + { + continue; + } + + if(l_hdr->nlmsg_type == NLMSG_DONE) + { + break; + } + + if(l_hdr->nlmsg_type == RTM_NEWADDR) + { + if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) + { + return -1; + } + } + } + } + return 0; +} + +int getifaddrs(struct ifaddrs **ifap) +{ + if(!ifap) + { + return -1; + } + *ifap = NULL; + + int l_socket = netlink_socket(); + if(l_socket < 0) + { + return -1; + } + + NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); + if(!l_linkResults) + { + close(l_socket); + return -1; + } + + NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); + if(!l_addrResults) + { + close(l_socket); + freeResultList(l_linkResults); + return -1; + } + + int l_result = 0; + int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); + if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) + { + l_result = -1; + } + + freeResultList(l_linkResults); + freeResultList(l_addrResults); + close(l_socket); + return l_result; +} + +void freeifaddrs(struct ifaddrs *ifa) +{ + struct ifaddrs *l_cur; + while(ifa) + { + l_cur = ifa; + ifa = ifa->ifa_next; + free(l_cur); + } +} + + +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +//#include +//#include +//#include +//#include +//#include +//#include + +/* + * Map an interface name into its corresponding index. + * Returns 0 on error, as 0 is not a valid index. + */ +unsigned int if_nametoindex(const char *ifname) +{ + int index; + int ctl_sock; + struct ifreq ifr; + + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + + index = 0; + if ((ctl_sock = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { + if (ioctl(ctl_sock, SIOCGIFINDEX, &ifr) >= 0) { + index = ifr.ifr_ifindex; + } + close(ctl_sock); + } + return index; +} diff --git a/resource/csdk/connectivity/src/bt_le_adapter/caleadapter_singlethread.c b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter_singlethread.c new file mode 100644 index 0000000..cdedbbd --- /dev/null +++ b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter_singlethread.c @@ -0,0 +1,427 @@ +/****************************************************************** +* +* Copyright 2014 Samsung Electronics All Rights Reserved. +* +* +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************/ +#include "caleadapter_singlethread.h" + +#include "caleinterface_singlethread.h" +#include "cableserver.h" +#include "logger.h" +#include "caadapterutils.h" +#include "cafragmentation.h" + +#define TAG "LAD" + +/** + * @def MAX_EVENT_COUNT + * @brief Maximum number of tries to get the event on BLE Shield address. + */ +#define MAX_EVENT_COUNT 20 + +static CANetworkChangeCallback g_networkCallback = NULL; +static bool g_serverRunning = false; +static CANetworkPacketReceivedCallback g_respCallback; +static char *g_coapBuffer = NULL; +static uint32_t g_dataLen = 0; +static uint32_t g_packetDataLen = 0; + +/** + * @brief API to register for BLE network notification. + * @param net_callback - network notification callback. + * @return - Error Code + */ +CAResult_t LERegisterNetworkNotifications(CANetworkChangeCallback netCallback); + +/** + * @brief API to send received data to upper layer. + * @param[in] data - data received from BLE characteristics. + * @param[in] dataLen - received data Length. + * @param[in] senderAdrs - sender Address. + * @param[in] senderPort - sender port. + * @return - Error Code + */ +void CANotifyCallback(const void *data, int32_t dataLen, const char *senderAdrs, + int32_t senderPort); + +/** + * @brief API to read the data from characteristics and invoke notifyCallback. + * @return - void + */ +void CACheckData(); + +/** + * @brief API to Send the data. + * @return - Number of bytes sent. -1 on error. + */ +int32_t CASendLEData(const void *data, uint32_t dataLen); + +CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, + CANetworkChangeCallback netCallback) +{ + OIC_LOG(DEBUG, TAG, "IN"); + if (NULL == registerCallback || NULL == reqRespCallback || NULL == netCallback) + { + OIC_LOG(ERROR, TAG, "i/p null"); + return CA_STATUS_INVALID_PARAM; + } + + CAResult_t result = CALEInitializeNetworkMonitor(); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, TAG, "n/w init fail: %d", result); + return CA_STATUS_FAILED; + } + + g_respCallback = reqRespCallback; + LERegisterNetworkNotifications(netCallback); + CAConnectivityHandler_t connHandler; + connHandler.startAdapter = CAStartLE; + connHandler.startListenServer = CAStartLEListeningServer; + connHandler.startDiscoveryServer = CAStartLEDiscoveryServer; + connHandler.sendData = CASendLEUnicastData; + connHandler.sendDataToAll = CASendLEMulticastData; + connHandler.GetnetInfo = CAGetLEInterfaceInformation; + connHandler.readData = CAReadLEData; + connHandler.stopAdapter = CAStopLE; + connHandler.terminate = CATerminateLE; + registerCallback(connHandler, CA_ADAPTER_GATT_BTLE); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAStartLE() +{ + OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAStartLEListeningServer() +{ + OIC_LOG(DEBUG, TAG, "IN"); + CAResult_t result = CAInitializeBle(); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, TAG, "ble init fail: %d", result); + return CA_STATUS_FAILED; + } + /** + * Below for loop is to process the BLE Events received from BLE Shield. + * BLE Events includes BLE Shield Address Added as a patch to RBL Library. + */ + for (int iter = 0; iter < MAX_EVENT_COUNT; iter++) + { + CACheckData(); + } + + g_serverRunning = true; + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAStartLEDiscoveryServer() +{ + OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAStartLENotifyServer() +{ + OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +uint32_t CASendLENotification(const CAEndpoint_t *endpoint, const void *data, + uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "OUT"); + return 1; +} + +int32_t CASendLEUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "IN"); + if (NULL == remoteEndpoint || NULL == data || dataLen == 0) + { + OIC_LOG(ERROR, TAG, "i/p null"); + return -1; + } + OIC_LOG(DEBUG, TAG, "OUT"); + return CASendLEData(data, dataLen); +} + +int32_t CASendLEMulticastData(const void *data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "IN"); + if (NULL == data || 0 == dataLen) + { + OIC_LOG(ERROR, TAG, "i/p null"); + return -1; + } + + OIC_LOG(DEBUG, TAG, "OUT"); + return CASendLEData(data, dataLen); +} + +CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info, uint32_t *size) +{ + OIC_LOG(DEBUG, TAG, "IN"); + + if (NULL == info || NULL == size) + { + OIC_LOG(ERROR, TAG, "i/p null"); + return CA_STATUS_INVALID_PARAM; + } + + char *leAddress = NULL; + CAResult_t res = CAGetLEAddress(&leAddress); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CAGetLEAddress has failed"); + return res; + } + + if (NULL == leAddress) + { + OIC_LOG(ERROR, TAG, "Failed to get Le addr"); + return CA_STATUS_FAILED; + } + + OIC_LOG_V(DEBUG, TAG, "leAddress = %s", leAddress); + + /** + * Create local endpoint using util function + */ + (*info) = CAAdapterCreateEndpoint(CA_DEFAULT_FLAGS, CA_ADAPTER_GATT_BTLE, leAddress, 0); + if (NULL == (*info)) + { + OIC_LOG(ERROR, TAG, "malloc fail"); + return CA_MEMORY_ALLOC_FAILED; + } + + (*size) = 1; + if (*leAddress) + { + OICFree(leAddress); + } + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAReadLEData() +{ + if (true == g_serverRunning) + { + CACheckData(); + } + return CA_STATUS_OK; +} + +CAResult_t CAStopLE() +{ + OIC_LOG(DEBUG, TAG, "IN"); + CAStopBleGattServer(); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +void CATerminateLE() +{ + OIC_LOG(DEBUG, TAG, "IN"); + g_respCallback = NULL; + LERegisterNetworkNotifications(NULL); + CAResult_t result = CATerminateBle(); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "ble terminate fail"); + return; + } + + CALETerminateNetworkMonitor(); + g_serverRunning = false; + OIC_LOG(DEBUG, TAG, "OUT"); + return; +} + +CAResult_t LERegisterNetworkNotifications(CANetworkChangeCallback netCallback) +{ + OIC_LOG(DEBUG, TAG, "IN"); + g_networkCallback = netCallback; + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAStartBleGattServer() +{ + OIC_LOG(DEBUG, TAG, "IN"); + // Done at time of setup i.e. in initializeBle api + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAStopBleGattServer() +{ + OIC_LOG(DEBUG, TAG, "IN"); + // There is no server running to stop. + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +void CANotifyCallback(const void *data, int32_t dataLen, const char *senderAdrs, int32_t senderPort) +{ + OIC_LOG(DEBUG, TAG, "IN"); + if (g_respCallback) + { + + /* Cannot get Address as of now */ + CAEndpoint_t *localEndpoint = CAAdapterCreateLocalEndpoint(CA_IPV4, CA_ADAPTER_GATT_BTLE, + senderAdrs, senderPort); + + g_respCallback(localEndpoint, data, dataLen); + } + OIC_LOG(DEBUG, TAG, "OUT"); +} + +void CACheckData() +{ + CABleDoEvents(); + + if (CAIsBleDataAvailable()) + { + // Allocate Memory for COAP Buffer and do ParseHeader + if (NULL == g_coapBuffer) + { + OIC_LOG(DEBUG, TAG, "IN"); + char headerArray[CA_HEADER_LENGTH] = ""; + while (CAIsBleDataAvailable() && g_dataLen < CA_HEADER_LENGTH) + { + headerArray[g_dataLen++] = CAReadBleData(); + } + + g_packetDataLen = CAParseHeader(headerArray); + + if (g_packetDataLen > COAP_MAX_PDU_SIZE) + { + OIC_LOG(ERROR, TAG, "len > pdu_size"); + return; + } + + g_coapBuffer = (char *)OICCalloc((size_t)g_packetDataLen, sizeof(char)); + if (NULL == g_coapBuffer) + { + OIC_LOG(ERROR, TAG, "malloc"); + return; + } + + OIC_LOG(DEBUG, TAG, "OUT"); + g_dataLen = 0; + } + + OIC_LOG(DEBUG, TAG, "IN"); + while (CAIsBleDataAvailable()) + { + OIC_LOG(DEBUG, TAG, "In While loop"); + g_coapBuffer[g_dataLen++] = CAReadBleData(); + if (g_dataLen == g_packetDataLen) + { + OIC_LOG(DEBUG, TAG, "Read Comp BLE Pckt"); + g_coapBuffer[g_dataLen] = '\0'; + if (g_dataLen > 0) + { + OIC_LOG_V(DEBUG, TAG, "recv dataLen=%d", g_dataLen); + CANotifyCallback((void *)g_coapBuffer, g_dataLen, "", 0); + } + g_dataLen = 0; + OICFree(g_coapBuffer); + g_coapBuffer = NULL; + break; + } + } + OIC_LOG(DEBUG, TAG, "OUT"); + } + else + { + OIC_LOG(DEBUG, TAG, "NoData"); + } + return; +} + +int32_t CASendLEData(const void *data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "IN"); + char header[CA_HEADER_LENGTH] = {0}; + + CAResult_t result = CAGenerateHeader(header, dataLen); + + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "Generate header failed"); + return -1; + } + + if (!CAIsBleConnected()) + { + OIC_LOG(ERROR, TAG, "le not conn"); + return -1; + } + + result = CAUpdateCharacteristicsToAllGattClients(header, CA_HEADER_LENGTH); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "Update characteristics failed"); + return -1; + } + + int32_t dataLimit = dataLen / CA_SUPPORTED_BLE_MTU_SIZE; + for (int32_t iter = 0; iter < dataLimit; iter++) + { + result = CAUpdateCharacteristicsToAllGattClients((data + + (iter * CA_SUPPORTED_BLE_MTU_SIZE)), + CA_SUPPORTED_BLE_MTU_SIZE); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "Update characteristics failed"); + return -1; + } + CABleDoEvents(); + } + + uint8_t remainingLen = dataLen % CA_SUPPORTED_BLE_MTU_SIZE; + if(remainingLen) + { + result = CAUpdateCharacteristicsToAllGattClients((data + + (dataLimit * CA_SUPPORTED_BLE_MTU_SIZE)), + remainingLen); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "Update characteristics failed"); + return -1; + } + CABleDoEvents(); + } + + OIC_LOG(DEBUG, TAG, "writebytes done"); + OIC_LOG(DEBUG, TAG, "OUT"); + // Arduino BLEWrite doesnot return value. So, Return the received DataLength + return dataLen; +} + diff --git a/resource/csdk/connectivity/src/caconnectivitymanager.c b/resource/csdk/connectivity/src/caconnectivitymanager.c index 910d167..b8e9f42 100644 --- a/resource/csdk/connectivity/src/caconnectivitymanager.c +++ b/resource/csdk/connectivity/src/caconnectivitymanager.c @@ -34,7 +34,7 @@ #include "caadapternetdtls.h" #endif -CAGlobals_t caglobals; +CAGlobals_t caglobals = { 0 }; #define TAG "CA_CONN_MGR" @@ -227,7 +227,7 @@ CAResult_t CASendResponse(const CAEndpoint_t *object, const CAResponseInfo_t *re } -CAResult_t CASelectNetwork(const uint32_t interestedNetwork) +CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork) { OIC_LOG_V(DEBUG, TAG, "Selected network : %d", interestedNetwork); @@ -261,7 +261,7 @@ CAResult_t CASelectNetwork(const uint32_t interestedNetwork) return res; } -CAResult_t CAUnSelectNetwork(const uint32_t nonInterestedNetwork) +CAResult_t CAUnSelectNetwork(CATransportAdapter_t nonInterestedNetwork) { OIC_LOG_V(DEBUG, TAG, "unselected network : %d", nonInterestedNetwork); diff --git a/resource/csdk/connectivity/src/camessagehandler.c b/resource/csdk/connectivity/src/camessagehandler.c index aada31e..9695e2f 100644 --- a/resource/csdk/connectivity/src/camessagehandler.c +++ b/resource/csdk/connectivity/src/camessagehandler.c @@ -340,6 +340,46 @@ static void CASendThreadProcess(void *threadData) OIC_LOG(DEBUG, TAG, "OUT"); } +/* + * If a second message arrives with the same token and the other address + * family, drop it. Typically, IPv6 beats IPv4, so the IPv4 message is dropped. + * This can be made more robust (for instance, another message could arrive + * in between), but it is good enough for now. + */ +static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId) +{ + if (!endpoint) + { + return true; + } + if (endpoint->adapter != CA_ADAPTER_IP) + { + return false; + } + + bool ret = false; + CATransportFlags_t familyFlags = endpoint->flags & CA_IPFAMILY_MASK; + + if (messageId == caglobals.ca.previousRequestMessageId) + { + if ((familyFlags ^ caglobals.ca.previousRequestFlags) == CA_IPFAMILY_MASK) + { + if (familyFlags & CA_IPV6) + { + OIC_LOG(INFO, TAG, PCF("IPv6 duplicate response ignored")); + } + else + { + OIC_LOG(INFO, TAG, PCF("IPv4 duplicate response ignored")); + } + ret = true; + } + } + caglobals.ca.previousRequestFlags = familyFlags; + caglobals.ca.previousRequestMessageId = messageId; + return ret; +} + static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, void *data, uint32_t dataLen) { OIC_LOG(DEBUG, TAG, "IN"); @@ -375,6 +415,13 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, void *data, u return; } + if (CADropSecondRequest(endpoint, ReqInfo->info.messageId)) + { + OICFree(ReqInfo); + coap_delete_pdu(pdu); + return; + } + if (NULL != ReqInfo->info.options) { uint32_t i; diff --git a/resource/csdk/connectivity/src/ip_adapter/SConscript b/resource/csdk/connectivity/src/ip_adapter/SConscript index db06815..5cc3798 100644 --- a/resource/csdk/connectivity/src/ip_adapter/SConscript +++ b/resource/csdk/connectivity/src/ip_adapter/SConscript @@ -21,7 +21,6 @@ if target_os == 'arduino': else: common_files = [ os.path.join(src_dir, 'caipadapter.c'), - os.path.join(src_dir, 'caipclient.c'), os.path.join(src_dir, 'caipserver.c') ] # Get list of target-specific source file base names, i.e. no parent @@ -52,5 +51,3 @@ if target_os in ['linux','darwin','ios']: # The list of BLE adapter source files is a combination of both the # common and target-specific source file lists. env.AppendUnique(CA_SRC = common_files + target_files) - - diff --git a/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c index ef3a5f7..2f4b5d5 100644 --- a/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c @@ -1,890 +1,109 @@ /****************************************************************** - * - * Copyright 2014 Samsung Electronics All Rights Reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************/ +* +* Copyright 2014 Samsung Electronics All Rights Reserved. +* +* +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************/ #include "caipinterface.h" -#include -#include -#include -#include +#include +#include +#include #include +#include #include #include +#include +#include + #include "caadapterutils.h" -#include "camutex.h" #include "logger.h" #include "oic_malloc.h" #include "oic_string.h" -#include "org_iotivity_ca_CaIpInterface.h" - -#define IP_MONITOR_TAG "IP_MONITOR" -#define MAX_INTERFACE_INFO_LENGTH (1024) - -/** - * @var g_stopNetworkMonitor - * @brief Used to stop the network monitor thread. - */ -static bool g_stopNetworkMonitor = false; - -/** - * @var g_stopNetworkMonitorMutex - * @brief Mutex for synchronizing access to g_stopNetworkMonitor flag. - */ -static ca_mutex g_stopNetworkMonitorMutex = NULL; - -/** - * @struct CAIPNwMonitorContext - * @brief Used for storing network monitor context information. - */ -typedef struct -{ - u_arraylist_t *netInterfaceList; - ca_thread_pool_t threadPool; - CANetworkStatus_t nwConnectivityStatus; - CAIPConnectionStateChangeCallback networkChangeCb; -} CAIPNetworkMonitorContext; - -/** - * @var g_networkMonitorContext - * @brief network monitor context. - */ -static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL; - -/** - * @var g_networkMonitorContextMutex - * @brief Mutex for synchronizing access to cached interface and IP address information. - */ -static ca_mutex g_networkMonitorContextMutex = NULL; - -/** - * @var g_jvm - * @brief pointer to store JavaVM - */ -static JavaVM *g_jvm = NULL; - -/** - * @var g_context - * @brief pointer to store Application Context - */ -static jobject g_context = NULL; - -/** - * @fn CAIPUpdateInterfaceInformation - * @brief This methods gets local interface name and IP address information. - */ -static CAResult_t CAIPUpdateInterfaceInformation(u_arraylist_t **netInterfaceList); -/** - * @fn CACreateIPJNIInterfaceObject - * @brief creates new instance of CaIpInterface through JNI - */ -static CAResult_t CACreateIPJNIInterfaceObject(jobject context); - -/** - * @fn CAIPSendNetworkChangeCallback - * @brief updates network status to IP adapter - */ -static void CAIPSendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus); - -CAResult_t CAIPJniInit() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPJniInit"); - g_jvm = CANativeJNIGetJavaVM(); - - if (!g_jvm) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "JNI initialize error"); - return CA_STATUS_FAILED; - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPJniSetContext() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPJniSetContext"); - g_context = (jobject) CANativeJNIGetContext(); - - if (!g_context) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "unable to get application context"); - return CA_STATUS_FAILED; - } - - return CA_STATUS_OK; -} - -CAResult_t CACreateIPJNIInterfaceObject(jobject context) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACreateIPJNIInterfaceObject"); - - VERIFY_NON_NULL(context, IP_MONITOR_TAG, "context"); - - JNIEnv* env; - - if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get JNIEnv pointer"); - return CA_STATUS_FAILED; - } - - //getApplicationContext - jclass contextClass = (*env)->FindClass(env, "android/content/Context"); - if (!contextClass) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get context object class"); - return CA_STATUS_FAILED; - } - - jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass, - "getApplicationContext", - "()Landroid/content/Context;"); - if (!getApplicationContextMethod) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get getApplicationContext method"); - return CA_STATUS_FAILED; - } - - jobject gApplicationContext = (*env)->CallObjectMethod(env, context, - getApplicationContextMethod); - if (!getApplicationContextMethod) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get getApplicationContext"); - return CA_STATUS_FAILED; - } - - //Create CaIpInterface jni instance - jclass IPJniInterface = (*env)->FindClass(env, "org/iotivity/ca/CaIpInterface"); - if (!IPJniInterface) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get CaIpInterface class"); - return CA_STATUS_FAILED; - } - - jmethodID IPInterfaceConstructorMethod = (*env)->GetMethodID(env, IPJniInterface, "", - "(Landroid/content/Context;)V"); - if (!IPInterfaceConstructorMethod) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get CaIpInterface constructor method"); - return CA_STATUS_FAILED; - } - (*env)->NewObject(env, IPJniInterface, IPInterfaceConstructorMethod, gApplicationContext); - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Create CaIpInterface instance, success"); +#define TAG "IP_MONITOR" - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -static CAResult_t CAIPUpdateInterfaceInformation(u_arraylist_t **netInterfaceList) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null"); - - /* Get a socket handle. */ - int sck = -1; -#ifdef SOCK_CLOEXEC - sck = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); -#endif - - if ( -1 == sck) - { - sck=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - } +char *getHostIPAddress(const char *ifa_name) { + static char address[INET_ADDRSTRLEN] = {}; + memset(&address, 0, INET_ADDRSTRLEN); + struct ifreq ifr; + int sck, status, len = sizeof(ifr.ifr_name) - 1; + char *ip; - if (sck < 0) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Error in socket creation"); - return CA_STATUS_FAILED; + if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return NULL; } - char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; - struct ifconf ifc; - - /* Query available interfaces. */ - ifc.ifc_len = MAX_INTERFACE_INFO_LENGTH; - ifc.ifc_buf = buf; - - if (ioctl(sck, SIOCGIFCONF, &ifc) < 0) - { + strncpy(ifr.ifr_name, ifa_name, len); + ifr.ifr_name[len] = '\0'; + if ((status = ioctl(sck, SIOCGIFADDR, &ifr)) < 0) { close(sck); - OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get interface info"); - return CA_STATUS_FAILED; - } - - /* Iterate through the list of interfaces. */ - struct ifreq* ifr = ifc.ifc_req; - int32_t interfaces = ifc.ifc_len / sizeof(struct ifreq); - - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPUpdateInterfaceInformation : %d", interfaces); - - if(0 == interfaces) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "no interfaces"); - return CA_STATUS_FAILED; - } - - for (int32_t i = 0; i < interfaces; i++) - { - struct ifreq temp_ifr = { 0 }; - struct ifreq* item = &ifr[i]; - - char interfaceAddress[CA_IPADDR_SIZE] = { 0 }; - char interfaceSubnetMask[CA_IPADDR_SIZE] = { 0 }; - socklen_t len = sizeof(struct sockaddr_in); - - OICStrcpy(temp_ifr.ifr_name, sizeof(temp_ifr.ifr_name), item->ifr_name); - - if (ioctl(sck, SIOCGIFFLAGS, &temp_ifr)) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, - "CAIPUpdateInterfaceInformation, SIOCGIFFLAGS Failed"); - close(sck); - return CA_STATUS_FAILED; - } - - if ((temp_ifr.ifr_flags & IFF_LOOPBACK) - || !(temp_ifr.ifr_flags & IFF_UP) || !(temp_ifr.ifr_flags & IFF_RUNNING)) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, - "interface is not up or not running or loopback = %x", temp_ifr.ifr_flags); - continue; - } - - if (AF_INET != ((struct sockaddr_in*) &item->ifr_addr)->sin_family) - { - continue; - } - - //get the interface ip address - if (0 != getnameinfo(&item->ifr_addr, len, interfaceAddress, sizeof(interfaceAddress), - NULL, 0, NI_NUMERICHOST)) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s", - strerror(errno)); - close(sck); - return CA_STATUS_FAILED; - } - - if (ioctl((int) sck, SIOCGIFNETMASK, item) < 0) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, - "CAIPUpdateInterfaceInformation, SIOCGIFNETMASK Failed"); - close(sck); - return CA_STATUS_FAILED; - } - - // get the interface subnet mask - if (0 != getnameinfo(&item->ifr_netmask, len, interfaceSubnetMask, - sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST)) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s", - strerror(errno)); - close(sck); - return CA_STATUS_FAILED; - } - - CANetInfo_t *netInfo = (CANetInfo_t *) OICCalloc(1, sizeof(CANetInfo_t)); - if (!netInfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed"); - close(sck); - return CA_MEMORY_ALLOC_FAILED; - } - - // set interface name - OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), item->ifr_name); - - // set local ip address - OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), interfaceAddress); - - // set subnet mask - OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), interfaceSubnetMask); - - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) netInfo); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting."); - close(sck); - return CA_STATUS_FAILED; - } - - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "ipAddress : %s, interfaceName : %s, subnetmask : %s", - netInfo->ipAddress, netInfo->interfaceName, netInfo->subnetMask); + return NULL; } - close(sck); - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; + ip = inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr); + len = sizeof(address) - 1; + strncpy(address, ip, len); + address[len] = '\0'; + return address; } -static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList, - const CANetInfo_t *info) +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { - VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false); - VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false); - - uint32_t list_length = u_arraylist_length(netInterfaceList); - for (uint32_t list_index = 0; list_index < list_length; list_index++) + u_arraylist_t *iflist = u_arraylist_create(); + if (!iflist) { - CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, list_index); - if (!netInfo) - { - continue; - } - if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0) - { - return false; - } + OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + return NULL; } - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down"); - return true; -} - -static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info) -{ - VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false); - - ca_mutex_lock(g_networkMonitorContextMutex); - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - for (uint32_t list_index = 0; list_index < list_length; list_index++) + char* ipAddr = getHostIPAddress("wlan0"); + if (NULL == ipAddr) { - CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!netInfo) - { - continue; - } - if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0) - { - if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0) - { - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - else - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed"); - if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index)) - { - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(netInfo->ipAddress, - CA_INTERFACE_DOWN); - } - OICFree(netInfo); - } - else - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); - } - break; - } - } - } + OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); + u_arraylist_destroy(iflist); + return NULL; + } + OIC_LOG_V(DEBUG, TAG, "Got ifaddrs:: %s", ipAddr); - CANetInfo_t *newNetInfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t)); - if (!newNetInfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - *newNetInfo = *info; + struct in_addr inaddr; + inet_pton(AF_INET, ipAddr, &(inaddr)); - OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found"); + CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));; + OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "wlan0"); + ifitem->index = 0; //if_nametoindex("wlan0"); + ifitem->family = AF_INET; //we support ipv4 only + ifitem->ipv4addr = inaddr.s_addr; + ifitem->flags = IFF_UP|IFF_RUNNING; - CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList, - (void *) newNetInfo); + CAResult_t result = u_arraylist_add(iflist, ifitem); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); - OICFree(newNetInfo); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - /*Callback will be unset only at the time of termination. By that time, all the threads will be - stopped gracefully. This callback is properly protected*/ - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP); - } - - return true; -} - -static CAResult_t CAInitializeNetworkMonitorMutexes() -{ - if (!g_networkMonitorContextMutex) - { - g_networkMonitorContextMutex = ca_mutex_new(); - if (!g_networkMonitorContextMutex) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc failed"); - return CA_MEMORY_ALLOC_FAILED; - } - } - - if (!g_stopNetworkMonitorMutex) - { - g_stopNetworkMonitorMutex = ca_mutex_new(); - if (!g_stopNetworkMonitorMutex) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc failed"); - ca_mutex_free(g_networkMonitorContextMutex); - return CA_MEMORY_ALLOC_FAILED; - } - } - return CA_STATUS_OK; -} - -static void CADestroyNetworkMonitorMutexes() -{ - ca_mutex_free(g_networkMonitorContextMutex); - g_networkMonitorContextMutex = NULL; - - ca_mutex_free(g_stopNetworkMonitorMutex); - g_stopNetworkMonitorMutex = NULL; -} - -CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPInitializeNetworkMonitor IN"); - - VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null"); - - CAResult_t ret = CAIPJniInit(); - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Initialization failed"); - return ret; - } - - ret = CAIPJniSetContext(); - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPJniSetContext failed"); - return ret; - } - - ret = CACreateIPJNIInterfaceObject(g_context); - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "unable to create CaIpInterface instance"); - return ret; + OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); + goto exit; } - ret = CAInitializeNetworkMonitorMutexes(); + OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family); - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed"); - return CA_STATUS_FAILED; - } - - ca_mutex_lock(g_networkMonitorContextMutex); - - g_networkMonitorContext = (CAIPNetworkMonitorContext *) OICCalloc( - 1, sizeof(*g_networkMonitorContext)); - if (!g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc failed"); - ca_mutex_unlock(g_networkMonitorContextMutex); - CADestroyNetworkMonitorMutexes(); - return CA_MEMORY_ALLOC_FAILED; - } - g_networkMonitorContext->threadPool = threadPool; - - g_networkMonitorContext->netInterfaceList = u_arraylist_create(); - if (!g_networkMonitorContext->netInterfaceList) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed"); - OICFree(g_networkMonitorContext); - ca_mutex_unlock(g_networkMonitorContextMutex); - CADestroyNetworkMonitorMutexes(); - return CA_MEMORY_ALLOC_FAILED; - } - - CAIPUpdateInterfaceInformation(&g_networkMonitorContext->netInterfaceList); - - if (u_arraylist_length(g_networkMonitorContext->netInterfaceList)) - { - g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP; - } - else - { - g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN; - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -void CAIPTerminateNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - ca_mutex_lock(g_networkMonitorContextMutex); - g_networkMonitorContext->threadPool = NULL; - - CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList); - - g_networkMonitorContext->netInterfaceList = NULL; - g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN; - g_networkMonitorContext->networkChangeCb = NULL; - g_networkMonitorContext->threadPool = NULL; - - OICFree(g_networkMonitorContext); - g_networkMonitorContext = NULL; - - ca_mutex_unlock(g_networkMonitorContextMutex); - - ca_mutex_lock(g_stopNetworkMonitorMutex); - g_stopNetworkMonitor = true; - ca_mutex_unlock(g_stopNetworkMonitorMutex); - - CADestroyNetworkMonitorMutexes(); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -CAResult_t CAIPStartNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - ca_mutex_lock(g_stopNetworkMonitorMutex); - g_stopNetworkMonitor = false; - ca_mutex_unlock(g_stopNetworkMonitorMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPStopNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_STATUS_FAILED; - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - ca_mutex_lock(g_stopNetworkMonitorMutex); - if (!g_stopNetworkMonitor) - { - g_stopNetworkMonitor = true; - } - else - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!"); - } - ca_mutex_unlock(g_stopNetworkMonitorMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null"); - VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null"); - VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG, - "g_networkMonitorContextMutex is null"); - - // Get the interface and ipaddress information from cache - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList - || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList))) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_ADAPTER_NOT_ENABLED; - } - - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]", - list_length); - for (uint32_t list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!info) - { - continue; - } - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]", - info->ipAddress); - CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t)); - if (!newNetinfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_MEMORY_ALLOC_FAILED; - } - - *newNetinfo = *info; - - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) newNetinfo); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_STATUS_FAILED; - } - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask"); - VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null"); - VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null"); - VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG, - "g_networkMonitorContextMutex is null"); - - // Get the interface and ipaddress information from cache - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList - || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_ADAPTER_NOT_ENABLED; - } - - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length); - for (uint32_t list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!info) - { - continue; - } - - if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0) - { - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, - "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask); - *subnetMask = OICStrdup(info->subnetMask); - break; - } - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -bool CAIPIsConnected() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - if (!g_networkMonitorContextMutex || !g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected"); - return false; - } - - ca_mutex_lock(g_networkMonitorContextMutex); - if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return true; -} - -void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - if (!g_networkMonitorContextMutex || !g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed"); - return; - } - ca_mutex_lock(g_networkMonitorContextMutex); - - g_networkMonitorContext->networkChangeCb = callback; - - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -void CAIPSendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - ca_mutex_lock(g_stopNetworkMonitorMutex); - - if (g_stopNetworkMonitor) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Stop Network Monitor Thread is called"); - ca_mutex_unlock(g_stopNetworkMonitorMutex); - return; - } - - ca_mutex_unlock(g_stopNetworkMonitorMutex); - - ca_mutex_lock(g_networkMonitorContextMutex); - - if (!g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is NULL"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return; - } - - if (!g_networkMonitorContext->networkChangeCb) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext->networkChangeCb is NULL"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return; - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - u_arraylist_t *netInterfaceList = u_arraylist_create(); - - VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, - "memory allocation failed for netInterfaceList"); - - // if network status is changed - CAResult_t ret = CAIPUpdateInterfaceInformation(&netInterfaceList); - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "could not update interface information"); - } - - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, - "u_arraylist_create failed. Network Monitor thread stopped"); - CAClearNetInterfaceInfoList(netInterfaceList); - ca_mutex_unlock(g_networkMonitorContextMutex); - return; - } - - uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - for (uint32_t listIndex = 0; listIndex < listLength;) - { - CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get( - g_networkMonitorContext->netInterfaceList, listIndex); - if (!info) - { - listIndex++; - continue; - } - - bool ret = CACheckIsAnyInterfaceDown(netInterfaceList, info); - if (ret) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down"); - if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, listIndex)) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "u_arraylist_remove success"); - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(info->ipAddress, CA_INTERFACE_DOWN); - } - OICFree(info); - listLength--; - } - else - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); - break; - } - } - else - { - listIndex++; - } - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - listLength = u_arraylist_length(netInterfaceList); - for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) - { - CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex); - if (!info) - { - continue; - } - bool ret = CACheckIsInterfaceInfoChanged(info); - if (ret) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true"); - } - } - - CAClearNetInterfaceInfoList(netInterfaceList); - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -JNIEXPORT void JNICALL -Java_org_iotivity_ca_CaIpInterface_caIpStateEnabled(JNIEnv *env, jclass class) -{ - CANetworkStatus_t currNetworkStatus = CA_INTERFACE_UP; - OIC_LOG(DEBUG, IP_MONITOR_TAG, "caIpStateEnabled"); - - CAIPSendNetworkChangeCallback(currNetworkStatus); -} - -JNIEXPORT void JNICALL -Java_org_iotivity_ca_CaIpInterface_caIpStateDisabled(JNIEnv *env, jclass class) -{ - CANetworkStatus_t currNetworkStatus = CA_INTERFACE_DOWN; - OIC_LOG(DEBUG, IP_MONITOR_TAG, "caIpStateDisabled"); + return iflist; - CAIPSendNetworkChangeCallback(currNetworkStatus); +exit: + u_arraylist_destroy(iflist); + return NULL; } diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_eth.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_eth.cpp index 3c997ad..3e234df 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_eth.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_eth.cpp @@ -68,16 +68,16 @@ void CAIPSetUnicastPort(uint16_t port) return; } -uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf, - uint32_t bufLen, bool isMulticast) +void CAIPSendData(CAEndpoint_t *endpoint, const void *buf, + uint32_t bufLen, bool isMulticast) { if (!isMulticast && 0 == g_unicastPort) { OIC_LOG(ERROR, TAG, "port 0"); - return 0; + return; } - VERIFY_NON_NULL(endpoint, TAG, "endpoint"); + VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint"); int socketID = 0; uint16_t port = endpoint->port; @@ -87,7 +87,7 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf, g_unicastPort, &socketID) != CA_STATUS_OK) { OIC_LOG(ERROR, TAG, "init mcast err"); - return 0; + return; } OIC_LOG_V(DEBUG, TAG, "MPORT:%d", port); OIC_LOG_V(DEBUG, TAG, "LPORT:%d", g_unicastPort); @@ -100,7 +100,7 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf, if (CAArduinoInitUdpSocket(&port, &socketID) != CA_STATUS_OK) { OIC_LOG(ERROR, TAG, "init ucast err"); - return 0; + return; } } else @@ -116,23 +116,26 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf, &parsedPort) != CA_STATUS_OK) { OIC_LOG(ERROR, TAG, "parse fail"); - return 0; + return; } if (bufLen > 65535) // Max value for uint16_t { // This will never happen as max buffer size we are dealing with is COAP_MAX_PDU_SIZE OIC_LOG(ERROR, TAG, "Size exceeded"); - return 0; + return; } ret = sendto(socketID, (const uint8_t *)buf, (uint16_t)bufLen, ipAddr, port); + if (ret <= 0) + { + OIC_LOG_V(ERROR, TAG, "SendData failed: %d", ret); + } if (g_sockID != socketID) { close(socketID); } OIC_LOG(DEBUG, TAG, "OUT"); - return ret; } diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_wifi.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_wifi.cpp index 724bcdc..9dda5aa 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_wifi.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_wifi.cpp @@ -49,13 +49,13 @@ void CAIPSetUnicastPort(uint16_t port) } -uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data, - uint32_t dataLength, bool isMulticast) +void CAIPSendData(CAEndpoint_t *endpoint, + const void *data, uint32_t dataLength, bool isMulticast) { OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_RET(data, TAG, "data", 0); - VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", 0); + VERIFY_NON_NULL_VOID(data, TAG, "data"); + VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint"); OIC_LOG_V(DEBUG, TAG, "remoteip: %s", endpoint->addr); OIC_LOG_V(DEBUG, TAG, "port: %d", endpoint->port); @@ -67,14 +67,14 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data, if (res != CA_STATUS_OK) { OIC_LOG_V(ERROR, TAG, "Remote adrs parse fail %d", res); - return 0; + return; } IPAddress remoteIp(ip); Udp.beginPacket(remoteIp, endpoint->port); uint32_t bytesWritten = 0; - while(bytesWritten < dataLength) + while (bytesWritten < dataLength) { // get remaining bytes size_t writeCount = dataLength - bytesWritten; @@ -94,9 +94,9 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data, if (Udp.endPacket() == 0) { OIC_LOG(ERROR, TAG, "Failed to send"); - return 0; + return; } OIC_LOG(DEBUG, TAG, "OUT"); - return bytesWritten; + return; } diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp index 61da510..1e8c208 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp @@ -20,7 +20,7 @@ /** * @file caipnwmonitor.cpp * @brief This file is to keep design in sync with other platforms. Right now there is no - * api for network monitioring in arduino. + * api for network monitoring in arduino. */ #include "caipinterface.h" @@ -37,105 +37,69 @@ #include "caipadapter.h" #include "caadapterutils.h" #include "oic_malloc.h" +#include "oic_string.h" #define TAG "IPNW" -CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool) -{ - return CA_STATUS_OK; -} - -CAResult_t CAIPStartNetworkMonitor(void) -{ - return CA_STATUS_OK; -} +// Since the CA abstraction expects a value for "family", AF_INET will be +// defined & used (as-is defined in the linux socket headers). +#define AF_INET (2) -void CAIPGetSubnetMask(char *subnetMask, int32_t addrLen) +/// Retrieves the IP address assigned to Arduino Ethernet shield +void CAArduinoGetInterfaceAddress(uint32_t *address) { OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_VOID(subnetMask, TAG, "subnetMask"); + VERIFY_NON_NULL_VOID(address, TAG, "address"); //TODO : Fix this for scenarios when this API is invoked when device is not connected uint8_t rawIPAddr[4]; - if (addrLen < CA_IPADDR_SIZE) - { - OIC_LOG(ERROR, TAG, "Invalid addrLen"); - return; - } - - W5100.getSubnetMask(rawIPAddr); - snprintf(subnetMask, addrLen, "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2], - rawIPAddr[3]); + W5100.getIPAddress(rawIPAddr); + *address = (uint32_t) rawIPAddr; - OIC_LOG_V(DEBUG, TAG, "subnetMask:%s", subnetMask); + OIC_LOG_V(DEBUG, TAG, "address:%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], + rawIPAddr[2], rawIPAddr[3]); OIC_LOG(DEBUG, TAG, "OUT"); return; } -/// Retrieves the IP address assigned to Arduino Ethernet shield -void CAArduinoGetInterfaceAddress(char *address, int32_t addrLen) +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { - OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_VOID(address, TAG, "address"); + CAResult_t result; - //TODO : Fix this for scenarios when this API is invoked when device is not connected - uint8_t rawIPAddr[4]; - if (addrLen < CA_IPADDR_SIZE) + u_arraylist_t *iflist = u_arraylist_create(); + if (!iflist) { - OIC_LOG(ERROR, TAG, "Invalid addrLen"); - return; + OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + return NULL; } - W5100.getIPAddress(rawIPAddr); - snprintf(address, addrLen, "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2], - rawIPAddr[3]); - - OIC_LOG_V(DEBUG, TAG, "address:%s", address); - OIC_LOG(DEBUG, TAG, "OUT"); - return; -} - -CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList) -{ - CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t)); - if (!netInfo) + CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); + if (!ifitem) { OIC_LOG(ERROR, TAG, "Malloc failed"); - return CA_STATUS_FAILED; + goto exit; } - CAArduinoGetInterfaceAddress(netInfo->ipAddress, CA_IPADDR_SIZE); + // Since Arduino currently only supports one interface, the next 4 lines are sufficient. + OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "ETH"); + ifitem->index = 1; + ifitem->family = AF_INET; + ifitem->flags = 0; + CAArduinoGetInterfaceAddress(&ifitem->ipv4addr); - CAIPGetSubnetMask(netInfo->subnetMask, CA_IPADDR_SIZE); - - // set interface name - strncpy(netInfo->interfaceName, "ETH", strlen(netInfo->interfaceName)); - - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo); + result = u_arraylist_add(iflist, ifitem); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, TAG, "u_arraylist_add failed"); - return result; + OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); + goto exit; } - return CA_STATUS_OK; -} -bool CAIPIsConnected(void) -{ - return true; -} + OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family); -void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback) -{ - return; -} + return iflist; -CAResult_t CAIPStopNetworkMonitor(void) -{ - return CA_STATUS_OK; +exit: + u_arraylist_destroy(iflist); + return NULL; } -void CAIPTerminateNetworkMonitor(void) -{ - return; -} diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp index 3268b6c..cc79fc9 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp @@ -20,7 +20,7 @@ /** * @file caipnwmonitor.cpp * @brief This file is to keep design in sync with other platforms. Right now there is no - * api for network monitioring in arduino. + * api for network monitoring in arduino. */ #include "caipinterface.h" @@ -38,20 +38,16 @@ #include "caipadapter.h" #include "caadapterutils.h" #include "oic_malloc.h" +#include "oic_string.h" #define TAG "IPNW" -CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool) -{ - return CA_STATUS_OK; -} - -CAResult_t CAIPStartNetworkMonitor(void) -{ - return CA_STATUS_OK; -} +// Since the CA abstraction expects a value for "family", AF_INET will be +// defined & used (as-is defined in the linux socket headers). +#define AF_INET (2) -void CAIPGetSubnetMask(char *subnetMaskAddr, int32_t addrLen) +/// Retrieves the IP address assigned to Arduino WiFi shield +void CAArduinoGetInterfaceAddress(uint32_t *address) { OIC_LOG(DEBUG, TAG, "IN"); if (WiFi.status() != WL_CONNECTED) @@ -60,87 +56,54 @@ void CAIPGetSubnetMask(char *subnetMaskAddr, int32_t addrLen) return; } - VERIFY_NON_NULL_VOID(subnetMaskAddr, TAG, "Invalid Input"); - if (addrLen < CA_IPADDR_SIZE) - { - OIC_LOG_V(ERROR, TAG, "AddrLen MUST be atleast %d", CA_IPADDR_SIZE); - return; - } + VERIFY_NON_NULL_VOID(address, TAG, "Invalid address"); - IPAddress ip = WiFi.subnetMask(); - snprintf((char *)subnetMaskAddr, addrLen, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + IPAddress ip = WiFi.localIP(); + *address = (uint32_t) ip; - OIC_LOG_V(DEBUG, TAG, "Wifi shield subnet mask is: %s", subnetMaskAddr); + OIC_LOG_V(DEBUG, TAG, "Wifi shield address is: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); OIC_LOG(DEBUG, TAG, "OUT"); return; } -/// Retrieves the IP address assigned to Arduino WiFi shield -void CAArduinoGetInterfaceAddress(char *address, int32_t addrLen) +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { - OIC_LOG(DEBUG, TAG, "IN"); - if (WiFi.status() != WL_CONNECTED) - { - OIC_LOG(DEBUG, TAG, "No WIFI"); - return; - } + CAResult_t result = CA_STATUS_OK; - VERIFY_NON_NULL_VOID(address, TAG, "Invalid address"); - if (addrLen < CA_IPADDR_SIZE) + u_arraylist_t *iflist = u_arraylist_create(); + if (!iflist) { - OIC_LOG_V(ERROR, TAG, "AddrLen MUST be atleast %d", CA_IPADDR_SIZE); - return; + OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + return NULL; } - IPAddress ip = WiFi.localIP(); - snprintf((char *)address, addrLen, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); - - OIC_LOG_V(DEBUG, TAG, "Wifi shield address is: %s", address); - OIC_LOG(DEBUG, TAG, "OUT"); - return; -} - -CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList) -{ - CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t)); - if (!netInfo) + CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); + if (!ifitem) { OIC_LOG(ERROR, TAG, "Malloc failed"); - return CA_STATUS_FAILED; + goto exit; } - CAArduinoGetInterfaceAddress(netInfo->ipAddress, CA_IPADDR_SIZE); - - CAIPGetSubnetMask(netInfo->subnetMask, CA_IPADDR_SIZE); + // Since Arduino currently only supports one interface, the next 4 lines are sufficient. + OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "WIFI"); + ifitem->index = 1; + ifitem->family = AF_INET; + ifitem->flags = 0; + CAArduinoGetInterfaceAddress(&ifitem->ipv4addr); - // set interface name - strncpy(netInfo->interfaceName, "WIFI", strlen(netInfo->interfaceName)); - - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo); + result = u_arraylist_add(iflist, ifitem); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, TAG, "u_arraylist_add failed"); - return result; + OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); + goto exit; } - return CA_STATUS_OK; -} -bool CAIPIsConnected(void) -{ - return true; -} + OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family); -void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback) -{ - return; -} + return iflist; -CAResult_t CAIPStopNetworkMonitor(void) -{ - return CA_STATUS_OK; +exit: + u_arraylist_destroy(iflist); + return NULL; } -void CAIPTerminateNetworkMonitor(void) -{ - return; -} diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp index a698260..5adb1a2 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp @@ -35,6 +35,7 @@ #include "caipadapterutils_eth.h" #include "caadapterutils.h" #include "oic_malloc.h" +#include "oic_string.h" #define TAG "IPS" @@ -132,6 +133,23 @@ CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multic return CA_STATUS_OK; } +CAResult_t CAIPStartServer() +{ + uint16_t unicastPort = 55555; + + CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(DEBUG, TAG, "Start unicast serv failed[%d]", ret); + } + ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret); + } + return ret; +} + CAResult_t CAIPStopUnicastServer() { OIC_LOG(DEBUG, TAG, "IN"); @@ -150,20 +168,14 @@ CAResult_t CAIPStopMulticastServer() return CA_STATUS_OK; } -CAResult_t CAIPStopServer(const char *interfaceAddress) -{ - /* For arduino, Server will be running in only one interface */ - return CAIPStopAllServers(); -} - -CAResult_t CAIPStopAllServers() +void CAIPStopServer() { OIC_LOG(DEBUG, TAG, "IN"); CAResult_t result = CAIPStopUnicastServer(); if (CA_STATUS_OK != result) { OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result); - return result; + return; } CAIPSetUnicastSocket(-1); CAIPSetUnicastPort(0); @@ -174,7 +186,6 @@ CAResult_t CAIPStopAllServers() OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result); } OIC_LOG(DEBUG, TAG, "OUT"); - return result; } void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port, @@ -290,3 +301,49 @@ void CAIPPullData() { CAArduinoCheckData(); } + +CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) +{ + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL(info, TAG, "info is NULL"); + VERIFY_NON_NULL(size, TAG, "size is NULL"); + + u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return CA_STATUS_FAILED; + } + + uint32_t len = u_arraylist_length(iflist); + + CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t)); + if (!eps) + { + OIC_LOG(ERROR, TAG, "Malloc Failed"); + u_arraylist_destroy(iflist); + return CA_MEMORY_ALLOC_FAILED; + } + + for (uint32_t i = 0, j = 0; i < len; i++) + { + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + + OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name); + eps[j].flags = CA_IPV4; + eps[j].adapter = CA_ADAPTER_IP; + eps[j].interface = 0; + eps[j].port = 0; + j++; + } + + *info = eps; + *size = len; + + u_arraylist_destroy(iflist); + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp index 5c31cf9..3b982a5 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp @@ -35,6 +35,7 @@ #include "caipadapter.h" #include "caadapterutils.h" #include "oic_malloc.h" +#include "oic_string.h" #define TAG "IPS" @@ -122,6 +123,23 @@ CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multic return CA_NOT_SUPPORTED; } +CAResult_t CAIPStartServer() +{ + uint16_t unicastPort = 55555; + + CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(DEBUG, TAG, "Start unicast serv failed[%d]", ret); + } + ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret); + } + return ret; +} + CAResult_t CAIPStopUnicastServer() { OIC_LOG(DEBUG, TAG, "IN"); @@ -137,20 +155,14 @@ CAResult_t CAIPStopMulticastServer() return CAIPStopUnicastServer(); } -CAResult_t CAIPStopServer(const char *interfaceAddress) -{ - /* For arduino, Server will be running in only one interface */ - return CAIPStopAllServers(); -} - -CAResult_t CAIPStopAllServers() +void CAIPStopServer() { OIC_LOG(DEBUG, TAG, "IN"); CAResult_t result = CAIPStopUnicastServer(); if (CA_STATUS_OK != result) { OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result); - return result; + return; } CAIPSetUnicastSocket(-1); CAIPSetUnicastPort(0); @@ -161,7 +173,6 @@ CAResult_t CAIPStopAllServers() OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result); } OIC_LOG(DEBUG, TAG, "OUT"); - return result; } void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port, @@ -234,3 +245,49 @@ void CAIPPullData() { CAArduinoCheckData(); } + +CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) +{ + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL(info, TAG, "info is NULL"); + VERIFY_NON_NULL(size, TAG, "size is NULL"); + + u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return CA_STATUS_FAILED; + } + + uint32_t len = u_arraylist_length(iflist); + + CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t)); + if (!eps) + { + OIC_LOG(ERROR, TAG, "Malloc Failed"); + u_arraylist_destroy(iflist); + return CA_MEMORY_ALLOC_FAILED; + } + + for (uint32_t i = 0, j = 0; i < len; i++) + { + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + + OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name); + eps[j].flags = CA_IPV4; + eps[j].adapter = CA_ADAPTER_IP; + eps[j].interface = 0; + eps[j].port = 0; + j++; + } + + *info = eps; + *size = len; + + u_arraylist_destroy(iflist); + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + diff --git a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c index 48905f6..3a320bd 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c @@ -38,38 +38,10 @@ #include "oic_string.h" /** - * @def IP_ADAPTER_TAG + * @def TAG * @brief Logging tag for module name */ -#define IP_ADAPTER_TAG "IPAD" - -/** - * @def CA_PORT - * @brief Port to listen for incoming data - */ -#ifdef ARDUINO -#define CA_PORT 55555 -#else -#define CA_PORT 0 -#endif - -/** - * @def CA_SECURE_PORT - * @brief Secured (unicast) port number as defined in COAP Specification, RFC-7252. - */ -#define CA_SECURE_PORT 5684 - -/** - * @def CA_MCAST_PORT - * @brief Multicast port number as defined in COAP Specification, RFC-7252. - */ -#define CA_MCAST_PORT 5683 - -/** - * @def CA_MULTICAST_IP - * @brief Multicast IP Address as defined in COAP Specification, RFC-7252. - */ -#define CA_MULTICAST_IP "224.0.1.187" +#define TAG "IP_ADAP" #ifndef SINGLE_THREAD /** @@ -109,28 +81,13 @@ static CANetworkChangeCallback g_networkChangeCallback = NULL; */ static CAErrorHandleCallback g_errorCallback = NULL; -/** - * @var g_threadPool - * @brief ThreadPool for storing ca_thread_pool_t handle passed from CA - */ -static ca_thread_pool_t g_threadPool = NULL; - -static void CAIPNotifyNetworkChange(const char *address, uint16_t port, - CANetworkStatus_t status); - -static void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status); - static void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength); -static void CAIPErrorHandler(const CAEndpoint_t *endpoint, const void *data, - uint32_t dataLength, CAResult_t result); #ifdef __WITH_DTLS__ -static uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint, - const void *data, uint32_t dataLength); +static void CAIPPacketSendCB(CAEndpoint_t *endpoint, + const void *data, uint32_t dataLength); #endif -static CAResult_t CAIPStopServers(); - #ifndef SINGLE_THREAD static CAResult_t CAIPInitializeQueueHandles(); @@ -140,19 +97,20 @@ static void CAIPDeinitializeQueueHandles(); static void CAIPSendDataThread(void *threadData); static CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint, - const void *data, uint32_t dataLength, bool isMulticast); + const void *data, uint32_t dataLength, + bool isMulticast); void CAFreeIPData(CAIPData *ipData); static void CADataDestroyer(void *data, uint32_t size); CAResult_t CAIPInitializeQueueHandles() { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); // Check if the message queue is already initialized if (g_sendQueueHandle) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "send queue handle is already initialized!"); + OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!"); return CA_STATUS_OK; } @@ -160,261 +118,70 @@ CAResult_t CAIPInitializeQueueHandles() g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t)); if (!g_sendQueueHandle) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory allocation failed!"); + OIC_LOG(ERROR, TAG, "Memory allocation failed!"); return CA_MEMORY_ALLOC_FAILED; } - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle, g_threadPool, - CAIPSendDataThread, CADataDestroyer)) + if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle, + (const ca_thread_pool_t)caglobals.ip.threadpool, + CAIPSendDataThread, CADataDestroyer)) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Initialize send queue thread"); + OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread"); OICFree(g_sendQueueHandle); g_sendQueueHandle = NULL; return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } void CAIPDeinitializeQueueHandles() { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); CAQueueingThreadDestroy(g_sendQueueHandle); OICFree(g_sendQueueHandle); g_sendQueueHandle = NULL; - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); -} - -void CAIPSendDataThread(void *threadData) -{ - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - - CAIPData *ipData = (CAIPData *) threadData; - uint32_t sentData = -1; - - if (!ipData) - { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Invalid ip data!"); - return; - } - - if (ipData->isMulticast) - { - //Processing for sending multicast - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Send Multicast Data is called"); - strncpy(ipData->remoteEndpoint->addr, CA_MULTICAST_IP, MAX_ADDR_STR_SIZE_CA); - ipData->remoteEndpoint->port = CA_MCAST_PORT; - sentData = CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, true); - } - else - { - //Processing for sending unicast -#ifdef __WITH_DTLS__ - if (ipData->remoteEndpoint->flags & CA_SECURE) - { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt called!"); - CAResult_t result = CAAdapterNetDtlsEncrypt(ipData->remoteEndpoint, - ipData->data, ipData->dataLen); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt failed!"); - sentData = 0; - } - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, - "CAAdapterNetDtlsEncrypt returned with result[%d]", result); - } - else - { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Send Unicast Data is called"); - sentData = CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false); - } -#else - sentData = CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false); -#endif - } - - if (0 == sentData) - { - g_errorCallback(ipData->remoteEndpoint, ipData->data, ipData->dataLen, - CA_SEND_FAILED); - } - - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); -} - -CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint, const void *data, - uint32_t dataLength, bool isMulticast) -{ - VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "IPData is NULL", NULL); - - CAIPData *ipData = (CAIPData *) OICMalloc(sizeof(CAIPData)); - if (!ipData) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory allocation failed!"); - return NULL; - } - - ipData->remoteEndpoint = CACloneEndpoint(remoteEndpoint); - ipData->data = (void *) OICMalloc(dataLength); - if (!ipData->data) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory allocation failed!"); - CAFreeIPData(ipData); - return NULL; - } - - memcpy(ipData->data, data, dataLength); - ipData->dataLen = dataLength; - - ipData->isMulticast = isMulticast; - - return ipData; -} - -void CAFreeIPData(CAIPData *ipData) -{ - VERIFY_NON_NULL_VOID(ipData, IP_ADAPTER_TAG, "ipData is NULL"); - - CAFreeEndpoint(ipData->remoteEndpoint); - OICFree(ipData->data); - OICFree(ipData); -} - -void CADataDestroyer(void *data, uint32_t size) -{ - CAIPData *etdata = (CAIPData *) data; - - CAFreeIPData(etdata); + OIC_LOG(DEBUG, TAG, "OUT"); } -#endif -void CAIPNotifyNetworkChange(const char *address, uint16_t port, CANetworkStatus_t status) -{ - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - - VERIFY_NON_NULL_VOID(address, IP_ADAPTER_TAG, "address is NULL"); - - CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, - CA_ADAPTER_IP, - address, port); - if (!localEndpoint) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "localEndpoint creation failed!"); - return; - } - - if (g_networkChangeCallback) - { - g_networkChangeCallback(localEndpoint, status); - } - else - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "g_networkChangeCallback is NULL"); - } - - CAFreeEndpoint(localEndpoint); - - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); -} +#endif // SINGLE_THREAD void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - - VERIFY_NON_NULL_VOID(ipAddress, IP_ADAPTER_TAG, "ipAddress is NULL"); - - if (CA_INTERFACE_UP == status) - { - uint16_t port = CA_PORT; - CAResult_t ret = CAIPStartUnicastServer(ipAddress, &port, false); - if (CA_STATUS_OK == ret) - { - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Unicast server started on %d port", port); - } - else - { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to start Unicast server port[%d]", ret); - } - -#ifdef __WITH_DTLS__ - port = CA_SECURE_PORT; - ret = CAIPStartUnicastServer(ipAddress, &port, true); - if (CA_STATUS_OK == ret) - { - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Secure Unicast server started on %d", port); - } - else - { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to start secure Unicast server [%d]", - ret); - } -#endif - ret = CAIPStartMulticastServer(ipAddress, CA_MULTICAST_IP, CA_MCAST_PORT); - if (CA_STATUS_OK == ret) - { - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Multicast server started on port[%d]", - CA_MCAST_PORT); - } - else - { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to start Multicast server port[%d]", - ret); - } - - // Notify network change to CA - CAIPNotifyNetworkChange(ipAddress, port, status); - } - else - { - CAIPNotifyNetworkChange(ipAddress, 0, status); - - // Stop Unicast, Secured unicast and Multicast servers - CAIPStopServer(ipAddress); - } - - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); } #ifdef __WITH_DTLS__ -uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength) +static void CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, uint32_t dataLength) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - - VERIFY_NON_NULL_RET(endpoint, IP_ADAPTER_TAG, "endpoint is NULL", 0); - VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data is NULL", 0); - - uint32_t sentLength = CAIPSendData(endpoint, data, dataLength, false); - - if (sentLength == 0) - { - g_errorCallback(endpoint, data, dataLength, CA_SEND_FAILED); - } + OIC_LOG(DEBUG, TAG, "IN"); - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Successfully sent %d of encrypted data!", sentLength); + VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); + VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); + CAIPSendData(endpoint, data, dataLength, false); - return sentLength; + OIC_LOG(DEBUG, TAG, "OUT"); } #endif void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_VOID(endpoint, IP_ADAPTER_TAG, "ipAddress is NULL"); - VERIFY_NON_NULL_VOID(data, IP_ADAPTER_TAG, "data is NULL"); + VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL"); + VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port); + OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port); void *buf = OICCalloc(dataLength + 1, sizeof (char)); if (!buf) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory Allocation failed!"); + OIC_LOG(ERROR, TAG, "Memory Allocation failed!"); return; } memcpy(buf, data, dataLength); @@ -427,22 +194,22 @@ void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data, { OICFree(buf); } - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "OUT"); } void CAIPErrorHandler (const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength, CAResult_t result) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_VOID(endpoint, IP_ADAPTER_TAG, "endpoint is NULL"); + VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); - VERIFY_NON_NULL_VOID(data, IP_ADAPTER_TAG, "data is NULL"); + VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); void *buf = (void*)OICMalloc(sizeof(char) * dataLength); if (!buf) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory Allocation failed!"); + OIC_LOG(ERROR, TAG, "Memory Allocation failed!"); return; } memcpy(buf, data, dataLength); @@ -455,48 +222,39 @@ void CAIPErrorHandler (const CAEndpoint_t *endpoint, const void *data, OICFree(buf); } - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - - return; + OIC_LOG(DEBUG, TAG, "OUT"); } -int32_t CAIPSendDataInternal(const CAEndpoint_t *remoteEndpoint, const void *data, - uint32_t dataLength, bool isMulticast) +static void CAInitializeIPGlobals() { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); -#ifdef SINGLE_THREAD - - // If remoteEndpoint is NULL, its Multicast, else its Unicast. - if(!isMulticast) - { - CAIPSendData(remoteEndpoint, data, dataLength, false); - } - else - { - CAEndpoint_t ep = { 0 }; - strcpy(ep.addr, CA_MULTICAST_IP); - ep.port = CA_MCAST_PORT; - CAIPSendData(&ep, data, dataLength, true); - } -#else - VERIFY_NON_NULL_RET(g_sendQueueHandle, IP_ADAPTER_TAG, "sendQueueHandle", -1); - - // Create IPData to add to queue - CAIPData *ipData = CACreateIPData(remoteEndpoint, data, dataLength, isMulticast); - - if (!ipData) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to create ipData!"); - return -1; - } - else - { - // Add message to send queue - CAQueueingThreadAddData(g_sendQueueHandle, ipData, sizeof(CAIPData)); - } -#endif - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return dataLength; + caglobals.ip.u6.fd = -1; + caglobals.ip.u6s.fd = -1; + caglobals.ip.u4.fd = -1; + caglobals.ip.u4s.fd = -1; + caglobals.ip.m6.fd = -1; + caglobals.ip.m6s.fd = -1; + caglobals.ip.m4.fd = -1; + caglobals.ip.m4s.fd = -1; + caglobals.ip.u6.port = 0; + caglobals.ip.u6s.port = 0; + caglobals.ip.u4.port = 0; + caglobals.ip.u4s.port = 0; + caglobals.ip.m6.port = CA_COAP; + caglobals.ip.m6s.port = CA_SECURE_COAP; + caglobals.ip.m4.port = CA_COAP; + caglobals.ip.m4s.port = CA_SECURE_COAP; + + CATransportFlags_t flags = 0; + if (caglobals.client) + { + flags |= caglobals.clientFlags; + } + if (caglobals.server) + { + flags |= caglobals.serverFlags; + } + caglobals.ip.ipv6enabled = flags & CA_IPV6; + caglobals.ip.ipv4enabled = flags & CA_IPV4; } CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback, @@ -504,37 +262,22 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback, CANetworkChangeCallback netCallback, CAErrorHandleCallback errorCallback, ca_thread_pool_t handle) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - VERIFY_NON_NULL(registerCallback, IP_ADAPTER_TAG, "registerCallback"); - VERIFY_NON_NULL(networkPacketCallback, IP_ADAPTER_TAG, "networkPacketCallback"); - VERIFY_NON_NULL(netCallback, IP_ADAPTER_TAG, "netCallback"); + OIC_LOG(DEBUG, TAG, "IN"); + VERIFY_NON_NULL(registerCallback, TAG, "registerCallback"); + VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback"); + VERIFY_NON_NULL(netCallback, TAG, "netCallback"); #ifndef SINGLE_THREAD - VERIFY_NON_NULL(handle, IP_ADAPTER_TAG, "thread pool handle"); + VERIFY_NON_NULL(handle, TAG, "thread pool handle"); #endif - g_threadPool = handle; g_networkChangeCallback = netCallback; g_networkPacketCallback = networkPacketCallback; g_errorCallback = errorCallback; - CAResult_t ret = CAIPInitializeNetworkMonitor(g_threadPool); - if (CA_STATUS_OK != ret) - { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to initialize n/w monitor[%d]", ret); - return ret; - } - CAIPSetConnectionStateChangeCallback(CAIPConnectionStateCB); - - ret = CAIPInitializeServer(g_threadPool); - if (CA_STATUS_OK != ret) - { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to initialize server![%d]", ret); - CATerminateIP(); - return ret; - } + CAInitializeIPGlobals(); + caglobals.ip.threadpool = handle; CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB); - CAIPSetErrorHandleCallback(CAIPErrorHandler); #ifdef __WITH_DTLS__ CAAdapterNetDtlsInit(); @@ -553,359 +296,259 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback, ipHandler.terminate = CATerminateIP; registerCallback(ipHandler, CA_ADAPTER_IP); -#ifndef SINGLE_THREAD - if (CA_STATUS_OK != CAIPInitializeQueueHandles()) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Initialize Queue Handle"); - CATerminateIP(); - return CA_STATUS_FAILED; - } -#endif - OIC_LOG(INFO, IP_ADAPTER_TAG, "OUT"); + OIC_LOG(INFO, TAG, "OUT IntializeIP is Success"); return CA_STATUS_OK; } CAResult_t CAStartIP() { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - // Start monitoring IP network - CAResult_t ret = CAIPStartNetworkMonitor(); +#ifdef SINGLE_THREAD + uint16_t unicastPort = 55555; + // Address is hardcoded as we are using Single Interface + CAResult_t ret = CAIPStartServer(); if (CA_STATUS_OK != ret) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Start n/w monitor"); + OIC_LOG_V(DEBUG, TAG, "CAIPStartServer failed[%d]", ret); return ret; } - -#ifndef SINGLE_THREAD - // Start send queue thread - if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle)) +#else + if (CA_STATUS_OK != CAIPInitializeQueueHandles()) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Start Send Data Thread"); + OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle"); + CATerminateIP(); return CA_STATUS_FAILED; } -#endif - bool retVal = CAIPIsConnected(); - if (false == retVal) - { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IP is not Connected"); - return CA_STATUS_OK; - } - -#ifdef ARDUINO - uint16_t unicastPort = CA_PORT; - // Address is hardcoded as we are using Single Interface - ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false); - if (CA_STATUS_OK != ret) + // Start send queue thread + if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle)) { - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Start unicast serv failed[%d]", ret); - + OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread"); + return CA_STATUS_FAILED; } -#else - u_arraylist_t *netInterfaceList = u_arraylist_create(); - - VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL"); - ret = CAIPGetInterfaceInfo(&netInterfaceList); + CAResult_t ret = CAIPStartServer((const ca_thread_pool_t)caglobals.ip.threadpool); if (CA_STATUS_OK != ret) { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to get IP interface info [%d]", ret); - CAClearNetInterfaceInfoList(netInterfaceList); + OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret); return ret; } - uint32_t listIndex = 0; - uint32_t listLength = u_arraylist_length(netInterfaceList); - for (listIndex = 0; listIndex < listLength; listIndex++) - { - CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex); - if (!netInfo) - { - continue; - } - uint16_t unicastPort = CA_PORT; - ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, false); - if (CA_STATUS_OK == ret) - { - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Unicast server started on %d port", - unicastPort); - } - -#ifdef __WITH_DTLS__ - unicastPort = CA_SECURE_PORT; - ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, true); - - if (CA_STATUS_OK == ret) - { - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, - "Secure Unicast server started on %d port", unicastPort); - } -#endif - } - CAClearNetInterfaceInfoList(netInterfaceList); #endif - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return ret; + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; } CAResult_t CAStartIPListeningServer() { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - - CAResult_t ret = CA_STATUS_OK; - bool retVal = CAIPIsConnected(); - if (false == retVal) - { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IP not Connected"); - return ret; - } - -#ifdef ARDUINO - //uint16_t multicastPort = CA_MCAST_PORT; - ret = CAIPStartMulticastServer("0.0.0.0", CA_MULTICAST_IP, CA_MCAST_PORT); - if (CA_STATUS_OK != ret) - { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret); - } -#else - u_arraylist_t *netInterfaceList = u_arraylist_create(); - - VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL"); - - ret = CAIPGetInterfaceInfo(&netInterfaceList); - if (CA_STATUS_OK != ret) - { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to get IP interface info [%d]", ret); - CAClearNetInterfaceInfoList(netInterfaceList); - return ret; - } - - uint32_t listIndex = 0; - uint32_t listLength = u_arraylist_length(netInterfaceList); - for (listIndex = 0; listIndex < listLength; listIndex++) - { - - CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex); - if (!netInfo) - { - continue; - } - - OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Ip address for multicast interface %s", - netInfo->ipAddress); - ret = CAIPStartMulticastServer(netInfo->ipAddress, CA_MULTICAST_IP, CA_MCAST_PORT); - if (CA_STATUS_OK == ret) - { - OIC_LOG(INFO, IP_ADAPTER_TAG, "Multicast Server is Started Successfully"); - } - } + OIC_LOG(DEBUG, TAG, "IN"); - CAClearNetInterfaceInfoList(netInterfaceList); -#endif - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return ret; + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; } CAResult_t CAStartIPDiscoveryServer() { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - /* Both listening and discovery server are same */ - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); return CAStartIPListeningServer(); } -int32_t CASendIPUnicastData(const CAEndpoint_t *remoteEndpoint, +static int32_t CAQueueIPData(bool isMulticast, const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1); + VERIFY_NON_NULL_RET(data, TAG, "data", -1); - VERIFY_NON_NULL_RET(remoteEndpoint, IP_ADAPTER_TAG, "remoteEndpoint", -1); - VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data", -1); if (0 == dataLength) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Invalid Data Length"); + OIC_LOG(ERROR, TAG, "Invalid Data Length"); return -1; } - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return CAIPSendDataInternal(remoteEndpoint, data, dataLength, false); -} +#ifdef SINGLE_THREAD -int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength) -{ - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + CAIPSendData(endpoint, data, dataLength, isMulticast); - VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data", -1); - if (0 == dataLength) +#else + + VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1); + // Create IPData to add to queue + CAIPData *ipData = CACreateIPData(endpoint, data, dataLength, isMulticast); + if (!ipData) { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Invalid Data Length"); + OIC_LOG(ERROR, TAG, "Failed to create ipData!"); return -1; } + // Add message to send queue + CAQueueingThreadAddData(g_sendQueueHandle, ipData, sizeof(CAIPData)); + + OIC_LOG(DEBUG, TAG, "OUT"); + return dataLength; - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return CAIPSendDataInternal(endpoint, data, dataLength, true); +#endif // SINGLE_THREAD } -CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) +int32_t CASendIPUnicastData(const CAEndpoint_t *endpoint, + const void *data, uint32_t dataLength) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); + return CAQueueIPData(false, endpoint, data, dataLength); +} - VERIFY_NON_NULL(info, IP_ADAPTER_TAG, "info is NULL"); - VERIFY_NON_NULL(size, IP_ADAPTER_TAG, "size is NULL"); +int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength) +{ + OIC_LOG(DEBUG, TAG, "IN"); + return CAQueueIPData(true, endpoint, data, dataLength); +} - bool retVal = CAIPIsConnected(); - if (false == retVal) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "IP not Connected"); - return CA_ADAPTER_NOT_ENABLED; - } +CAResult_t CAReadIPData() +{ + OIC_LOG(DEBUG, TAG, "IN"); + CAIPPullData(); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} - u_arraylist_t *netInterfaceList = u_arraylist_create(); +CAResult_t CAStopIP() +{ + OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL"); +#ifdef __WITH_DTLS__ + CAAdapterNetDtlsDeInit(); +#endif - CAResult_t ret = CAIPGetInterfaceInfo(&netInterfaceList); - if (CA_STATUS_OK != ret) +#ifndef SINGLE_THREAD + if (g_sendQueueHandle && g_sendQueueHandle->threadMutex) { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "CAIPGetInterfaceInfo failed:%d", ret); - CAClearNetInterfaceInfoList(netInterfaceList); - return ret; + CAQueueingThreadStop(g_sendQueueHandle); } - uint32_t listLength = u_arraylist_length(netInterfaceList); - uint32_t netInfoSize = listLength; - -#ifdef __WITH_DTLS__ - if (listLength) - { - netInfoSize = listLength * 2; - } + CAIPDeinitializeQueueHandles(); #endif - CAEndpoint_t *conInfo = (CAEndpoint_t *)OICCalloc(netInfoSize, sizeof (CAEndpoint_t)); - if (!conInfo) - { - OIC_LOG(ERROR, IP_ADAPTER_TAG, "Malloc Failed"); - CAClearNetInterfaceInfoList(netInterfaceList); - return CA_MEMORY_ALLOC_FAILED; - } + CAIPStopServer(); - uint32_t listIndex = 0; - uint32_t count = 0; - for (listIndex = 0; listIndex < listLength; listIndex++) - { - CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex); - if (!netInfo) - { - continue; - } + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} - conInfo[count].adapter = CA_ADAPTER_IP; - conInfo[count].flags = 0; - conInfo[count].port = CAGetServerPortNum(netInfo->ipAddress, false); - OICStrcpy(conInfo[count].addr, - sizeof(conInfo[count].addr), - netInfo->ipAddress); +void CATerminateIP() +{ + OIC_LOG(DEBUG, TAG, "IN"); #ifdef __WITH_DTLS__ - // copy secure unicast server information - { - count ++; - conInfo[count].adapter = CA_ADAPTER_IP; - conInfo[count].flags = CA_SECURE; - conInfo[count].port = CAGetServerPortNum(netInfo->ipAddress, true); - OICStrcpy(conInfo[count].addr, - sizeof(conInfo[count].addr), - netInfo->ipAddress); - } + CADTLSSetAdapterCallbacks(NULL, NULL, 0); #endif - count ++; - } - *size = count; - *info = conInfo; - CAClearNetInterfaceInfoList(netInterfaceList); - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} + CAIPSetPacketReceiveCallback(NULL); -CAResult_t CAReadIPData() -{ - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - CAIPPullData(); - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return CA_STATUS_OK; +#ifndef SINGLE_THREAD + CAIPDeinitializeQueueHandles(); +#endif + + OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CAIPStopServers() +#ifndef SINGLE_THREAD + +void CAIPSendDataThread(void *threadData) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - // Stop all unicast and multicast servers. - if (CA_STATUS_OK == CAIPStopAllServers()) + CAIPData *ipData = (CAIPData *) threadData; + if (!ipData) { - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "CAIPStopAllServers success"); + OIC_LOG(DEBUG, TAG, "Invalid ip data!"); + return; } - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAStopIP() -{ - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); - + if (ipData->isMulticast) + { + //Processing for sending multicast + OIC_LOG(DEBUG, TAG, "Send Multicast Data is called"); + CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, true); + } + else + { + //Processing for sending unicast #ifdef __WITH_DTLS__ - CAAdapterNetDtlsDeInit(); + if (ipData->remoteEndpoint->flags & CA_SECURE) + { + OIC_LOG(DEBUG, TAG, "CAAdapterNetDtlsEncrypt called!"); + CAResult_t result = CAAdapterNetDtlsEncrypt(ipData->remoteEndpoint, + ipData->data, ipData->dataLen); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "CAAdapterNetDtlsEncrypt failed!"); + } + OIC_LOG_V(DEBUG, TAG, + "CAAdapterNetDtlsEncrypt returned with result[%d]", result); + } + else + { + OIC_LOG(DEBUG, TAG, "Send Unicast Data is called"); + CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false); + } +#else + CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false); #endif + } - // Stop IP network monitor - CAIPStopNetworkMonitor(); + OIC_LOG(DEBUG, TAG, "OUT"); +} + +#endif #ifndef SINGLE_THREAD - // Stop send queue thread - if (g_sendQueueHandle) + +CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint, const void *data, + uint32_t dataLength, bool isMulticast) +{ + VERIFY_NON_NULL_RET(data, TAG, "IPData is NULL", NULL); + + CAIPData *ipData = (CAIPData *) OICMalloc(sizeof(CAIPData)); + if (!ipData) { - CAQueueingThreadStop(g_sendQueueHandle); + OIC_LOG(ERROR, TAG, "Memory allocation failed!"); + return NULL; } -#endif - // Stop Unicast, Secured unicast and Multicast servers running - CAResult_t result = CAIPStopServers(); - if (CA_STATUS_OK != result) + ipData->remoteEndpoint = CACloneEndpoint(remoteEndpoint); + ipData->data = (void *) OICMalloc(dataLength); + if (!ipData->data) { - OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "stop srv fail:%d", result); + OIC_LOG(ERROR, TAG, "Memory allocation failed!"); + CAFreeIPData(ipData); + return NULL; } - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); - return result; -} + memcpy(ipData->data, data, dataLength); + ipData->dataLen = dataLength; -void CATerminateIP() -{ - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN"); + ipData->isMulticast = isMulticast; - // Stop IP adapter - CAStopIP(); + return ipData; +} -#ifdef __WITH_DTLS__ - CADTLSSetAdapterCallbacks(NULL, NULL, 0); -#endif +void CAFreeIPData(CAIPData *ipData) +{ + VERIFY_NON_NULL_VOID(ipData, TAG, "ipData is NULL"); - CAIPSetPacketReceiveCallback(NULL); + CAFreeEndpoint(ipData->remoteEndpoint); + OICFree(ipData->data); + OICFree(ipData); +} - // Terminate IP server - CAIPTerminateServer(); +void CADataDestroyer(void *data, uint32_t size) +{ + CAIPData *etdata = (CAIPData *) data; - // Terminate network monitor - CAIPSetConnectionStateChangeCallback(NULL); - CAIPTerminateNetworkMonitor(); + CAFreeIPData(etdata); +} -#ifndef SINGLE_THREAD - // Terminate message queue handler - CAIPDeinitializeQueueHandles(); -#endif +#endif // SINGLE_THREAD - OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT"); -} diff --git a/resource/csdk/connectivity/src/ip_adapter/caipclient.c b/resource/csdk/connectivity/src/ip_adapter/caipclient.c deleted file mode 100644 index 4d57e70..0000000 --- a/resource/csdk/connectivity/src/ip_adapter/caipclient.c +++ /dev/null @@ -1,145 +0,0 @@ -/****************************************************************** - * - * Copyright 2014 Samsung Electronics All Rights Reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************/ -#include "caipinterface.h" - -#include -#include -#include -#include -#include - -#include "caadapterutils.h" - -/** - * @def IP_CLIENT_TAG - * @brief Logging tag for module name - */ -#define IP_CLIENT_TAG "IP_CLIENT" -#define OC_MULTICAST_IP "224.0.1.187" - -static uint32_t CASendData(const CAEndpoint_t *endpoint, const void *data, - uint32_t dataLength, int sockfd) -{ - OIC_LOG(DEBUG, IP_CLIENT_TAG, "IN"); - - VERIFY_NON_NULL_RET(endpoint, IP_CLIENT_TAG, "IP address is NULL", 0); - VERIFY_NON_NULL_RET(data, IP_CLIENT_TAG, "data is NULL", 0); - - if (0 == dataLength) - { - OIC_LOG(ERROR, IP_CLIENT_TAG, "Data length is 0!"); - return 0; - } - - if (0 > sockfd) - { - OIC_LOG(ERROR, IP_CLIENT_TAG, "Unicast Server is not running!"); - return 0; - } - - struct sockaddr_in destAddr = { 0 }; - destAddr.sin_family = AF_INET; - destAddr.sin_port = htons(endpoint->port); - - int ret = inet_pton(AF_INET, endpoint->addr, &(destAddr.sin_addr)); - if (1 != ret) - { - OIC_LOG(ERROR, IP_CLIENT_TAG, "inet_pton failed!"); - return 0; - } - - ssize_t sendDataLength = sendto(sockfd, data, dataLength, 0, (struct sockaddr *) &destAddr, - sizeof(destAddr)); - if (-1 == sendDataLength) - { - OIC_LOG_V(ERROR, IP_CLIENT_TAG, "sendto failed, Error code: %s", - strerror(errno)); - return 0; - } - - OIC_LOG_V(INFO, IP_CLIENT_TAG, "Sending data is successful, sent bytes[%d] to ip[%s:%d]", - sendDataLength, endpoint->addr, endpoint->port); - OIC_LOG(DEBUG, IP_CLIENT_TAG, "OUT"); - return sendDataLength; -} - -uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data, - uint32_t dataLength, bool isMulticast) -{ - u_arraylist_t *tempServerInfoList = u_arraylist_create(); - if (!tempServerInfoList) - { - OIC_LOG(ERROR, IP_CLIENT_TAG, "u_arraylist_create failed"); - return 0; - } - - CAResult_t res = CAGetIPServerInfoList(&tempServerInfoList); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, IP_CLIENT_TAG, "CAGetIPServerInfoList failed"); - CAClearServerInfoList(tempServerInfoList); - return 0; - } - - uint32_t len = 0; - if (isMulticast || strcmp(endpoint->addr, OC_MULTICAST_IP) == 0) - { - uint32_t listIndex = 0; - uint32_t listLength = u_arraylist_length(tempServerInfoList); - for (listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(tempServerInfoList, - listIndex); - if (!info || info->isMulticastServer || (info->endpoint.flags & CA_SECURE)) - { - continue; - } - - if (info->socketFd < 0) - { - OIC_LOG(ERROR, IP_CLIENT_TAG, "Invalid Socket Fd"); - continue; - } - - OIC_LOG_V(DEBUG, IP_CLIENT_TAG, - "CA IP Multicast SendData with src ip %s port %d sockFd %d", - info->endpoint.addr, info->endpoint.port, info->socketFd); - len = CASendData(endpoint, data, dataLength, info->socketFd); - } - } - else - { - int sockFd = CAGetSocketFdForUnicastServer(tempServerInfoList, isMulticast, endpoint); - if (sockFd < 0) - { - OIC_LOG(ERROR, IP_CLIENT_TAG, "Invalid Socket Fd"); - CAClearServerInfoList(tempServerInfoList); - return 0; - } - - OIC_LOG_V(DEBUG, IP_CLIENT_TAG, "IP unicast SendData sockFd %d", sockFd); - - len = CASendData(endpoint, data, dataLength, sockFd); - - } - CAClearServerInfoList(tempServerInfoList); - return len; -} - diff --git a/resource/csdk/connectivity/src/ip_adapter/caipserver.c b/resource/csdk/connectivity/src/ip_adapter/caipserver.c index 9c0712f..404d4a8 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipserver.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipserver.c @@ -1,4 +1,4 @@ -/****************************************************************** +/*****************************************************************j * * Copyright 2014 Samsung Electronics All Rights Reserved. * @@ -20,14 +20,28 @@ #include "caipinterface.h" +#ifndef __APPLE__ +#include +#else + #ifndef IPV6_ADD_MEMBERSHIP + #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP + #endif +#endif #include #include +#include #include +#include #include #include #include #include +#include #include +#ifdef __linux__ +#include +#include +#endif #include "pdu.h" #include "caadapterutils.h" @@ -39,971 +53,813 @@ #include "oic_string.h" /** - * @def IP_SERVER_TAG + * @def TAG * @brief Logging tag for module name */ -#define IP_SERVER_TAG "IP_SERVER" - -/** - * @def CA_UDP_BIND_RETRY_COUNT - * @brief Retry count in case of socket bind failure. - */ -#define CA_UDP_BIND_RETRY_COUNT 10 - -/** - * @def IPNAMESIZE - * @brief Max length for ip address. - */ -#define IPNAMESIZE 16 - -/** - * @def SOCKETOPTION - * @brief Socket option. - */ -#define SOCKETOPTION 1 - -/** - * @var g_packetHandlerStopFlag - * @brief Flag for stopping packet handler thread. - */ -static bool g_packetHandlerStopFlag = false; +#define TAG "IP_SERVER" + +#define SELECT_TIMEOUT 1 // select() seconds (and termination latency) + +#define IPv4_MULTICAST "224.0.1.187" +static struct in_addr IPv4MulticastAddress = { 0 }; + +#define IPv6_DOMAINS 16 +#define IPv6_MULTICAST_INT "ff01::fd" +static struct in6_addr IPv6MulticastAddressInt; +#define IPv6_MULTICAST_LNK "ff02::fd" +static struct in6_addr IPv6MulticastAddressLnk; +#define IPv6_MULTICAST_RLM "ff03::fd" +static struct in6_addr IPv6MulticastAddressRlm; +#define IPv6_MULTICAST_ADM "ff04::fd" +static struct in6_addr IPv6MulticastAddressAdm; +#define IPv6_MULTICAST_SIT "ff05::fd" +static struct in6_addr IPv6MulticastAddressSit; +#define IPv6_MULTICAST_ORG "ff08::fd" +static struct in6_addr IPv6MulticastAddressOrg; +#define IPv6_MULTICAST_GLB "ff0e::fd" +static struct in6_addr IPv6MulticastAddressGlb; + +static char *ipv6mcnames[IPv6_DOMAINS] = { + NULL, + IPv6_MULTICAST_INT, + IPv6_MULTICAST_LNK, + IPv6_MULTICAST_RLM, + IPv6_MULTICAST_ADM, + IPv6_MULTICAST_SIT, + NULL, + NULL, + IPv6_MULTICAST_ORG, + NULL, + NULL, + NULL, + NULL, + NULL, + IPv6_MULTICAST_GLB, + NULL +}; + +static CAIPExceptionCallback g_exceptionCallback; + +static CAIPPacketReceivedCallback g_packetReceivedCallback; + +static void CAHandleNetlink(); +static void CAApplyInterfaces(); +static void CAFindReadyMessage(); +static void CASelectReturned(fd_set *readFds, int ret); +static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags); + +#define SET(TYPE, FDS) \ + if (caglobals.ip.TYPE.fd != -1) \ + { \ + FD_SET(caglobals.ip.TYPE.fd, FDS); \ + } + +#define ISSET(TYPE, FDS, FLAGS) \ + if (caglobals.ip.TYPE.fd != -1 && FD_ISSET(caglobals.ip.TYPE.fd, FDS)) \ + { \ + fd = caglobals.ip.TYPE.fd; \ + flags = FLAGS; \ + } -/** - * @var CAAdapterIPServerContext_t - * @brief Thread context information for callbacks and threadpool. - */ -typedef struct +static void CAReceiveHandler(void *data) { - ca_thread_pool_t threadPool; - CAIPPacketReceivedCallback packetReceivedCallback; - CAIPExceptionCallback exceptionCallback; - CAIPErrorHandleCallback IPErrorCallback; -} CAAdapterIPServerContext_t; - -/** - * @var g_serverInfoList - * @brief Mutex to synchronize ethenet adapter context. - */ -static u_arraylist_t *g_serverInfoList = NULL; - -/** - * @var g_mutexServerInfoList - * @brief Mutex to synchronize Server Information. - */ -static ca_mutex g_mutexServerInfoList = NULL; + OIC_LOG(DEBUG, TAG, "IN"); -/** - * @var g_adapterIPServerContext - * @brief Mutex to synchronize ethenet adapter context. - */ -static CAAdapterIPServerContext_t *g_adapterIPServerContext = NULL; + while (!caglobals.ip.terminate) + { + CAFindReadyMessage(); + } -/** - * @var g_mutexAdapterServerContext - * @brief Mutex to synchronize unicast server - */ -static ca_mutex g_mutexAdapterServerContext = NULL; + OIC_LOG(DEBUG, TAG, "OUT"); +} -static void CAReceiveHandler(void *data) +static void CAFindReadyMessage() { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - fd_set readFds; - int maxSd = 0; struct timeval timeout; - char recvBuffer[COAP_MAX_PDU_SIZE] = { 0 }; - while (true != g_packetHandlerStopFlag) + timeout.tv_sec = caglobals.ip.selectTimeout; + timeout.tv_usec = 0; + struct timeval *tv = caglobals.ip.selectTimeout == -1 ? NULL : &timeout; + + FD_ZERO(&readFds); + SET(u6, &readFds) + SET(u6s, &readFds) + SET(u4, &readFds) + SET(u4s, &readFds) + SET(m6, &readFds) + SET(m6s, &readFds) + SET(m4, &readFds) + SET(m4s, &readFds) + if (caglobals.ip.shutdownFds[0] != -1) { - timeout.tv_sec = 1; - timeout.tv_usec = 0; - FD_ZERO(&readFds); + FD_SET(caglobals.ip.shutdownFds[0], &readFds); + } + if (caglobals.ip.netlinkFd != -1) + { + FD_SET(caglobals.ip.netlinkFd, &readFds); + } - ca_mutex_lock(g_mutexServerInfoList); - uint32_t listIndex = 0; - uint32_t listLength = u_arraylist_length(g_serverInfoList); + int ret = select(caglobals.ip.maxfd + 1, &readFds, NULL, NULL, tv); - u_arraylist_t *tempServerInfoList = u_arraylist_create(); - if (!tempServerInfoList) + if (caglobals.ip.terminate) + { + OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received."); + return; + } + if (ret <= 0) + { + if (ret < 0) { - OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed"); - ca_mutex_unlock(g_mutexServerInfoList); - return; + OIC_LOG_V(FATAL, TAG, "select error %s", strerror(errno)); } + return; + } - for (listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex); - if (!info) - { - listIndex++; - continue; - } + CASelectReturned(&readFds, ret); +} - int sd = info->socketFd; - //if valid socket descriptor then add to read list - if (sd > 0) - { - FD_SET(sd, &readFds); - } +static void CASelectReturned(fd_set *readFds, int ret) +{ + int fd = -1; + CATransportFlags_t flags = CA_DEFAULT_FLAGS; + + while (!caglobals.ip.terminate) + { + ISSET(u6, readFds, CA_IPV6) + else ISSET(u6s, readFds, CA_IPV6 | CA_SECURE) + else ISSET(u4, readFds, CA_IPV4) + else ISSET(u4s, readFds, CA_IPV4 | CA_SECURE) + else ISSET(m6, readFds, CA_MULTICAST | CA_IPV6) + else ISSET(m6s, readFds, CA_MULTICAST | CA_IPV6 | CA_SECURE) + else ISSET(m4, readFds, CA_MULTICAST | CA_IPV4) + else ISSET(m4s, readFds, CA_MULTICAST | CA_IPV4 | CA_SECURE) + else if (FD_ISSET(caglobals.ip.netlinkFd, readFds)) + { + CAHandleNetlink(); + break; + } + else + { + break; + } - //highest file descriptor number, need it for the select function - if (sd > maxSd) - { - maxSd = sd; - } + (void)CAReceiveMessage(fd, flags); + FD_CLR(fd, readFds); + } +} - CAServerInfo_t *newInfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t)); - if (!newInfo) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed"); - CAClearServerInfoList(tempServerInfoList); - ca_mutex_unlock(g_mutexServerInfoList); - return; - } +static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags) +{ + char recvBuffer[COAP_MAX_PDU_SIZE]; - *newInfo = *info; + struct sockaddr_storage srcAddr; + socklen_t srcAddrLen = sizeof (srcAddr); - CAResult_t result = u_arraylist_add(tempServerInfoList, (void *) newInfo); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!Thread exit"); - CAClearServerInfoList(tempServerInfoList); - ca_mutex_unlock(g_mutexServerInfoList); - return; - } - } + ssize_t recvLen = recvfrom(fd, + recvBuffer, + sizeof (recvBuffer), + 0, + (struct sockaddr *)&srcAddr, + &srcAddrLen); + if (-1 == recvLen) + { + OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno)); + return CA_STATUS_FAILED; + } - ca_mutex_unlock(g_mutexServerInfoList); + CAEndpoint_t ep = { CA_ADAPTER_IP, flags }; - int ret = select(maxSd + 1, &readFds, NULL, NULL, &timeout); - if (g_packetHandlerStopFlag) - { - OIC_LOG_V(DEBUG, IP_SERVER_TAG, - "Packet receiver handler Stop request received. Thread exited"); - CAClearServerInfoList(tempServerInfoList); - break; - } - if (ret < 0) - { - OIC_LOG_V(FATAL, IP_SERVER_TAG, "select returned error %s", strerror(errno)); - CAClearServerInfoList(tempServerInfoList); - continue; - } - - listLength = u_arraylist_length(tempServerInfoList); - for (listIndex = 0; listIndex < listLength; listIndex++) - { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(tempServerInfoList, - listIndex); - if (!info) - { - continue; - } + if (flags & CA_IPV6) + { + ep.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id; + ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0; + } + CAConvertAddrToName(&srcAddr, ep.addr, &ep.port); - int sd = info->socketFd; - if (FD_ISSET(sd , &readFds)) - { - OIC_LOG_V(ERROR, IP_SERVER_TAG, - "data Received server information ip %s, port %d socket %d", - info->endpoint.addr, info->endpoint.port, sd); - memset(recvBuffer, 0, sizeof(recvBuffer)); - - struct sockaddr_in srcSockAddress = { 0 }; - socklen_t srcAddressLen = sizeof(srcSockAddress); - - //Reading from socket - ssize_t recvLen = recvfrom(sd, recvBuffer, sizeof(recvBuffer), 0, - (struct sockaddr *) &srcSockAddress, &srcAddressLen); - if (-1 == recvLen) - { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Recvfrom failed %s", strerror(errno)); - continue; - } - else if (0 == recvLen) - { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Server socket shutdown sock fd[%d]", sd); - ca_mutex_lock(g_mutexAdapterServerContext); - // Notify upper layer this exception - if (g_adapterIPServerContext->exceptionCallback) - { - // need to make proper exception callback. - //g_adapterIPServerContext->exceptionCallback(ctx->type); - } - ca_mutex_unlock(g_mutexAdapterServerContext); - } - - char srcIPAddress[CA_IPADDR_SIZE] = { 0 }; - if (!inet_ntop(AF_INET, &srcSockAddress.sin_addr.s_addr, srcIPAddress, - sizeof(srcIPAddress))) - { - - OIC_LOG(ERROR, IP_SERVER_TAG, "inet_ntop is failed!"); - continue; - } - - uint16_t srcPort = ntohs(srcSockAddress.sin_port); - - OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Received packet from %s:%d len %d", - srcIPAddress, srcPort, recvLen); - - char *netMask = NULL; - if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(info->ifAddr, &netMask)) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet"); - continue; - } - - if (!CAAdapterIsSameSubnet(info->ifAddr, srcIPAddress, netMask)) - { - OIC_LOG(DEBUG, IP_SERVER_TAG, - "Packet received from different subnet, Ignore!"); - OICFree(netMask); - continue; - } - OICFree(netMask); - - CAEndpoint_t ep; - strncpy(ep.addr, srcIPAddress, MAX_ADDR_STR_SIZE_CA); - ep.port = srcPort; - ep.flags = (CATransportFlags_t)CA_IPV4; - ep.adapter = CA_ADAPTER_IP; - - if (info->endpoint.flags & CA_SECURE) - { + if (flags & CA_SECURE) + { #ifdef __WITH_DTLS__ - ep.flags |= CA_SECURE; - (void)CAAdapterNetDtlsDecrypt(&ep, (uint8_t *)recvBuffer, recvLen); - OIC_LOG_V(DEBUG, IP_SERVER_TAG, - "CAAdapterNetDtlsDecrypt returns [%d]", ret); + int ret = CAAdapterNetDtlsDecrypt(&ep, (uint8_t *)recvBuffer, recvLen); + OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret); +#else + OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS"); #endif - } - else //both multicast and unicast - { - ca_mutex_lock(g_mutexAdapterServerContext); - - if (g_adapterIPServerContext->packetReceivedCallback) - { - g_adapterIPServerContext->packetReceivedCallback(&ep, - recvBuffer, recvLen); - } - - ca_mutex_unlock(g_mutexAdapterServerContext); - } - } + } + else + { + if (g_packetReceivedCallback) + { + g_packetReceivedCallback(&ep, recvBuffer, recvLen); } - CAClearServerInfoList(tempServerInfoList); } - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); + + return CA_STATUS_OK; } -static CAResult_t CACreateSocket(int *socketFD, const char *localIp, uint16_t *port, bool isSecured) +void CAIPPullData() { - VERIFY_NON_NULL(socketFD, IP_SERVER_TAG, "socketFD is NULL"); - VERIFY_NON_NULL(localIp, IP_SERVER_TAG, "localIp is NULL"); - VERIFY_NON_NULL(port, IP_SERVER_TAG, "port is NULL"); - // Create a UDP socket - int sock = -1; - -#ifdef SOCK_CLOEXEC - sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); -#endif + OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "OUT"); +} - if (-1 == sock) +static int CACreateSocket(int family, uint16_t *port) +{ + int socktype = SOCK_DGRAM; + #ifdef SOCK_CLOEXEC + socktype |= SOCK_CLOEXEC; + #endif + int fd = socket(family, socktype, IPPROTO_UDP); + if (-1 == fd) { - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno)); + return -1; } - if (-1 == sock) + #ifndef SOCK_CLOEXEC + int fl = fcntl(fd, F_GETFD); + if (-1 == fl || -1 == fcntl(fd, F_SETFD, fl|FD_CLOEXEC)) { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to create Socket, Error code: %s", - strerror(errno)); - return CA_STATUS_FAILED; + OIC_LOG_V(ERROR, TAG, "set FD_CLOEXEC failed: %s", strerror(errno)); + close(fd); + return -1; } + #endif - // Make the socket non-blocking - if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK)) + struct sockaddr_storage sa = { family }; + if (family == AF_INET6) { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set non-block mode, Error code: %s", - strerror(errno)); - - close(sock); - return CA_STATUS_FAILED; + int on = 1; + if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on))) + { + OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", strerror(errno)); + } + ((struct sockaddr_in6 *)&sa)->sin6_port = htons(*port); + } + else + { + ((struct sockaddr_in *)&sa)->sin_port = htons(*port); } - if (0 != *port && !isSecured) + if (*port) // use the given port { - int setOptionOn = SOCKETOPTION; - if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &setOptionOn, - sizeof(setOptionOn))) + int on = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on))) { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s", - strerror(errno)); - close(sock); - return CA_STATUS_FAILED; + OIC_LOG_V(ERROR, TAG, "SO_REUSEADDR failed: %s", strerror(errno)); + close(fd); + return -1; } } - struct sockaddr_in sockAddr = { 0 }; - uint16_t serverPort = *port; - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons(serverPort); - if (localIp) + if (-1 == bind(fd, (struct sockaddr *)&sa, sizeof(sa))) { - sockAddr.sin_addr.s_addr = inet_addr(localIp); + OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno)); + close(fd); + return -1; } - bool isBound = false; - if (-1 != bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr))) - { - isBound = true; - } - else if (isSecured) + if (!*port) // return the assigned port { - //if secure port 5684 is occupied, trying for another port - serverPort = 0; - sockAddr.sin_port = htons(serverPort); - if (-1 != bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr))) + struct sockaddr_storage sa; + socklen_t socklen = sizeof (sa); + if (-1 == getsockname(fd, (struct sockaddr *)&sa, &socklen)) { - isBound = true; + OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", strerror(errno)); + close(fd); + return -1; } + *port = ntohs(family == AF_INET6 ? + ((struct sockaddr_in6 *)&sa)->sin6_port : + ((struct sockaddr_in *)&sa)->sin_port); } - if (true == isBound) - { - struct sockaddr_in sin; - socklen_t len = sizeof(sin); + return fd; +} + +#define CHECKFD(FD) \ + if (FD > caglobals.ip.maxfd) \ + caglobals.ip.maxfd = FD; +#define NEWSOCKET(FAMILY, NAME) \ + caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port); \ + CHECKFD(caglobals.ip.NAME.fd) + +static void CAInitializeNetlink() +{ +#ifdef __linux__ + // create NETLINK fd for interface change notifications + struct sockaddr_nl sa = { AF_NETLINK, 0, 0, RTMGRP_LINK }; - if (-1 == getsockname(sock, (struct sockaddr *)&sin, &len)) + caglobals.ip.netlinkFd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE); + if (caglobals.ip.netlinkFd == -1) + { + OIC_LOG_V(ERROR, TAG, "netlink socket failed: %s", strerror(errno)); + } + else + { + int r = bind(caglobals.ip.netlinkFd, (struct sockaddr *)&sa, sizeof (sa)); + if (r) { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to get socket[%s]!", - strerror(errno)); - close(sock); - return CA_STATUS_FAILED; + OIC_LOG_V(ERROR, TAG, "netlink bind failed: %s", strerror(errno)); + close(caglobals.ip.netlinkFd); + caglobals.ip.netlinkFd = -1; } else { - serverPort = (uint16_t) ntohs(sin.sin_port); + CHECKFD(caglobals.ip.netlinkFd); } } - else - { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to bind socket[%s]!", strerror(errno)); - close(sock); - return CA_STATUS_FAILED; - } - - *port = serverPort; - *socketFD = sock; - return CA_STATUS_OK; +#endif } -static void CACloseSocket(int socketFD) +static void CAInitializePipe() { - if (-1 == socketFD) + caglobals.ip.selectTimeout = -1; +#ifdef HAVE_PIPE2 + int ret = pipe2(caglobals.ip.shutdownFds, O_CLOEXEC); +#else + int ret = pipe(caglobals.ip.shutdownFds); + if (-1 != ret) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid Socket Fd"); - return; + ret = fcntl(caglobals.ip.shutdownFds[0], F_GETFD); + if (-1 != ret) + { + ret = fcntl(caglobals.ip.shutdownFds[0], F_SETFD, ret|FD_CLOEXEC); + } + if (-1 != ret) + { + ret = fcntl(caglobals.ip.shutdownFds[1], F_GETFD); + } + if (-1 != ret) + { + ret = fcntl(caglobals.ip.shutdownFds[1], F_SETFD, ret|FD_CLOEXEC); + } + if (-1 == ret) + { + close(caglobals.ip.shutdownFds[1]); + close(caglobals.ip.shutdownFds[0]); + caglobals.ip.shutdownFds[0] = -1; + caglobals.ip.shutdownFds[1] = -1; + } } - - // close the socket - if (-1 == close(socketFD)) +#endif + if (-1 == ret) { - OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to close the socket, Error code: %s\n", - strerror(errno)); + OIC_LOG_V(ERROR, TAG, "pipe failed: %s", strerror(errno)); + caglobals.ip.selectTimeout = SELECT_TIMEOUT; //poll needed for shutdown } } -static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port, - bool isSecured, int *serverFD) +CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - - VERIFY_NON_NULL(serverFD, IP_SERVER_TAG, "serverFD"); - VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress"); - VERIFY_NON_NULL(port, IP_SERVER_TAG, "port"); + CAResult_t res = CA_STATUS_OK; - CAResult_t ret = CACreateSocket(serverFD, localAddress, port, isSecured); - if (CA_STATUS_OK != ret) + if (caglobals.ip.started) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create unicast socket"); + return res; } - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - return ret; -} - -static CAResult_t CAIPStartPacketReceiverHandler() -{ - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - - ca_mutex_lock(g_mutexServerInfoList); - - uint32_t listLength = u_arraylist_length(g_serverInfoList); - - ca_mutex_unlock(g_mutexServerInfoList); - - ca_mutex_lock(g_mutexAdapterServerContext); + if (!IPv4MulticastAddress.s_addr) + { + (void)inet_aton(IPv4_MULTICAST, &IPv4MulticastAddress); + (void)inet_pton(AF_INET6, IPv6_MULTICAST_INT, &IPv6MulticastAddressInt); + (void)inet_pton(AF_INET6, IPv6_MULTICAST_LNK, &IPv6MulticastAddressLnk); + (void)inet_pton(AF_INET6, IPv6_MULTICAST_RLM, &IPv6MulticastAddressRlm); + (void)inet_pton(AF_INET6, IPv6_MULTICAST_ADM, &IPv6MulticastAddressAdm); + (void)inet_pton(AF_INET6, IPv6_MULTICAST_SIT, &IPv6MulticastAddressSit); + (void)inet_pton(AF_INET6, IPv6_MULTICAST_ORG, &IPv6MulticastAddressOrg); + (void)inet_pton(AF_INET6, IPv6_MULTICAST_GLB, &IPv6MulticastAddressGlb); + } - if (!g_adapterIPServerContext) + if (!caglobals.ip.ipv6enabled && !caglobals.ip.ipv4enabled) { - OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL"); - ca_mutex_unlock(g_mutexAdapterServerContext); - return CA_STATUS_FAILED; + caglobals.ip.ipv4enabled = true; // only needed to run CA tests } - if (1 == listLength) //Its first time. + if (caglobals.ip.ipv6enabled) { - g_packetHandlerStopFlag = false; - if (CA_STATUS_OK != ca_thread_pool_add_task(g_adapterIPServerContext->threadPool, - CAReceiveHandler, NULL )) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "thread_pool_add_task failed!"); - ca_mutex_unlock(g_mutexAdapterServerContext); - return CA_STATUS_FAILED; - } - OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread started successfully."); + NEWSOCKET(AF_INET6, u6) + NEWSOCKET(AF_INET6, u6s) + NEWSOCKET(AF_INET6, m6) + NEWSOCKET(AF_INET6, m6s) } - else + if (caglobals.ip.ipv4enabled) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread already is running"); + NEWSOCKET(AF_INET, u4) + NEWSOCKET(AF_INET, u4s) + NEWSOCKET(AF_INET, m4) + NEWSOCKET(AF_INET, m4s) } - ca_mutex_unlock(g_mutexAdapterServerContext); - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); + const char f[] = "socket summary: u6=%d, u6s=%d, u4=%d, u4s=%d, m6=%d, m6s=%d, m4=%d, m4s=%d"; + OIC_LOG_V(DEBUG, TAG, f, caglobals.ip.u6.fd, caglobals.ip.u6s.fd, + caglobals.ip.u4.fd, caglobals.ip.u4s.fd, + caglobals.ip.m6.fd, caglobals.ip.m6s.fd, + caglobals.ip.m4.fd, caglobals.ip.m4s.fd); + (void)f; // eliminates release warning - return CA_STATUS_OK; -} + // create pipe for fast shutdown + CAInitializePipe(); + CHECKFD(caglobals.ip.shutdownFds[0]); + CHECKFD(caglobals.ip.shutdownFds[1]); -static void CAIPServerDestroyMutex(void) -{ - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); + // create source of network interface change notifications + CAInitializeNetlink(); - if (g_mutexServerInfoList) - { - ca_mutex_free(g_mutexServerInfoList); - g_mutexServerInfoList = NULL; - } + CAApplyInterfaces(); - if (g_mutexAdapterServerContext) + caglobals.ip.terminate = false; + res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL); + if (CA_STATUS_OK != res) { - ca_mutex_free(g_mutexAdapterServerContext); - g_mutexAdapterServerContext = NULL; + OIC_LOG(ERROR, TAG, "thread_pool_add_task failed"); + return res; } + OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully."); - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); + caglobals.ip.started = true; + return CA_STATUS_OK; } -static CAResult_t CAIPServerCreateMutex(void) +void CAIPStopServer() { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - g_mutexServerInfoList = ca_mutex_new(); - if (!g_mutexServerInfoList) + caglobals.ip.terminate = true; + + if (caglobals.ip.shutdownFds[1] != -1) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - return CA_MEMORY_ALLOC_FAILED; + close(caglobals.ip.shutdownFds[1]); + // receive thread will stop immediately } - - g_mutexAdapterServerContext = ca_mutex_new(); - if (!g_mutexAdapterServerContext) + else { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to created mutex!"); - ca_mutex_free(g_mutexServerInfoList); - g_mutexServerInfoList = NULL; - return CA_MEMORY_ALLOC_FAILED; + // receive thread will stop in SELECT_TIMEOUT seconds. } - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - return CA_STATUS_OK; + OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool) +static void applyMulticastToInterface4(struct in_addr inaddr) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - - // Input validation - VERIFY_NON_NULL(threadPool, IP_SERVER_TAG, "Thread pool handle is NULL"); - - // Initialize mutex - if (CA_STATUS_OK != CAIPServerCreateMutex()) + if (!caglobals.ip.ipv4enabled) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create mutex!"); - return CA_STATUS_FAILED; + return; } - ca_mutex_lock(g_mutexAdapterServerContext); - g_adapterIPServerContext = (CAAdapterIPServerContext_t *) OICCalloc(1, - sizeof(CAAdapterIPServerContext_t)); - - if (!g_adapterIPServerContext) + struct ip_mreq mreq = { IPv4MulticastAddress }; + mreq.imr_interface = inaddr; + if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed"); - ca_mutex_unlock(g_mutexAdapterServerContext); - return CA_MEMORY_ALLOC_FAILED; + if (EADDRINUSE != errno) + { + OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); + } } + if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) + { + if (EADDRINUSE != errno) + { + OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); + } + } +} - g_adapterIPServerContext->threadPool = threadPool; - - ca_mutex_unlock(g_mutexAdapterServerContext); - - ca_mutex_lock(g_mutexServerInfoList); - - g_serverInfoList = u_arraylist_create(); - if (!g_serverInfoList) +static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface) +{ + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = *addr; + mreq.ipv6mr_interface = interface; + if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { - OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed"); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_MEMORY_ALLOC_FAILED; + if (EADDRINUSE != errno) + { + OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); + } } - ca_mutex_unlock(g_mutexServerInfoList); - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - return CA_STATUS_OK; } -void CAIPTerminateServer() +static void applyMulticastToInterface6(uint32_t interface) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - ca_mutex_lock(g_mutexAdapterServerContext); - if (!g_adapterIPServerContext) + if (!caglobals.ip.ipv6enabled) { - OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL"); - ca_mutex_unlock(g_mutexAdapterServerContext); return; } - - OICFree(g_adapterIPServerContext); - g_adapterIPServerContext = NULL; - - ca_mutex_unlock(g_mutexAdapterServerContext); - - ca_mutex_lock(g_mutexServerInfoList); - - CAClearServerInfoList(g_serverInfoList); - g_serverInfoList = NULL; - - ca_mutex_unlock(g_mutexServerInfoList); - // Destroy mutex - CAIPServerDestroyMutex(); - - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - + //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface); + applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface); + //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface); + //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface); + //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface); + //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface); + //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface); + //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface); + applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface); + //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface); + //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface); + //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface); + //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface); + //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface); } -CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port, bool isSecured) +static void CAApplyInterfaces() { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); + u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return; + } - // Input validation - VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress"); - VERIFY_NON_NULL(port, IP_SERVER_TAG, "port"); + uint32_t len = u_arraylist_length(iflist); + OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); - ca_mutex_lock(g_mutexServerInfoList); - bool isUnicastServerStarted = CAIsUnicastServerStarted(g_serverInfoList, localAddress, *port); - if (!isUnicastServerStarted) + for (uint32_t i = 0; i < len; i++) { - int unicastServerFd = -1; - if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, isSecured, - &unicastServerFd)) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to start unicast server!"); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_STATUS_FAILED; - } - - CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t)); - if (!info) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed"); - close(unicastServerFd); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_MEMORY_ALLOC_FAILED; - } + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); - char *netMask = NULL; - if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask)) + if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet"); + continue; } - if (netMask) + if (ifitem->family == AF_INET) { - OICStrcpy(info->subNetMask, sizeof(info->subNetMask), netMask); - OICFree(netMask); + struct in_addr inaddr; + inaddr.s_addr = ifitem->ipv4addr; + applyMulticastToInterface4(inaddr); + OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name); } - OICStrcpy(info->endpoint.addr, sizeof(info->endpoint.addr), localAddress); - info->endpoint.port = *port; - info->endpoint.flags = isSecured ? CA_SECURE : 0; - info->endpoint.adapter = CA_ADAPTER_IP; - info->socketFd = unicastServerFd; - info->isServerStarted = true; - info->isMulticastServer = false; - OICStrcpy(info->ifAddr, sizeof(info->ifAddr), localAddress); - - CAResult_t res = CAAddServerInfo(g_serverInfoList, info); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!"); - close(unicastServerFd); - ca_mutex_unlock(g_mutexServerInfoList); - return res; - } - ca_mutex_unlock(g_mutexServerInfoList); - - res = CAIPStartPacketReceiverHandler(); - if (CA_STATUS_OK != res) + if (ifitem->family == AF_INET6) { - OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!"); - close(unicastServerFd); - return res; + applyMulticastToInterface6(ifitem->index); + OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } - else - { - OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Already Unicast Server Started ip [%s] port [%d]", - localAddress, *port); - ca_mutex_unlock(g_mutexServerInfoList); - } - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - return CA_STATUS_OK; + u_arraylist_destroy(iflist); } -CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress, - uint16_t multicastPort) +static void CAHandleNetlink() { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - - // Input validation - VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress"); - VERIFY_NON_NULL(multicastAddress, IP_SERVER_TAG, "port"); - - uint16_t port = multicastPort; - if (0 >= port) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid input: Multicast port is invalid!"); - return CA_STATUS_INVALID_PARAM; - } - - ca_mutex_lock(g_mutexServerInfoList); - bool isMulticastServerStarted = CAIsMulticastServerStarted(g_serverInfoList, localAddress, - multicastAddress, port); - if (!isMulticastServerStarted) +#ifdef __linux__ +char buf[4096]; +struct nlmsghdr *nh; +struct sockaddr_nl sa; +struct iovec iov = { buf, sizeof(buf) }; +struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 }; + +int len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); +for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) +{ + if (nh->nlmsg_type == RTM_NEWLINK) { - int mulicastServerFd = -1; - CAResult_t ret = CACreateSocket(&mulicastServerFd, multicastAddress, &port, false); - if (ret != CA_STATUS_OK) + struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); + if ((ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create multicast socket"); - ca_mutex_unlock(g_mutexServerInfoList); - return ret; + continue; } - struct ip_mreq multicastMemberReq = {.imr_interface.s_addr = inet_addr(localAddress)}; - inet_aton(multicastAddress, &multicastMemberReq.imr_multiaddr); + int newIndex = ifi->ifi_index; - if (-1 == setsockopt(mulicastServerFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *) &multicastMemberReq, sizeof(struct ip_mreq))) + u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex); + if (!iflist) { - OIC_LOG_V(ERROR, IP_SERVER_TAG, - "Failed to add to multicast group, Error code: %s\n", strerror(errno)); - close(mulicastServerFd); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_STATUS_FAILED; + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return; } - CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t)); - if (!info) + uint32_t len = u_arraylist_length(iflist); + for (uint32_t i = 0; i < len; i++) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed"); - close(mulicastServerFd); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_MEMORY_ALLOC_FAILED; - } + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + if (ifitem->index != newIndex) + { + continue; + } - char *netMask = NULL; - if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask)) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet"); - } - if (netMask) - { - OICStrcpy(info->subNetMask, sizeof(info->subNetMask), netMask); - OICFree(netMask); + applyMulticastToInterface6(newIndex); + struct in_addr inaddr; + inaddr.s_addr = ifitem->ipv4addr; + applyMulticastToInterface4(inaddr); + break; // we found the one we were looking for } + u_arraylist_destroy(iflist); + } +} +#endif // __linux__ +} - OICStrcpy(info->endpoint.addr, sizeof(info->endpoint.addr), multicastAddress); - info->endpoint.port = multicastPort; - info->endpoint.flags = 0; - info->socketFd = mulicastServerFd; - info->isServerStarted = true; - info->isMulticastServer = true; - OICStrcpy(info->ifAddr, sizeof(info->ifAddr), localAddress); +void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback) +{ +OIC_LOG(DEBUG, TAG, "IN"); - ret = CAAddServerInfo(g_serverInfoList, info); +g_packetReceivedCallback = callback; - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!"); - close(mulicastServerFd); - ca_mutex_unlock(g_mutexServerInfoList); - return ret; - } - ca_mutex_unlock(g_mutexServerInfoList); +OIC_LOG(DEBUG, TAG, "OUT"); +} + +void CAIPSetExceptionCallback(CAIPExceptionCallback callback) +{ +OIC_LOG(DEBUG, TAG, "IN"); + + g_exceptionCallback = callback; + + OIC_LOG(DEBUG, TAG, "OUT"); +} + +static void sendData(int fd, const CAEndpoint_t *endpoint, + const void *data, uint32_t dlen, + const char *cast, const char *fam) +{ + OIC_LOG(DEBUG, TAG, "IN"); - ret = CAIPStartPacketReceiverHandler(); - if (CA_STATUS_OK != ret) + char *secure = (endpoint->flags & CA_SECURE) ? "secure " : ""; + (void)secure; // eliminates release warning + struct sockaddr_storage sock; + CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock); + + if (sock.ss_family == AF_INET6) + { + struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock; + if (!sock6->sin6_scope_id) { - OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!"); - close(mulicastServerFd); - return ret; + sock6->sin6_scope_id = endpoint->interface; } } + + ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, sizeof (sock)); + if (-1 == len) + { + OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno)); + } else { - OIC_LOG_V(DEBUG, IP_SERVER_TAG, - "Multicast Server is already started on interface addr[%s]", localAddress); - ca_mutex_unlock(g_mutexServerInfoList); + OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %d bytes", secure, cast, fam, len); } - - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - return CA_STATUS_OK; } -CAResult_t CAIPStopServer(const char *interfaceAddress) +static void sendMulticastData6(const u_arraylist_t *iflist, + CAEndpoint_t *endpoint, + const void *data, uint32_t datalen) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - - VERIFY_NON_NULL(interfaceAddress, IP_SERVER_TAG, "interfaceAddress is NULL"); - - ca_mutex_lock(g_mutexServerInfoList); - uint32_t listIndex = 0; - uint32_t listLength = u_arraylist_length(g_serverInfoList); + int scope = endpoint->flags & CA_SCOPE_MASK; + char *ipv6mcname = ipv6mcnames[scope]; + if (!ipv6mcname) + { + OIC_LOG_V(INFO, TAG, "IPv6 multicast scope invalid: %d", scope); + return; + } + strncpy(endpoint->addr, ipv6mcname, MAX_ADDR_STR_SIZE_CA); + int fd = caglobals.ip.u6.fd; - for (listIndex = 0; listIndex < listLength;) + uint32_t len = u_arraylist_length(iflist); + for (uint32_t i = 0; i < len; i++) { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex); - if (!info) + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - listIndex++; continue; } - - if (info->isMulticastServer && strncmp(interfaceAddress, info->ifAddr, strlen(info->ifAddr)) - == 0) - { - if (u_arraylist_remove(g_serverInfoList, listIndex)) - { - struct ip_mreq multicastMemberReq = { { 0 }, { 0 } }; - - multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr); - inet_aton(info->endpoint.addr, &multicastMemberReq.imr_multiaddr); - if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP, - (char *) &multicastMemberReq, sizeof(struct ip_mreq))) - { - OIC_LOG_V(ERROR, IP_SERVER_TAG, - "Failed to leave multicast group, Error code: %s", strerror(errno)); - } - CACloseSocket(info->socketFd); - OICFree(info); - OIC_LOG(DEBUG, IP_SERVER_TAG, "Multicast server is stopped successfully."); - // Reduce list length by 1 as we removed one element. - listLength--; - } - else - { - OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed."); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_STATUS_FAILED; - } - } - else if (strncmp(interfaceAddress, info->endpoint.addr, strlen(info->endpoint.addr)) == 0) + if (ifitem->family != AF_INET6) { - if (u_arraylist_remove(g_serverInfoList, listIndex)) - { - CACloseSocket(info->socketFd); - OICFree(info); - OIC_LOG(DEBUG, IP_SERVER_TAG, "Unicast server is stopped successfully."); - // Reduce list length by 1 as we removed one element. - listLength--; - } - else - { - OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed."); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_STATUS_FAILED; - } + continue; } - else + + int index = ifitem->index; + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof (index))) { - listIndex++; + OIC_LOG_V(ERROR, TAG, "setsockopt6 failed: %s", strerror(errno)); + return; } + sendData(fd, endpoint, data, datalen, "multicast", "ipv6"); } - - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_STATUS_OK; } -CAResult_t CAIPStopAllServers() +static void sendMulticastData4(const u_arraylist_t *iflist, + CAEndpoint_t *endpoint, + const void *data, uint32_t datalen) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - - g_packetHandlerStopFlag = true; + struct ip_mreq mreq = { IPv4MulticastAddress }; + strncpy(endpoint->addr, IPv4_MULTICAST, MAX_ADDR_STR_SIZE_CA); + int fd = caglobals.ip.u4.fd; - ca_mutex_lock(g_mutexServerInfoList); - - uint32_t listIndex = 0; - uint32_t listLength = u_arraylist_length(g_serverInfoList); - for (listIndex = 0; listIndex < listLength;) + uint32_t len = u_arraylist_length(iflist); + for (uint32_t i = 0; i < len; i++) { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex); - if (!info) + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - listIndex++; continue; } - if (u_arraylist_remove(g_serverInfoList, listIndex)) + if (ifitem->family != AF_INET) { - if (info->isMulticastServer) - { - struct ip_mreq multicastMemberReq = { { 0 }, { 0 } }; - - multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr); - inet_aton(info->endpoint.addr, &multicastMemberReq.imr_multiaddr); - if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP, - (char *) &multicastMemberReq, sizeof(struct ip_mreq))) - { - OIC_LOG_V(ERROR, IP_SERVER_TAG, - "Failed to leave multicast group, Error code: %s", strerror(errno)); - } - } - CACloseSocket(info->socketFd); - //Freeing server info. - OICFree(info); - // Reduce list length by 1 as we removed one element. - listLength--; + continue; } - else + + struct in_addr inaddr; + inaddr.s_addr = ifitem->ipv4addr; + mreq.imr_interface = inaddr; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq))) { - OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed."); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_STATUS_FAILED; + OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)", strerror(errno)); } + sendData(fd, endpoint, data, datalen, "multicast", "ipv4"); } - - ca_mutex_unlock(g_mutexServerInfoList); - - OIC_LOG(DEBUG, IP_SERVER_TAG, "All Server stopped successfully. OUT"); - return CA_STATUS_OK; } -void CAIPPullData() +void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen, + bool isMulticast) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); -} - -uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured) -{ - ca_mutex_lock(g_mutexServerInfoList); - - uint16_t port = CAGetServerPort(g_serverInfoList, ipAddress, isSecured); - - ca_mutex_unlock(g_mutexServerInfoList); + VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); + VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); - return port; -} - -CAResult_t CAGetIPServerInfoList(u_arraylist_t **serverInfoList) -{ - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - ca_mutex_lock(g_mutexServerInfoList); + bool isSecure = (endpoint->flags & CA_SECURE) != 0; - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_serverInfoList); - for (list_index = 0; list_index < list_length; list_index++) + if (isMulticast) { - CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, list_index); - if (!info) + endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP; + + u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); + if (!iflist) { - continue; + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return; } - CAServerInfo_t *newNetinfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t)); - if (!newNetinfo) + if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled) { - OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed!"); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_MEMORY_ALLOC_FAILED; + sendMulticastData6(iflist, endpoint, data, datalen); } - - *newNetinfo = *info; - - CAResult_t result = u_arraylist_add(*serverInfoList, (void *) newNetinfo); - if (CA_STATUS_OK != result) + if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled) { - OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!"); - ca_mutex_unlock(g_mutexServerInfoList); - return CA_STATUS_FAILED; + sendMulticastData4(iflist, endpoint, data, datalen); } - } - ca_mutex_unlock(g_mutexServerInfoList); - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); - return CA_STATUS_OK; -} - -void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback) -{ - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - - ca_mutex_lock(g_mutexAdapterServerContext); - if (g_adapterIPServerContext) - { - g_adapterIPServerContext->packetReceivedCallback = callback; + u_arraylist_destroy(iflist); } else { - OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL"); + int fd; + if (endpoint->flags & CA_IPV6) + { + fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd; + #ifndef __WITH_DTLS__ + fd = caglobals.ip.u6.fd; + #endif + sendData(fd, endpoint, data, datalen, "unicast", "ipv6"); + } + if (endpoint->flags & CA_IPV4) + { + fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd; + #ifndef __WITH_DTLS__ + fd = caglobals.ip.u4.fd; + #endif + sendData(fd, endpoint, data, datalen, "unicast", "ipv4"); + } } - - ca_mutex_unlock(g_mutexAdapterServerContext); - - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); } -void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback) +CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) { - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - ca_mutex_lock(g_mutexAdapterServerContext); + VERIFY_NON_NULL(info, TAG, "info is NULL"); + VERIFY_NON_NULL(size, TAG, "size is NULL"); - if (g_adapterIPServerContext) + u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); + if (!iflist) { - g_adapterIPServerContext->IPErrorCallback = ipErrorCallback; + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return CA_STATUS_FAILED; } - ca_mutex_unlock(g_mutexAdapterServerContext); - - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); -} + uint32_t len = u_arraylist_length(iflist); -void CAIPSetExceptionCallback(CAIPExceptionCallback callback) -{ - OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); - ca_mutex_lock(g_mutexAdapterServerContext); - - if (g_adapterIPServerContext) + CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t)); + if (!eps) { - g_adapterIPServerContext->exceptionCallback = callback; + OIC_LOG(ERROR, TAG, "Malloc Failed"); + u_arraylist_destroy(iflist); + return CA_MEMORY_ALLOC_FAILED; } - else + + for (uint32_t i = 0, j = 0; i < len; i++) { - OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL"); + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + + OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name); + eps[j].flags = ifitem->family == AF_INET6 ? CA_IPV6 : CA_IPV4; + eps[j].adapter = CA_ADAPTER_IP; + eps[j].interface = 0; + eps[j].port = 0; + j++; } - ca_mutex_unlock(g_mutexAdapterServerContext); + *info = eps; + *size = len; - OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); + u_arraylist_destroy(iflist); + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; } diff --git a/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c index d9d8f3b..a04b1c7 100644 --- a/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c @@ -30,634 +30,89 @@ #include #include "caadapterutils.h" -#include "camutex.h" #include "logger.h" #include "oic_malloc.h" #include "oic_string.h" -#define IP_MONITOR_TAG "IP_MONITOR" +#define TAG "IP_MONITOR" -/** - * @var g_networkMonitorContextMutex - * @brief Mutex for synchronizing access to cached interface and IP address information. - */ -static ca_mutex g_networkMonitorContextMutex = NULL; - -/** - * @var g_stopNetworkMonitor - * @brief Used to stop the network monitor thread. - */ -static bool g_stopNetworkMonitor = false; - -/** - * @var g_stopNetworkMonitorMutex - * @brief Mutex for synchronizing access to g_stopNetworkMonitor flag. - */ -static ca_mutex g_stopNetworkMonitorMutex = NULL; - -/** - * @struct CAIPNwMonitorContext - * @brief Used for storing network monitor context information. - */ -typedef struct +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { - u_arraylist_t *netInterfaceList; - ca_thread_pool_t threadPool; - CANetworkStatus_t nwConnectivityStatus; - CAIPConnectionStateChangeCallback networkChangeCb; -} CAIPNetworkMonitorContext; - -/** - * @var g_networkMonitorContext - * @brief network monitor context. - */ -static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL; - -static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList) -{ - - VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null"); + u_arraylist_t *iflist = u_arraylist_create(); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + return NULL; + } struct ifaddrs *ifp = NULL; if (-1 == getifaddrs(&ifp)) { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface list!, Error code: %s", - strerror(errno)); - return; + OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); + u_arraylist_destroy(iflist); + return NULL; } + OIC_LOG(DEBUG, TAG, "Got ifaddrs"); struct ifaddrs *ifa = NULL; for (ifa = ifp; ifa; ifa = ifa->ifa_next) { - char interfaceAddress[CA_IPADDR_SIZE] = {0}; - char interfaceSubnetMask[CA_IPADDR_SIZE] = {0}; - socklen_t len = sizeof(struct sockaddr_in); - - if (!ifa->ifa_addr) - { - continue; - } - - int type = ifa->ifa_addr->sa_family; - if (ifa->ifa_flags & IFF_LOOPBACK - || !((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_RUNNING))) + int family = ifa->ifa_addr->sa_family; + if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) { continue; } - if (AF_INET != type) + int ifindex = if_nametoindex(ifa->ifa_name); + if (desiredIndex && (ifindex != desiredIndex)) { continue; } - // get the interface ip address - if (0 != getnameinfo(ifa->ifa_addr, len, interfaceAddress, - sizeof(interfaceAddress), NULL, 0, NI_NUMERICHOST)) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s", - strerror(errno)); - continue; - } - - // get the interface subnet mask - if (0 != getnameinfo(ifa->ifa_netmask, len, interfaceSubnetMask, - sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST)) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s", - strerror(errno)); - continue; - } - - CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t)); - if (!netInfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed"); - freeifaddrs(ifp); - return; - } - // set interface name - OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), ifa->ifa_name); - - // set local ip address - OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), interfaceAddress); - - // set subnet mask - OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), interfaceSubnetMask); - - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo); - if (CA_STATUS_OK != result) + int length = u_arraylist_length(iflist); + int already = false; + for (int i = length-1; i >= 0; i--) { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting."); - freeifaddrs(ifp); - return; - } - } - - freeifaddrs(ifp); -} - -static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList, - const CANetInfo_t *info) -{ - VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false); - VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false); - - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(netInterfaceList); - for (list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(netInterfaceList, - list_index); - if (!netInfo) - { - continue; - } - if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0) - { - return false; - } - } - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down"); - return true; -} - -static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info) -{ - VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false); - - ca_mutex_lock(g_networkMonitorContextMutex); - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - for (list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!netInfo) - { - continue; - } - if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0) - { - if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0) + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + if (ifitem->index == ifindex && ifitem->family == family) { - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - else - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed"); - if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index)) - { - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(netInfo->ipAddress, - CA_INTERFACE_DOWN); - } - OICFree(netInfo); - } - else - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); - } + already = true; break; } } - } - - CANetInfo_t *newNetInfo = (CANetInfo_t *)OICMalloc(sizeof(CANetInfo_t)); - if (!newNetInfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - *newNetInfo = *info; - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found"); - - CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList, - (void *)newNetInfo); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); - OICFree(newNetInfo); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - /*Callback will be unset only at the time of termination. By that time, all the threads will be - stopped gracefully. This callback is properly protected*/ - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP); - } - - return true; -} - -static void CANetworkMonitorThread(void *threadData) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - while (!g_stopNetworkMonitor) - { - u_arraylist_t *netInterfaceList = u_arraylist_create(); - - VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null"); - - CAIPGetInterfaceInformation(&netInterfaceList); - - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, - "u_arraylist_create failed. Network Monitor thread stopped"); - CAClearNetInterfaceInfoList(netInterfaceList); - ca_mutex_unlock(g_networkMonitorContextMutex); - return; - } - - uint32_t listIndex = 0; - uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - for (listIndex = 0; listIndex < listLength;) - { - CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, listIndex); - if (!info) - { - listIndex++; - continue; - } - - bool ret = CACheckIsAnyInterfaceDown(netInterfaceList, info); - if (ret) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down"); - if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, listIndex)) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "u_arraylist_remove success"); - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(info->ipAddress, - CA_INTERFACE_DOWN); - } - OICFree(info); - listLength--; - } - else - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); - break; - } - } - else - { - listIndex++; - } - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - listLength = u_arraylist_length(netInterfaceList); - for (listIndex = 0; listIndex < listLength; listIndex++) - { - CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(netInterfaceList, listIndex); - if (!info) - { - continue; - } - bool ret = CACheckIsInterfaceInfoChanged(info); - if (ret) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true"); - } - } - CAClearNetInterfaceInfoList(netInterfaceList); - sleep(2); // To avoid maximum cpu usage. - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -static CAResult_t CAInitializeNetworkMonitorMutexes() -{ - if (!g_networkMonitorContextMutex) - { - g_networkMonitorContextMutex = ca_mutex_new(); - if (!g_networkMonitorContextMutex) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc failed"); - return CA_MEMORY_ALLOC_FAILED; - } - } - - if (!g_stopNetworkMonitorMutex) - { - g_stopNetworkMonitorMutex = ca_mutex_new(); - if (!g_stopNetworkMonitorMutex) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc failed"); - ca_mutex_free(g_networkMonitorContextMutex); - return CA_MEMORY_ALLOC_FAILED; - } - } - return CA_STATUS_OK; -} -static void CADestroyNetworkMonitorMutexes() -{ - ca_mutex_free(g_networkMonitorContextMutex); - g_networkMonitorContextMutex = NULL; - - ca_mutex_free(g_stopNetworkMonitorMutex); - g_stopNetworkMonitorMutex = NULL; -} - -CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null"); - - CAResult_t ret = CAInitializeNetworkMonitorMutexes(); - - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed"); - return CA_STATUS_FAILED; - } - - ca_mutex_lock(g_networkMonitorContextMutex); - - g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1, - sizeof(*g_networkMonitorContext)); - if (!g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc failed"); - ca_mutex_unlock(g_networkMonitorContextMutex); - CADestroyNetworkMonitorMutexes(); - return CA_MEMORY_ALLOC_FAILED; - } - g_networkMonitorContext->threadPool = threadPool; - - g_networkMonitorContext->netInterfaceList = u_arraylist_create(); - if (!g_networkMonitorContext->netInterfaceList) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed"); - OICFree(g_networkMonitorContext); - ca_mutex_unlock(g_networkMonitorContextMutex); - CADestroyNetworkMonitorMutexes(); - return CA_MEMORY_ALLOC_FAILED; - } - - CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList); - - - if (u_arraylist_length(g_networkMonitorContext->netInterfaceList)) - { - g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP; - } - else - { - g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN; - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -void CAIPTerminateNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - ca_mutex_lock(g_networkMonitorContextMutex); - g_networkMonitorContext->threadPool = NULL; - - CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList); - - g_networkMonitorContext->netInterfaceList = NULL; - g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN; - g_networkMonitorContext->networkChangeCb = NULL; - g_networkMonitorContext->threadPool = NULL; - - OICFree(g_networkMonitorContext); - g_networkMonitorContext = NULL; - - ca_mutex_unlock(g_networkMonitorContextMutex); - - ca_mutex_lock(g_stopNetworkMonitorMutex); - g_stopNetworkMonitor = true; - ca_mutex_unlock(g_stopNetworkMonitorMutex); - - CADestroyNetworkMonitorMutexes(); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -CAResult_t CAIPStartNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - ca_mutex_lock(g_stopNetworkMonitorMutex); - - g_stopNetworkMonitor = false; - - ca_mutex_unlock(g_stopNetworkMonitorMutex); - - ca_mutex_lock(g_networkMonitorContextMutex); - - if (!g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_STATUS_FAILED; - } - - if (CA_STATUS_OK != ca_thread_pool_add_task(g_networkMonitorContext->threadPool, - CANetworkMonitorThread, NULL)) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "[ThreadPool] thread_pool_add_task failed!"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_STATUS_FAILED; - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPStopNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_STATUS_FAILED; - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - ca_mutex_lock(g_stopNetworkMonitorMutex); - if (!g_stopNetworkMonitor) - { - g_stopNetworkMonitor = true; - } - else - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!"); - } - ca_mutex_unlock(g_stopNetworkMonitorMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null"); - VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, - "g_networkMonitorContext is null"); - VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG, - "g_networkMonitorContextMutex is null"); - - // Get the interface and ipaddress information from cache - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList - || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList))) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_ADAPTER_NOT_ENABLED; - } - - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]", - list_length); - for (list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!info) + if (already) { continue; } - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]", - info->ipAddress); - CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t)); - if (!newNetinfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_MEMORY_ALLOC_FAILED; - } - - *newNetinfo = *info; - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo); - if (CA_STATUS_OK != result) + CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); + if (!ifitem) { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, TAG, "Malloc failed"); + goto exit; } - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask"); - VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null"); - VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, - "g_networkMonitorContext is null"); - VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG, - "g_networkMonitorContextMutex is null"); + OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name); + ifitem->index = ifindex; + ifitem->family = family; + ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr; + ifitem->flags = ifa->ifa_flags; - // Get the interface and ipaddress information from cache - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList - || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_ADAPTER_NOT_ENABLED; - } - - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length); - for (list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!info) - { - continue; - } - - if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0) + CAResult_t result = u_arraylist_add(iflist, ifitem); + if (CA_STATUS_OK != result) { - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, - "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask); - *subnetMask = OICStrdup(info->subnetMask); - break; + OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); + goto exit; } - } - ca_mutex_unlock(g_networkMonitorContextMutex); - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -bool CAIPIsConnected() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - if (!g_networkMonitorContextMutex || !g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected"); - return false; + OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, family); } - ca_mutex_lock(g_networkMonitorContextMutex); - if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return true; -} - -void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - if (!g_networkMonitorContextMutex || !g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed"); - return; - } - ca_mutex_lock(g_networkMonitorContextMutex); - - g_networkMonitorContext->networkChangeCb = callback; - - ca_mutex_unlock(g_networkMonitorContextMutex); + freeifaddrs(ifp); + return iflist; - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); +exit: + freeifaddrs(ifp); + u_arraylist_destroy(iflist); + return NULL; } - diff --git a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c index 729968e..0fb68e6 100644 --- a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c @@ -20,627 +20,91 @@ #include "caipinterface.h" -#include +#include +#include +#include +#include +#include +#include +#include +#include #include "caadapterutils.h" -#include "camutex.h" #include "logger.h" #include "oic_malloc.h" #include "oic_string.h" -#define IP_MONITOR_TAG "IP_MONITOR" +#define TAG "IP_MONITOR" -/** - * @var g_networkMonitorContextMutex - * @brief Mutex for synchronizing access to cached interface and IP address information. - */ -static ca_mutex g_networkMonitorContextMutex = NULL; - -/** - * @struct CAIPNwMonitorContext - * @brief Used for storing network monitor context information. - */ -typedef struct -{ - u_arraylist_t *netInterfaceList; - ca_thread_pool_t threadPool; - CANetworkStatus_t nwConnectivityStatus; - CAIPConnectionStateChangeCallback networkChangeCb; -} CAIPNetworkMonitorContext; - -/** - * @var g_networkMonitorContext - * @brief network monitor context. - */ -static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL; - -static void CARemoveInterfaceInfo() +u_arraylist_t *CAIPGetInterfaceInformation() { - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList) + u_arraylist_t *iflist = u_arraylist_create(); + if (!iflist) { - OIC_LOG(ERROR, IP_MONITOR_TAG, - "netInterfaceList is empty"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return; + OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + return NULL; } - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - for (list_index = 0; list_index < list_length; list_index++) + struct ifaddrs *ifp = NULL; + if (-1 == getifaddrs(&ifp)) { - CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!netInfo) - { - continue; - } - - if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index)) - { - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(netInfo->ipAddress, - CA_INTERFACE_DOWN); - } - } - else - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); - } - - OICFree(netInfo); + OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); + u_arraylist_destroy(iflist); + return NULL; } - u_arraylist_free(&g_networkMonitorContext->netInterfaceList); - - ca_mutex_unlock(g_networkMonitorContextMutex); -} - -static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info) -{ - VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false); - - ca_mutex_lock(g_networkMonitorContextMutex); - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - for (list_index = 0; list_index < list_length; list_index++) + struct ifaddrs *ifa = NULL; + for (ifa = ifp; ifa; ifa = ifa->ifa_next) { - CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!netInfo) + int family = ifa->ifa_addr->sa_family; + if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) { continue; } - if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0) + int ifindex = if_nametoindex(ifa->ifa_name); + int length = u_arraylist_length(iflist); + int already = false; + for (int i = length-1; i >= 0; i--) { - if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0) + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + if (ifitem->index == ifindex && ifitem->family == family) { - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - else - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed"); - if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index)) - { - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(netInfo->ipAddress, - CA_INTERFACE_DOWN); - } - OICFree(netInfo); - } - else - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); - } + already = true; break; } } - } - - CANetInfo_t *newNetInfo = (CANetInfo_t *)OICMalloc(sizeof(CANetInfo_t)); - if (!newNetInfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - *newNetInfo = *info; - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found"); - - CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList, - (void *)newNetInfo); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); - OICFree(newNetInfo); - ca_mutex_unlock(g_networkMonitorContextMutex); - return false; - } - ca_mutex_unlock(g_networkMonitorContextMutex); - - /*Callback will be unset only at the time of termination. By that time, all the threads will be - stopped gracefully. This callback is properly protected*/ - if (g_networkMonitorContext->networkChangeCb) - { - g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP); - } - - return true; -} - -void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress, char **subnetMask) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - int ret = WIFI_ERROR_NONE; - - if (!interfaceName || !ipAddress || !subnetMask) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Invalid input: interface/ipaddress holder is NULL!"); - return; - } - - // Get wifi interface name - if (WIFI_ERROR_NONE != (ret = wifi_get_network_interface_name(interfaceName))) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface name! error num [%d]", ret); - return; - } - - // Get wifi connected IP address - wifi_ap_h accessPoint = NULL; - if (WIFI_ERROR_NONE != (ret = wifi_get_connected_ap(&accessPoint))) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get access point! error num [%d]", - ret); - - OICFree(*interfaceName); - *interfaceName = NULL; - return; - } - - if (WIFI_ERROR_NONE != (ret = wifi_ap_get_ip_address(accessPoint, WIFI_ADDRESS_FAMILY_IPV4, - ipAddress))) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]", - ret); - OICFree(*interfaceName); - *interfaceName = NULL; - return; - } - - if (WIFI_ERROR_NONE != (ret = wifi_ap_get_subnet_mask(accessPoint, WIFI_ADDRESS_FAMILY_IPV4, - subnetMask))) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]", - ret); - OICFree(*ipAddress); - OICFree(*interfaceName); - *ipAddress = NULL; - *interfaceName = NULL; - return; - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList) -{ - VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null"); - - // Get wifi network information - char *interfaceName = NULL; - char *ipAddress = NULL; - char *subnetMask = NULL; - ///TODO: currently we are filling single interface. Once found the proper tizen apis for - // getting multiple interfaces, then this function will be updated. - CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask); - - if (!interfaceName || !ipAddress || !subnetMask) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "interface/ipaddress/subnetmask is NULL!"); - return; - } - - CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t)); - if (!netInfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed"); - OICFree(interfaceName); - OICFree(ipAddress); - OICFree(subnetMask); - return; - } - - // set interface name - OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName); - - // set local ip address - OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress); - - // set subnet mask - OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask); - - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); - } - OICFree(interfaceName); - OICFree(ipAddress); - OICFree(subnetMask); -} - - -void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, - void *userData) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - if (WIFI_CONNECTION_STATE_ASSOCIATION == state - || WIFI_CONNECTION_STATE_CONFIGURATION == state) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Connection is in Association State"); - return; - } - - // If Wifi is connected, then get the latest IP from the WIFI Interface - if (WIFI_CONNECTION_STATE_CONNECTED == state) - { - // Get network information - char *interfaceName = NULL; - char *ipAddress = NULL; - char *subnetMask = NULL; - CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask); - - CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t)); - if (!netInfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed"); - OICFree(interfaceName); - OICFree(ipAddress); - OICFree(subnetMask); - return; - } - - // set interface name - OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName); - - // set local ip address - OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress); - - // set subnet mask - OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask); - - bool ret = CACheckIsInterfaceInfoChanged(netInfo); - if (ret) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true"); - } - OICFree(netInfo); - - OICFree(interfaceName); - OICFree(ipAddress); - OICFree(subnetMask); - } - else - { - CARemoveInterfaceInfo(); - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - if (WIFI_DEVICE_STATE_ACTIVATED == state) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Activated State"); - } - else - { - CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL); - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Deactivated State"); - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -static CAResult_t CAInitializeNetworkMonitorMutexes() -{ - if (!g_networkMonitorContextMutex) - { - g_networkMonitorContextMutex = ca_mutex_new(); - if (!g_networkMonitorContextMutex) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc failed"); - return CA_MEMORY_ALLOC_FAILED; - } - } - - return CA_STATUS_OK; -} - -static void CADestroyNetworkMonitorMutexes() -{ - ca_mutex_free(g_networkMonitorContextMutex); - g_networkMonitorContextMutex = NULL; -} - -CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null"); - - CAResult_t ret = CAInitializeNetworkMonitorMutexes(); - - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed"); - return CA_STATUS_FAILED; - } - ca_mutex_lock(g_networkMonitorContextMutex); - - // Initialize Wifi service - wifi_error_e retValue = wifi_initialize(); - if (WIFI_ERROR_NONE != retValue) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_initialize failed"); - return CA_STATUS_FAILED; - } - - g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1, - sizeof(*g_networkMonitorContext)); - if (!g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc failed"); - ca_mutex_unlock(g_networkMonitorContextMutex); - CADestroyNetworkMonitorMutexes(); - return CA_MEMORY_ALLOC_FAILED; - } - - g_networkMonitorContext->netInterfaceList = u_arraylist_create(); - if (!g_networkMonitorContext->netInterfaceList) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed"); - OICFree(g_networkMonitorContext); - ca_mutex_unlock(g_networkMonitorContextMutex); - CADestroyNetworkMonitorMutexes(); - return CA_MEMORY_ALLOC_FAILED; - } - - CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList); - - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -void CAIPTerminateNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - ca_mutex_lock(g_networkMonitorContextMutex); - - // Deinitialize Wifi service - wifi_error_e ret = wifi_deinitialize(); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_deinitialize failed"); - } - - CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList); - - g_networkMonitorContext->netInterfaceList = NULL; - g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN; - g_networkMonitorContext->networkChangeCb = NULL; - - OICFree(g_networkMonitorContext); - g_networkMonitorContext = NULL; - - ca_mutex_unlock(g_networkMonitorContextMutex); - - CADestroyNetworkMonitorMutexes(); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); -} - -CAResult_t CAIPStartNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - // Set callback for receiving state changes - wifi_error_e ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_device_state_changed_cb failed"); - return CA_STATUS_FAILED; - } - - // Set callback for receiving connection state changes - ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_connection_state_changed_cb failed"); - return CA_STATUS_FAILED; - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPStopNetworkMonitor() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - // Reset callback for receiving state changes - wifi_error_e ret = wifi_unset_device_state_changed_cb(); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_device_state_changed_cb failed"); - } - - // Reset callback for receiving connection state changes - ret = wifi_unset_connection_state_changed_cb(); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_connection_state_changed_cb failed"); - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null"); - VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, - "g_networkMonitorContext is null"); - VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG, - "g_networkMonitorContextMutex is null"); - - // Get the interface and ipaddress information from cache - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList - || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList))) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_ADAPTER_NOT_ENABLED; - } - - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]", - list_length); - for (list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!info) + if (already) { continue; } - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]", - info->ipAddress); - CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t)); - if (!newNetinfo) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_MEMORY_ALLOC_FAILED; - } - - *newNetinfo = *info; - CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo); - if (CA_STATUS_OK != result) + CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); + if (!ifitem) { - OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, TAG, "Malloc failed"); + goto exit; } - } - - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask"); - VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null"); - VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, - "g_networkMonitorContext is null"); - VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG, - "g_networkMonitorContextMutex is null"); + OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name); + ifitem->index = ifindex; + ifitem->family = family; + ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr; + ifitem->flags = ifa->ifa_flags; - // Get the interface and ipaddress information from cache - ca_mutex_lock(g_networkMonitorContextMutex); - if (!g_networkMonitorContext->netInterfaceList - || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList))) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled"); - ca_mutex_unlock(g_networkMonitorContextMutex); - return CA_ADAPTER_NOT_ENABLED; - } - - uint32_t list_index = 0; - uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length); - for (list_index = 0; list_index < list_length; list_index++) - { - CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get( - g_networkMonitorContext->netInterfaceList, list_index); - if (!info) - { - continue; - } - - if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0) + CAResult_t result = u_arraylist_add(iflist, ifitem); + if (CA_STATUS_OK != result) { - OIC_LOG_V(DEBUG, IP_MONITOR_TAG, - "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask); - *subnetMask = OICStrdup(info->subnetMask); - break; + OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); + goto exit; } } - ca_mutex_unlock(g_networkMonitorContextMutex); - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return CA_STATUS_OK; -} - -bool CAIPIsConnected() -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - - wifi_connection_state_e connection_state; - wifi_error_e ret = wifi_get_connection_state(&connection_state); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get the Connection State"); - return false; - } - - if (WIFI_CONNECTION_STATE_DISCONNECTED == connection_state) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "WIFI is not Connected"); - return false; - } - - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); - return true; -} - -void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback) -{ - OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); - if (!g_networkMonitorContextMutex || !g_networkMonitorContext) - { - OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed"); - return; - } - ca_mutex_lock(g_networkMonitorContextMutex); - - g_networkMonitorContext->networkChangeCb = callback; - ca_mutex_unlock(g_networkMonitorContextMutex); + freeifaddrs(ifp); + return iflist; - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); +exit: + freeifaddrs(ifp); + u_arraylist_destroy(iflist); + return NULL; } diff --git a/resource/csdk/connectivity/test/ca_api_unittest.cpp b/resource/csdk/connectivity/test/ca_api_unittest.cpp index 3449647..486f28a 100644 --- a/resource/csdk/connectivity/test/ca_api_unittest.cpp +++ b/resource/csdk/connectivity/test/ca_api_unittest.cpp @@ -168,7 +168,7 @@ TEST_F(CATests, TerminateTest) // check return value TEST(StartListeningServerTest, DISABLED_TC_03_Positive_01) { - CASelectNetwork(CA_IPV4); + CASelectNetwork(CA_ADAPTER_IP); EXPECT_EQ(CA_STATUS_OK, CAStartListeningServer()); } @@ -438,14 +438,14 @@ CAResult_t checkSelectNetwork() TEST_F(CATests, SelectNetworkTestBad) { //Select disable network - EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork(1000)); + EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork((CATransportAdapter_t)1000)); } // check return value when selected network is disable TEST_F(CATests, UnSelectNetworkTest) { //UnSelect disable network - EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork(1000)); + EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork((CATransportAdapter_t)1000)); } // CAHandlerRequestResponse TC diff --git a/resource/csdk/stack/include/internal/ocresourcehandler.h b/resource/csdk/stack/include/internal/ocresourcehandler.h index d76208a..2d3d6d3 100644 --- a/resource/csdk/stack/include/internal/ocresourcehandler.h +++ b/resource/csdk/stack/include/internal/ocresourcehandler.h @@ -149,7 +149,7 @@ void DeleteDeviceInfo(); */ OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, OCDiscoveryPayload* payload, - CATransportAdapter_t adapter); + OCDevAddr *endpoint); /** * A helper function that Maps an @ref OCEntityHandlerResult type to an diff --git a/resource/csdk/stack/include/internal/ocserverrequest.h b/resource/csdk/stack/include/internal/ocserverrequest.h index 16f8dc6..228055b 100644 --- a/resource/csdk/stack/include/internal/ocserverrequest.h +++ b/resource/csdk/stack/include/internal/ocserverrequest.h @@ -170,6 +170,7 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID, * @param entityHandlerRequest - pointer to the OCEntityHandlerRequest struct that is created * @param request - request handle * @param method - RESTful method + * @param endpoint - requesting endpoint * @param resource - resource handle * @param queryBuf - resource query of request * @param payload - payload of request @@ -182,12 +183,19 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID, * @return * OCStackResult */ -OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, - OCRequestHandle request, - OCMethod method, OCResourceHandle resource, char * queryBuf, - uint8_t * payload, size_t payloadSize, - uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction, - OCObservationId observeID); +OCStackResult FormOCEntityHandlerRequest( + OCEntityHandlerRequest *entityHandlerRequest, + OCRequestHandle request, + OCMethod method, + OCDevAddr *endpoint, + OCResourceHandle resource, + char *queryBuf, + uint8_t *payload, + size_t payloadSize, + uint8_t numVendorOptions, + OCHeaderOption *vendorOptions, + OCObserveAction observeAction, + OCObservationId observeID); /** * Find a server request in the server request list and delete diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index 3ff3933..a9603ea 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -158,6 +158,8 @@ typedef enum OC_IP_USE_V6 = (1 << 5), // IP adapter only OC_IP_USE_V4 = (1 << 6), // IP adapter only + OC_RESERVED1 = (1 << 7), // internal use only + // Link-Local multicast is the default multicast scope for IPv6. // These are placed here to correspond to the IPv6 multicast address bits. OC_SCOPE_INTERFACE = 0x1, // IPv6 Interface-Local scope (loopback) @@ -171,6 +173,7 @@ typedef enum #define OC_MASK_SCOPE (0x000F) #define OC_MASK_MODS (0x0FF0) +#define OC_MASK_FAMS (OC_IP_USE_V6|OC_IP_USE_V4) /* * endpoint identity @@ -667,6 +670,8 @@ typedef struct OCRequestHandle requestHandle; // the REST method retrieved from received request PDU OCMethod method; + // description of endpoint that sent the request + OCDevAddr devAddr; // resource query send by client char * query; // Information associated with observation - valid only when OCEntityHandler diff --git a/resource/csdk/stack/src/occollection.c b/resource/csdk/stack/src/occollection.c index a851da3..6f3d7a0 100644 --- a/resource/csdk/stack/src/occollection.c +++ b/resource/csdk/stack/src/occollection.c @@ -239,8 +239,7 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, uint8_t filterOn, c if(ret == OC_STACK_OK) { - ret = BuildVirtualResourceResponse(collResource, payload, - CA_ADAPTER_IP); + ret = BuildVirtualResourceResponse(collResource, payload, &ehRequest->devAddr); } if (ret == OC_STACK_OK) @@ -252,8 +251,7 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, uint8_t filterOn, c { //TODO : Add resource type filtering once collections // start supporting queries. - ret = BuildVirtualResourceResponse(temp, payload, - CA_ADAPTER_IP); + ret = BuildVirtualResourceResponse(temp, payload, &ehRequest->devAddr); } } } @@ -287,8 +285,7 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest) if(stackRet == OC_STACK_OK) { - stackRet = BuildVirtualResourceResponse(collResource, payload, - CA_ADAPTER_IP); + stackRet = BuildVirtualResourceResponse(collResource, payload, &ehRequest->devAddr); } if(stackRet == OC_STACK_OK) @@ -492,5 +489,3 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag, } return result; } - - diff --git a/resource/csdk/stack/src/ocobserve.c b/resource/csdk/stack/src/ocobserve.c index 6f94bb3..201dac8 100644 --- a/resource/csdk/stack/src/ocobserve.c +++ b/resource/csdk/stack/src/ocobserve.c @@ -141,12 +141,19 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, request->observeResult = OC_STACK_OK; if(result == OC_STACK_OK) { - result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, - request->method, (OCResourceHandle) resPtr, request->query, - request->payload, request->payloadSize, + result = FormOCEntityHandlerRequest( + &ehRequest, + (OCRequestHandle) request, + request->method, + &request->devAddr, + (OCResourceHandle) resPtr, + request->query, + request->payload, + request->payloadSize, request->numRcvdVendorSpecificHeaderOptions, request->rcvdVendorSpecificHeaderOptions, - OC_OBSERVE_NO_OPTION, 0); + OC_OBSERVE_NO_OPTION, + 0); if(result == OC_STACK_OK) { ehResult = resPtr->entityHandler(OC_REQUEST_FLAG, &ehRequest, diff --git a/resource/csdk/stack/src/ocresource.c b/resource/csdk/stack/src/ocresource.c index f5984e9..71db404 100644 --- a/resource/csdk/stack/src/ocresource.c +++ b/resource/csdk/stack/src/ocresource.c @@ -67,31 +67,24 @@ OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, } /* This method will retrieve the port at which the secure resource is hosted */ -static OCStackResult GetSecurePortInfo(CATransportAdapter_t connType, uint16_t *port) +static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port) { - CAEndpoint_t* info = NULL; - uint32_t size = 0; - OCStackResult ret = OC_STACK_ERROR; + uint16_t p = 0; - CAResult_t caResult = CAGetNetworkInformation(&info, &size); - if ((caResult == CA_STATUS_OK) && info && size) + if (endpoint->adapter == OC_ADAPTER_IP) { - while (size--) + if (endpoint->flags & OC_IP_USE_V6) { - if ((info[size].flags & CA_SECURE) && info[size].adapter == connType) - { - if (info[size].adapter == CA_ADAPTER_IP) - { - *port = info[size].port; - ret = OC_STACK_OK; - break; - } - } + p = caglobals.ip.u6s.port; + } + else if (endpoint->flags & OC_IP_USE_V4) + { + p = caglobals.ip.u4s.port; } } - OICFree(info); - return ret; + *port = p; + return OC_STACK_OK; } /* @@ -210,7 +203,7 @@ static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *q } OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, - OCDiscoveryPayload* payload, CATransportAdapter_t adapter ) + OCDiscoveryPayload *payload, OCDevAddr *devAddr) { if (!resourcePtr || !payload) { @@ -219,7 +212,7 @@ OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, uint16_t port = 0; if (resourcePtr->resourceProperties & OC_SECURE) { - if(GetSecurePortInfo (adapter, &port) != OC_STACK_OK) + if (GetSecurePortInfo(devAddr, &port) != OC_STACK_OK) { port = 0; } @@ -523,7 +516,7 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource { discoveryResult = BuildVirtualResourceResponse(resource, (OCDiscoveryPayload*)payload, - (CATransportAdapter_t)request->devAddr.adapter); + &request->devAddr); } } } @@ -599,12 +592,17 @@ HandleDefaultDeviceEntityHandler (OCServerRequest *request) OCEntityHandlerRequest ehRequest = {}; OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler")); - result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, - request->method, (OCResourceHandle) NULL, request->query, - request->payload, request->payloadSize, - request->numRcvdVendorSpecificHeaderOptions, - request->rcvdVendorSpecificHeaderOptions, - (OCObserveAction)request->observationOption, (OCObservationId)0); + result = FormOCEntityHandlerRequest(&ehRequest, + (OCRequestHandle) request, + request->method, + &request->devAddr, + (OCResourceHandle) NULL, request->query, + request->payload, + request->payloadSize, + request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, + (OCObserveAction)request->observationOption, + (OCObservationId)0); VERIFY_SUCCESS(result, OC_STACK_OK); // At this point we know for sure that defaultDeviceHandler exists @@ -643,11 +641,18 @@ HandleResourceWithEntityHandler (OCServerRequest *request, OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler")); - result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, - request->method, (OCResourceHandle) resource, request->query, - request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions, - request->rcvdVendorSpecificHeaderOptions, - (OCObserveAction)request->observationOption, 0); + result = FormOCEntityHandlerRequest(&ehRequest, + (OCRequestHandle)request, + request->method, + &request->devAddr, + (OCResourceHandle)resource, + request->query, + request->payload, + request->payloadSize, + request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, + (OCObserveAction)request->observationOption, + 0); VERIFY_SUCCESS(result, OC_STACK_OK); if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION) @@ -750,11 +755,18 @@ HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request, OCStackResult result = OC_STACK_ERROR; OCEntityHandlerRequest ehRequest = {}; - result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, - request->method, (OCResourceHandle) resource, request->query, - request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions, - request->rcvdVendorSpecificHeaderOptions, - (OCObserveAction)request->observationOption, (OCObservationId) 0); + result = FormOCEntityHandlerRequest(&ehRequest, + (OCRequestHandle)request, + request->method, + &request->devAddr, + (OCResourceHandle)resource, + request->query, + request->payload, + request->payloadSize, + request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, + (OCObserveAction)request->observationOption, + (OCObservationId)0); if(result != OC_STACK_OK) { return result; diff --git a/resource/csdk/stack/src/ocserverrequest.c b/resource/csdk/stack/src/ocserverrequest.c index 3f9c2b0..db84e9e 100644 --- a/resource/csdk/stack/src/ocserverrequest.c +++ b/resource/csdk/stack/src/ocserverrequest.c @@ -302,6 +302,7 @@ OCStackResult FormOCEntityHandlerRequest( OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request, OCMethod method, + OCDevAddr *endpoint, OCResourceHandle resource, char * queryBuf, uint8_t * payload, @@ -316,6 +317,7 @@ OCStackResult FormOCEntityHandlerRequest( entityHandlerRequest->resource = (OCResourceHandle) resource; entityHandlerRequest->requestHandle = request; entityHandlerRequest->method = method; + entityHandlerRequest->devAddr = *endpoint; entityHandlerRequest->query = queryBuf; entityHandlerRequest->obsInfo.action = observeAction; entityHandlerRequest->obsInfo.obsId = observeID; diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index 44b1e65..d2c730a 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -421,6 +421,10 @@ static OCStackResult OCCreateEndpoint(OCDevAddr *devAddr, CAEndpoint_t **endpoin } ep->adapter = (CATransportAdapter_t)devAddr->adapter; + if (!ep->adapter) + { + ep->adapter = CA_ADAPTER_IP; + } ep->flags = OCToCATransportFlags(devAddr->flags); strncpy(ep->addr, devAddr->addr, MAX_ADDR_STR_SIZE_CA); ep->port = devAddr->port; @@ -463,9 +467,14 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat observer = GetObserverUsingToken (token, tokenLength); if(observer) { - result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL, - OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, 0, - NULL, OC_OBSERVE_DEREGISTER, observer->observeId); + result = FormOCEntityHandlerRequest(&ehRequest, + (OCRequestHandle)NULL, + OC_REST_NOMETHOD, + &observer->devAddr, + (OCResourceHandle)NULL, + NULL, NULL, 0, 0, NULL, + OC_OBSERVE_DEREGISTER, + observer->observeId); if(result != OC_STACK_OK) { return result; @@ -508,9 +517,14 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat { if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM) { - result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL, - OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, 0, - NULL, OC_OBSERVE_DEREGISTER, observer->observeId); + result = FormOCEntityHandlerRequest(&ehRequest, + (OCRequestHandle)NULL, + OC_REST_NOMETHOD, + &observer->devAddr, + (OCResourceHandle)NULL, + NULL, NULL, 0, 0, NULL, + OC_OBSERVE_DEREGISTER, + observer->observeId); if(result != OC_STACK_OK) { return OC_STACK_ERROR; @@ -737,18 +751,38 @@ static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resource VERIFY_NON_NULL(presenceUri, FATAL, OC_STACK_INVALID_PARAM); const char *format; + CAEndpoint_t *ep = (CAEndpoint_t *)endpoint; - if ((endpoint->flags & CA_IPV6) && !(endpoint->flags & CA_IPV4)) - { - format = "coap://[%s]:%u%s"; - } - else + if (ep->adapter == CA_ADAPTER_IP) { - format = "coap://%s:%u%s"; + if (ep->flags & CA_IPV6) + { + if ('\0' == ep->addr[0]) // multicast + { + return snprintf(presenceUri, CA_MAX_URI_LENGTH, OC_RSRVD_PRESENCE_URI); + } + else + { + format = "coap://[%s]:%u%s"; + } + } + else + { + if ('\0' == ep->addr[0]) // multicast + { + OICStrcpy(ep->addr, sizeof(ep->addr), OC_MULTICAST_IP); + ep->port = OC_MULTICAST_PORT; + } + format = "coap://%s:%u%s"; + } + return snprintf(presenceUri, CA_MAX_URI_LENGTH, format, ep->addr, + ep->port, OC_RSRVD_PRESENCE_URI); } - return snprintf(presenceUri, CA_MAX_URI_LENGTH, format, endpoint->addr, - endpoint->port, OC_RSRVD_PRESENCE_URI); + // might work for other adapters (untested, but better than nothing) + format = "coap://%s%s"; + return snprintf(presenceUri, CA_MAX_URI_LENGTH, format, ep->addr, + OC_RSRVD_PRESENCE_URI); } @@ -776,6 +810,7 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, return OC_STACK_ERROR; } + // check for unicast presence uriLen = FormCanonicalPresenceUri(endpoint, OC_RSRVD_PRESENCE_URI, presenceUri); if (uriLen < 0 || uriLen >= sizeof (presenceUri)) { @@ -789,17 +824,12 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, } else { - CAEndpoint_t endpointMulticast; - endpointMulticast.flags = endpoint->flags; - OICStrcpy(endpointMulticast.addr, sizeof(endpointMulticast.addr), OC_MULTICAST_IP); - endpointMulticast.port = OC_MULTICAST_PORT; + // check for multiicast presence + CAEndpoint_t ep = { endpoint->adapter, endpoint->flags }; + OICStrcpy(ep.addr, sizeof(ep.addr), OC_MULTICAST_IP); + ep.port = OC_MULTICAST_PORT; - uriLen = FormCanonicalPresenceUri(&endpointMulticast, OC_RSRVD_PRESENCE_URI, presenceUri); - - if (uriLen < 0 || uriLen >= sizeof (presenceUri)) - { - return OC_STACK_INVALID_URI; - } + uriLen = FormCanonicalPresenceUri(&ep, OC_RSRVD_PRESENCE_URI, presenceUri); cbNode = GetClientCB(NULL, 0, NULL, presenceUri); if (cbNode) @@ -1526,8 +1556,25 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag } myStackMode = mode; + if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER) + { + caglobals.client = true; + } + if (mode == OC_SERVER || mode == OC_CLIENT_SERVER) + { + caglobals.server = true; + } + caglobals.serverFlags = (CATransportFlags_t)serverFlags; + if (!(caglobals.serverFlags & CA_IPFAMILY_MASK)) + { + caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4); + } caglobals.clientFlags = (CATransportFlags_t)clientFlags; + if (!(caglobals.clientFlags & CA_IPFAMILY_MASK)) + { + caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4); + } defaultDeviceHandler = NULL; defaultDeviceHandlerCallbackParameter = NULL; -- 2.7.4