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
// 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
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.
*/
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;
* @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
*/
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
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);
+}
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);
/**
*/
#define IPV4_ADDR_ONE_OCTECT_LEN 4
+#ifdef SINGLE_THREAD
/**
- * @brief Network Interface Information.
+ * @brief Network Interface Information. Only needed for Arduino.
*/
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.
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.
*
* @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.
* @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
*/
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
--- /dev/null
+/*
+ * 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 <net/if.h>. Note that if <net/if.h> 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 <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int getifaddrs(struct ifaddrs **ifap);
+extern void freeifaddrs(struct ifaddrs *ifa);
+__END_DECLS
+
+#endif
{
g_isLeSelected = false;
}
- CAUnSelectNetwork(1 << number);
+ CAUnSelectNetwork((CATransportAdapter_t)(1 << number));
Serial.println("Terminate");
CATerminate();
Serial.println("============");
'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')])
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,
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)
{
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.
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)
--- /dev/null
+/*
+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 <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+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 <string.h>
+//#include <unistd.h>
+//#include <linux/sockios.h>
+//#include <net/if.h>
+//#include <sys/socket.h>
+//#include <sys/ioctl.h>
+
+/*
+ * 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;
+}
--- /dev/null
+/******************************************************************
+*
+* 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;
+}
+
#include "caadapternetdtls.h"
#endif
-CAGlobals_t caglobals;
+CAGlobals_t caglobals = { 0 };
#define TAG "CA_CONN_MGR"
}
-CAResult_t CASelectNetwork(const uint32_t interestedNetwork)
+CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork)
{
OIC_LOG_V(DEBUG, TAG, "Selected network : %d", 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);
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");
return;
}
+ if (CADropSecondRequest(endpoint, ReqInfo->info.messageId))
+ {
+ OICFree(ReqInfo);
+ coap_delete_pdu(pdu);
+ return;
+ }
+
if (NULL != ReqInfo->info.options)
{
uint32_t i;
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
# 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)
-
-
/******************************************************************
- *
- * 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 <string.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-#include <linux/if.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <sys/socket.h>
#include <netdb.h>
+#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include <arpa/inet.h>
+#include <linux/if.h>
+
#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, "<init>",
- "(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;
}
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;
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);
if (CAArduinoInitUdpSocket(&port, &socketID) != CA_STATUS_OK)
{
OIC_LOG(ERROR, TAG, "init ucast err");
- return 0;
+ return;
}
}
else
&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;
}
}
-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);
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;
if (Udp.endPacket() == 0)
{
OIC_LOG(ERROR, TAG, "Failed to send");
- return 0;
+ return;
}
OIC_LOG(DEBUG, TAG, "OUT");
- return bytesWritten;
+ return;
}
/**
* @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"
#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;
-}
/**
* @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"
#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)
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;
-}
#include "caipadapterutils_eth.h"
#include "caadapterutils.h"
#include "oic_malloc.h"
+#include "oic_string.h"
#define TAG "IPS"
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");
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);
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,
{
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;
+}
+
#include "caipadapter.h"
#include "caadapterutils.h"
#include "oic_malloc.h"
+#include "oic_string.h"
#define TAG "IPS"
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");
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);
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,
{
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;
+}
+
#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
/**
*/
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();
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;
}
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);
{
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);
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,
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();
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");
-}
+++ /dev/null
-/******************************************************************
- *
- * 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 <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <errno.h>
-
-#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;
-}
-
-/******************************************************************
+/*****************************************************************j
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
#include "caipinterface.h"
+#ifndef __APPLE__
+#include <asm/types.h>
+#else
+ #ifndef IPV6_ADD_MEMBERSHIP
+ #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+ #endif
+#endif
#include <sys/types.h>
#include <sys/socket.h>
+#include <stdio.h>
#include <unistd.h>
+#include <sys/types.h>
#include <fcntl.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <net/if.h>
#include <errno.h>
+#ifdef __linux__
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#endif
#include "pdu.h"
#include "caadapterutils.h"
#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;
}
#include <unistd.h>
#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;
}
-
#include "caipinterface.h"
-#include <wifi.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
#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;
}
// check return value
TEST(StartListeningServerTest, DISABLED_TC_03_Positive_01)
{
- CASelectNetwork(CA_IPV4);
+ CASelectNetwork(CA_ADAPTER_IP);
EXPECT_EQ(CA_STATUS_OK, CAStartListeningServer());
}
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
*/
OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
OCDiscoveryPayload* payload,
- CATransportAdapter_t adapter);
+ OCDevAddr *endpoint);
/**
* A helper function that Maps an @ref OCEntityHandlerResult type to an
* @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
* @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
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)
#define OC_MASK_SCOPE (0x000F)
#define OC_MASK_MODS (0x0FF0)
+#define OC_MASK_FAMS (OC_IP_USE_V6|OC_IP_USE_V4)
/*
* endpoint identity
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
if(ret == OC_STACK_OK)
{
- ret = BuildVirtualResourceResponse(collResource, payload,
- CA_ADAPTER_IP);
+ ret = BuildVirtualResourceResponse(collResource, payload, &ehRequest->devAddr);
}
if (ret == OC_STACK_OK)
{
//TODO : Add resource type filtering once collections
// start supporting queries.
- ret = BuildVirtualResourceResponse(temp, payload,
- CA_ADAPTER_IP);
+ ret = BuildVirtualResourceResponse(temp, payload, &ehRequest->devAddr);
}
}
}
if(stackRet == OC_STACK_OK)
{
- stackRet = BuildVirtualResourceResponse(collResource, payload,
- CA_ADAPTER_IP);
+ stackRet = BuildVirtualResourceResponse(collResource, payload, &ehRequest->devAddr);
}
if(stackRet == OC_STACK_OK)
}
return result;
}
-
-
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,
}
/* 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;
}
/*
}
OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
- OCDiscoveryPayload* payload, CATransportAdapter_t adapter )
+ OCDiscoveryPayload *payload, OCDevAddr *devAddr)
{
if (!resourcePtr || !payload)
{
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;
}
{
discoveryResult = BuildVirtualResourceResponse(resource,
(OCDiscoveryPayload*)payload,
- (CATransportAdapter_t)request->devAddr.adapter);
+ &request->devAddr);
}
}
}
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
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)
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;
OCEntityHandlerRequest * entityHandlerRequest,
OCRequestHandle request,
OCMethod method,
+ OCDevAddr *endpoint,
OCResourceHandle resource,
char * queryBuf,
uint8_t * payload,
entityHandlerRequest->resource = (OCResourceHandle) resource;
entityHandlerRequest->requestHandle = request;
entityHandlerRequest->method = method;
+ entityHandlerRequest->devAddr = *endpoint;
entityHandlerRequest->query = queryBuf;
entityHandlerRequest->obsInfo.action = observeAction;
entityHandlerRequest->obsInfo.obsId = observeID;
}
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;
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;
{
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;
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);
}
return OC_STACK_ERROR;
}
+ // check for unicast presence
uriLen = FormCanonicalPresenceUri(endpoint, OC_RSRVD_PRESENCE_URI, presenceUri);
if (uriLen < 0 || uriLen >= sizeof (presenceUri))
{
}
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)
}
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;