help_vars.Add(BoolVariable('WITH_RA', 'Build with Remote Access module', False))
if target_os in targets_disallow_multitransport:
- help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'IP', ['BT', 'BLE', 'IP']))
+ help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'IP', ['BT', 'BLE', 'IP', 'CI']))
else:
- help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP']))
+ help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP', 'CI']))
help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
help_vars.Add(EnumVariable('SECURED', 'Build with DTLS', '0', allowed_values=('0', '1')))
if with_ra == True:
env.AppendUnique(CPPDEFINES = ['RA_ADAPTER'])
if target_os == 'linux':
- env.AppendUnique(CPPDEFINES = ['IP_ADAPTER','NO_EDR_ADAPTER','LE_ADAPTER'])
+ env.AppendUnique(CPPDEFINES = ['IP_ADAPTER','NO_EDR_ADAPTER','LE_ADAPTER', 'CI_ADAPTER'])
elif target_os == 'tizen':
env.AppendUnique(CPPDEFINES = ['IP_ADAPTER','EDR_ADAPTER','LE_ADAPTER'])
elif target_os in['darwin','ios']:
else:
env.AppendUnique(CPPDEFINES = ['NO_IP_ADAPTER'])
+ if 'CI' in transport:
+ if target_os in['linux']:
+ env.AppendUnique(CPPDEFINES = ['CI_ADAPTER'])
+ print "CA Transport is CI"
+ else:
+ print "CA Transport CI is not supported "
+ Exit(1)
+ else:
+ env.AppendUnique(CPPDEFINES = ['NO_CI_ADAPTER'])
+
env.SConscript('./src/SConscript')
if build_sample == 'ON':
#define COAP_MAX_PDU_SIZE 1400 /* maximum size of a CoAP PDU for big platforms*/
#endif
+#ifdef CI_ADAPTER
+#define COAP_TCP_MAX_PDU_SIZE 64 * 1024 /* maximum size of a CoAP over TCP PDU for Linux platform*/
+#endif
+
#ifdef WITH_BWT
#define CA_DEFAULT_BLOCK_SIZE CA_BLOCK_SIZE_1024_BYTE
#endif
#endif
#ifdef CI_ADAPTER
- CA_ADAPTER_CLOUD_INTERFACE = (1 << 4), // CoAP over TCP for Cloud Interface
+ CA_ADAPTER_CLOUD_INTERFACE = (1 << 5), // CoAP over TCP for Cloud Interface
#endif
CA_ALL_ADAPTERS = 0xffffffff
// Indication that a message was received by multicast.
CA_MULTICAST = (1 << 7),
#ifdef CI_ADAPTER
+ // A TCP transport for the CoAP
CA_IPV4_TCP = (1 << 8),
#endif
// Link-Local multicast is the default multicast scope for IPv6.
int32_t ifIndex; /**< network interface index */
} CAIfItem_t;
+#ifdef CI_ADAPTER
+/**
+ * CI Server Information for IPv4 TCP transport
+ */
+typedef struct
+{
+ char addr[MAX_ADDR_STR_SIZE_CA]; /**< CI Server address */
+ CASocket_t u4tcp; /**< CI Server port */
+} CACIServerInfo_t;
+#endif
+
typedef struct
{
CATransportFlags_t clientFlags; /**< flag for client */
CATransportFlags_t previousRequestFlags;/**< address family filtering */
uint16_t previousRequestMessageId; /**< address family filtering */
} ca;
+
+ #ifdef CI_ADAPTER
+ /**
+ * Hold global variables for CI Adapter.
+ */
+ struct cisockets
+ {
+ void *threadpool; /**< threadpool between Initialize and Start */
+ void *svrlist; /**< unicast IPv4 CI server information*/
+ int selectTimeout; /**< in seconds */
+ int maxfd; /**< highest fd (for select) */
+ bool started; /**< the CI adapter has started */
+ bool terminate; /**< the CI adapter needs to stop */
+ bool ipv4tcpenabled; /**< IPv4 TCP enabled by OCInit flags */
+ } ci;
+ #endif
} CAGlobals_t;
extern CAGlobals_t caglobals;
*/
CAResult_t CAHandleRequestResponse();
+#ifdef CI_ADAPTER
+/**
+ * Connect to CI Server.
+ * @param[in] ciServerInfo CI Server information
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or
+ * ::CA_STATUS_INVALID_PARAM or ::CA_MEMORY_ALLOC_FAILED
+ */
+CAResult_t CACreateTCPConnection(const CACIServerInfo_t *ciServerInfo);
+
+/**
+ * Disconnect to CI Server.
+ * @param[in] ciServerInfo CI Server information
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or
+ * ::CA_STATUS_INVALID_PARAM or ::CA_MEMORY_ALLOC_FAILED
+ */
+CAResult_t CADestroyTCPConnection(const CACIServerInfo_t *ciServerInfo);
+#endif
+
#ifdef RA_ADAPTER
/**
* Set Remote Access information for XMPP Client.
help_vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
help_vars.Add(BoolVariable('LOGGING', 'Enable stack logging', False))
help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map[host]))
-help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP']))
+help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP', 'CI']))
help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
help_vars.Add(EnumVariable('SECURED', 'Build with DTLS', '0', allowed_values=('0', '1')))
help_vars.Add(BoolVariable('UPLOAD', 'Upload binary ? (For Arduino)', require_upload))
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2015 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the APIs for CI Adapter.
+ */
+#ifndef CA_CI_ADAPTER_H_
+#define CA_CI_ADAPTER_H_
+
+#include "cacommon.h"
+#include "caadapterinterface.h"
+#include "cathreadpool.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * API to initialize CI Interface.
+ * @param[in] registerCallback Callback to register CI interfaces to
+ * Connectivity Abstraction Layer.
+ * @param[in] networkPacketCallback Callback to notify request and
+ * response messages from server(s)
+ * started at Connectivity Abstraction Layer.
+ * @param[in] netCallback Callback to notify the network additions
+ * to Connectivity Abstraction Layer.
+ * @param[in] errorCallback Callback to notify the network errors to
+ * Connectivity Abstraction Layer.
+ * @param[in] handle Threadpool Handle.
+ * @return ::CA_STATUS_OK or Appropriate error code
+ */
+CAResult_t CAInitializeCI(CARegisterConnectivityCallback registerCallback,
+ CANetworkPacketReceivedCallback networkPacketCallback,
+ CANetworkChangeCallback netCallback,
+ CAErrorHandleCallback errorCallback, ca_thread_pool_t handle);
+
+/**
+ * Start CI Interface adapter.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStartCI();
+
+/**
+ * Start listening server for receiving connect requests.
+ * Transport Specific Behavior:
+ * CI Starts Listening Server on a particular interface and prefixed port
+ * number and as per OIC Specification.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStartCIListeningServer();
+
+/**
+ * Start discovery servers for receiving advertisements.
+ * Transport Specific Behavior:
+ * CI Starts Discovery server on a particular interface and prefixed port
+ * number as per OIC Specification.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStartCIDiscoveryServer();
+
+/**
+ * Sends data to the endpoint using the adapter connectivity.
+ * @param[in] endpoint Remote Endpoint information (like ipaddress,
+ * port, reference uri and transport type) to
+ * which the unicast data has to be sent.
+ * @param[in] data Data which is required to be sent.
+ * @param[in] dataLen Size of data to be sent.
+ * @note dataLen must be > 0.
+ * @return The number of bytes sent on the network, or -1 upon error.
+ */
+int32_t CASendCIUnicastData(const CAEndpoint_t *endpoint, const void *data,
+ uint32_t dataLen);
+
+/**
+ * Send Multicast data to the endpoint using the CI connectivity.
+ * @param[in] endpoint Remote Endpoint information (like ipaddress,
+ * port)
+ * @param[in] data Data which is required to be sent.
+ * @param[in] dataLen Size of data to be sent.
+ * @note dataLen must be > 0.
+ * @return The number of bytes sent on the network, or -1 upon error.
+ */
+int32_t CASendCIMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLen);
+
+/**
+ * Get CI Connectivity network information.
+ * @param[out] info Local connectivity information structures.
+ * @note info is allocated in this API and should be freed by the caller.
+ * @param[out] size Number of local connectivity structures.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAGetCIInterfaceInformation(CAEndpoint_t **info, uint32_t *size);
+
+/**
+ * Read Synchronous API callback.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAReadCIData();
+
+/**
+ * Stops Unicast, servers and close the sockets.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStopCI();
+
+/**
+ * Terminate the CI connectivity adapter.
+ * Configuration information will be deleted from further use.
+ */
+void CATerminateCI();
+
+/**
+ * Start CI clients and create the sockets.
+ * @param[in] ciServerInfo CI Server information.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CACreateCIClient(const CACIServerInfo_t *ciServerInfo);
+
+/**
+ * Stop CI clients and close the sockets.
+ * @param[in] ciServerInfo CI Server information.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CADestroyCIClient(const CACIServerInfo_t *ciServerInfo);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // CA_CI_ADAPTER_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file provides APIs CI client/server/network monitor modules.
+ */
+
+#ifndef CA_CI_INTERFACE_H_
+#define CA_CI_INTERFACE_H_
+
+#include <stdbool.h>
+
+#include "cacommon.h"
+#include "cathreadpool.h"
+#include "uarraylist.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Callback to be notified on reception of any data from remote OIC devices.
+ *
+ * @param[in] endpoint network endpoint description.
+ * @param[in] data Data received from remote OIC device.
+ * @param[in] dataLength Length of data in bytes.
+ * @pre Callback must be registered using CAIPSetPacketReceiveCallback().
+ */
+typedef void (*CACIPacketReceivedCallback)(const CAEndpoint_t *endpoint,
+ const void *data,
+ uint32_t dataLength);
+
+/**
+ * Callback to notify error in the CI adapter.
+ *
+ * @param[in] endpoint network endpoint description.
+ * @param[in] data Data sent/received.
+ * @param[in] dataLength Length of data in bytes.
+ * @param[in] result result of request from R.I.
+ * @pre Callback must be registered using CAIPSetPacketReceiveCallback().
+ */
+typedef void (*CACIErrorHandleCallback)(const CAEndpoint_t *endpoint, const void *data,
+ uint32_t dataLength, CAResult_t result);
+
+/**
+ * set error callback to notify error in CI adapter.
+ *
+ * @param[in] errorHandleCallback Callback function to notify the error
+ * in the CI adapter.
+ */
+void CACISetErrorHandler(CACIErrorHandleCallback errorHandleCallback);
+
+/**
+ * Start CI server.
+ *
+ * @param threadPool Thread pool for managing Unicast server threads.
+ * @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 CACIStartServer(const ca_thread_pool_t threadPool);
+
+/**
+ * Stop CI server.
+ */
+void CACIStopServer();
+
+/**
+ * Set this callback for receiving data packets from peer devices.
+ *
+ * @param[in] callback Callback to be notified on reception of unicast data packets.
+ */
+void CACISetPacketReceiveCallback(CACIPacketReceivedCallback callback);
+
+/**
+ * API to send unicast CI data.
+ *
+ * @param[in] endpoint complete network address to send to.
+ * @param[in] data Data to be send.
+ * @param[in] dataLength Length of data in bytes.
+ * @param[in] isMulticast Whether data needs to be sent to multicast ip.
+ */
+void CACISendData(CAEndpoint_t *endpoint, const void *data, uint32_t dataLength,
+ bool isMulticast);
+
+/**
+ * Get a list of CAInterface_t items.
+ *
+ * @return List of CAInterface_t items.
+ */
+u_arraylist_t *CACIGetInterfaceInformation(int desiredIndex);
+
+/**
+ * Connect to CI Server.
+ * @param[in] ciServerInfo CI Server information.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAConnectToCIServer(CACIServerInfo_t *ciServerInfo);
+
+/**
+ * Disconnect from CI Server.
+ * @param[in] ciServerInfo CI Server information.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CADisconnectFromCIServer(const CACIServerInfo_t *ciServerInfo);
+
+/**
+ * Get CI Connection Information from list.
+ * @param[in] addr CI Server address.
+ * @param[in] port CI Server port.
+ * @param[out] index index of array list.
+ * @return CI Server Information structure.
+ */
+CACIServerInfo_t *CAGetCIServerInfoFromList(const char *addr, const uint16_t port,
+ uint32_t *index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CA_CI_INTERFACE_H_ */
#define SYSTEM_INVOKE_ERROR 127
#define SYSTEM_ERROR -1
+#ifdef WITH_BWT
#define BLOCK_SIZE(arg) (1 << ((arg) + 4))
+#endif
/**
* @def RS_IDENTITY
void handle_request_response();
void get_network_info();
void send_secure_request();
+#ifdef CI_ADAPTER
+void create_tcp_connection();
+#endif
void request_handler(const CAEndpoint_t *object, const CARequestInfo_t *requestInfo);
void response_handler(const CAEndpoint_t *object, const CAResponseInfo_t *responseInfo);
static const char COAP_PREFIX[] = "coap://";
static const char COAPS_PREFIX[] = "coaps://";
+static const char COAP_TCP_PREFIX[] = "coap+tcp://";
+
static const uint16_t COAP_PREFIX_LEN = sizeof(COAP_PREFIX) - 1;
static const uint16_t COAPS_PREFIX_LEN = sizeof(COAPS_PREFIX) - 1;
+static const uint16_t COAP_TCP_PREFIX_LEN = sizeof(COAP_TCP_PREFIX) - 1;
static const char SECURE_INFO_DATA[] =
"{\"oc\":[{\"href\":\"%s\",\"prop\":{\"rt\":[\"core.led\"],"
get_network_info();
break;
+#ifdef CI_ADAPTER
+ case 'p': // create tcp connection
+ case 'P':
+ create_tcp_connection();
+ break;
+#endif
+
default:
printf("not supported menu!!\n");
break;
printf("Enter the URI like below....\n");
printf("coap://10.11.12.13:4545/resource_uri ( for IP )\n");
printf("coap://10:11:12:13:45:45/resource_uri ( for BT )\n");
+#ifdef CI_ADAPTER
+ printf("coap+tcp://10:11:12:13:45:45/resource_uri ( for CI )\n");
+#endif
}
else
{
printf("Enter the URI like below....\n");
printf("coap://10.11.12.13:4545/resource_uri ( for IP )\n");
printf("coap://10:11:12:13:45:45/resource_uri ( for BT )\n");
+#ifdef CI_ADAPTER
+ printf("coap+tcp://10:11:12:13:45:45/resource_uri ( for CI )\n");
+#endif
printf("uri : ");
char uri[MAX_BUF_LEN] = { 0 };
printf("IP : 0\n");
printf("GATT : 1\n");
printf("RFCOMM : 2\n");
+#ifdef CI_ADAPTER
+ printf("CI : 5\n");
+#endif
printf("select : ");
char buf[MAX_BUF_LEN] = { 0 };
int number = buf[0] - '0';
- if (number < 0 || number > 3)
+ if (number < 0 || number > 5)
{
printf("Invalid network type\n");
return;
printf("IP : 0\n");
printf("GATT : 1\n");
printf("RFCOMM : 2\n");
+#ifdef CI_ADAPTER
+ printf("CI : 5\n");
+#endif
printf("select : ");
char buf[MAX_BUF_LEN] = { 0 };
int number = buf[0] - '0';
- if (number < 0 || number > 3)
+ if (number < 0 || number > 5)
{
printf("Invalid network type\n");
return;
printf("\th : handle request response\n");
printf("\tz : run static server\n");
printf("\tw : send secure request\n");
+#ifdef CI_ADAPTER
+ printf("\tp : create tcp connection\n");
+#endif
printf("\tq : quit\n");
printf("=============================================\n");
printf("select : ");
}
}
+#ifdef WITH_BWT
// if received message is bulk data, create output file
if ((requestInfo->info.payload) &&
(requestInfo->info.payloadSize > BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE)))
{
create_file(requestInfo->info.payload, requestInfo->info.payloadSize);
}
+#endif
printf("Send response with URI\n");
send_response(object, &requestInfo->info);
}
}
+#ifdef WITH_BWT
// if received message is bulk data, create output file
if ((responseInfo->info.payload) &&
(responseInfo->info.payloadSize > BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE)))
{
create_file(responseInfo->info.payload, responseInfo->info.payloadSize);
}
+#endif
}
void error_handler(const CAEndpoint_t *rep, const CAErrorInfo_t* errorInfo)
printf("IP : 0\n");
printf("GATT : 1\n");
printf("RFCOMM : 2\n");
+#ifdef CI_ADAPTER
+ printf("CI : 5\n");
+#endif
printf("select : ");
if (CA_STATUS_OK != get_input_data(buf, MAX_BUF_LEN))
int number = buf[0] - '0';
- number = (number < 0 || number > 3) ? 0 : 1 << number;
+ number = (number < 0 || number > 5) ? 0 : 1 << number;
- if (number == 1)
+ switch (number)
{
- g_selected_nw_type = CA_ADAPTER_IP;
- return CA_STATUS_OK;
- }
- if (number == 2)
- {
- g_selected_nw_type = CA_ADAPTER_GATT_BTLE;
- return CA_STATUS_OK;
- }
- if (number == 3)
- {
- g_selected_nw_type = CA_ADAPTER_RFCOMM_BTEDR;
- return CA_STATUS_OK;
+ case CA_ADAPTER_IP:
+ case CA_ADAPTER_GATT_BTLE:
+ case CA_ADAPTER_RFCOMM_BTEDR:
+#ifdef CI_ADAPTER
+ case CA_ADAPTER_CLOUD_INTERFACE:
+#endif
+ g_selected_nw_type = number;
+ return CA_STATUS_OK;
+ default:
+ return CA_NOT_SUPPORTED;
}
-
- return CA_NOT_SUPPORTED;
}
CAResult_t get_input_data(char *buf, int32_t length)
startIndex = COAP_PREFIX_LEN;
*flags = CA_IPV4;
}
+#ifdef CI_ADAPTER
+ else if (strncmp(COAP_TCP_PREFIX, uri, COAP_TCP_PREFIX_LEN) == 0)
+ {
+ printf("uri has '%s' prefix\n", COAP_TCP_PREFIX);
+ startIndex = COAP_TCP_PREFIX_LEN;
+ *flags = CA_IPV4_TCP;
+ }
+#endif
// #2. copy uri for parse
int32_t len = strlen(uri) - startIndex;
return true;
}
+
+#ifdef CI_ADAPTER
+void create_tcp_connection()
+{
+ printf("Enter the CI Server information....\n");
+ printf("IP: ");
+ char address[MAX_BUF_LEN] = {'\0'};
+ if (CA_STATUS_OK != get_input_data(address, MAX_BUF_LEN))
+ {
+ return;
+ }
+ printf("Port: ");
+ char port[MAX_BUF_LEN] = {'\0'};
+ if (CA_STATUS_OK != get_input_data(port, MAX_BUF_LEN))
+ {
+ return;
+ }
+
+ int portNum = atoi(port);
+ CACIServerInfo_t serverInfo = { .u4tcp.port = portNum };
+ strncpy(serverInfo.addr, address, strlen(address));
+
+ CAResult_t res = CACreateTCPConnection(&serverInfo);
+ if (CA_STATUS_OK != res)
+ {
+ printf("Failed to create TCP Connection");
+ }
+}
+#endif
env.AppendUnique(CA_SRC = ca_common_src)
if 'ALL' in ca_transport:
- transports = [ 'ip_adapter', 'bt_edr_adapter', 'bt_le_adapter' ]
+ transports = [ 'ip_adapter', 'bt_edr_adapter', 'bt_le_adapter', 'ci_adapter']
if with_ra:
transports.append ('ra_adapter')
env.SConscript(dirs = [
if 'BLE' in ca_transport:
env.SConscript(os.path.join(ca_path, 'bt_le_adapter/SConscript'))
+if 'CI' in ca_transport:
+ env.SConscript(os.path.join(ca_path, 'ci_adapter/SConscript'))
+
print "Include path is %s" % env.get('CPPPATH')
print "Files path is %s" % env.get('CA_SRC')
if ca_os in ['android', 'tizen']:
#include "caadapternetdtls.h"
#endif
+#ifdef CI_ADAPTER
+#include "caciadapter.h"
+#endif
+
CAGlobals_t caglobals = { 0 };
#define TAG "CA_CONN_MGR"
else if (interestedNetwork & CA_ADAPTER_REMOTE_ACCESS)
{
res = CAAddNetworkType(CA_ADAPTER_REMOTE_ACCESS);
- OIC_LOG_V(ERROR, TAG, "CAAddNetworkType(CA_ADAPTER_REMOTE_ACCESS) function returns error : %d",
- res);
+ OIC_LOG_V(ERROR, TAG,
+ "CAAddNetworkType(CA_ADAPTER_REMOTE_ACCESS) function returns error : %d", res);
}
#endif
+
+ #ifdef CI_ADAPTER
+ else if (interestedNetwork & CA_ADAPTER_CLOUD_INTERFACE)
+ {
+ res = CAAddNetworkType(CA_ADAPTER_CLOUD_INTERFACE);
+ OIC_LOG_V(ERROR, TAG,
+ "CAAddNetworkType(CA_ADAPTER_CLOUD_INTERFACE) function returns error : %d", res);
+ }
+ #endif
+
else
{
res = CA_NOT_SUPPORTED;
res);
}
#endif
+
+ #ifdef CI_ADAPTER
+ else if (nonInterestedNetwork & CA_ADAPTER_CLOUD_INTERFACE)
+ {
+ res = CARemoveNetworkType(CA_ADAPTER_CLOUD_INTERFACE);
+ OIC_LOG_V(ERROR, TAG, "CARemoveNetworkType(CA_ADAPTER_CLOUD_INTERFACE) function returns error : %d",
+ res);
+ }
+ #endif
+
else
{
res = CA_STATUS_FAILED;
return CA_STATUS_OK;
}
+#ifdef CI_ADAPTER
+CAResult_t CACreateTCPConnection(const CACIServerInfo_t *ciServerInfo)
+{
+ if (!g_isInitialized)
+ {
+ OIC_LOG(ERROR, TAG, "not initialized");
+ return CA_STATUS_NOT_INITIALIZED;
+ }
+
+ CAResult_t res = CACreateCIClient(ciServerInfo);
+ return res;
+}
+
+CAResult_t CADestroyTCPConnection(const CACIServerInfo_t *ciServerInfo)
+{
+ if (!g_isInitialized)
+ {
+ OIC_LOG(ERROR, TAG, "not initialized");
+ return CA_STATUS_NOT_INITIALIZED;
+ }
+
+ CAResult_t res = CADestroyCIClient(ciServerInfo);
+ return res;
+}
+#endif
+
#ifdef __WITH_DTLS__
CAResult_t CASelectCipherSuite(const uint16_t cipher)
#include "caraadapter.h"
#endif
-#define TAG "CA_INTRFC_CNTRLR"
-#ifdef RA_ADAPTER
-#include "caraadapter.h"
+#ifdef CI_ADAPTER
+#include "caciadapter.h"
#endif
+#define TAG "CA_INTRFC_CNTRLR"
#define CA_MEMORY_ALLOC_CHECK(arg) {if (arg == NULL) \
{OIC_LOG(ERROR, TAG, "memory error");goto memory_error_exit;} }
-#ifdef RA_ADAPTER
+#ifdef CI_ADAPTER
+#define CA_TRANSPORT_TYPE_NUM 6
+#elif RA_ADAPTER
#define CA_TRANSPORT_TYPE_NUM 4
#else
#define CA_TRANSPORT_TYPE_NUM 3
return 3;
#endif
+ #ifdef CI_ADAPTER
+ case CA_ADAPTER_CLOUD_INTERFACE:
+ return 5;
+ #endif
+
default:
break;
}
handle);
#endif /* RA_ADAPTER */
-
+#ifdef CI_ADAPTER
+ CAInitializeCI(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback,
+ CAAdapterErrorHandleCallback, handle);
+#endif /* CI_ADAPTER */
}
void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback)
static uint32_t NETWORK_RA = CA_ADAPTER_REMOTE_ACCESS;
#endif
+#ifdef CI_ADAPTER
+static uint32_t NETWORK_CI = CA_ADAPTER_CLOUD_INTERFACE;
+#endif
+
CAResult_t CAAddNetworkType(CATransportAdapter_t transportType)
{
OIC_LOG(DEBUG, TAG, "IN");
break;
#endif /* RA_ADAPTER */
+#ifdef CI_ADAPTER
+ case CA_ADAPTER_CLOUD_INTERFACE:
+
+ OIC_LOG(DEBUG, TAG, "Add network type(CI)");
+ if (u_arraylist_contains(g_selectedNetworkList, &NETWORK_CI))
+ {
+ goto exit;
+ }
+ res = u_arraylist_add(g_selectedNetworkList, &NETWORK_CI);
+ break;
+#endif /* CI_ADAPTER */
+
default:
break;
}
break;
#endif /* RA_ADAPTER */
+#ifdef CI_ADAPTER
+ case CA_ADAPTER_CLOUD_INTERFACE:
+ OIC_LOG(DEBUG, TAG, "Remove network type(RA)");
+ u_arraylist_remove(g_selectedNetworkList, index);
+ break;
+#endif /* CI_ADAPTER */
+
default:
break;
}
--- /dev/null
+#######################################################
+# Build CI adapter
+#######################################################
+
+Import('env')
+import os.path
+
+print "Reading IP adapter script"
+
+target_os = env.get('TARGET_OS')
+inc_files = env.get('CPPPATH')
+secured = env.get('SECURED')
+src_dir = './ci_adapter/'
+
+
+# Source files to build common for all platforms
+common_files = None
+if target_os == 'linux':
+ common_files = [
+ os.path.join(src_dir, 'caciadapter.c'),
+ os.path.join(src_dir, 'caciserver.c') ]
+
+# Get list of target-specific source file base names, i.e. no parent
+# directories prepended to the path.
+#
+# Target-specific SConscript files are expected to return that list.
+target_files = []
+target_sconscript = os.path.join(target_os, 'SConscript')
+
+# Check for the existence of the platform-specific SConscript file
+# relative to the top-level source directory, not the build (variant)
+# directory, before calling that SConscript file to prevent a missing
+# file warning platforms that don't provide one.
+target_sconscript_abspath = str(File(target_sconscript).srcnode().abspath)
+if os.path.exists(target_sconscript_abspath):
+ target_files = env.SConscript(target_sconscript, exports='src_dir')
+
+# Now prepend the appropriate parent directories
+# (e.g. ./ip_adapter/android) to each of the target source files in
+# the list.
+target_files = [ os.path.join(src_dir, target_os, f) for f in target_files ]
+
+# Source files to build for Linux-like platforms
+
+# 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)
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2015 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "caciadapter.h"
+#include "caciinterface.h"
+#include "caqueueingthread.h"
+#include "caadapterutils.h"
+#include "camutex.h"
+#include "uarraylist.h"
+#include "caremotehandler.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "CI_ADAP"
+
+/**
+ * Holds internal thread CI data information.
+ */
+typedef struct
+{
+ CAEndpoint_t *remoteEndpoint;
+ void *data;
+ uint32_t dataLen;
+ bool isMulticast;
+} CACIData;
+
+/**
+ * Queue handle for Send Data.
+ */
+static CAQueueingThread_t *g_sendQueueHandle = NULL;
+
+/**
+ * Network Packet Received Callback to CA.
+ */
+static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
+
+/**
+ * Network Changed Callback to CA.
+ */
+static CANetworkChangeCallback g_networkChangeCallback = NULL;
+
+/**
+ * error Callback to CA adapter.
+ */
+static CAErrorHandleCallback g_errorCallback = NULL;
+
+static void CACIPacketReceivedCB(const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dataLength);
+
+static CAResult_t CACIInitializeQueueHandles();
+
+static void CACIDeinitializeQueueHandles();
+
+static void CACISendDataThread(void *threadData);
+
+static CACIData *CACreateCIData(const CAEndpoint_t *remoteEndpoint,
+ const void *data, uint32_t dataLength,
+ bool isMulticast);
+void CAFreeCIData(CACIData *ipData);
+
+static void CADataDestroyer(void *data, uint32_t size);
+
+CAResult_t CACIInitializeQueueHandles()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ // Check if the message queue is already initialized
+ if (g_sendQueueHandle)
+ {
+ OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
+ return CA_STATUS_OK;
+ }
+
+ // Create send message queue
+ g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
+ if (!g_sendQueueHandle)
+ {
+ OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
+ (const ca_thread_pool_t)caglobals.ci.threadpool,
+ CACISendDataThread, CADataDestroyer))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
+ OICFree(g_sendQueueHandle);
+ g_sendQueueHandle = NULL;
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CACIDeinitializeQueueHandles()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ CAQueueingThreadDestroy(g_sendQueueHandle);
+ OICFree(g_sendQueueHandle);
+ g_sendQueueHandle = NULL;
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CACIConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
+{
+ (void)ipAddress;
+ (void)status;
+ OIC_LOG(DEBUG, TAG, "IN");
+}
+
+void CACIPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
+ uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL");
+ VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+ OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
+
+ if (g_networkPacketCallback)
+ {
+ g_networkPacketCallback(endpoint, data, dataLength);
+ }
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CACIErrorHandler (const CAEndpoint_t *endpoint, const void *data,
+ uint32_t dataLength, CAResult_t result)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+
+ VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+ void *buf = (void*)OICMalloc(sizeof(char) * dataLength);
+ if (!buf)
+ {
+ OIC_LOG(ERROR, TAG, "Memory Allocation failed!");
+ return;
+ }
+ memcpy(buf, data, dataLength);
+ if (g_errorCallback)
+ {
+ g_errorCallback(endpoint, buf, dataLength, result);
+ }
+ else
+ {
+ OICFree(buf);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+static void CAInitializeCIGlobals()
+{
+ caglobals.ci.selectTimeout = 5000;
+ caglobals.ci.svrlist = NULL;
+
+ CATransportFlags_t flags = 0;
+ if (caglobals.client)
+ {
+ flags |= caglobals.clientFlags;
+ }
+
+ caglobals.ci.ipv4tcpenabled = flags & CA_IPV4_TCP;
+}
+
+CAResult_t CAInitializeCI(CARegisterConnectivityCallback registerCallback,
+ CANetworkPacketReceivedCallback networkPacketCallback,
+ CANetworkChangeCallback netCallback,
+ CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
+ VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
+ VERIFY_NON_NULL(netCallback, TAG, "netCallback");
+ VERIFY_NON_NULL(handle, TAG, "thread pool handle");
+
+ g_networkChangeCallback = netCallback;
+ g_networkPacketCallback = networkPacketCallback;
+ g_errorCallback = errorCallback;
+
+ CAInitializeCIGlobals();
+ caglobals.ci.threadpool = handle;
+
+ CACISetPacketReceiveCallback(CACIPacketReceivedCB);
+ CACISetErrorHandler(CACIErrorHandler);
+
+ CAConnectivityHandler_t ciHandler;
+ ciHandler.startAdapter = CAStartCI;
+ ciHandler.startListenServer = CAStartCIListeningServer;
+ ciHandler.startDiscoveryServer = CAStartCIDiscoveryServer;
+ ciHandler.sendData = CASendCIUnicastData;
+ ciHandler.sendDataToAll = CASendCIMulticastData;
+ ciHandler.GetnetInfo = CAGetCIInterfaceInformation;
+ ciHandler.readData = CAReadCIData;
+ ciHandler.stopAdapter = CAStopCI;
+ ciHandler.terminate = CATerminateCI;
+ registerCallback(ciHandler, CA_ADAPTER_CLOUD_INTERFACE);
+
+ OIC_LOG(INFO, TAG, "OUT IntializeCI is Success");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartCI()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ if (CA_STATUS_OK != CACIInitializeQueueHandles())
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
+ CATerminateCI();
+ return CA_STATUS_FAILED;
+ }
+
+ // Start send queue thread
+ if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
+ return CA_STATUS_FAILED;
+ }
+
+ CAResult_t ret = CACIStartServer((const ca_thread_pool_t)caglobals.ci.threadpool);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
+ return ret;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartCIListeningServer()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartCIDiscoveryServer()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+static int32_t CAQueueCIData(bool isMulticast, const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
+ VERIFY_NON_NULL_RET(data, TAG, "data", -1);
+
+ if (0 == dataLength)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid Data Length");
+ return -1;
+ }
+
+ VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
+
+ // Create CIData to add to queue
+ CACIData *ciData = CACreateCIData(endpoint, data, dataLength, isMulticast);
+ if (!ciData)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create ipData!");
+ return -1;
+ }
+ // Add message to send queue
+ CAQueueingThreadAddData(g_sendQueueHandle, ciData, sizeof(CACIData));
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return dataLength;
+}
+
+int32_t CASendCIUnicastData(const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ return CAQueueCIData(false, endpoint, data, dataLength);
+}
+
+int32_t CASendCIMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ return CAQueueCIData(true, endpoint, data, dataLength);
+}
+
+CAResult_t CAReadCIData()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStopCI()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
+ {
+ CAQueueingThreadStop(g_sendQueueHandle);
+ }
+
+ CACIDeinitializeQueueHandles();
+
+ CACIStopServer();
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CATerminateCI()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ CACISetPacketReceiveCallback(NULL);
+
+ CACIDeinitializeQueueHandles();
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CACISendDataThread(void *threadData)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ CACIData *ciData = (CACIData *) threadData;
+ if (!ciData)
+ {
+ OIC_LOG(DEBUG, TAG, "Invalid CI data!");
+ return;
+ }
+
+ if (ciData->isMulticast)
+ {
+ return;
+ }
+ else
+ {
+ CACISendData(ciData->remoteEndpoint, ciData->data, ciData->dataLen, false);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+CACIData *CACreateCIData(const CAEndpoint_t *remoteEndpoint, const void *data,
+ uint32_t dataLength, bool isMulticast)
+{
+ VERIFY_NON_NULL_RET(data, TAG, "CIData is NULL", NULL);
+
+ CACIData *ciData = (CACIData *) OICMalloc(sizeof(CACIData));
+ if (!ciData)
+ {
+ OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+ return NULL;
+ }
+
+ ciData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
+ ciData->data = (void *) OICMalloc(dataLength);
+ if (!ciData->data)
+ {
+ OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+ CAFreeCIData(ciData);
+ return NULL;
+ }
+
+ memcpy(ciData->data, data, dataLength);
+ ciData->dataLen = dataLength;
+
+ ciData->isMulticast = isMulticast;
+
+ return ciData;
+}
+
+void CAFreeCIData(CACIData *ciData)
+{
+ VERIFY_NON_NULL_VOID(ciData, TAG, "ciData is NULL");
+
+ CAFreeEndpoint(ciData->remoteEndpoint);
+ OICFree(ciData->data);
+ OICFree(ciData);
+}
+
+void CADataDestroyer(void *data, uint32_t size)
+{
+ if (size < sizeof(CACIData))
+ {
+ OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
+ }
+ CACIData *ciData = (CACIData *) data;
+
+ CAFreeCIData(ciData);
+}
+
+CAResult_t CACreateCIClient(const CACIServerInfo_t *ciServerInfo)
+{
+ VERIFY_NON_NULL(ciServerInfo, TAG, "CI server info is NULL");
+
+ // #1. create CI server object
+ CACIServerInfo_t *svritem = (CACIServerInfo_t *) OICMalloc(sizeof (CACIServerInfo_t));
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "Out of memory");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memcpy(svritem, ciServerInfo, sizeof (CACIServerInfo_t));
+
+ // #2. create socket and connect to CI server
+ CAResult_t res = CAConnectToCIServer(svritem);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to start CI Client");
+ OICFree(svritem);
+ return res;
+ }
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CADestroyCIClient(const CACIServerInfo_t *ciServerInfo)
+{
+ VERIFY_NON_NULL(ciServerInfo, TAG, "CI server info is NULL");
+
+ CAResult_t res = CADisconnectFromCIServer(ciServerInfo);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to stop CI Client");
+ return res;
+ }
+
+ return CA_STATUS_OK;
+}
--- /dev/null
+/*****************************************************************j
+ *
+ * Copyright 2015 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 <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.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>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <error.h>
+
+#include "caciinterface.h"
+#include "pdu.h"
+#include "caadapterutils.h"
+#include "camutex.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "CI_SERVER"
+
+/**
+ * Server port number for local test.
+ */
+#define SERVER_PORT 8000
+
+/**
+ * Mutex to synchronize device object list.
+ */
+static ca_mutex g_mutexObjectList = NULL;
+
+/**
+ * Maintains the callback to be notified when data received from remote
+ * Bluetooth device.
+ */
+static CACIPacketReceivedCallback g_packetReceivedCallback;
+
+/**
+ * Error callback to update error in CI.
+ */
+static CACIErrorHandleCallback g_ciErrorHandler = NULL;
+
+static CAResult_t CAReceiveMessage();
+
+/**
+ * Destroy Mutex.
+ */
+static void CACIDestroyMutex()
+{
+ if (g_mutexObjectList)
+ {
+ ca_mutex_free(g_mutexObjectList);
+ g_mutexObjectList = NULL;
+ }
+}
+
+/*
+ * Create Mutex.
+ */
+static CAResult_t CACICreateMutex()
+{
+ g_mutexObjectList = ca_mutex_new();
+ if (!g_mutexObjectList)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to created mutex!");
+
+ CACIDestroyMutex();
+ return CA_STATUS_FAILED;
+ }
+
+ return CA_STATUS_OK;
+}
+
+static void CACIDisconnectAll()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ ca_mutex_lock(g_mutexObjectList);
+ uint32_t length = u_arraylist_length(caglobals.ci.svrlist);
+
+ CACIServerInfo_t *svritem = NULL;
+ for (size_t i = 0; i < length; i++)
+ {
+ svritem = (CACIServerInfo_t *) u_arraylist_get(caglobals.ci.svrlist, i);
+ if (svritem && svritem->u4tcp.fd >= 0)
+ {
+ close(svritem->u4tcp.fd);
+ }
+ }
+ u_arraylist_destroy(caglobals.ci.svrlist);
+
+ ca_mutex_unlock(g_mutexObjectList);
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+static void CAReceiveHandler(void *data)
+{
+ (void)data;
+ OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler");
+
+ while (!caglobals.ci.terminate)
+ {
+ CAReceiveMessage();
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
+}
+
+static CAResult_t CAReceiveMessage()
+{
+ uint32_t length = u_arraylist_length(caglobals.ci.svrlist);
+
+ CACIServerInfo_t *svritem = NULL;
+ for (size_t i = 0; i < length; i++)
+ {
+ svritem = (CACIServerInfo_t *) u_arraylist_get(caglobals.ci.svrlist, i);
+
+ if (svritem->u4tcp.fd < 0)
+ {
+ continue;
+ }
+
+ char recvBuffer[COAP_TCP_MAX_PDU_SIZE] = { 0 };
+ ssize_t recvLen = recv(svritem->u4tcp.fd, recvBuffer, sizeof (recvBuffer), 0);
+ if (recvLen <= 0)
+ {
+ if(EAGAIN == errno)
+ {
+ continue;
+ }
+ OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
+ close(svritem->u4tcp.fd);
+ u_arraylist_remove(caglobals.ci.svrlist, i);
+ }
+ else
+ {
+ CAEndpoint_t ep = { .adapter = CA_ADAPTER_CLOUD_INTERFACE,
+ .flags = CA_IPV4_TCP,
+ .port = svritem->u4tcp.port };
+ strncpy(ep.addr, svritem->addr, MAX_ADDR_STR_SIZE_CA);
+
+ if (g_packetReceivedCallback)
+ {
+ g_packetReceivedCallback(&ep, recvBuffer, recvLen);
+ }
+ }
+ }
+ return CA_STATUS_OK;
+}
+
+static int CACICreateTCPSocket(int family, CACIServerInfo_t *ciServerInfo)
+{
+ // create tcp socket
+ int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
+ if (-1 == fd)
+ {
+ OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno));
+ goto exit;
+ }
+
+ // set non-blocking socket
+ unsigned long nonblock = 1;
+ if (ioctl(fd, FIONBIO, &nonblock))
+ {
+ OIC_LOG(ERROR, TAG, "set non-blocking socket error!");
+ }
+
+ struct sockaddr_in sa = { .sin_family = family };
+ inet_pton(family, ciServerInfo->addr, &sa.sin_addr.s_addr);
+ sa.sin_port = htons(ciServerInfo->u4tcp.port);
+
+ // connect to CI server
+ socklen_t socklen = sizeof(sa);
+ if (connect(fd, (struct sockaddr *)&sa, socklen) != 0)
+ {
+ OIC_LOG(ERROR, TAG, "first connect, error");
+ }
+
+ // update the max file descriptor
+ if (fd > caglobals.ci.maxfd)
+ {
+ caglobals.ci.maxfd = fd;
+ }
+
+ struct timeval timeout = { .tv_sec = caglobals.ci.selectTimeout / 1000,
+ .tv_usec = (caglobals.ci.selectTimeout % 1000) * 1000};
+
+ fd_set writeFd;
+ FD_ZERO(&writeFd);
+ FD_SET(caglobals.ci.maxfd, &writeFd);
+
+ int error = 0;
+ int state = select(caglobals.ci.maxfd + 1, NULL, &writeFd, NULL, &timeout);
+ switch (state)
+ {
+ case -1:
+ OIC_LOG(ERROR, TAG, "select() error");
+ goto exit;
+ break;
+ case 0:
+ OIC_LOG(ERROR, TAG, "time out error");
+ goto exit;
+ break;
+ default:
+ if (FD_ISSET(fd, &writeFd))
+ {
+ socklen_t len = sizeof(error);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len))
+ {
+ OIC_LOG(ERROR, TAG, "getsockopt error");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "select error: sockfd not set");
+ }
+ OIC_LOG(ERROR, TAG, "connect socket success");
+ break;
+ }
+
+ // set blocking socket
+ nonblock = 0;
+ if (ioctl(fd, FIONBIO, &nonblock))
+ {
+ OIC_LOG(ERROR, TAG, "set blocking socket error!");
+ }
+
+ return fd;
+
+exit:
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+ return -1;
+}
+
+#define CHECKFD(FD) \
+ if (FD > caglobals.ci.maxfd) \
+ caglobals.ci.maxfd = FD;
+#define NEWTCPSOCKET(FAMILY, NAME, SERVER) \
+ SERVER->NAME.fd = CACICreateTCPSocket(FAMILY, SERVER);
+
+static void CACIConvertAddrToString(struct sockaddr_in *addr, char *addr_str)
+{
+ inet_ntop(AF_INET, &(addr->sin_addr), addr_str, INET_ADDRSTRLEN);
+}
+
+static void CAAcceptHandler(void *data)
+{
+ (void)data;
+ OIC_LOG(DEBUG, TAG, "IN - CAAcceptHandler");
+
+ int reuse = 1;
+ struct sockaddr_in server;
+
+ server.sin_addr.s_addr = INADDR_ANY;
+ server.sin_family = AF_INET;
+ server.sin_port = htons(SERVER_PORT);
+
+ int svrsockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (svrsockfd < 0)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create socket");
+ }
+
+ if (setsockopt(svrsockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
+ {
+ OIC_LOG(ERROR, TAG, "setsockopt SO_REUSEADDR");
+ }
+
+ int serverlen = sizeof(server);
+ if (bind(svrsockfd, (struct sockaddr *)&server, serverlen) < 0)
+ {
+ OIC_LOG(ERROR, TAG, "bind() error");
+ }
+
+ if (listen(svrsockfd, 3) != 0)
+ {
+ OIC_LOG(ERROR, TAG, "listen() error");
+ }
+
+ struct sockaddr clientaddr;
+ socklen_t clientlen = sizeof(clientaddr);
+
+ while (!caglobals.ci.terminate)
+ {
+ int sockfd = accept(svrsockfd, (struct sockaddr *)&clientaddr, &clientlen);
+ if (sockfd != -1)
+ {
+ CACIServerInfo_t *svritem = (CACIServerInfo_t *) OICMalloc(sizeof (CACIServerInfo_t));
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "Out of memory");
+ return;
+ }
+ svritem->u4tcp.fd = sockfd;
+ svritem->u4tcp.port = SERVER_PORT;
+ CACIConvertAddrToString((struct sockaddr_in *)&clientaddr, (char *) &svritem->addr);
+
+ ca_mutex_lock(g_mutexObjectList);
+ bool res = u_arraylist_add(caglobals.ci.svrlist, svritem);
+ if (!res)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+ OICFree(svritem);
+ ca_mutex_unlock(g_mutexObjectList);
+ return;
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+ }
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT - CAAcceptHandler");
+}
+
+CAResult_t CACIStartServer(const ca_thread_pool_t threadPool)
+{
+ if (caglobals.ci.started)
+ {
+ return CA_STATUS_OK;
+ }
+
+ if (!caglobals.ci.ipv4tcpenabled)
+ {
+ caglobals.ci.ipv4tcpenabled = true;
+ }
+
+ CACICreateMutex();
+
+ ca_mutex_lock(g_mutexObjectList);
+ if (!caglobals.ci.svrlist)
+ {
+ caglobals.ci.svrlist = u_arraylist_create();
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+
+ caglobals.ci.terminate = false;
+
+ CAResult_t res = ca_thread_pool_add_task(threadPool, CAAcceptHandler, NULL);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
+ return res;
+ }
+ OIC_LOG(DEBUG, TAG, "CAAcceptHandler thread started successfully.");
+
+ res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
+ return res;
+ }
+ OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully.");
+
+ caglobals.ci.started = true;
+
+ return CA_STATUS_OK;
+}
+
+void CACIStopServer()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ caglobals.ci.terminate = true;
+
+ CACIDisconnectAll();
+
+ CACIDestroyMutex();
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CACISetPacketReceiveCallback(CACIPacketReceivedCallback callback)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ g_packetReceivedCallback = callback;
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+static void sendData(const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dlen,
+ const char *cast, const char *fam)
+{
+ uint32_t index = 0;
+ CACIServerInfo_t *svritem = CAGetCIServerInfoFromList(endpoint->addr, endpoint->port,
+ &index);
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to get TCP Server Info");
+ return;
+ }
+
+ if (svritem->u4tcp.fd < 0)
+ {
+ return;
+ }
+
+ struct timeval timeout = { .tv_sec = caglobals.ci.selectTimeout / 1000,
+ .tv_usec = (caglobals.ci.selectTimeout % 1000) * 1000};
+
+ if (setsockopt(svritem->u4tcp.fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) == -1)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to set socket option");
+ return;
+ }
+
+ ssize_t len = send(svritem->u4tcp.fd, data, dlen, 0);
+ if (-1 == len)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s %s sendTo failed: %s", cast, fam, strerror(errno));
+ g_ciErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
+ }
+ else
+ {
+ OIC_LOG_V(INFO, TAG, "%s %s sendTo is successful: %d bytes", cast, fam, len);
+ }
+}
+
+void CACISendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
+ bool isMulticast)
+{
+ VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+ VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+ if (!isMulticast)
+ {
+ if (caglobals.ci.ipv4tcpenabled && (endpoint->flags & CA_IPV4_TCP))
+ {
+ sendData(endpoint, data, datalen, "unicast", "ipv4tcp");
+ }
+ }
+}
+
+CAResult_t CAGetCIInterfaceInformation(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");
+
+ return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAConnectToCIServer(CACIServerInfo_t *ciServerInfo)
+{
+ VERIFY_NON_NULL(ciServerInfo, TAG, "CI server info is NULL");
+
+ // create the socket and connect to CI server
+ if (caglobals.ci.ipv4tcpenabled)
+ {
+ NEWTCPSOCKET(AF_INET, u4tcp, ciServerInfo);
+ if (-1 == ciServerInfo->u4tcp.fd)
+ {
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ // add TCP connection info to list
+ ca_mutex_lock(g_mutexObjectList);
+ if (!caglobals.ci.svrlist)
+ {
+ caglobals.ci.svrlist = u_arraylist_create();
+ }
+
+ bool res = u_arraylist_add(caglobals.ci.svrlist, ciServerInfo);
+ if (!res)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+ ca_mutex_unlock(g_mutexObjectList);
+ return CA_STATUS_FAILED;
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CADisconnectFromCIServer(const CACIServerInfo_t *ciServerInfo)
+{
+ VERIFY_NON_NULL(ciServerInfo, TAG, "CI server info is NULL");
+
+ // #1. get server info
+ uint32_t index = 0;
+ ca_mutex_lock(g_mutexObjectList);
+ CACIServerInfo_t *svritem = CAGetCIServerInfoFromList(ciServerInfo->addr,
+ ciServerInfo->u4tcp.port,
+ &index);
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "there is no connection info");
+ ca_mutex_unlock(g_mutexObjectList);
+ return CA_STATUS_FAILED;
+ }
+
+ // #2. close the socket and remove CI connection info in list
+ close(svritem->u4tcp.fd);
+ u_arraylist_remove(caglobals.ci.svrlist, index);
+ ca_mutex_unlock(g_mutexObjectList);
+
+ return CA_STATUS_OK;
+}
+
+CACIServerInfo_t *CAGetCIServerInfoFromList(const char *addr, const uint16_t port,
+ uint32_t *index)
+{
+ VERIFY_NON_NULL_RET(addr, TAG, "addr is NULL", NULL);
+ VERIFY_NON_NULL_RET(index, TAG, "index is NULL", NULL);
+
+ // get connection info from list
+ uint32_t length = u_arraylist_length(caglobals.ci.svrlist);
+
+ CACIServerInfo_t *svritem = NULL;
+ for (size_t i = 0; i < length; i++)
+ {
+ svritem = (CACIServerInfo_t *) u_arraylist_get(caglobals.ci.svrlist, i);
+
+ if (svritem->addr)
+ {
+ if (!strncmp(svritem->addr, addr, MAX_ADDR_STR_SIZE_CA)
+ && (svritem->u4tcp.port == port))
+ {
+ *index = i;
+ return svritem;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void CACISetErrorHandler(CACIErrorHandleCallback errorHandleCallback)
+{
+ g_ciErrorHandler = errorHandleCallback;
+}
TEST_F(CATests, SelectNetworkTestBad)
{
//Select disable network
- EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork((CATransportAdapter_t)1000));
+ EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork((CATransportAdapter_t)10000));
}
// check return value when selected network is disable
TEST_F(CATests, UnSelectNetworkTest)
{
//UnSelect disable network
- EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork((CATransportAdapter_t)1000));
+ EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork((CATransportAdapter_t)10000));
}
// CAHandlerRequestResponse TC