+++ /dev/null
-Project Name: IoTivity
-Release Version No. / Label Name: CA_v0.1
-API Version: CA_v0.4
-
-Release Description:
-Connectivity Abstraction provides a unified approach to send different OIC messages across multiple transports.
-
-Scope of Release:
-1. Supported APIs ( please check below APIs)
-2. Samples to test Supported APIs.
-3. OIC Coding guidelines followed based on the current CSDK source.
-4. Multi-Threaded Connectivity abstraction
-5. Executed Open Source Verification and Prevent analysis.
-
-The following Connectivity Abstraction API features are supported in this release:
-
-Supported APIs
-CAInitialize()
-CATerminate()
-CAStartListeningServer()
-CAStartDiscoveryServer()
-CARegisterHandler()
-CAhandleRequestResponse()
-FindResource()
-SendRequest()
-SendResponse()
-SelectNetwork()
-UnselectNetwork()
-
-Non Supported APIs
-SendNotification()
-AdvertizeResource()
-CAGenerateToken()
-CADestryToken()
-CAGetNetworkInfo()
-
-Type of Release: Source,
-Platform OS: Ubuntu 12.0.4 and above:
-
-Connectivity: WIFI only
-Preconditions:
-1)gcc 4.6.3 and above.
-2)glib library (sudo apt-get install libglib2.0-dev)
-3)libcoap.a library ( do make @lib/libcoap-4.1.1)
-
-Known and Open Issues:
-1) OIC Log, OIC malloc will be removed once name changes applied to OIC Bases code
-2) Support only WIFI Interface.
-3) URI length is 16 characters.
-
-Nature of Release: Partial
-
-How to Build:
-Follow below steps to execute CA Client / server in different systems
-Step 1: Build Libcoap library
-Make File Location @connectivity\lib\libcoap-4.1.1
-Step 2: Build CA library
-Make File Location @connectivity\build\linux
-Step 3: Samples
-Make File Location @connectivity\samples\linux
-
-NOTE: sample.sh script can be used @connectivity\samples\linux for 3 steps together
-
-Execution:
-linux$ export LD_LIBRARY_PATH=../../build/out/
-linux$ ./out/sample_main
-
-Client Option : d, f, h Client
-Server Option : s, h
--- /dev/null
+Project Name: IoTivity
+Release Version No: CA_v0.2
+API Version: CA_v0.4
+
+Release Description:
+Connectivity Abstraction provides a unified approach to send different OIC messages across multiple transports.
+
+Supported Platform OS:
+1) Ubuntu 12.0.4 and above:
+ Connectivity : WIFI, ETHERNET
+2) Tizen 2.3
+ Connectivity : WIFI, EDR, BLE(1:1).
+
+Preconditions:
+1)gcc 4.6.3 and above.
+2)glib library (sudo apt-get install libglib2.0-dev)
+3)libcoap.a library ( do make @lib/libcoap-4.1.1)
+
+
+Scope of Release:
+1. Supported APIs ( please check below APIs)
+2. Samples to test for Supported APIs.
+3. OIC Coding guidelines followed based on the current CSDK source.
+4. Multi-Threaded Connectivity abstraction.
+5. Executed Open Source Verification and Prevent analysis.
+
+The following Connectivity Abstraction API features are supported in this release:
+
+Supported APIs
+CAInitialize()
+CATerminate()
+CAStartListeningServer()
+CAStartDiscoveryServer()
+CARegisterHandler()
+CAhandleRequestResponse()
+FindResource()
+SendRequest()
+SendResponse()
+SelectNetwork()
+UnselectNetwork()
+SendNotification()
+AdvertizeResource()
+CAGenerateToken()
+CADestryToken()
+
+Non Supported APIs
+CAGetNetworkInfo()
+
+Type of Release: Source
+
+
+Known and Open Issues:
+1) OIC Log, OIC Malloc will be removed once name changes applied to OIC Bases code
+3) Termination sequence is not working.Its blocked.
+
+Nature of Release: Partial
+
+How to Build:
+Follow below steps to execute CA Client / server in different systems
+Step 1: Build Libcoap library
+Make File Location @connectivity\lib\libcoap-4.1.1
+Step 2: Build CA library
+Make File Location @connectivity\build\linux
+Step 3: Samples
+Make File Location @connectivity\samples\linux
+
+Execution:
+linux$ export LD_LIBRARY_PATH=../../build/out/
+linux$ ./out/sample_main
+
+
+Follow below sequence to test
+
+Client Option: c
+Server Option: s
+
+Client Option: f (provide a/light)
+Server Option: h (will pick from queue and send response)
+Client Option: h (to pick server response)
+
+Client Option: r (provide “ServerIP:5383/a/request”)
+Server Option: h (will pick from queue and send response)
+Client Option: h (to pick server response)
+
+Server Option: a
+Client Option: h (to pick server response)
+
+Server Option: b (provide ServerIP:5383/a/notify)
+Client Option: h (to pick server response)
+
+Client: Server side: n for network selection (WIFI enabled by default)
* @file cacommon.h
* @brief This file contains the common data structures between Resource , CA and adapters
*/
+
#ifndef __CA_COMMON_H_
#define __CA_COMMON_H_
#endif
/**
- @brief IP Address Length
+ @brief IP address Length
*/
#define CA_IPADDR_SIZE 16
/**
- @brief Mac Address Length for BT
+ @brief Mac address length for BT port
*/
#define CA_MACADDR_SIZE 18
/**
- @brief Max Header Options data length
+ @brief Max header options data length
*/
#define CA_MAX_HEADER_OPTION_DATA_LENGTH 16
/**
- @brief CAPayload_t
+ @brief Max URI length
+ */
+#define CA_MAX_URI_LENGTH 128
+
+/**
+@brief option types - the highest option number 63
+*/
+#define CA_OPTION_IF_MATCH 1
+#define CA_OPTION_ETAG 4
+#define CA_OPTION_IF_NONE_MATCH 5
+#define CA_OPTION_LOCATION_PATH 8
+#define CA_OPTION_URI_PATH 11
+#define CA_OPTION_CONTENT_FORMAT 12
+#define CA_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT
+#define CA_OPTION_MAXAGE 14
+#define CA_OPTION_URI_QUERY 15
+#define CA_OPTION_ACCEPT 17
+#define CA_OPTION_LOCATION_QUERY 20
+#define CA_OPTION_OBSERVE 6
+
+/**
+ @brief Payload information from resource model
*/
typedef char* CAPayload_t;
/**
- @brief CAURI_t
+ @brief URI for the OIC base.CA considers relative URI as the URI.
*/
typedef char* CAURI_t;
/**
- @brief CAToken_t
+ @brief Token information for mapping the request and responses by resource model
*/
typedef char* CAToken_t;
/**
- @brief CABool_t
+ @brief Boolean value used for specifying the success or failure
*/
+
typedef enum
{
- CA_FALSE = 0, CA_TRUE
+ CA_FALSE = 0,
+ CA_TRUE
} CABool_t;
/**
- @brief CAConnectivityType_t
+ @brief Different connectivities that are handled in Connectivity Abstraction
*/
typedef enum
{
- CA_ETHERNET = (1 << 0), CA_WIFI = (1 << 1), CA_EDR = (1 << 2), CA_LE = (1 << 3)
+ CA_ETHERNET = (1 << 0),
+ CA_WIFI = (1 << 1),
+ CA_EDR = (1 << 2),
+ CA_LE = (1 << 3)
} CAConnectivityType_t;
/**
- @brief CANetworkStatus_t
+ @brief Information about the network status.CA_INTERFACE_UP means connectivity is available
*/
typedef enum
{
- CA_INTERFACE_UP, CA_INTERFACE_DOWN
+ CA_INTERFACE_UP,
+ CA_INTERFACE_DOWN
} CANetworkStatus_t;
/**
typedef union
{
/**
- @brief BT Information
+ @brief BT Mac Information
*/
struct
{
- /** @brief Bluettoth Mac Address **/
+ /** @brief BT mac address **/
char btMacAddress[CA_MACADDR_SIZE];
} BT;
+
+ /**
+ @brief LE MAC Information
+ */
+ struct
+ {
+ /** @brief BLE mac address **/
+ char leMacAddress[CA_MACADDR_SIZE];
+ } LE;
+
/**
- @brief IP Information
+ @brief IP Information for wifi and ethernet ports
*/
struct
{
} CAAddress_t;
/**
- @brief CAQualityOfService
+ @brief Quality of service for Base source code
*/
typedef enum
{
- CA_LOW_QOS = 0, CA_MEDIUM_QOS, CA_HIGH_QOS, CA_NA_QOS // No Quality is defined, let the stack decide
+ CA_LOW_QOS = 0,
+ CA_MEDIUM_QOS,
+ CA_HIGH_QOS,
+ CA_NA_QOS // No Quality is defined, let the stack decide
} CAQualityOfService_t;
/**
- @brief CAMethod_t
+ @brief Allowed method to be used by resource model
*/
typedef enum
{
- CA_GET = 1, CA_POST, CA_PUT, CA_DELETE
+ CA_GET = 1,
+ CA_POST,
+ CA_PUT,
+ CA_DELETE
} CAMethod_t;
/**
- @brief RemoteEndpoint information for connectivities
+ @brief Remote endpoint information for connectivities
*/
typedef struct
{
CAAddress_t addressInfo;
/** Connectivity type that localconnectivity avaialble **/
CAConnectivityType_t type;
-} CALocalConnectivityt_t;
+} CALocalConnectivity_t;
/**
@brief Enums for CA return values
/* Success status code - START HERE */
CA_STATUS_OK = 0,
CA_STATUS_INVALID_PARAM,
+ CA_ADAPTER_NOT_ENABLED,
+ CA_SERVER_STARTED_ALREADY,
+ CA_SERVER_NOT_STARTED,
CA_DESTINATION_NOT_REACHABLE,
+ CA_SOCKET_OPERATION_FAILED,
CA_SEND_FAILED,
CA_RECEVIE_FAILED,
CA_MEMORY_ALLOC_FAILED,
CA_DESTINATION_DISCONNECTED,
CA_STATUS_FAILED,
CA_NOT_SUPPORTED
-/* Error status code - END HERE */
+/* Result code - END HERE */
} CAResult_t;
/**
CA_BAD_REQ = 400,
CA_BAD_OPT = 402,
CA_NOT_FOUND = 404
-/* Error status code - END HERE */
+/* Response status code - END HERE */
} CAResponseResult_t;
/**
- @brief Transport Protocol IDs
+ @brief Transport Protocol IDs for additional options
*/
typedef enum
{
- CA_INVALID_ID = (1 << 0), CA_COAP_ID = (1 << 1)
+ CA_INVALID_ID = (1 << 0),
+ CA_COAP_ID = (1 << 1)
} CATransportProtocolID_t;
/**
CATransportProtocolID_t protocolID;
/** The header option ID which will be added to communication packets**/
uint16_t optionID;
- /** its length 191**/
+ /** its length **/
uint16_t optionLength;
/** optional data values**/
uint8_t optionData[CA_MAX_HEADER_OPTION_DATA_LENGTH];
} CAHeaderOption_t;
-/**
- * @brief Request Information to be sent
- *
- * This structure is used to hold request information
- */
-
/**
* @brief Base Information received
*
CAPayload_t payload;
} CAInfo_t;
+/**
+ * @brief Request Information to be sent
+ *
+ * This structure is used to hold request information
+ */
typedef struct
{
/** Name of the Method Allowed **/
CAMethod_t method;
- /** Base Information **/
+ /** Information of the request. **/
CAInfo_t info;
} CARequestInfo_t;
/**
- * @brief Response Information received
+ * @brief Response information received
*
* This structure is used to hold response information
*/
typedef struct
{
- /**Response Result by Resource Model**/
+ /**Result for response by resource model**/
CAResponseResult_t result;
- /**Base Information **/
+ /**Information of the response.**/
CAInfo_t info;
} CAResponseInfo_t;
* address based on the connectivity type.
* @param requestInfo [OUT] Identifier which needs to be sent with request.
*/
-typedef void (*CARequestCallback)(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo);
+typedef void (*CARequestCallback)(const CARemoteEndpoint_t* object,
+ const CARequestInfo_t* requestInfo);
/**
* @brief Callback function type for response delivery.
* @param object [OUT] Endpoint object from which the response is received.
* @param responseInfo [OUT] Identifier which needs to be mapped with response.
*/
-typedef void (*CAResponseCallback)(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo);
+typedef void (*CAResponseCallback)(const CARemoteEndpoint_t* object,
+ const CAResponseInfo_t* responseInfo);
/**
* @brief Initialize the connectivity abstraction module.
* @param size [OUT] No Of Array objects
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
-CAResult_t CAGetNetworkInformation(CALocalConnectivityt_t **info, uint32_t* size);
+CAResult_t CAGetNetworkInformation(CALocalConnectivity_t **info, uint32_t* size);
/**
* @brief for usage of singled threaded application.
--- /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.
+# *
+#******************************************************************/
+
+##
+# override with `make BUILD=debug`
+# override with `make PLATFORM=arduinomega` or `make PLATFORM=arduinodue`
+# default to release build
+# default to build for linux
+BUILD := debug
+PLATFORM := linux
+TRANSPORT := ALL
+OBJ_DIR := ./bin
+VERSION_MAJOR := 0
+VERSION_MINOR := 1
+VERSION_PATCH := 0
+
+ifeq ($(PLATFORM),tizen)
+$(info *******************tizen Build !!******************)
+all:
+ sudo sh tizen/gbsbuild.sh $(TRANSPORT)
+
+else ifeq ($(PLATFORM),arduinomega)
+$(info *********ArduinoMega Build!!**********)
+all:
+ sudo sh arduino/build.sh clean $(PLATFORM) $(TRANSPORT)
+ sudo sh arduino/build.sh make $(PLATFORM) $(TRANSPORT)
+
+clean:
+ sudo sh arduino/build.sh clean $(PLATFORM) $(TRANSPORT)
+
+install:
+ sudo sh arduino/build.sh install $(PLATFORM) $(TRANSPORT)
+
+else
+ $(info *********error**********)
+ $(error Wrong value for PLATFORM !!)
+endif
+
+
--- /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.
+# *
+#******************************************************************/
+
+##
+## Definitions
+##
+SHELL = /bin/bash
+PROJECT_NAME = connectivity_abstraction
+PROJECT_ROOT_PATH = ..
+PROJECT_API_PATH = $(PROJECT_ROOT_PATH)/api
+PROJECT_INC_PATH = $(PROJECT_ROOT_PATH)/inc
+PROJECT_SRC_PATH = $(PROJECT_ROOT_PATH)/src
+PROJECT_COMMON_INC_PATH = $(PROJECT_ROOT_PATH)/common/inc
+PROJECT_COMMON_SRC_PATH = $(PROJECT_ROOT_PATH)/common/src
+PROJECT_COMMON_PATH = $(PROJECT_ROOT_PATH)/common
+PROJECT_OUT_PATH = $(PROJECT_ROOT_PATH)/build/out
+PROJECT_LIB_PATH = $(PROJECT_ROOT_PATH)/lib
+
+##
+## macro
+##
+define MAKE_PROJECT_OUT_PATH
+ @if [ ! -d $(PROJECT_OUT_PATH) ]; then \
+ mkdir $(PROJECT_OUT_PATH); \
+ fi
+endef
+
+
+##
+## Commands
+##
+CC = gcc
+CXX = g++
+RM = rm -rf
+CP = cp
+MV = mv
+AR = ar
+LD = ld
+LN = ln
+CD = cd
+RANLIB = ranlib
+
# override with `make BUILD=debug`
# default to release build
# default to build for linux
-BUILD = release
+BUILD = debug
PLATFORM = linux
TRANSPORT = ALL
OBJ_DIR = ./$(BUILD)
EDR = NO_EDR_ADAPTER
WIFI = WIFI_ADAPTER
LE = NO_LE_ADAPTER
-ETHERNET = NO_ETHERNET_ADAPTER
+ETHERNET = ETHERNET_ADAPTER
#Add Pre processor definitions
DEFINE_FLAG = -D$(EDR) -D$(LE) -D$(WIFI) -D$(ETHERNET)
caconnectivitymanager.c caremotehandler.c cainterfacecontroller.c camessagehandler.c \
canetworkconfigurator.c caedradapter.c caleadapter.c \
caethernetadapter.c cawifiadapter.c \
-caprotocolmessage.c cawificore.c \
+caprotocolmessage.c cawificore.c caethernetcore.c\
+caqueueingthread.c \
uqueue.c uarraylist.c umutex.c uthreadpool.c \
COMPONENT_OBJS = $(COMPONENT_SRCS:%.c=$(OBJ_DIR)/%.o)
-I$(BLE_ADAPTER_PATH) \
-I$(libcoap_build_dir)
-DFLAGS = -DLINUX \
+DFLAGS = -D__LINUX__ \
-DWITH_POSIX \
$(BUILD_FLAG)\
##
@echo "======================"
$(TARGET) : $(COMPONENT_OBJS)
+ cd $(libcoap_build_dir); $(MAKE)
@$(MAKE_PROJECT_OUT_PATH)
@$(CC) -shared -Wl,-soname,$(TARGET) -o $@ $(COMPONENT_OBJS) $(LFLAGS) $(LDFLAGS) $(LDLIBS)
@$(MV) $(TARGET) $(PROJECT_OUT_PATH)/.
@$(CD) $(PROJECT_OUT_PATH); $(MAKE_TARGET_ALIAS)
-
+
clean :
+ cd $(libcoap_build_dir) && make clean
@$(RM) $(DEBUG_DIR) $(RELEASE_DIR)\
$(PROJECT_OUT_PATH)
--- /dev/null
+##
+# override with `make BUILD=debug`
+# override with `make PLATFORM=arduinomega` or `make PLATFORM=arduinodue`
+# default to release build
+# default to build for linux
+BUILD := debug
+PLATFORM := tizen
+OBJ_DIR := ./bin
+VERSION_MAJOR := 0
+VERSION_MINOR := 1
+VERSION_PATCH := 0
+ADAPTER_MACRO := -DWIFI_ADAPTER
+
+$(info *******************tizen Build !!******************)
+
+CC=gcc
+LIBCOAP=./lib/libcoap-4.1.1/
+LIBCOAP_OBJ_DIR=./lib/libcoap-4.1.1/obj
+
+# TODO : Currently Hardcoded WIFI_ADAPTER. Change it to generic
+CFLAGS.debug = -DWITH_POSIX -D__TIZEN__ -Wall -DSLP_SDK_LOG -g -D_GNU_SOURCE -DTIZEN_DEBUG_ENABLE -DTB_LOG $(ADAPTER_MACRO)
+CFLAGS.release = -DWITH_POSIX -D__TIZEN__ -Wall -DSLP_SDK_LOG -D_GNU_SOURCE -DTIZEN_DEBUG_ENABLE -DTB_LOG $(ADAPTER_MACRO)
+COMPILEFLAG = `pkg-config --cflags --libs capi-network-wifi dlog capi-network-bluetooth glib-2.0`
+
+# Include files will be copied into a single folder on gbsbuild.
+# NO NEED to mention the path explicitly.
+
+SRC = $(wildcard *.c)
+OBJECTS = $(patsubst %.c, %.o, $(SRC))
+
+#Currently compiling libcoap objects. If it's provided by external party.
+#Then don't compile, Instead directly extract objects and create liboicinterface.a
+all: $(OBJECTS)
+ $(MAKE) -C $(LIBCOAP) clean
+ $(MAKE) -C $(LIBCOAP)
+ -mkdir $(LIBCOAP_OBJ_DIR)
+ @cd $(LIBCOAP_OBJ_DIR) && $(AR) -x ../libcoap.a
+ ar rcs liboicinterface.a $(OBJECTS) $(LIBCOAP_OBJ_DIR)/*.o
+
+%.o : %.c
+ $(CC) -c $(CFLAGS.$(BUILD)) $(COMPILEFLAG) $< -o $@
+
+
+pack:
+#$(CC) $(CFLAGS) $(COMPILEFLAG) WiFiInterface.c bt_interface.c tc_interface.c sample_main.c -o sample /usr/lib/liboctbstack.a -lm -pthread
+ $(info **************************************TEST***************************)
+install:
+#cp -rf sample ./usr/apps/com.samsung.oicca/bin/sample
+
+clean:
+ rm -rf *.o sample
+ rm -f *.o *.d *.elf *.eep core.a *.hex *.bin *.map *-
+ rm -rf $(OBJ_DIR)
+ rm -rf $(LIBCOAP_OBJ_DIR)
--- /dev/null
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${prefix}/lib
+includedir=${prefix}/include/interfaceHeaders
+
+Name: com.samsung.oicca
+Description: Oic core library
+Version: 1.0
+Cflags: -I${includedir}
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+spec=`ls tizen/packaging/*.spec`
+version=`rpm --query --queryformat '%{version}\n' --specfile $spec`
+
+name=`echo $name|cut -d" " -f 1`
+version=`echo $version|cut -d" " -f 1`
+
+name=cmsample
+
+sudo rm -rf $name-$version
+
+builddir=`pwd`
+sourcedir=`pwd`
+
+
+cd $sourcedir/tizen
+mkdir ./tmp
+
+cp -R ./* $sourcedir/tizen/tmp/
+rm -rf $sourcedir/tizen/tmp/tmp/
+cp -R ../../inc/* $sourcedir/tizen/tmp/
+cp -R ../../api/* $sourcedir/tizen/tmp/
+cp ../../src/adapter_util/* $sourcedir/tizen/tmp/
+# Including All CA Adapter code for Tizen Compilation
+cp -R ../../common/src/* $sourcedir/tizen/tmp/
+cp -R ../../common/inc/* $sourcedir/tizen/tmp/
+cp ../../src/* $sourcedir/tizen/tmp/
+cp ../../lib/libcoap-4.1.1/*.h $sourcedir/tizen/tmp/
+cp ../../lib $sourcedir/tizen/tmp/ -rf
+adapterMacro=""
+
+if echo $1 | grep -q -i "ALL"
+then
+echo "Building All the Transports"
+cp ../../src/wifi_adapter/tizen/* $sourcedir/tizen/tmp/
+cp ../../src/bt_edr_adapter/* $sourcedir/tizen/tmp/
+cp ../../src/bt_edr_adapter/tizen/* $sourcedir/tizen/tmp/
+cp ../../src/bt_le_adapter/* $sourcedir/tizen/tmp/
+cp ../../src/bt_le_adapter/tizen/* $sourcedir/tizen/tmp/
+adapterMacro=" -DETHERNET_ADAPTER -DWIFI_ADAPTER -DEDR_ADAPTER -DLE_ADAPTER"
+else
+if echo $1 | grep -q -i "WIFI"
+then
+echo "Copying WIFI Adapter Source Codes"
+cp ../../src/wifi_adapter/tizen/* $sourcedir/tizen/tmp/
+adapterMacro="$adapterMacro -DWIFI_ADAPTER"
+fi
+
+if echo $1 | grep -q -i "BT"
+then
+echo "Copying BT Adapter Source Codes"
+cp ../../src/bt_edr_adapter/* $sourcedir/tizen/tmp/
+cp ../../src/bt_edr_adapter/tizen/* $sourcedir/tizen/tmp/
+adapterMacro="$adapterMacro -DEDR_ADAPTER"
+fi
+
+if echo $1 | grep -q -i "BLE"
+then
+echo "Copying BLE Adapter Source Codes"
+cp ../../src/bt_le_adapter/* $sourcedir/tizen/tmp/
+cp ../../src/bt_le_adapter/tizen/* $sourcedir/tizen/tmp/
+adapterMacro="$adapterMacro -DLE_ADAPTER"
+fi
+fi
+
+sed "/ADAPTER_MACRO :=/ c ADAPTER_MACRO :=$adapterMacro" Makefile > Makefile_bkp
+cp Makefile_bkp $sourcedir/tizen/tmp/Makefile
+rm Makefile_bkp
+cd $sourcedir/tizen/tmp/
+
+#removing the files which needs for only arduino to avoid
+#multiple definition error.
+rm -rf *_singlethread.*
+
+#cd $builddir
+#cp -R ./* $sourcedir/tmp/
+
+#cd $sourcedir
+#mv ./tmp $builddir/
+
+#cp -R ./* $builddir/tmp
+
+#cd $builddir
+#mv tmp $name-$version
+
+#build
+#cd $name-$version
+git init
+gbs build -A armv7l --include-all
+
+rm -rf $sourcedir/tizen/tmp
+#cd $builddir
+#sudo rm -rf $name-$version
--- /dev/null
+%define PREFIX /usr/apps/com.samsung.oicca
+%define ROOTDIR %{_builddir}/%{name}-%{version}
+%define USR_INC_DIR /usr/include
+%define DEST_INC_DIR %{buildroot}%{USR_INC_DIR}/interfaceHeaders
+%define DEST_LIB_DIR %{buildroot}/usr/lib
+
+Name: com.samsung.oicca
+Version: 0.1
+Release: 1
+Summary: Tizen oicca application
+URL: http://slp-source.sec.samsung.net
+Source: %{name}-%{version}.tar.gz
+License: SAMSUNG
+Group: Samsung/Application
+#BuildRequires: cmake
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(capi-network-wifi)
+BuildRequires: pkgconfig(capi-network-bluetooth)
+BuildRequires: boost-devel
+BuildRequires: boost-thread
+BuildRequires: boost-system
+BuildRequires: boost-filesystem
+#BuildRequires: oic-core
+
+%description
+SLP oicca application
+
+%prep
+%setup -q
+
+%build
+
+make clean
+make
+
+#make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+mkdir -p %{buildroot}/usr/share/packages
+mkdir -p %{buildroot}/etc/smack/accesses2.d
+mkdir -p %{buildroot}/usr/apps/com.samsung.oicca/bin/
+mkdir -p %{buildroot}/usr/lib
+mkdir -p %{DEST_INC_DIR}
+mkdir -p %{DEST_LIB_DIR}/pkgconfig
+
+cp -rf %{ROOTDIR}/liboicinterface.a %{buildroot}/usr/lib
+cp -rf %{ROOTDIR}/cacommon.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/caadapterinterface.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/uthreadpool.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/cawifiadapter.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/caethernetadapter.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/caedradapter.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/caleadapter.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/cainterface.h* %{DEST_INC_DIR}/
+cp -rf %{ROOTDIR}/com.samsung.oicca.pc %{DEST_LIB_DIR}/pkgconfig/
+
+
+%files
+%defattr(-,root,root,-)
+%attr(-,inhouse,inhouse)
+%{_libdir}/lib*.a*
+%{_includedir}/interfaceHeaders/*
+%{_libdir}/pkgconfig/*.pc
#ifdef __ANDROID__
#include <android/log.h>
+#elif defined(__TIZEN__)
+#include <dlog.h>
#elif defined ARDUINO
#include "Arduino.h"
#include <avr/pgmspace.h>
#define MAX_LOG_V_BUFFER_SIZE (256)
// Log levels
+#ifndef __TIZEN__
typedef enum
{
DEBUG = 0, INFO, WARNING, ERROR, FATAL
} LogLevel;
+#else
+#define DEBUG DLOG_DEBUG
+#define INFO DLOG_INFO
+#define WARNING DLOG_WARNING
+#define ERROR DLOG_ERROR
+#define FATAL DLOG_ERROR
+#endif
#ifndef ARDUINO
-
+#ifdef __TIZEN__
+#define OICLog(level,tag,mes) LOG(level,tag,mes)
+#define OICLogv(level,tag,fmt,args...) LOG(level,tag,fmt,##args)
+#else
/**
* Configure logger to use a context that defines a custom logger function
*
* @param bufferSize - max number of byte in buffer
*/
void OICLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize);
+#endif //__TIZEN__
#else
/**
* Initialize the serial logger for Arduino
#endif
#ifdef TB_LOG
-// These macros are defined for Linux, Android, and Arduino
+
+#ifdef __TIZEN__
+#define OIC_LOG(level,tag,mes) LOG_(LOG_ID_MAIN, level, tag, mes)
+#define OIC_LOG_V(level,tag,fmt,args...) LOG_(LOG_ID_MAIN, level, tag, fmt,##args)
+#else // These macros are defined for Linux, Android, and Arduino
#define OIC_LOG_INIT() OICLogInit()
#define OIC_LOG(level, tag, logStr) OICLog((level), (tag), (logStr))
#define OIC_LOG_BUFFER(level, tag, buffer, bufferSize) OICLogBuffer((level), (tag), (buffer), (bufferSize))
-
#ifdef ARDUINO
#define OIC_LOG_CONFIG(ctx)
#define OIC_LOG_SHUTDOWN()
#define OIC_LOG_SHUTDOWN() OICLogShutdown()
// Define variable argument log function for Linux and Android
#define OIC_LOG_V(level, tag, ...) OICLogv((level), (tag), __VA_ARGS__)
-#endif
+#endif //ARDUINO
+#endif //__TIZEN__
+
+#else //TB_LOG
-#else
#define OIC_LOG_CONFIG(ctx)
#define OIC_LOG_SHUTDOWN()
#define OIC_LOG(level, tag, logStr)
--- /dev/null
+/******************************************************************\r
+ *\r
+ * Copyright 2014 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ ******************************************************************/\r
+#ifndef _OIC_STRING_H_\r
+#define _OIC_STRING_H_\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "oic_malloc.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif // __cplusplus\r/**\r
+ * Duplicates the source string and returns it.\r
+ *\r
+ * NOTE: Caller needs to clear this memory by calling OICFree.\r
+ *\r
+ * @param str - Original valid string which needs to be duplicated\r
+ *\r
+ * @return\r
+ * on success, a pointer to the duplicated string\r
+ * on failure, a null pointer is returned\r
+ */\r
+char *OICStrdup(const char *str);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r#endif /* _OIC_STRING_H_ */\r
#include <stdio.h>
#include <malloc.h>
#include <glib.h>
-#include <glib/gthreadpool.h>
#include "cacommon.h"
#define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';}
#endif
#endif // __ANDROID__
-#ifndef ARDUINO
+#ifndef ARDUINO
+#ifndef __TIZEN__
void OICLogConfig(oic_log_ctx_t *ctx)
{
logCtx = ctx;
OICLog(level, tag, lineBuffer);
}
}
-
+#endif //__TIZEN__
#else
/**
* Initialize the serial logger for Arduino
va_end(ap);
}
-#endif
+#endif //ARDUINO
--- /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 "oic_string.h"
+
+char *OICStrdup(const char *str)
+{
+ // Allocate memory for original string length and 1 extra byte for '\0'
+ size_t length = strlen(str) + 1;
+ char *dup = OICMalloc(length);
+ if (NULL != dup)
+ {
+ memcpy(dup, str, length);
+ }
+ return dup;
+}
if (NULL == element)
{
- OIC_LOG(DEBUG, TAG, "QueueGetElement : FAIL, no messages");
+ OIC_LOG(DEBUG, TAG, "QueueGetElement : empty, no messages");
return NULL;
}
gThreadpool = g_thread_pool_new(run, NULL, num_of_threads, FALSE, &error);
if (NULL == gThreadpool)
{
- OIC_LOG_V(ERROR, TAG, "Error: g_thread_pool_new failed!");
+ OIC_LOG_V(ERROR, TAG, "g_thread_pool_new failed!");
if (NULL != error)
{
OIC_LOG_V(ERROR, TAG, "Error is: %s", error->message);
gboolean result = FALSE;
if (NULL == routine)
{
- OIC_LOG_V(ERROR, TAG, "Error: routine is NULL!");
+ OIC_LOG_V(ERROR, TAG, "routine is NULL!");
return CA_STATUS_FAILED;
}
u_thread_msg_t *message = (u_thread_msg_t *) OICMalloc(sizeof(u_thread_msg_t));
+ if (NULL == message)
+ {
+ OIC_LOG_V(ERROR, TAG, "Memory allocation failed!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
message->data = data;
message->func = routine;
result = g_thread_pool_push((GThreadPool *) thread_pool, (void *) message, NULL);
if (FALSE == result)
{
- OIC_LOG_V(ERROR, TAG, "Error: Failed to push the task to threadpool!");
+ OIC_LOG_V(ERROR, TAG, "Failed to push the task to threadpool!");
return CA_STATUS_FAILED;
}
}
else
{
- OIC_LOG_V(ERROR, TAG, "Error: Invalid task data");
+ OIC_LOG_V(ERROR, TAG, "Invalid task data");
return;
}
--- /dev/null
+Project Name: IoTivity
+Release Version No. / Label Name: CA_v0.1
+API Version: CA_v0.4
+
+Release Description:
+Connectivity Abstraction provides a unified approach to send different OIC messages across multiple transports.
+
+Scope of Release:
+1. Supported APIs ( please check below APIs)
+2. Samples to test Supported APIs.
+3. OIC Coding guidelines followed based on the current CSDK source.
+4. Multi-Threaded Connectivity abstraction
+5. Executed Open Source Verification and Prevent analysis.
+
+The following Connectivity Abstraction API features are supported in this release:
+
+Supported APIs
+CAInitialize()
+CATerminate()
+CAStartListeningServer()
+CAStartDiscoveryServer()
+CARegisterHandler()
+CAhandleRequestResponse()
+FindResource()
+SendRequest()
+SendResponse()
+SelectNetwork()
+UnselectNetwork()
+
+Non Supported APIs
+SendNotification()
+AdvertizeResource()
+CAGenerateToken()
+CADestryToken()
+CAGetNetworkInfo()
+
+Type of Release: Source,
+Platform OS: Ubuntu 12.0.4 and above:
+
+Connectivity: WIFI only
+Preconditions:
+1)gcc 4.6.3 and above.
+2)glib library (sudo apt-get install libglib2.0-dev)
+3)libcoap.a library ( do make @lib/libcoap-4.1.1)
+
+Known and Open Issues:
+1) OIC Log, OIC malloc will be removed once name changes applied to OIC Bases code
+2) Support only WIFI Interface.
+3) URI length is 16 characters.
+
+Nature of Release: Partial
+
+How to Build:
+Follow below steps to execute CA Client / server in different systems
+Step 1: Build Libcoap library
+Make File Location @connectivity\lib\libcoap-4.1.1
+Step 2: Build CA library
+Make File Location @connectivity\build\linux
+Step 3: Samples
+Make File Location @connectivity\samples\linux
+
+NOTE: sample.sh script can be used @connectivity\samples\linux for 3 steps together
+
+Execution:
+linux$ export LD_LIBRARY_PATH=../../build/out/
+linux$ ./out/sample_main
+
+Client Option : d, f, h Client
+Server Option : s, h
/**
* @brief Starting connectivity adapters and each adapter have transport specific behavior.
- * Transport Specific Behavior:
- * WIFI/ETH connectivity Starts unicast server on all available IPs and defined port number as per specification.
- * EDR will not start any specific servers.
- * LE will not start any specific servers.
+ * Transport Specific Behavior:
+ * WIFI/ETH connectivity Starts unicast server on all available IPs and defined
+ * port number as per specification.
+ * EDR will not start any specific servers.
+ * LE will not start any specific servers.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
typedef CAResult_t (*CAAdapterStart)();
/**
* @brief Starting listening server for receiving multicast search requests
* Transport Specific Behavior:
- * WIFI/ETH Starts multicast server on all available IPs and defined port number and as per specification.
- * EDR Starts RFCOMM Server with prefixed UUID as per specification.
- * LE Start GATT Server with prefixed UUID and Characteristics as per OIC Specification.
+ * WIFI/ETH Starts multicast server on all available IPs and defined
+ * port number and as per specification.
+ * EDR Starts RFCOMM Server with prefixed UUID as per specification.
+ * LE Start GATT Server with prefixed UUID and Characteristics as per OIC Specification.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
typedef CAResult_t (*CAAdapterStartListeningServer)();
/**
* @brief for starting discovery servers for receiving multicast advertisements
* Transport Specific Behavior:
- * WIFI/ETH Starts multicast server on all available IPs and defined port number as per OIC Specification.
- * EDR Starts RFCOMM Server with prefixed UUID as per OIC Specification.
- * LE Starts GATT Server with prefixed UUID and Characteristics as per OIC Specification.
+ * WIFI/ETH Starts multicast server on all available IPs and defined port
+ * number as per OIC Specification.
+ * EDR Starts RFCOMM Server with prefixed UUID as per OIC Specification.
+ * LE Starts GATT Server with prefixed UUID and Characteristics as per OIC Specification.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
typedef CAResult_t (*CAAdapterStartDiscoveryServer)();
/**
* @brief Sends data to the endpoint using the adapter connectivity.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port,
+ * reference uri and connectivity type) to which the unicast data has to be sent.
* @param data [IN] Data which required to be sent.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-typedef uint32_t (*CAAdapterSendUnitcastData)(const CARemoteEndpoint_t* endpoint, void* data,
+typedef uint32_t (*CAAdapterSendUnitcastData)(const CARemoteEndpoint_t *endpoint, void *data,
uint32_t dataLen);
/**
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-typedef uint32_t (*CAAdapterSendMulticastData)(void* data, uint32_t dataLen);
+typedef uint32_t (*CAAdapterSendMulticastData)(void *data, uint32_t dataLen);
/**
* @brief Starts notification server on adapters.
/**
* @brief Send notification information to the given endpoint.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri
+ * and connectivity type) to which the unicast data has to be sent.
* @param data [IN] Data which required to be sent.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-typedef uint32_t (*CAAdapterSendNotification)(const CARemoteEndpoint_t* endpoint, void* data,
+typedef uint32_t (*CAAdapterSendNotification)(const CARemoteEndpoint_t *endpoint, void *data,
uint32_t dataLen);
/**
* @param size [OUT] Number of local connectivity structures.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
-typedef CAResult_t (*CAAdapterGetNetworkInfo)(CALocalConnectivityt_t** info, uint32_t* size);
+typedef CAResult_t (*CAAdapterGetNetworkInfo)(CALocalConnectivity_t **info, uint32_t *size);
/**
* @brief Read Synchronous API callback.
/**
* @brief Stopping the adapters and close socket connections
* Transport Specific Behavior:
- * WIFI/ETH Stops all listening servers and close sockets.
- * EDR Stops all RFCOMM servers and close sockets.
- * LE Stops all GATT servers and close sockets.
+ * WIFI/ETH Stops all listening servers and close sockets.
+ * EDR Stops all RFCOMM servers and close sockets.
+ * LE Stops all GATT servers and close sockets.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
typedef CAResult_t (*CAAdapterStop)();
/**
- * @brief Terminate the connectivity adapter.Configuration information will be deleted from further use
+ * @brief Terminate the connectivity adapter.Configuration information will be deleted from
+ * further use
*/
typedef void (*CAAdapterTerminate)();
* @brief This will be used during the recive of network requests and response.
* @see SendUnitcastData(), SendMulticastData()
*/
-typedef void (*CANetworkPacketReceivedCallback)(CARemoteEndpoint_t* endPoint, void* data,
+typedef void (*CANetworkPacketReceivedCallback)(CARemoteEndpoint_t *endPoint, void *data,
uint32_t dataLen);
/**
* @brief This will be used to intimate network changes to the connectivity common logic layer
* @see SendUnitcastData(), SendMulticastData()
*/
-typedef void (*CANetworkChangeCallback)(CALocalConnectivityt_t* info, CANetworkStatus_t status);
+typedef void (*CANetworkChangeCallback)(CALocalConnectivity_t *info, CANetworkStatus_t status);
#ifdef __cplusplus
} /* extern "C" */
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file caadapterutils.h
+ * @brief This file contains common utility function for CA transport adaptors.
+ */
+
+#ifndef _CA_ADAPTER_UTILS_H_
+#define _CA_ADAPTER_UTILS_H_
+
+#include "cacommon.h"
+#include "logger.h"
+#include "oic_malloc.h"
+
+/**
+ * @def VERIFY_NON_NULL
+ * @brief Macro to verify the validity of input argument
+ */
+#define VERIFY_NON_NULL(arg, log_tag, log_message) \
+ if (NULL == arg ){ \
+ OIC_LOG_V(ERROR, log_tag, "Invalid input: %s!", log_message); \
+ return CA_STATUS_INVALID_PARAM; \
+ } \
+
+/**
+ * @def VERIFY_NON_NULL_RET
+ * @brief Macro to verify the validity of input argument
+ */
+#define VERIFY_NON_NULL_RET(arg, log_tag, log_message,ret) \
+ if (NULL == arg ){ \
+ OIC_LOG_V(ERROR, log_tag, "Invalid input: %s!", log_message); \
+ return ret; \
+ } \
+
+/**
+ * @def VERIFY_NON_NULL_VOID
+ * @brief Macro to verify the validity of input argument
+ */
+#define VERIFY_NON_NULL_VOID(arg, log_tag, log_message) \
+ if (NULL == arg ){ \
+ OIC_LOG_V(ERROR, log_tag, "Invalid input: %s!", log_message); \
+ return; \
+ } \
+
+/**
+ * @fn CAAdapterCreateLocalEndpoint
+ * @brief Create CALocalConnectivity_t instance.
+ */
+CALocalConnectivity_t *CAAdapterCreateLocalEndpoint(CAConnectivityType_t type, const char *address,
+ const char *interfaceName);
+
+/**
+ * @fn CAAdapterCopyLocalEndpoint
+ * @brief Create CALocalConnectivity_t duplicate instance.
+ */
+CALocalConnectivity_t *CAAdapterCopyLocalEndpoint(CALocalConnectivity_t *connectivity);
+
+/**
+ * @fn CAAdapterFreeLocalEndpoint
+ * @brief Deallocate CALocalConnectivity_t instance.
+ */
+void CAAdapterFreeLocalEndpoint(CALocalConnectivity_t *localEndPoint);
+
+/**
+ * @fn CAAdapterCreateRemoteEndpoint
+ * @brief Allocate CARemoteEndpoint_t instance.
+ */
+CARemoteEndpoint_t *CAAdapterCreateRemoteEndpoint(CAConnectivityType_t type, const char *address,
+ const char *resourceUri);
+
+/**
+ * @fn CAAdapterCopyRemoteEndpoint
+ * @brief Create CARemoteEndpoint_t duplicate instance.
+ */
+CARemoteEndpoint_t *CAAdapterCopyRemoteEndpoint(CARemoteEndpoint_t *remoteEndpoint);
+
+/**
+ * @fn CAAdapterFreeRemoteEndpoint
+ * @brief Deallocate CARemoteEndpoint_t instance.
+ */
+void CAAdapterFreeRemoteEndpoint(CARemoteEndpoint_t *remoteEndPoint);
+
+#endif // _CA_ADAPTER_UTILS_H_
**/
#include "cacommon.h"
#include "caadapterinterface.h"
+#include "uthreadpool.h" /* for thread pool */
#ifdef __cplusplus
extern "C"
{
#endif
-#ifndef BLUETOOTH_ADAPTER_TAG
-#define BLUETOOTH_ADAPTER_TAG "CA_EDR"
-#endif //BLUETOOTH_ADAPTER_TAG
/**
* @brief Initialize EDR connectivity interface.
* @param registerCallback [IN] To register EDR interfaces to Connectivity Abstraction Layer
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback);
+ CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle);
/**
* @brief Starting EDR connectivity adapters .As its peer to peer it doesnot require to start any servers
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendEDRUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
+uint32_t CASendEDRUnicastData(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen);
/**
* @brief Sends Multicast data to the endpoint using the EDR connectivity.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendEDRMulticastData(void* data, uint32_t dataLen);
+uint32_t CASendEDRMulticastData(void *data, uint32_t dataLen);
/**
* @brief Starts notification server on EDR adapters.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendEDRNotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
+uint32_t CASendEDRNotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen);
/**
* @brief Get EDR Connectivity network information
* @param size [OUT] Number of local connectivity structures.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
-CAResult_t CAGetEDRInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size);
+CAResult_t CAGetEDRInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size);
/**
* @brief Read Synchronous API callback.
+++ /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.
- *
- ******************************************************************/
-
-#ifndef __CA_ERROR_CODE_H_
-#define __CA_ERROR_CODE_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * Declares Stack Results & Errors
- */
-typedef enum
-{
- OC_STACK_OK = 0,
- OC_STACK_INVALID_URI,
- OC_STACK_INVALID_QUERY,
- OC_STACK_INVALID_IP,
- OC_STACK_INVALID_PORT,
- OC_STACK_INVALID_CALLBACK,
- OC_STACK_INVALID_METHOD,
- OC_STACK_INVALID_PARAM,
- OC_STACK_INVALID_OBSERVE_PARAM,
- OC_STACK_NO_MEMORY,
- OC_STACK_COMM_ERROR,
- OC_STACK_NOTIMPL,
- OC_STACK_NO_RESOURCE, /* resource not found*/
- OC_STACK_RESOURCE_ERROR, /*ex: not supported method or interface*/
- OC_STACK_SLOW_RESOURCE,
- OC_STACK_NO_OBSERVERS, /* resource has no registered observers */
- OC_STACK_OBSERVER_NOT_FOUND,
- OC_STACK_OBSERVER_NOT_ADDED,
- OC_STACK_OBSERVER_NOT_REMOVED,
-#ifdef WITH_PRESENCE
- OC_STACK_PRESENCE_NO_UPDATE,
- OC_STACK_PRESENCE_STOPPED,
- OC_STACK_PRESENCE_DO_NOT_HANDLE,
-#endif
- OC_STACK_ERROR
-} OCStackResult;
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif //#ifndef __CA_ERROR_CODE_H_
#include "cacommon.h"
#include "caadapterinterface.h"
+#include "uthreadpool.h" /* for thread pool */
#ifdef __cplusplus
extern "C"
#endif
/**
- * @brief Initialize Ethernet connectivity interface.
+ * @brief API to initialize Ethernet Interface.
* @param registerCallback [IN] To register Ethernet interfaces to Connectivity Abstraction Layer
- * @param reqRespCallback [IN] sending responses and discovery messages from unicast , multicast servers
+ * @param reqRespCallback [IN] sending responses and discovery messages from unicast,
+ * multicast servers
* @param netCallback [IN] Intimate the network additions to Connectivity Abstraction Layer.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAInitializeEthernet(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback);
+ CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle);
/**
* @brief Start Ethernet Interface adapter.
/**
* @brief Starting listening server for receiving multicast search requests
* Transport Specific Behavior:
- * Ethernet Starts Multicast Server on all available IPs and prefixed port number and as per OIC Specification.
+ * Ethernet Starts Multicast Server on all available IPs and prefixed port number and
+ * as per OIC Specification.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAStartEthernetListeningServer();
/**
* @brief for starting discovery servers for receiving multicast advertisements
* Transport Specific Behavior:
- * Ethernet Starts Start multicast server on all available IPs and prefixed port number as per OIC Specification
+ * Ethernet Starts Start multicast server on all available IPs and prefixed port number as per
+ * OIC Specification
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAStartEthernetDiscoveryServer();
/**
* @brief Sends data to the endpoint using the adapter connectivity.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference
+ * uri and connectivity type) to which the unicast data has to be sent.
* @param data [IN] Data which required to be sent.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendEthernetUnicastData(const CARemoteEndpoint_t* endpoint, void* data,
- uint32_t dataLen);
+uint32_t CASendEthernetUnicastData(const CARemoteEndpoint_t *endpoint, void *data,
+ uint32_t dataLen);
/**
- * @brief Sends Multicast data to the endpoint using the WIFI connectivity.
+ * @brief Sends Multicast data to the endpoint using the Ethernet connectivity.
* Note: length must be > 0.
* @param data [IN] Data which required to be sent.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendEthernetMulticastData(void* data, uint32_t dataLen);
+uint32_t CASendEthernetMulticastData(void *data, uint32_t dataLen);
/**
* @brief Starts notification server on Ethernet adapters.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
-CAResult_t CAStartEthernetNotifyServer();
+CAResult_t CAStartEthernetNotifyRecvServers();
/**
* @brief Send notification information.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port,
+ * reference uri and connectivity type) to which the unicast data has to be sent.
* @param data [IN] Data which required to be sent.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendEthernetNotification(const CARemoteEndpoint_t* endpoint, void* data,
- uint32_t dataLen);
+uint32_t CASendEthernetNotification(const CARemoteEndpoint_t *endpoint, void *data,
+ uint32_t dataLen);
/**
* @brief Get Ethernet Connectivity network information
* @param info [OUT] Local connectivity information structures
* @param size [OUT] Number of local connectivity structures.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
-CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size);
+CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size);
/**
* @brief Read Synchronous API callback.
} /* extern "C" */
#endif
-#endif
+#endif//#ifndef __CA_ETHERNET_ADAPTER_H__
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file caethernetcore.h
+ * @brief This file contains the APIs for Ethernet communications.
+ */
+#ifndef __CA_ETHERNETCORE_H_
+#define __CA_ETHERNETCORE_H_
+
+#include "cacommon.h"
+#include "config.h"
+#include "coap.h"
+#include "uthreadpool.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef void (*CAPacketReceiveCallback)(const char* address, const char* data);
+
+void CAEthernetInitialize(u_thread_pool_t handle);
+
+void CAEthernetTerminate();
+
+int32_t CAEthernetSendUnicastMessage(const char* address, const char* data, int32_t length);
+
+int32_t CAEthernetSendMulticastMessage(const char* m_address, const char* data);
+
+int32_t CAEthernetStartUnicastServer();
+
+int32_t CAEthernetStartMulticastServer();
+
+int32_t CAEthernetStopUnicastServer();
+
+int32_t CAEthernetStopMulticastServer();
+
+void CAEthernetSetCallback(CAPacketReceiveCallback callback);
+
+void CAEthernetGetLocalAddress(char* addressBuffer);
+
+int32_t CAEthernetSendUnicastMessageImpl(const char* address, const char* data);
+
+int32_t CAEthernetSendMulticastMessageImpl(const char* msg);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
#define __CA_INTERFACE_CONTROLLER_H_
#include "caadapterinterface.h"
+#include "uthreadpool.h" /* for thread pool */
#ifdef __cplusplus
extern "C"
{
#endif
-void CAInitializeAdapters();
+void CAInitializeAdapters(u_thread_pool_t handle);
void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback);
+void CASetNetworkChangeCallback(CANetworkChangeCallback callback);
+
void CAStartAdapter(CAConnectivityType_t connectivity);
void CAStopAdapter(CAConnectivityType_t connectivity);
+CAResult_t CAGetNetworkInfo(CALocalConnectivity_t **info, uint32_t* size);
+
CAResult_t CASendUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t length);
CAResult_t CASendMulticastData(void* data, uint32_t length);
#include "cacommon.h"
#include "caadapterinterface.h"
+#include "uthreadpool.h" /* for thread pool */
/**
* BLE Interface APIs.
/**
* @brief Initialize LE connectivity interface.
* @param registerCallback [IN] To register LE interfaces to Connectivity Abstraction Layer
- * @param reqRespCallback [IN] sending responses and discovery messages from unicast , multicast servers
+ * @param reqRespCallback [IN] sending responses and discovery messages from unicast , \
+ * multicast servers
* @param netCallback [IN] Intimate the network additions to Connectivity Abstraction Layer.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
+
CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback);
+ CANetworkPacketReceivedCallback reqRespCallback,
+ CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle);
/**
- * @brief Starting LE connectivity adapters .As its peer to peer it doesnot require to start any servers
+ * @brief Starting LE connectivity adapters . \
+ * As its peer to peer it doesnot require to start any servers
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAStartLE();
/**
* @brief Sends data to the endpoint using the adapter connectivity.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
- * @param data [IN] Data which required to be sent.
- * @param dataLen [IN] Size of data to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri \
+ * and connectivity type) to which the unicast data has to be sent.
+ * @param data [IN] Data which required to be sent.
+ * @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendLEUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
+uint32_t CASendLEUnicastData(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen);
/**
* @brief Sends Multicast data to the endpoint using the LE connectivity.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendLEMulticastData(void* data, uint32_t dataLen);
+uint32_t CASendLEMulticastData(void *data, uint32_t dataLen);
/**
* @brief Starts notification server on EDR adapters.
/**
* @brief Send notification information.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri \
+ * and connectivity type) to which the unicast data has to be sent.
* @param data [IN] Data which required to be sent.
- * @param dataLen [IN] Size of data to be sent.
+ * @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendLENotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
+uint32_t CASendLENotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen);
/**
* @brief Get LE Connectivity network information
* @param size [OUT] Number of local connectivity structures.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
-CAResult_t CAGetLEInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size);
+CAResult_t CAGetLEInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size);
/**
* @brief Read Synchronous API callback.
{
#endif
-typedef enum
-{
- SUCCESS = 0, NETWORK_ERROR, FAIL
-} CADetachErrorCode;
-
-typedef void (*CAMessageHandlerCallback)(int32_t id, CADetachErrorCode code);
-
-int32_t CADetachRequestMessage(const CARemoteEndpoint_t* object, const CARequestInfo_t* request);
-
-int32_t CADetachResponseMessage(const CARemoteEndpoint_t* object, const CAResponseInfo_t* response);
+CAResult_t CADetachRequestMessage(const CARemoteEndpoint_t* object, const CARequestInfo_t* request);
-int32_t CADetachMessageResourceUri(const CAURI_t resourceUri);
+CAResult_t CADetachResponseMessage(const CARemoteEndpoint_t* object,
+ const CAResponseInfo_t* response);
-void CASetMessageHandlerCallback(CAMessageHandlerCallback callback);
+CAResult_t CADetachMessageResourceUri(const CAURI_t resourceUri, const CAHeaderOption_t* options,
+ uint8_t numOptions);
void CASetRequestResponseCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler);
--- /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.
+ *
+ ******************************************************************/
+
+#ifndef _CA_MESSAGE_QUEUE_H_
+#define _CA_MESSAGE_QUEUE_H_
+
+#include "umutex.h"
+#include "cacommon.h"
+
+/**
+ @brief Adapter message information
+ */
+typedef struct CAAdapterMessage_t
+{
+ CARemoteEndpoint_t *remoteEndpoint;
+ void *data;
+ uint32_t dataLen;
+ struct CAAdapterMessage_t *next;
+} CAAdapterMessage_t;
+
+/**
+ @brief Adapter message queue
+ */
+typedef struct
+{
+ u_mutex queueMutex;
+ CAAdapterMessage_t *begin;
+ CAAdapterMessage_t *end;
+} CAAdapterMessageQueue_t;
+
+/**
+ * @brief API to initialize Message queue.
+ * @param queueHandle will be set on successfull initialization of message queue.
+ * This param to be passed in all subsequent calls to queue handling api's.
+ * @return Error Code
+ */
+CAResult_t CAAdapterInitializeMessageQueue(CAAdapterMessageQueue_t **queueHandle);
+
+/**
+ * @brief API to terminate Message queue.
+ * This api will delete entire message queue and will take care of freeing all memory.
+ * queueHandle will become invalid after this api call.
+ * @param queueHandle handle of queue obtained via CAAdapterInitializeMessageQueue()
+ */
+void CAAdapterTerminateMessageQueue(CAAdapterMessageQueue_t *queueHandle);
+
+/**
+ * @brief API to add Message to queue.
+ * This api will duplicate all passed arguments and add entry to end of message queue.
+ * @param queueHandle handle of queue obtained via CAAdapterInitializeMessageQueue()
+ * @param remoteEndpoint remoteEndpoint from which data is received or is supposed to be sent.
+ * Would be NULL for outgoing multicast data.
+ * @param data Data that is received or supposed to be sent.
+ * @param dataLen Data length.
+ * @return Error Code
+ */
+CAResult_t CAAdapterEnqueueMessage(CAAdapterMessageQueue_t *queueHandle,
+ CARemoteEndpoint_t *remoteEndpoint,
+ void *data, uint32_t dataLen);
+
+/**
+ * @brief API to get oldest message and remove it from the queue
+ * @param queueHandle handle of queue obtained via CAAdapterInitializeMessageQueue()
+ * @param message oldest message in queue. To be freed by caller using CAAdapterFreeMessage() api.
+ * @return Error Code
+ */
+CAResult_t CAAdapterDequeueMessage(CAAdapterMessageQueue_t *queueHandle,
+ CAAdapterMessage_t **message);
+
+/**
+ * @brief API to help caller free the message obtained via CAAdapterDequeueMessage() api.
+ * @param message to be freed.
+ */
+void CAAdapterFreeMessage(CAAdapterMessage_t *message);
+
+#endif //#ifndef _CA_MESSAGE_QUEUE_H_
+
#ifndef _NETWORK_CONFIGURATOR_H_
#define _NETWORK_CONFIGURATOR_H_
+#include "cacommon.h"
#include "uarraylist.h"
#ifdef __cplusplus
u_arraylist_t* CAGetSelectedNetworkList();
+CAResult_t CAGetNetworkInformationInternal(CALocalConnectivity_t **info, uint32_t* size);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
{
#endif
-uint32_t flags = 0;
-
-uint8_t msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */
-
-coap_block_t block =
-{ .num = 0, .m = 0, .szx = 6};
-
typedef uint32_t code_t;
/**
- * function for generate
+ * function for generating
*/
coap_pdu_t* CAGeneratePdu(const char* uri, const uint32_t code, const CAInfo_t info);
+
/**
- * function for parsing
+ * function for generating
*/
-uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t* outReqInfo);
+uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t* outReqInfo, char* outUri);
-uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t* outResInfo);
+uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t* outResInfo,
+ char* outUri);
coap_pdu_t* CACreatePDUforRequest(const code_t code, coap_list_t *options);
coap_pdu_t* CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *optlist,
const char* payload);
+/**
+ * funtion for parsing
+ */
void CAParseURI(const char* uriInfo, coap_list_t **options);
+/**
+ * funtion for parsing
+ */
void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist);
coap_list_t* CACreateNewOptionNode(const uint16_t key, const uint32_t length, const uint8_t *data);
int32_t CAOrderOpts(void *a, void *b);
-void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t* outCode, CAInfo_t* outInfo);
+uint32_t getOptionCount(coap_opt_iterator_t opt_iter);
+/**
+ * funtion for get PDU information
+ */
+void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t* outCode, CAInfo_t* outInfo, char* outUri);
+
+/**
+ * funtion for parsing
+ */
coap_pdu_t* CAParsePDU(const char* data, uint32_t* outCode);
/**
void CADestroyTokenInternal(CAToken_t token);
+/**
+ * Deinitialize
+ */
+void CADeinitialize(CAInfo_t* info);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file caqueueingthread.h
+ */
+#ifndef __CA_THREAD_H_
+#define __CA_THREAD_H_
+
+#include <stdint.h>
+
+#include "uthreadpool.h"
+#include "umutex.h"
+#include "uqueue.h"
+#include "cacommon.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef void (*CAThreadTask)(void* threadData);
+
+typedef struct
+{
+ u_thread_pool_t threadPool;
+ u_mutex threadMutex;
+ u_cond threadCond;
+ CAThreadTask threadTask;
+ CABool_t isStop;
+ u_queue_t* dataQueue;
+} CAQueueingThread_t;
+
+CAResult_t CAQueueingThreadInitialize(CAQueueingThread_t* thread, u_thread_pool_t handle,
+ CAThreadTask task);
+
+CAResult_t CAQueueingThreadStart(CAQueueingThread_t* thread);
+
+// shallow copy
+CAResult_t CAQueueingThreadAddData(CAQueueingThread_t* thread, void* data, uint32_t size);
+
+CAResult_t CAQueueingThreadStop(CAQueueingThread_t* thread);
+
+CAResult_t CAQueueingThreadDestroy(CAQueueingThread_t* thread);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // __CA_THREAD_H_
#include "cacommon.h"
#include "caadapterinterface.h"
+#include "uthreadpool.h" /* for thread pool */
#ifdef __cplusplus
extern "C"
/**
* @brief API to initialize WiFi Interface.
* @param registerCallback [IN] To register WIFI interfaces to Connectivity Abstraction Layer
- * @param reqRespCallback [IN] sending responses and discovery messages from unicast , multicast servers
+ * @param networkPacketCallback [IN] sending responses and discovery messages
+ * from unicast , multicast servers
* @param netCallback [IN] Intimate the network additions to Connectivity Abstraction Layer.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback);
+ CANetworkPacketReceivedCallback networkPacketCallback,
+ CANetworkChangeCallback netCallback, u_thread_pool_t handle);
/**
* @brief Start WiFi Interface adapter.
/**
* @brief Starting listening server for receiving multicast search requests
* Transport Specific Behavior:
- * WIFI Starts Multicast Server on all available IPs and prefixed port number and as per OIC Specification.
+ * WIFI Starts Multicast Server on all available IPs and prefixed port number and
+ * as per OIC Specification.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAStartWIFIListeningServer();
/**
* @brief for starting discovery servers for receiving multicast advertisements
* Transport Specific Behavior:
- * WIFI Starts Start multicast server on all available IPs and prefixed port number as per OIC Specification
+ * WIFI Starts Start multicast server on all available IPs and prefixed port
+ * number as per OIC Specification
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
CAResult_t CAStartWIFIDiscoveryServer();
/**
* @brief Sends data to the endpoint using the adapter connectivity.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port,
+ * reference uri and connectivity type) to which the unicast data has to be sent.
* @param data [IN] Data which required to be sent.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
+uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen);
/**
* @brief Sends Multicast data to the endpoint using the WIFI connectivity.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendWIFIMulticastData(void* data, uint32_t dataLen);
+uint32_t CASendWIFIMulticastData(void *data, uint32_t dataLen);
/**
* @brief Starts notification server on WIFI adapters.
/**
* @brief Send notification information.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to
- * which the unicast data has to be sent.
+ * @param endpoint [IN] Remote Endpoint information (like ipaddress , port,
+ * reference uri and connectivity type) to which the unicast data has to be sent.
* @param data [IN] Data which required to be sent.
* @param dataLen [IN] Size of data to be sent.
* @return - The number of bytes sent on the network. Return value equal to zero indicates error.
*/
-uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
+uint32_t CASendWIFINotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen);
/**
* @brief Get WIFI Connectivity network information
* @param info [OUT] Local connectivity information structures
* @param size [OUT] Number of local connectivity structures.
* @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
*/
-CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size);
+CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size);
/**
* @brief Read Synchronous API callback.
} /* extern "C" */
#endif
-#endif//#ifndef __CA_WIFI_ADAPTER_H__
+#endif // #ifndef __CA_WIFI_ADAPTER_H__
#include "cacommon.h"
#include "config.h"
#include "coap.h"
+#include "uthreadpool.h"
#ifdef __cplusplus
extern "C"
typedef void (*CAPacketReceiveCallback)(const char* address, const char* data);
-void CAWiFiInitialize();
+void CAWiFiInitialize(u_thread_pool_t handle);
void CAWiFiTerminate();
int32_t CAWiFiSendMulticastMessage(const char* m_address, const char* data);
-int32_t CAWiFiStartUnicastServer(const char* address, int32_t port);
+int32_t CAWiFiStartUnicastServer();
-int32_t CAWiFiStartMulticastServer(const char* m_address, int32_t port);
+int32_t CAWiFiStartMulticastServer();
-int32_t CAWiFiStopUnicastServer(int32_t server_id);
+int32_t CAWiFiStopUnicastServer();
-int32_t CAWiFiStopMulticastServer(int32_t server_id);
+int32_t CAWiFiStopMulticastServer();
void CAWiFiSetCallback(CAPacketReceiveCallback callback);
-void* CAUnicastReceiveThread(void* data);
-
-void* CAUnicastSendThread(void* data);
-
-void CASendUnicastMessage(char* address, void* data);
-
-int32_t CASendUnicastMessageImpl(const char* address, const char* data, int32_t lengh);
-
-void CAStopUnicastSendThread();
-
-void* CAMulticastReceiveThread(void* data);
-
-void* CAMulticastSendThread(void* data);
+void CAGetLocalAddress(char* addressBuffer);
-void CASendMulticastMessage(void* data);
+int32_t CASendUnicastMessageImpl(const char* address, const char* data);
int32_t CASendMulticastMessageImpl(const char* msg);
-void CAStopMulticastSendThread();
-
-void CAGetLocalAddress(char* addressBuffer);
-
#ifdef __cplusplus
} /* extern "C" */
#endif
+++ /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.
- *
- ******************************************************************/
-
-/**
- * @file cawifiethernetadapter.h
- * @brief This file contains the APIs for WiFi/Ethernet Adapter.
- */
-#ifndef __CA_WIFI_ETHERNET_ADAPTER_H__
-#define __CA_WIFI_ETHERNET_ADAPTER_H__
-
-#include "cacommon.h"
-#include "caadapterinterface.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @brief API to initialize WiFi Interface.
- * @param registerCallback to register WIFI interfaces to things communication
- * @param reqRespCallback for sending responses and discovery messages from unicast , multicast servers
- * @param netCallback to intimate the network additions to things communication
- * @return Error Code
- */
-CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback);
-
-/**
- * @brief API to Start WiFi Interface.
- * @return Error Code
- */
-CAResult_t CAStartWIFI();
-
-/**
- * @brief starting listening server
- * Transport Specific Behaviour
- * IP :- Start Multicast Server on all available IPs and prefixed port number and as per OIC Specification.
- * @return Error Code CAResult_t.
- */
-CAResult_t CAStartWIFIListeningServer();
-
-/**
- * @brief for starting discovery servers.
- * Transport Specific Behaviour
- * IP :- Start Multicast Server on all available IPs and prefixed port number as per OIC Specification.
- * @return CAResult_t.
- * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h)
- */
-CAResult_t CAStartWIFIDiscoveryServer();
-
-/**
- * @brief Send Multicast Data interface API callback.
- * Note: length must be > 0
- * @param endpoint - Endpoint information (like ipaddress , port, reference uri and connectivity type) to which the multicast data has to be sent.
- * @param data - void pointer data which will be sent via client
- * @param dataLen - size of data to be sent
- * @return - Will return the number of bytes sent on the network. Return value equal to zero indicates error.
- */
-uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
-
-/**
- * @brief API to send data to a group of remote addresses.
- * @param endpoint - Endpoint information (like ipaddress , port, reference uri and connectivity type) to which the multicast data has to be sent.
- * @param data - void pointer data which will be sent via client
- * @param dataLen - size of data to be sent
- * @return - size of data sent or -1 on error
- */
-uint32_t CASendWIFIMulticastData(void* data, uint32_t dataLen);
-
-/**
- * @brief Start Notification Server interface API callback.
- *
- * @return CAResult_t.
- * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h)
- */
-CAResult_t CAStartWIFINotifyRecvServers();
-
-/**
- * @brief Send Notification Data interface API callback.
- * Note: length must be > 0
- * @param endpoint - remote endpoint having endpoint details
- * @param data - data to be sent
- * @param dataLen - length of data to be sent
- * @return Will return the number of bytes sent on the network. Return value equal to zero indicates error.
- */
-uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen);
-/**
- * @brief Get Network Information
- *
- * @return CAResult_t.
- * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h)
- */
-CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size);
-
-/**
- * @brief Read Synchronous API callback.
- * @return Error Code CAResult_t.
- * @return CAResult_t.
- * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h)
- */
-CAResult_t CAReadWIFIData();
-
-/**
- * @brief API to Stop WiFi Interface.
- * @return CAResult_t
- */
-CAResult_t CAStopWIFI();
-
-/**
- * @brief API to terminate WiFi Interface.
- * @return none.
- */
-void CATerminateWifi();
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
-/**
+/**
* @file address.h
* @brief representation of network addresses
*/
{
if (!a)
{
- printf("[COAP] address - coap_address_t is false\n");
return 0;
}
switch (a->addr.sa.sa_family)
{
case AF_INET:
- printf("[COAP] address - local address : %s\n", a->addr.sin.sin_addr.s_addr);
return IN_MULTICAST(a->addr.sin.sin_addr.s_addr);
case AF_INET6:
return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr);
default: /* fall through and signal error */
- printf("[COAP] address - sa_family is default value\n");
;
}
return 0;
}
#endif /* WITH_POSIX */
-/**
+/**
* Resets the given coap_address_t object @p addr to its default
* values. In particular, the member size must be initialized to the
* available size for storing addresses.
- *
+ *
* @param addr The coap_address_t object to initialize.
*/
static inline void coap_address_init(coap_address_t *addr)
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
-/**
+/**
* @file async.h
* @brief state management for asynchronous messages
*/
{
unsigned char flags; /**< holds the flags to control behaviour */
- /**
+ /**
* Holds the internal time when the object was registered with a
* resource. This field will be updated whenever
* coap_register_async() is called for a specific resource.
/** release application data on destruction */
#define COAP_ASYNC_RELEASE_DATA 0x08
-/**
+/**
* Allocates a new coap_async_state_t object and fills its fields
* according to the given @p request. The @p flags are used to control
* generation of empty ACK responses to stop retransmissions and to
* coap_async_t object or @c NULL on error. Note that this function will
* return @c NULL in case that an object with the same identifier is
* already registered.
- *
+ *
* @param context The context to use.
* @param peer The remote peer that is to be asynchronously notified.
* @param request The request that is handled asynchronously.
* @param data Opaque application data to register. Note that the
* storage occupied by @p data is released on destruction
* only if flag COAP_ASYNC_RELEASE_DATA is set.
- *
+ *
* @return A pointer to the registered coap_async_state_t object or
* @c NULL in case of an error.
*/
coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request,
unsigned char flags, void *data);
-/**
+/**
* Removes the state object identified by @p id from @p context. The
* removed object is returned in @p s, if found. Otherwise, @p s is
* undefined. This function returns @c 1 if the object was removed, @c
* 0 otherwise. Note that the storage allocated for the stored object
* is not released by this functions. You will have to call
* coap_free_async() to do so.
- *
+ *
* @param context The context where the async object is registered.
* @param id The identifier of the asynchronous transaction.
- * @param s Will be set to the object identified by @p id
+ * @param s Will be set to the object identified by @p id
* after removal.
- *
+ *
* @return @c 1 if object was removed and @p s updated, or @c 0 if no
* object was found with the given id. @p s is valid only if the
* return value is @c 1.
*/
int coap_remove_async(coap_context_t *context, coap_tid_t id, coap_async_state_t **s);
-/**
+/**
* Releases the memory that was allocated by coap_async_state_init()
* for the object @p s. The registered application data will be
* released automatically if COAP_ASYNC_RELEASE_DATA is set.
- *
+ *
* @param s The object to delete.
*/
void
coap_free_async(coap_async_state_t *state);
-/**
+/**
* Retrieves the object identified by @p id from the list of asynchronous
* transactions that are registered with @p context. This function returns
* a pointer to that object or @c NULL if not found.
- *
- * @param context The context where the asynchronous objects are
+ *
+ * @param context The context where the asynchronous objects are
* registered with.
* @param id The id of the object to retrieve.
- *
+ *
* @return A pointer to the object identified by @p id or @c NULL if
* not found.
*/
coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id);
-/**
+/**
* Updates the time stamp of @p s.
- *
+ *
* @param s The state object to update.
*/
static inline void coap_touch_async(coap_async_state_t *s)
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
/**
#include <sys/types.h>
#include <stdint.h>
-/**
+/**
* Sets the bit @p bit in bit-vector @p vec. This function returns @c
* 1 if bit was set or @c -1 on error (i.e. when the given bit does
* not fit in the vector).
- *
+ *
* @param vec The bit-vector to change.
* @param size The size of @p vec in bytes.
* @param bit The bit to set in @p vec.
- *
+ *
* @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
*/
inline static int bits_setb(uint8_t *vec, size_t size, uint8_t bit)
return 1;
}
-/**
+/**
* Clears the bit @p bit from bit-vector @p vec. This function returns
* @c 1 if bit was cleared or @c -1 on error (i.e. when the given bit
* does not fit in the vector).
- *
+ *
* @param vec The bit-vector to change.
* @param size The size of @p vec in bytes.
* @param bit The bit to clear from @p vec.
- *
+ *
* @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
*/
inline static int bits_clrb(uint8_t *vec, size_t size, uint8_t bit)
return 1;
}
-/**
+/**
* Gets the status of bit @p bit from bit-vector @p vec. This function returns
* @c 1 if the bit is set, @c 0 otherwise (even in case of an error)..
- *
+ *
* @param vec The bit-vector to read from..
* @param size The size of @p vec in bytes.
* @param bit The bit to get from @p vec.
- *
+ *
* @return @c 1 if the bit is set, @c 0 otherwise.
*/
inline static int bits_getb(const uint8_t *vec, size_t size, uint8_t bit)
* Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
* Copyright (C) 2010--2012,2014 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_BLOCK_H_
#endif
/**
- * Structure of Block options.
+ * Structure of Block options.
*/
typedef struct
{
} coap_block_t;
/**
- * Returns the value of the least significant byte of a Block option @p opt.
+ * Returns the value of the least significant byte of a Block option @p opt.
* For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST
* returns @c NULL.
*/
* value @c 1. Otherwise, @c 0 is returned.
*
* @param pdu The pdu to search for option @p type.
- * @param type The option to search for (must be COAP_OPTION_BLOCK1 or
+ * @param type The option to search for (must be COAP_OPTION_BLOCK1 or
* COAP_OPTION_BLOCK2)
* @param block The block structure to initilize.
* @return @c 1 on success, @c 0 otherwise.
* space is required. The actual length of the resource is specified
* in @p data_length.
*
- * This function may change *block to reflect the values written to
+ * This function may change *block to reflect the values written to
* @p pdu. As the function takes into consideration the remaining space
- * @p pdu, no more options should be added after coap_write_block_opt()
+ * @p pdu, no more options should be added after coap_write_block_opt()
* has returned.
*
* @param block The block structure to use. On return, this object
int coap_write_block_opt(coap_block_t *block, unsigned short type, coap_pdu_t *pdu,
size_t data_length);
-/**
+/**
* Adds the @p block_num block of size 1 << (@p block_szx + 4) from
* source @p data to @p pdu.
*
#endif
#endif /* _COAP_H_ */
+
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_LIST_H_
* Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
-/**
+/**
* @file coap_time.h
* @brief Clock Handling
*/
clock_offset = time(NULL);
#else
# ifdef __GNUC__
- /* Issue a warning when using gcc. Other prepropressors do
+ /* Issue a warning when using gcc. Other prepropressors do
* not seem to have a similar feature. */
# warning "cannot initialize clock"
# endif
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
examples/Makefile
tests/Makefile])
AC_OUTPUT
+
* Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
#ifndef NDEBUG
#ifndef HAVE_STRNLEN
-/**
- * A length-safe strlen() fake.
- *
+/**
+ * A length-safe strlen() fake.
+ *
* @param s The string to count characters != 0.
* @param maxlen The maximum length of @p s.
- *
+ *
* @return The length of @p s.
*/
static inline size_t
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_DEBUG_H_
/** Sets the log level to the specified value. */
void coap_set_log_level(coap_log_t level);
-/**
+/**
* Writes the given text to @c COAP_ERR_FD (for @p level <= @c
* LOG_CRIT) or @c COAP_DEBUG_FD (for @p level >= @c LOG_WARNING). The
* text is output only when @p level is below or equal to the log
void coap_show_pdu(const coap_pdu_t *);
struct coap_address_t;
+unsigned int print_readable(const unsigned char *data, unsigned int len, unsigned char *result,
+ unsigned int buflen, int encode_always);
size_t coap_print_addr(const struct coap_address_t *, unsigned char *, size_t);
#else
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef NDEBUG
* Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_ENCODE_H_
dist: $(FILES)
test -d $(DISTDIR)/examples || mkdir $(DISTDIR)/examples
cp $(FILES) $(DISTDIR)/examples
+
dist: $(FILES)
test -d $(DISTDIR)/examples || mkdir $(DISTDIR)/examples
cp $(FILES) $(DISTDIR)/examples
+
* Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
return coap_option_next(opt_iter);
}
-#define HANDLE_BLOCK1(Pdu) \
- ((method == COAP_REQUEST_PUT || method == COAP_REQUEST_POST) && \
- ((flags & FLAGS_BLOCK) == 0) && \
- ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \
+#define HANDLE_BLOCK1(Pdu) \
+ ((method == COAP_REQUEST_PUT || method == COAP_REQUEST_POST) && \
+ ((flags & FLAGS_BLOCK) == 0) && \
+ ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \
(Pdu)->hdr->code == COAP_RESPONSE_CODE(204)))
inline int check_token(coap_pdu_t *received)
return 1;
}
-/* Called after processing the options from the commandline to set
+/* Called after processing the options from the commandline to set
* Block1 or Block2 depending on method. */
void set_blocksize()
{
#define COAP_OPT_BLOCK_SZX_MAX 6 /**< allowed maximum for block szx value */
-#define REQUIRE_ETAG 0x01 /* flag for coap_payload_t: require ETag option */
+#define REQUIRE_ETAG 0x01 /* flag for coap_payload_t: require ETag option */
typedef struct
{
UT_hash_handle hh;
}
#define INDEX "libcoap server for ETSI CoAP Plugtest, March 2012, Paris\n" \
- "Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>\n\n"
+ "Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>\n\n"
coap_payload_t *
coap_new_payload(size_t size)
* Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
/**
* Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <string.h>
}
#define INDEX "This is a test server made with libcoap (see http://libcoap.sf.net)\n" \
- "Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>\n\n"
+ "Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>\n\n"
void hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer,
coap_pdu_t *request, str *token, coap_pdu_t *response)
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <string.h>
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "hashkey.h"
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
-/**
+/**
* @file hashkey.h
* @brief definition of hash key type and helper functions
*/
typedef unsigned char coap_key_t[4];
#ifndef coap_hash
-/**
+/**
* Calculates a fast hash over the given string @p s of length @p len
* and stores the result into @p h. Depending on the exact
* implementation, this function cannot be used as one-way function to
* check message integrity or simlar.
- *
+ *
* @param s The string used for hash calculation.
* @param len The length of @p s.
* @param h The result buffer to store the calculated hash key.
#undef __COAP_DEFAULT_HASH
#endif /* coap_hash */
-/**
+/**
* Calls coap_hash() with given @c str object as parameter.
- *
+ *
* @param Str Must contain a pointer to a coap string object.
* @param H A coap_key_t object to store the result.
- *
+ *
* @hideinitializer
*/
-#define coap_str_hash(Str,H) { \
- assert(Str); \
- memset((H), 0, sizeof(coap_key_t)); \
- coap_hash((H), (Str)->s, (Str)->length); \
+#define coap_str_hash(Str,H) { \
+ assert(Str); \
+ memset((H), 0, sizeof(coap_key_t)); \
+ coap_hash((H), (Str)->s, (Str)->length); \
}
#endif /* _COAP_HASHKEY_H_ */
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_MEM_H_
* Copyright (C) 2010--2014 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
context->pending_address.addr = addr->addr; /* FIXME: this has to become address-type independent, probably there'll be an lwip function for that */
context->pending_port = port;
- char* data;
- coap_read(context, data);
+ coap_read(context);
}
#endif /* WITH_LWIP */
#ifdef COAP_DEFAULT_WKC_HASHKEY
/** Checks if @p Key is equal to the pre-defined hash key for.well-known/core. */
-#define is_wkc(Key) \
+#define is_wkc(Key) \
(memcmp((Key), COAP_DEFAULT_WKC_HASHKEY, sizeof(coap_key_t)) == 0)
#else
/* Implements a singleton to store a hash key for the .wellknown/core
const coap_address_t *dst,
coap_pdu_t *pdu)
{
-
- char* z = inet_ntoa(*(struct in_addr *)&(dst->addr));
-
ssize_t bytes_written;
coap_tid_t id = COAP_INVALID_TID;
return 0;
}
-int coap_read(coap_context_t *ctx, char* data)
+int coap_read(coap_context_t *ctx)
{
#ifdef WITH_POSIX
static char buf[COAP_MAX_PDU_SIZE];
void coap_cancel_all_messages(coap_context_t *context, const coap_address_t *dst,
const unsigned char *token, size_t token_length)
{
- /* cancel all messages in sendqueue that are for dst
+ /* cancel all messages in sendqueue that are for dst
* and use the specified token */
coap_queue_t *p, *q;
need_block2 = 1;
}
- /* Check if there is sufficient space to add Content-Format option
+ /* Check if there is sufficient space to add Content-Format option
* and data. We do this before adding the Content-Format option to
* avoid sending error responses with that option but no actual
* content. */
return resp;
}
-#define WANT_WKC(Pdu,Key) \
+#define WANT_WKC(Pdu,Key) \
(((Pdu)->hdr->code == COAP_REQUEST_GET) && is_wkc(Key))
void handle_request(coap_context_t *context, coap_queue_t *node, const char* responseData)
str token =
{ node->pdu->hdr->token_length, node->pdu->hdr->token };
- //h(context, resource, &node->remote,
- //node->pdu, &token, response);
+ h(context, resource, &node->remote, node->pdu, &token, response);
unsigned char buf[3];
response->hdr->code = COAP_RESPONSE_CODE(205);
str token =
{ 0, NULL };
- /* remove observer for this resource, if any
+ /* remove observer for this resource, if any
* get token from sent and try to find a matching resource. Uh!
*/
}
}
#endif /* WITH_CONTIKI */
-#endif /* WITOUT_OBSERVE */
+#endif /* WITOUT_OBSERVE */
}
void coap_dispatch(coap_context_t *context, const char* responseData)
if (rcvd->pdu->hdr->code == 0)
goto cleanup;
- /* FIXME: if sent code was >= 64 the message might have been a
+ /* FIXME: if sent code was >= 64 the message might have been a
* notification. Then, we must flag the observer to be alive
* by setting obs->fail_cnt = 0. */
if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->code) == 2)
if (coap_option_check_critical(context, rcvd->pdu, opt_filter) == 0)
{
- /* FIXME: send response only if we have received a request. Otherwise,
+ /* FIXME: send response only if we have received a request. Otherwise,
* send RST. */
response = coap_new_error_response(rcvd->pdu, COAP_RESPONSE_CODE(402),
opt_filter);
* Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_NET_H_
/**
* Registers a new message handler that is called whenever a response
- * was received that matches an ongoing transaction.
- *
+ * was received that matches an ongoing transaction.
+ *
* @param context The context to register the handler for.
* @param handler The response handler to register.
*/
context->response_handler = handler;
}
- /**
+ /**
* Registers the option type @p type with the given context object @p
* ctx.
- *
+ *
* @param ctx The context to use.
* @param type The option type to register.
*/
/** Creates a new coap_context_t object that will hold the CoAP stack status. */
coap_context_t *coap_new_context(const coap_address_t *listen_addr);
- /**
+ /**
* Returns a new message id and updates @p context->message_id
* accordingly. The message id is returned in network byte order
- * to make it easier to read in tracing tools.
+ * to make it easier to read in tracing tools.
*
* @param context the current coap_context_t object
* @return incremented message id in network byte order
coap_tid_t coap_send_confirmed(coap_context_t *context, const coap_address_t *dst,
coap_pdu_t *pdu);
- /**
+ /**
* Creates a new ACK PDU with specified error @p code. The options
* specified by the filter expression @p opts will be copied from the
* original request contained in @p request. Unless @c
* 0. This function returns a pointer to the new response message, or
* @c NULL on error. The storage allocated for the new message must be
* relased with coap_free().
- *
+ *
* @param request Specification of the received (confirmable) request.
* @param code The error code to set.
* @param opts An option filter that specifies which options to copy
* from the original request in @p node.
- *
+ *
* @return A pointer to the new message or @c NULL on error.
*/
coap_pdu_t *coap_new_error_response(coap_pdu_t *request, unsigned char code,
*/
coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu);
- /**
+ /**
* Sends an error response with code @p code for request @p request to
* @p dst. @p opts will be passed to coap_new_error_response() to
* copy marked options from the request. This function returns the
* transaction id if the message was sent, or @c COAP_INVALID_TID
* otherwise.
- *
+ *
* @param context The context to use.
* @param request The original request to respond to.
* @param dst The remote peer that sent the request.
* @param code The reponse code.
- * @param opts A filter that specifies the options to copy from the
+ * @param opts A filter that specifies the options to copy from the
* @p request.
- *
+ *
* @return The transaction id if the message was sent, or @c
* COAP_INVALID_TID otherwise.
*/
coap_tid_t coap_send_error(coap_context_t *context, coap_pdu_t *request,
const coap_address_t *dst, unsigned char code, coap_opt_filter_t opts);
- /**
+ /**
* Helper funktion to create and send a message with @p type (usually
* ACK or RST). This function returns @c COAP_INVALID_TID when the
* message was not sent, a valid transaction id otherwise.
coap_tid_t
coap_send_message_type(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *request,
unsigned char type);
- /**
+ /**
* Sends an ACK message with code @c 0 for the specified @p request to
* @p dst. This function returns the corresponding transaction id if
* the message was sent or @c COAP_INVALID_TID on error.
- *
+ *
* @param context The context to use.
* @param dst The destination address.
* @param request The request to be acknowledged.
- *
+ *
* @return The transaction id if ACK was sent or @c COAP_INVALID_TID
* on error.
*/
coap_tid_t coap_send_ack(coap_context_t *context, const coap_address_t *dst,
coap_pdu_t *request);
- /**
+ /**
* Sends an RST message with code @c 0 for the specified @p request to
* @p dst. This function returns the corresponding transaction id if
* the message was sent or @c COAP_INVALID_TID on error.
- *
+ *
* @param context The context to use.
* @param dst The destination address.
* @param request The request to be reset.
- *
+ *
* @return The transaction id if RST was sent or @c COAP_INVALID_TID
* on error.
*/
* and a new node with the parsed PDU is added to the receive queue in the specified context
* object.
*/
- int coap_read(coap_context_t *context, char* data);
+ int coap_read(coap_context_t *context);
- /**
+ /**
* Calculates a unique transaction id from given arguments @p peer and
* @p pdu. The id is returned in @p id.
*
*/
void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, coap_tid_t *id);
- /**
+ /**
* This function removes the element with given @p id from the list
* given list. If @p id was found, @p node is updated to point to the
- * removed element. Note that the storage allocated by @p node is
+ * removed element. Note that the storage allocated by @p node is
* @b not released. The caller must do this manually using
* coap_delete_node(). This function returns @c 1 if the element with
* id @p id was found, @c 0 otherwise. For a return value of @c 0,
* the contents of @p node is undefined.
- *
+ *
* @param queue The queue to search for @p id.
* @param id The node id to look for.
- * @param node If found, @p node is updated to point to the
+ * @param node If found, @p node is updated to point to the
* removed node. You must release the storage pointed to by
* @p node manually.
- *
+ *
* @return @c 1 if @p id was found, @c 0 otherwise.
*/
int coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id, coap_queue_t **node);
- /**
+ /**
* Removes the transaction identified by @p id from given @p queue.
* This is a convenience function for coap_remove_from_queue() with
* automatic deletion of the removed node.
- *
+ *
* @param queue The queue to search for @p id.
* @param id The transaction id.
- *
+ *
* @return @c 1 if node was found, removed and destroyed, @c 0 otherwise.
*/
inline static int coap_remove_transaction(coap_queue_t **queue, coap_tid_t id)
coap_queue_t *coap_find_transaction(coap_queue_t *queue, coap_tid_t id);
/**
- * Cancels all outstanding messages for peer @p dst that have the
+ * Cancels all outstanding messages for peer @p dst that have the
* specified token.
*
* @param context The context in use
* @param dst Destination address of the messages to remove.
* @param token Message token
- * @param token_length Actual length of @p token
+ * @param token_length Actual length of @p token
*/
void coap_cancel_all_messages(coap_context_t *context, const coap_address_t *dst,
const unsigned char *token, size_t token_length);
/**
* Returns the current value of an internal tick counter. The counter
- * counts \c COAP_TICKS_PER_SECOND ticks every second.
+ * counts \c COAP_TICKS_PER_SECOND ticks every second.
*/
void coap_ticks(coap_tick_t *);
- /**
+ /**
* Verifies that @p pdu contains no unknown critical options. Options
* must be registered at @p ctx, using the function
* coap_register_option(). A basic set of options is registered
* @p pdu is ok, @c 0 otherwise. The given filter object @p unknown
* will be updated with the unknown options. As only @c COAP_MAX_OPT
* options can be signalled this way, remaining options must be
- * examined manually.
+ * examined manually.
*
* @code
coap_opt_filter_t f = COAP_OPT_NONE;
}
}
}
- * @endcode
+ * @endcode
*
* @param ctx The context where all known options are registered.
* @param pdu The PDU to check.
* @param unknown The output filter that will be updated to indicate the
* unknown critical options found in @p pdu.
- *
+ *
* @return @c 1 if everything was ok, @c 0 otherwise.
*/
int coap_option_check_critical(coap_context_t *ctx, coap_pdu_t *pdu, coap_opt_filter_t unknown);
* Copyright (C) 2010-2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
assert(opt);
assert(result);
-#define ADVANCE_OPT(o,e,step) if ((e) < step) { \
- debug("cannot advance opt past end\n"); \
- return 0; \
- } else { \
- (e) -= step; \
- (o) = ((unsigned char *)(o)) + step; \
+#define ADVANCE_OPT(o,e,step) if ((e) < step) { \
+ debug("cannot advance opt past end\n"); \
+ return 0; \
+ } else { \
+ (e) -= step; \
+ (o) = ((unsigned char *)(o)) + step; \
}
if (length < 1)
/* Exit the while loop when:
* - no filtering is done at all
* - the filter matches for the current option
- * - the filter is too small for the current option number
+ * - the filter is too small for the current option number
*/
if (!oi->filtered || (b = coap_option_getb(oi->filter, oi->type)) > 0)
break;
* Copyright (C) 2010-2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
/**
#include "bits.h"
#include "pdu.h"
-/**
+/**
* Use byte-oriented access methods here because sliding a complex
* struct coap_opt_t over the data buffer may cause bus error on
* certain platforms.
* function returns the number of bytes that have been parsed, or @c 0
* on error. An error is signaled when illegal delta or length values
* are encountered or when option parsing would result in reading past
- * the option (i.e. beyond opt + length).
+ * the option (i.e. beyond opt + length).
*
* @param opt The beginning of the option to parse.
* @param length The maximum length of @p opt.
/**
* Calculates the beginning of the PDU's option section.
- *
+ *
* @param pdu The PDU containing the options.
* @return A pointer to the first option if available, or @c NULL otherwise.
*/
* @{
*/
-/**
+/**
* Fixed-size bit-vector we use for option filtering. It is large
* enough to hold the highest option number known at build time (20 in
* the core spec).
/** Pre-defined filter that includes all options. */
#define COAP_OPT_ALL NULL
-/**
+/**
* Clears filter @p f.
- *
+ *
* @param f The filter to clear.
*/
static inline void coap_option_filter_clear(coap_opt_filter_t f)
memset(f, 0, sizeof(coap_opt_filter_t));
}
-/**
+/**
* Sets the corresponding bit for @p type in @p filter. This function
* returns @c 1 if bit was set or @c -1 on error (i.e. when the given
* type does not fit in the filter).
- *
+ *
* @param filter The filter object to change.
- * @param type The type for which the bit should be set.
- *
+ * @param type The type for which the bit should be set.
+ *
* @return @c 1 if bit was set, @c -1 otherwise.
*/
inline static int coap_option_setb(coap_opt_filter_t filter, unsigned short type)
return bits_setb((uint8_t *) filter, sizeof(coap_opt_filter_t), type);
}
-/**
+/**
* Clears the corresponding bit for @p type in @p filter. This function
* returns @c 1 if bit was cleared or @c -1 on error (i.e. when the given
* type does not fit in the filter).
- *
+ *
* @param filter The filter object to change.
- * @param type The type for which the bit should be cleared.
- *
+ * @param type The type for which the bit should be cleared.
+ *
* @return @c 1 if bit was set, @c -1 otherwise.
*/
inline static int coap_option_clrb(coap_opt_filter_t filter, unsigned short type)
return bits_clrb((uint8_t *) filter, sizeof(coap_opt_filter_t), type);
}
-/**
+/**
* Gets the corresponding bit for @p type in @p filter. This function
* returns @c 1 if the bit is set @c 0 if not, or @c -1 on error (i.e.
* when the given type does not fit in the filter).
- *
+ *
* @param filter The filter object to read bit from..
* @param type The type for which the bit should be read.
- *
+ *
* @return @c 1 if bit was set, @c 0 if not, @c -1 on error.
*/
inline static int coap_option_getb(const coap_opt_filter_t filter, unsigned short type)
return bits_getb((uint8_t *) filter, sizeof(coap_opt_filter_t), type);
}
-/**
+/**
* Iterator to run through PDU options. This object must be
* initialized with coap_option_iterator_init(). Call
* coap_option_next() to walk through the list of options until
coap_opt_filter_t filter; /**< option filter */
} coap_opt_iterator_t;
-/**
+/**
* Initializes the given option iterator @p oi to point to the
* beginning of the @p pdu's option list. This function returns @p oi
* on success, @c NULL otherwise (i.e. when no options exist).
* Note that a length check on the option list must be performed before
* coap_option_iterator_init() is called.
- *
+ *
* @param pdu The PDU the options of which should be walked through.
* @param oi An iterator object that will be initilized.
- * @param filter An optional option type filter.
- * With @p type != @c COAP_OPT_ALL, coap_option_next()
- * will return only options matching this bitmask.
+ * @param filter An optional option type filter.
+ * With @p type != @c COAP_OPT_ALL, coap_option_next()
+ * will return only options matching this bitmask.
* Fence-post options @c 14, @c 28, @c 42, ... are always
* skipped.
- *
+ *
* @return The iterator object @p oi on success, @c NULL otherwise.
*/
coap_opt_iterator_t *coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi,
const coap_opt_filter_t filter);
-/**
+/**
* Updates the iterator @p oi to point to the next option. This
* function returns a pointer to that option or @c NULL if no more
* options exist. The contents of @p oi will be updated. In
* oi->option points to the beginning of the current option
* itself. When advanced past the last option, @c oi->option will be
* @c NULL.
- *
+ *
* Note that options are skipped whose corresponding bits in the
* filter specified with coap_option_iterator_init() are @c 0. Options
* with type codes that do not fit in this filter hence will always be
* returned.
- *
+ *
* @param oi The option iterator to update.
- *
+ *
* @return The next option or @c NULL if no more options exist.
*/
coap_opt_t *coap_option_next(coap_opt_iterator_t *oi);
-/**
+/**
* Retrieves the first option of type @p type from @p pdu. @p oi must
* point to a coap_opt_iterator_t object that will be initialized by
* this function to filter only options with code @p type. This
* function returns the first option with this type, or @c NULL if not
* found.
- *
+ *
* @param pdu The PDU to parse for options.
* @param type The option type code to search for.
* @param oi An iterator object to use.
- *
- * @return A pointer to the first option of type @p type, or @c NULL
+ *
+ * @return A pointer to the first option of type @p type, or @c NULL
* if not found.
*/
coap_opt_t *coap_check_option(coap_pdu_t *pdu, unsigned char type, coap_opt_iterator_t *oi);
#define COAP_OPT_DELTA(opt) coap_opt_delta(opt)
/** @deprecated { Use coap_opt_encode() instead. } */
-#define COAP_OPT_SETDELTA(opt,val) \
+#define COAP_OPT_SETDELTA(opt,val) \
coap_opt_encode((opt), COAP_MAX_PDU_SIZE, (val), NULL, 0)
/**
/**
* Returns a pointer to the value of the given option. @p opt must
- * point to an option jump or the beginning of the option. This
+ * point to an option jump or the beginning of the option. This
* function returns @c NULL if @p opt is not a valid option.
*
* @param opt The option whose value should be returned.
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
char *phrase;
} error_desc_t;
-/* if you change anything here, make sure, that the longest string does not
+/* if you change anything here, make sure, that the longest string does not
* exceed COAP_ERROR_PHRASE_LENGTH. */
error_desc_t coap_error[] =
{
#endif
/**
- * Advances *optp to next option if still in PDU. This function
+ * Advances *optp to next option if still in PDU. This function
* returns the number of bytes opt has been advanced or @c 0
* on error.
*/
{
coap_opt_t *opt;
- char optionResult[256] =
- { 0, };
-
assert(data);
assert(pdu);
* Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _PDU_H_
#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF)
#ifndef SHORT_ERROR_RESPONSE
-/**
+/**
* Returns a human-readable response phrase for the specified CoAP
* response @p code. This function returns @c NULL if not found.
- *
+ *
* @param code The response code for which the literal phrase should
* be retrieved.
- *
+ *
* @return A zero-terminated string describing the error, or @c NULL
* if not found.
*/
#endif
#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0)
-#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \
- && ((MSG)->code < 32))
+#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \
+ && ((MSG)->code < 32))
#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64 && (MSG)->code <= 191)
-#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list in a
- * CoAP message is limited by 0b11110000 marker */
+#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list in a
+ * CoAP message is limited by 0b11110000 marker */
-#define COAP_OPT_END 0xF0 /* end marker */
+#define COAP_OPT_END 0xF0 /* end marker */
-#define COAP_PAYLOAD_START 0xFF /* payload marker */
+#define COAP_PAYLOAD_START 0xFF /* payload marker */
/**
* Structures for more convenient handling of options. (To be used with ordered
coap_pdu_t * coap_pdu_from_pbuf(struct pbuf *pbuf);
#endif
-/**
- * Creates a new CoAP PDU of given @p size (must be large enough to hold the
+/**
+ * Creates a new CoAP PDU of given @p size (must be large enough to hold the
* basic CoAP message header (coap_hdr_t). The function returns a pointer to
* the node coap_pdu_t object on success, or @c NULL on error. The storage
* allocated for the result must be released with coap_delete_pdu().
- *
+ *
* @param type The type of the PDU (one of COAP_MESSAGE_CON,
- * COAP_MESSAGE_NON, COAP_MESSAGE_ACK, COAP_MESSAGE_RST).
+ * COAP_MESSAGE_NON, COAP_MESSAGE_ACK, COAP_MESSAGE_RST).
* @param code The message code.
* @param id The message id to set or COAP_INVALID_TID if unknown.
* @param size The number of bytes to allocate for the actual message.
- *
+ *
* @return A pointer to the new PDU object or @c NULL on error.
*/
coap_pdu_t *
coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size);
-/**
+/**
* Clears any contents from @p pdu and resets @c version field, @c
* length and @c data pointers. @c max_size is set to @p size, any
* other field is set to @c 0. Note that @p pdu must be a valid
/**
* Creates a new CoAP PDU. The object is created on the heap and must be released
* using coap_delete_pdu();
- *
+ *
* @deprecated This function allocates the maximum storage for each
- * PDU. Use coap_pdu_init() instead.
+ * PDU. Use coap_pdu_init() instead.
*/
coap_pdu_t *coap_new_pdu();
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
-/**
+/**
* @file prng.h
* @brief Pseudo Random Numbers
*/
#include "config.h"
-/**
+/**
* @defgroup prng Pseudo Random Numbers
* @{
*/
#endif /* WITH_CONTIKI */
#ifndef prng
-/**
- * Fills \p Buf with \p Length bytes of random data.
- *
+/**
+ * Fills \p Buf with \p Length bytes of random data.
+ *
* @hideinitializer
*/
#define prng(Buf,Length) coap_prng_impl((Buf), (Length))
#endif
#ifndef prng_init
-/**
+/**
* Called to set the PRNG seed. You may want to re-define this to
* allow for a better PRNG.
*
* Copyright (C) 2010--2014 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
* Adds Char to Buf if Offset is zero. Otherwise, Char is not written
* and Offset is decremented.
*/
-#define PRINT_WITH_OFFSET(Buf,Offset,Char) \
- if ((Offset) == 0) { \
- (*(Buf)++) = (Char); \
- } else { \
- (Offset)--; \
- } \
+#define PRINT_WITH_OFFSET(Buf,Offset,Char) \
+ if ((Offset) == 0) { \
+ (*(Buf)++) = (Char); \
+ } else { \
+ (Offset)--; \
+ } \
/**
* Adds Char to Buf if Offset is zero and Buf is less than Bufend.
*/
-#define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \
- if ((Buf) < (Bufend)) { \
- PRINT_WITH_OFFSET(Buf,Offset,Char); \
- } \
- (Result)++; \
+#define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \
+ if ((Buf) < (Bufend)) { \
+ PRINT_WITH_OFFSET(Buf,Offset,Char); \
+ } \
+ (Result)++; \
}
/**
* characters are skipped. Output may be truncated to Bufend - Buf
* characters.
*/
-#define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \
- size_t i; \
- for (i = 0; i < (Length); i++) { \
+#define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \
+ size_t i; \
+ for (i = 0; i < (Length); i++) { \
PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \
- } \
+ } \
}
int match(const str *text, const str *pattern, int match_prefix, int match_substring)
&& memcmp(text->s, pattern->s, pattern->length) == 0;
}
-/**
+/**
* Prints the names of all known resources to @p buf. This function
* sets @p buflen to the number of bytes actually written and returns
* @c 1 on succes. On error, the value in @p buflen is undefined and
* the return value will be @c 0.
- *
+ *
* @param context The context with the resource map.
* @param buf The buffer to write the result.
* @param buflen Must be initialized to the maximum length of @p buf and will be
* set to the length of the well-known response on return.
* @param offset The offset in bytes where the output shall start and is
* shifted accordingly with the characters that have been
- * processed. This parameter is used to support the block
- * option.
+ * processed. This parameter is used to support the block
+ * option.
* @param query_filter A filter query according to <a href="http://tools.ietf.org/html/draft-ietf-core-link-format-11#section-4.1">Link Format</a>
- *
+ *
* @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are
* set to the number of bytes that have actually been written to
* @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been
for (attr = list_head(resource->link_attr); attr;
attr = list_item_next(attr))
{
-#endif /* WITH_CONTIKI */
+#endif /* WITH_CONTIKI */
if (attr->name.length == nlen && memcmp(attr->name.s, name, nlen) == 0)
return attr;
}
* Copyright (C) 2010,2011,2014 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
-/**
+/**
* @file resource.h
* @brief generic resource handling
*/
unsigned int observable :1; /**< can be observed */
unsigned int cacheable :1; /**< can be cached */
- /**
+ /**
* Used to store handlers for the four coap methods @c GET, @c POST,
* @c PUT, and @c DELETE. coap_dispatch() will pass incoming
* requests to the handler that corresponds to its request method or
} coap_resource_t;
-/**
+/**
* Creates a new resource object and initializes the link field to the
* string of length @p len. This function returns the
* new coap_resource_t object.
- *
+ *
* @param uri The URI path of the new resource.
* @param len The length of @p uri.
* @param flags Flags for memory management (in particular release of memory)
- *
+ *
* @return A pointer to the new object or @c NULL on error.
*/
coap_resource_t *coap_resource_init(const unsigned char *uri, size_t len, int flags);
* Registers the given @p resource for @p context. The resource must
* have been created by coap_resource_init(), the storage allocated
* for the resource will be released by coap_delete_resource().
- *
+ *
* @param context The context to use.
* @param resource The resource to store.
*/
void coap_add_resource(coap_context_t *context, coap_resource_t *resource);
-/**
+/**
* Deletes a resource identified by @p key. The storage allocated for
* that resource is freed.
- *
+ *
* @param context The context where the resources are stored.
* @param key The unique key for the resource to delete.
- *
+ *
* @return @c 1 if the resource was found (and destroyed), @c 0 otherwise.
*/
int coap_delete_resource(coap_context_t *context, coap_key_t key);
-/**
+/**
* Registers a new attribute with the given @p resource. As the
- * attributes str fields will point to @p name and @p val the
+ * attributes str fields will point to @p name and @p val the
* caller must ensure that these pointers are valid during the
* attribute's lifetime.
- *
+ *
* @param resource The resource to register the attribute with.
* @param name The attribute's name.
* @param nlen Length of @p name.
*/
coap_attr_t *coap_find_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen);
-/**
+/**
* Deletes an attribute
- *
+ *
* @param attr Pointer to a previously created attribute
- *
+ *
*/
void coap_delete_attr(coap_attr_t *attr);
#define COAP_PRINT_STATUS_ERROR 0x80000000u
#define COAP_PRINT_STATUS_TRUNC 0x40000000u
-/**
+/**
* Writes a description of this resource in link-format to given text
* buffer. @p len must be initialized to the maximum length of @p buf
* and will be set to the number of characters actually written if
* successful. This function returns @c 1 on success or @c 0 on
* error.
- *
+ *
* @param resource The resource to describe.
* @param buf The output buffer to write the description to.
- * @param len Must be initialized to the length of @p buf and
+ * @param len Must be initialized to the length of @p buf and
* will be set to the length of the printed link description.
* @param offset The offset within the resource description where to
* start writing into @p buf. This is useful for dealing
* with the Block2 option. @p offset is updated during
* output as it is consumed.
- *
+ *
* @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise,
* the lower 28 bits will indicate the number of characters that
* have actually been output into @p buffer. The flag
coap_print_status_t coap_print_link(const coap_resource_t *resource, unsigned char *buf,
size_t *len, size_t *offset);
-/**
+/**
* Registers the specified @p handler as message handler for the request type
* @p method
- *
+ *
* @param resource The resource for which the handler shall be registered.
- * @param method The CoAP request method to handle.
+ * @param method The CoAP request method to handle.
* @param handler The handler to register with @p resource.
*/
static inline void coap_register_handler(coap_resource_t *resource, unsigned char method,
resource->handler[method - 1] = handler;
}
-/**
+/**
* Returns the resource identified by the unique string @p key. If no
* resource was found, this function returns @c NULL.
- *
+ *
* @param context The context to look for this resource.
* @param key The unique key of the resource.
- *
+ *
* @return A pointer to the resource or @c NULL if not found.
*/
coap_resource_t *coap_get_resource_from_key(coap_context_t *context, coap_key_t key);
-/**
+/**
* Calculates the hash key for the resource requested by the
* Uri-Options of @p request. This function calls coap_hash() for
* every path segment.
- *
+ *
* @param request The requesting pdu.
* @param key The resulting hash is stored in @p key
*/
void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key);
-/**
+/**
* @addtogroup observe
*/
* @param token The token that identifies this subscription.
* @param token_length The actual length of @p token. Must be @c 0 when
* @p token is @c NULL.
- * @return A pointer to the added/updated subscription information or
+ * @return A pointer to the added/updated subscription information or
* @c NULL on error.
*/
coap_subscription_t *coap_add_observer(coap_resource_t *resource, const coap_address_t *observer,
*
* @param context The CoAP context to use
* @param observer The transport address of the observer
- * @param token The corresponding token that has been used for
+ * @param token The corresponding token that has been used for
* the subscription
*/
void coap_touch_observer(coap_context_t *context, const coap_address_t *observer, const str *token);
void coap_delete_observer(coap_resource_t *resource, const coap_address_t *observer,
const str *token);
-/**
+/**
* Checks for all known resources, if they are dirty and notifies
* subscribed observers.
*/
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_STR_H_
* Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
* Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_SUBSCRIBE_H_
#include "config.h"
#include "address.h"
-/**
+/**
* @defgroup observe Resource observation
* @{
*/
#define LIST_CONCAT(s1, s2) s1##s2
-#define LIST_STRUCT(name) \
- void *LIST_CONCAT(name, _list); \
+#define LIST_STRUCT(name) \
+ void *LIST_CONCAT(name, _list); \
list_t name
-#define LIST_STRUCT_INIT(struct_ptr, name) { \
- (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \
- (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \
+#define LIST_STRUCT_INIT(struct_ptr, name) { \
+ (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \
+ (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \
}
static inline void *
dist: $(FILES)
test -d $(DISTDIR)/tests || mkdir $(DISTDIR)/tests
cp $(FILES) $(DISTDIR)/tests
+
dist: $(FILES)
test -d $(DISTDIR)/tests || mkdir $(DISTDIR)/tests
cp $(FILES) $(DISTDIR)/tests
+
* Copyright (C) 2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <assert.h>
return NULL;
}
-#define ERROR_RESPONSE_TEST(s,t) \
- if (!CU_ADD_TEST(s,t)) { \
+#define ERROR_RESPONSE_TEST(s,t) \
+ if (!CU_ADD_TEST(s,t)) { \
fprintf(stderr, "W: cannot add error response generator test (%s)\n", \
- CU_get_error_msg()); \
+ CU_get_error_msg()); \
}
ERROR_RESPONSE_TEST(suite[0], t_error_response1);
* Copyright (C) 2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <CUnit/CUnit.h>
* Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <stdio.h>
return NULL;
}
-#define OPTION_TEST(n,s) \
- if (!CU_add_test(suite[0], s, t_parse_option##n)) { \
- fprintf(stderr, "W: cannot add option parser test (%s)\n", \
- CU_get_error_msg()); \
+#define OPTION_TEST(n,s) \
+ if (!CU_add_test(suite[0], s, t_parse_option##n)) { \
+ fprintf(stderr, "W: cannot add option parser test (%s)\n", \
+ CU_get_error_msg()); \
}
OPTION_TEST(1, "parse option #1");
if ((suite[1] = CU_add_suite("option encoder", NULL, NULL)))
{
-#define OPTION_ENCODER_TEST(n,s) \
- if (!CU_add_test(suite[1], s, t_encode_option##n)) { \
+#define OPTION_ENCODER_TEST(n,s) \
+ if (!CU_add_test(suite[1], s, t_encode_option##n)) { \
fprintf(stderr, "W: cannot add option encoder test (%s)\n", \
- CU_get_error_msg()); \
+ CU_get_error_msg()); \
}
OPTION_ENCODER_TEST(1, "encode option #1");
if ((suite[2] = CU_add_suite("option accessors", NULL, NULL)))
{
-#define OPTION_ACCESSOR_TEST(n,s) \
- if (!CU_add_test(suite[2], s, t_access_option##n)) { \
+#define OPTION_ACCESSOR_TEST(n,s) \
+ if (!CU_add_test(suite[2], s, t_access_option##n)) { \
fprintf(stderr, "W: cannot add option accessor function test (%s)\n", \
- CU_get_error_msg()); \
+ CU_get_error_msg()); \
}
OPTION_ACCESSOR_TEST(1, "access option #1");
if ((suite[3] = CU_add_suite("option iterator", NULL, NULL)))
{
-#define OPTION_ITERATOR_TEST(n,s) \
- if (!CU_add_test(suite[3], s, t_iterate_option##n)) { \
+#define OPTION_ITERATOR_TEST(n,s) \
+ if (!CU_add_test(suite[3], s, t_iterate_option##n)) { \
fprintf(stderr, "W: cannot add option iterator test (%s)\n", \
- CU_get_error_msg()); \
+ CU_get_error_msg()); \
}
OPTION_ITERATOR_TEST(1, "option iterator #1");
* Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <CUnit/CUnit.h>
* Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <assert.h>
return NULL;
}
-#define PDU_TEST(s,t) \
- if (!CU_ADD_TEST(s,t)) { \
- fprintf(stderr, "W: cannot add pdu parser test (%s)\n", \
- CU_get_error_msg()); \
+#define PDU_TEST(s,t) \
+ if (!CU_ADD_TEST(s,t)) { \
+ fprintf(stderr, "W: cannot add pdu parser test (%s)\n", \
+ CU_get_error_msg()); \
}
PDU_TEST(suite[0], t_parse_pdu1);
suite[1] = CU_add_suite("pdu encoder", t_pdu_tests_create, t_pdu_tests_remove);
if (suite[1])
{
-#define PDU_ENCODER_TEST(s,t) \
- if (!CU_ADD_TEST(s,t)) { \
- fprintf(stderr, "W: cannot add pdu encoder test (%s)\n", \
- CU_get_error_msg()); \
+#define PDU_ENCODER_TEST(s,t) \
+ if (!CU_ADD_TEST(s,t)) { \
+ fprintf(stderr, "W: cannot add pdu encoder test (%s)\n", \
+ CU_get_error_msg()); \
}
PDU_ENCODER_TEST(suite[1], t_encode_pdu1);
PDU_ENCODER_TEST(suite[1], t_encode_pdu2);
* Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <CUnit/CUnit.h>
* Copyright (C) 2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <stdio.h>
/* This function creates a set of nodes for testing. These nodes
* will exist for all tests and are modified by coap_insert_node()
- * and
+ * and
*/
int t_sendqueue_tests_create(void)
{
return NULL;
}
-#define SENDQUEUE_TEST(s,t) \
- if (!CU_ADD_TEST(s,t)) { \
- fprintf(stderr, "W: cannot add sendqueue test (%s)\n", \
- CU_get_error_msg()); \
+#define SENDQUEUE_TEST(s,t) \
+ if (!CU_ADD_TEST(s,t)) { \
+ fprintf(stderr, "W: cannot add sendqueue test (%s)\n", \
+ CU_get_error_msg()); \
}
SENDQUEUE_TEST(suite, t_sendqueue1);
* Copyright (C) 2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <CUnit/CUnit.h>
* Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <stdio.h>
return NULL;
}
-#define URI_TEST(s,t) \
- if (!CU_ADD_TEST(s,t)) { \
- fprintf(stderr, "W: cannot add uri parser test (%s)\n", \
- CU_get_error_msg()); \
+#define URI_TEST(s,t) \
+ if (!CU_ADD_TEST(s,t)) { \
+ fprintf(stderr, "W: cannot add uri parser test (%s)\n", \
+ CU_get_error_msg()); \
}
URI_TEST(suite, t_parse_uri1);
* Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <CUnit/CUnit.h>
* Copyright (C) 2013--2014 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <assert.h>
}
}
-#endif
+#endif
return ctx == NULL || pdu == NULL;
}
return NULL;
}
-#define WKC_TEST(s,t) \
- if (!CU_ADD_TEST(s,t)) { \
- fprintf(stderr, "W: cannot add .well-known/core test (%s)\n", \
- CU_get_error_msg()); \
+#define WKC_TEST(s,t) \
+ if (!CU_ADD_TEST(s,t)) { \
+ fprintf(stderr, "W: cannot add .well-known/core test (%s)\n", \
+ CU_get_error_msg()); \
}
WKC_TEST(suite, t_wellknown1);
* Copyright (C) 2013 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include <CUnit/CUnit.h>
* Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#include "config.h"
#include "option.h"
#include "uri.h"
-/**
+/**
* A length-safe version of strchr(). This function returns a pointer
* to the first occurrence of @p c in @p s, or @c NULL if not found.
- *
+ *
* @param s The string to search for @p c.
* @param len The length of @p s.
* @param c The character to search.
- *
- * @return A pointer to the first occurence of @p c, or @c NULL
+ *
+ * @return A pointer to the first occurence of @p c, or @c NULL
* if not found.
*/
static inline unsigned char *
{ /* IPv4 address or FQDN */
while (len && *q != ':' && *q != '/' && *q != '?')
{
- // *q = tolower(*q);
+ *q = tolower(*q);
++q;
--len;
error: return res;
}
-/**
+/**
* Calculates decimal value from hexadecimal ASCII character given in
* @p c. The caller must ensure that @p c actually represents a valid
- * heaxdecimal character, e.g. with isxdigit(3).
+ * heaxdecimal character, e.g. with isxdigit(3).
*
* @hideinitializer
*/
#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F))
-/**
+/**
* Decodes percent-encoded characters while copying the string @p seg
* of size @p length to @p buf. The caller of this function must
* ensure that the percent-encodings are correct (i.e. the character
* '%' is always followed by two hex digits. and that @p buf provides
* sufficient space to hold the result. This function is supposed to
* be called by make_decoded_option() only.
- *
+ *
* @param seg The segment to decode and copy.
* @param length Length of @p seg.
* @param buf The result buffer.
return n;
}
-/**
+/**
* Writes a coap option from given string @p s to @p buf. @p s should
* point to a (percent-encoded) path or query segment of a coap_uri_t
* object. The created option will have type @c 0, and the length
* On success, this function returns the option's size, or a value
* less than zero on error. This function must be called from
* coap_split_path_impl() only.
- *
+ *
* @param s The string to decode.
* @param length The size of the percent-encoded string @p s.
* @param buf The buffer to store the new coap option.
* @param buflen The maximum size of @p buf.
- *
+ *
* @return The option's size, or @c -1 on error.
*
* @bug This function does not split segments that are bigger than 270
typedef void (*segment_handler_t)(unsigned char *, size_t, void *);
-/**
+/**
* Splits the given string into segments. You should call one of the
* macros coap_split_path() or coap_split_query() instead.
- *
+ *
* @param parse_iter The iterator used for tokenizing.
* @param h A handler that is called with every token.
* @param data Opaque data that is passed to @p h when called.
- *
+ *
* @return The number of characters that have been parsed from @p s.
*/
size_t coap_split_path_impl(coap_parse_iterator_t *parse_iter, segment_handler_t h, void *data)
assert(state);
/* skip empty segments and those that consist of only one or two dots */
- if (memcmp(s, "..", min(len,2)) == 0)
+ if (memcmp(s, "..", min(len, 2)) == 0)
return;
res = make_decoded_option(s, len, state->buf.s, state->buf.length);
if (!uri)
return NULL;
- result = (coap_uri_t *) coap_malloc( uri->query.length + uri->host.length +
- uri->path.length + sizeof(coap_uri_t) + 1);
+ result = (coap_uri_t *) coap_malloc(
+ uri->query.length + uri->host.length + uri->path.length + sizeof(coap_uri_t) + 1);
if (!result)
return NULL;
* Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_URI_H_
{
str host; /**< host part of the URI */
unsigned short port; /**< The port in host byte order */
- str path; /**< Beginning of the first path segment.
+ str path; /**< Beginning of the first path segment.
Use coap_split_path() to create Uri-Path options */
str query; /**< The query part if present */
} coap_uri_t;
* be released with coap_free(). */
coap_uri_t *coap_clone_uri(const coap_uri_t *uri);
-/**
- * Calculates a hash over the given path and stores the result in
+/**
+ * Calculates a hash over the given path and stores the result in
* @p key. This function returns @c 0 on error or @c 1 on success.
- *
+ *
* @param path The URI path to generate hash for.
* @param len The length of @p path.
* @param key The output buffer.
- *
+ *
* @return @c 1 if @p key was set, @c 0 otherwise.
*/
int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key);
* @{
*/
-/**
+/**
* Iterator to for tokenizing a URI path or query. This structure must
* be initialized with coap_parse_iterator_init(). Call
* coap_parse_next() to walk through the tokens.
size_t segment_length; /**< length of current segment */
} coap_parse_iterator_t;
-/**
- * Initializes the given iterator @p pi.
- *
+/**
+ * Initializes the given iterator @p pi.
+ *
* @param s The string to tokenize.
* @param n The length of @p s.
* @param separator The separator character that delimits tokens.
* @param delim A set of characters that delimit @s.
* @param dlen The length of @p delim.
* @param pi The iterator object to initialize.
- *
+ *
* @return The initialized iterator object @p pi.
*/
coap_parse_iterator_t *
coap_parse_iterator_init(unsigned char *s, size_t n, unsigned char separator, unsigned char *delim,
size_t dlen, coap_parse_iterator_t *pi);
-/**
+/**
* Updates the iterator @p pi to point to the next token. This
* function returns a pointer to that token or @c NULL if no more
* tokens exist. The contents of @p pi will be updated. In particular,
* @c pi->segment_length specifies the length of the current token, @c
* pi->pos points to its beginning.
- *
+ *
* @param pi The iterator to update.
- *
+ *
* @return The next token or @c NULL if no more tokens exist.
*/
unsigned char *coap_parse_next(coap_parse_iterator_t *pi);
-/**
+/**
* Parses a given string into URI components. The identified syntactic
* components are stored in the result parameter @p uri. Optional URI
* components that are not specified will be set to { 0, 0 }, except
* for the port which is set to @c COAP_DEFAULT_PORT. This function
* returns @p 0 if parsing succeeded, a value less than zero
* otherwise.
- *
+ *
* @param str_var The string to split up.
* @param len The actual length of @p str_var
* @param uri The coap_uri_t object to store the result.
int
coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri);
-/**
+/**
* Splits the given URI path into segments. Each segment is preceded
* by an option pseudo-header with delta-value 0 and the actual length
* of the respective segment after percent-decoding.
- *
- * @param s The path string to split.
+ *
+ * @param s The path string to split.
* @param length The actual length of @p s.
- * @param buf Result buffer for parsed segments.
+ * @param buf Result buffer for parsed segments.
* @param buflen Maximum length of @p buf. Will be set to the actual number
* of bytes written into buf on success.
- *
+ *
* @return The number of segments created or @c -1 on error.
*/
int coap_split_path(const unsigned char *s, size_t length, unsigned char *buf, size_t *buflen);
-/**
+/**
* Splits the given URI query into segments. Each segment is preceded
* by an option pseudo-header with delta-value 0 and the actual length
* of the respective query term.
- *
- * @param s The query string to split.
+ *
+ * @param s The query string to split.
* @param length The actual length of @p s.
- * @param buf Result buffer for parsed segments.
+ * @param buf Result buffer for parsed segments.
* @param buflen Maximum length of @p buf. Will be set to the actual number
* of bytes written into buf on success.
- *
+ *
* @return The number of segments created or @c -1 on error.
*
* @bug This function does not reserve additional space for delta > 12.
*/
#ifndef UTHASH_H
-#define UTHASH_H
+#define UTHASH_H
#include <string.h> /* memcmp,strlen */
#include <stddef.h> /* ptrdiff_t */
char **_da_dst = (char**)(&(dst)); \
*_da_dst = (char*)(src); \
} while(0)
-#else
+#else
#define DECLTYPE_ASSIGN(dst,src) \
do { \
(dst) = DECLTYPE(dst)(src); \
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#else
-#define HASH_BLOOM_MAKE(tbl)
-#define HASH_BLOOM_FREE(tbl)
-#define HASH_BLOOM_ADD(tbl,hashv)
+#define HASH_BLOOM_MAKE(tbl)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
#define HASH_BLOOM_TEST(tbl,hashv) (1)
#endif
} \
} while (0)
#else
-#define HASH_FSCK(hh,head)
+#define HASH_FSCK(hh,head)
#endif
-/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
* the descriptor to which this macro is defined for tuning the hash function.
* The app can #include <unistd.h> to get the prototype for write(2). */
#ifdef HASH_EMIT_KEYS
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
} while (0)
-#else
-#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
-#ifdef HASH_FUNCTION
+#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
bkt = (hashv) & (num_bkts-1); \
} while (0)
-/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
do { \
/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
* So MurmurHash comes in two versions, the faster unaligned one and the slower
- * aligned one. We only use the faster one on CPU's where we know it's safe.
+ * aligned one. We only use the faster one on CPU's where we know it's safe.
*
* Note the preprocessor built-in defines can be emitted using:
*
* gcc -m64 -dM -E - < /dev/null (on gcc)
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
*/
-#if (defined(__i386__) || defined(__x86_64__))
+#if (defined(__i386__) || defined(__x86_64__))
#define HASH_MUR HASH_MUR_UNALIGNED
#else
#define HASH_MUR HASH_MUR_ALIGNED
#endif /* HASH_USING_NO_STRICT_ALIASING */
/* key comparison function; return 0 if keys equal */
-#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
/* iterate over items in a known bucket to find desired item */
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
} \
if (hh_del->hh_next) { \
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
- }
+ }
/* Bucket expansion has the effect of doubling the number of buckets
* and redistributing the items into the new buckets. Ideally the
* items will distribute more or less evenly into the new buckets
* (the extent to which this is true is a measure of the quality of
- * the hash function as it applies to the key domain).
- *
+ * the hash function as it applies to the key domain).
+ *
* With the items distributed into more buckets, the chain length
* (item count) in each bucket is reduced. Thus by expanding buckets
- * the hash keeps a bound on the chain length. This bounded chain
+ * the hash keeps a bound on the chain length. This bounded chain
* length is the essence of how a hash provides constant time lookup.
- *
+ *
* The calculation of tbl->ideal_chain_maxlen below deserves some
* explanation. First, keep in mind that we're calculating the ideal
* maximum chain length based on the *new* (doubled) bucket count.
* In fractions this is just n/b (n=number of items,b=new num buckets).
- * Since the ideal chain length is an integer, we want to calculate
+ * Since the ideal chain length is an integer, we want to calculate
* ceil(n/b). We don't depend on floating point arithmetic in this
* hash, so to calculate ceil(n/b) with integers we could write
- *
+ *
* ceil(n/b) = (n/b) + ((n%b)?1:0)
- *
+ *
* and in fact a previous version of this hash did just that.
* But now we have improved things a bit by recognizing that b is
* always a power of two. We keep its base 2 log handy (call it lb),
* so now we can write this with a bit shift and logical AND:
- *
+ *
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
- *
+ *
*/
#define HASH_EXPAND_BUCKETS(tbl) \
do { \
} while(0)
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
-/* Note that HASH_SORT assumes the hash handle name to be hh.
+/* Note that HASH_SORT assumes the hash handle name to be hh.
* HASH_SRT was added to allow the hash handle name to be passed in. */
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
#define HASH_SRT(hh,head,cmpfcn) \
} \
} while (0)
-/* This function selects items from one hash into another hash.
- * The end result is that the selected items have dual presence
- * in both hashes. There is no copy of the items made; rather
- * they are added into the new hash through a secondary hash
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
* hash handle that must be present in the structure. */
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
do { \
#ifdef NO_DECLTYPE
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
- el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
+ el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
#else
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
#endif
/* obtain a count of items in the hash */
-#define HASH_COUNT(head) HASH_CNT(hh,head)
+#define HASH_COUNT(head) HASH_CNT(hh,head)
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
typedef struct UT_hash_bucket
/* expand_mult is normally set to 0. In this situation, the max chain length
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
- * the bucket's chain exceeds this length, bucket expansion is triggered).
+ * the bucket's chain exceeds this length, bucket expansion is triggered).
* However, setting expand_mult to a non-zero value delays bucket expansion
* (that would be triggered by additions to this particular bucket)
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
* multiplier is to reduce bucket expansions, since they are expensive, in
* situations where we know that a particular bucket tends to be overused.
* It is better to let its chain length grow to a longer yet-still-bounded
- * value, than to do an O(n) bucket expansion too often.
+ * value, than to do an O(n) bucket expansion too often.
*/
unsigned expand_mult;
* hash distribution; reaching them in a chain traversal takes >ideal steps */
unsigned nonideal_items;
- /* ineffective expands occur when a bucket doubling was performed, but
+ /* ineffective expands occur when a bucket doubling was performed, but
* afterward, more than half the items in the hash had nonideal chain
* positions. If this happens on two consecutive expansions we inhibit any
* further expansion, as it's not helping; this happens when the hash
#define UTLIST_VERSION 1.9.1
-/*
+/*
* This file contains macros to manipulate singly and doubly-linked lists.
*
* 1. LL_ macros: singly-linked lists.
* To use singly-linked lists, your structure must have a "next" pointer.
* To use doubly-linked lists, your structure must "prev" and "next" pointers.
* Either way, the pointer to the head of the list must be initialized to NULL.
- *
+ *
* ----------------.EXAMPLE -------------------------
* struct item {
* int id;
#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
-#else
+#else
#define _SV(elt,list)
#define _NEXT(elt,list) ((elt)->next)
#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
LL_FOREACH(head,out) { \
if ((out)->field == (val)) break; \
} \
-} while(0)
+} while(0)
#define LL_SEARCH(head,out,elt,cmp) \
do { \
LL_FOREACH(head,out) { \
if ((cmp(out,elt))==0) break; \
} \
-} while(0)
+} while(0)
/******************************************************************************
* doubly linked list macros (non-circular) *
} while (0);
#define CDL_FOREACH(head,el) \
- for(el=head;el;el=(el->next==head ? 0L : el->next))
+ for(el=head;el;el=(el->next==head ? 0L : el->next))
#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
CDL_FOREACH(head,out) { \
if ((out)->field == (val)) break; \
} \
-} while(0)
+} while(0)
#define CDL_SEARCH(head,out,elt,cmp) \
do { \
CDL_FOREACH(head,out) { \
if ((cmp(out,elt))==0) break; \
} \
-} while(0)
+} while(0)
#endif /* UTLIST_H */
make clean
make
-cd ../../build/linux
+cd ../../build/linux
make clean
make
-
cd ../../samples/linux
make clean
make
#include "cainterface.h"
#define MAX_BUF_LEN 1024
+#define MAX_OPT_LEN 16
char get_menu();
void process();
void send_request();
void send_response();
void advertise_resource();
+void send_notification();
void select_network();
void unselect_network();
void handle_request_response();
-void request_handler(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo);
-void response_handler(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo);
+void request_handler(const CARemoteEndpoint_t* object, const CARequestInfo_t* requestInfo);
+void response_handler(const CARemoteEndpoint_t* object, const CAResponseInfo_t* responseInfo);
void send_request_tmp(CARemoteEndpoint_t* endpoint, CAToken_t token);
int main()
printf("quit..!!\n");
return;
- case 's': // start listening server
+ case 's': // start server
case 'S':
start_listening_server();
break;
- case 'd': // start discovery server
+ case 'c': // start client
case 'D':
start_discovery_server();
break;
advertise_resource();
break;
+ case 'b': // send notification
+ case 'B':
+ send_notification();
+ break;
+
case 'n': // select network
case 'N':
select_network();
void start_discovery_server()
{
- printf("start discovery server!!\n");
+ printf("start discovery client!!\n");
CAStartDiscoveryServer();
}
}
else
{
- printf("find resource fo %s URI\n", buf);
+ printf("find resource to %s URI\n", buf);
}
printf("=============================================\n");
memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
printf("\n=============================================\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");
+ printf("10.11.12.13:4545/resource_uri ( for IP )\n");
+ printf("10:11:12:13:45:45/resource_uri ( for BT )\n");
printf("uri : ");
gets(buf);
// create remote endpoint
CARemoteEndpoint_t* endpoint = NULL;
CAResult_t res = CACreateRemoteEndpoint(buf, &endpoint);
- endpoint->connectivityType = CA_WIFI; //
if (res != CA_STATUS_OK)
{
printf("create remote endpoint error!!");
+ CADestroyRemoteEndpoint(endpoint);
return;
}
void advertise_resource()
{
+ char buf[MAX_BUF_LEN];
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+
printf("\n=============================================\n");
+ printf("uri : ");
- printf("not implemented yet.\n");
+ scanf("%s", buf);
+
+ int optionNum = 0;
+ char optionData[MAX_OPT_LEN];
+
+ printf("Option Num : ");
+ scanf("%d", &optionNum);
+ CAHeaderOption_t *headerOpt;
+ headerOpt = (CAHeaderOption_t*) malloc(sizeof(CAHeaderOption_t) * optionNum);
+ if (NULL == headerOpt)
+ {
+ printf("Memory allocation failed!\n");
+ return;
+ }
+ memset(headerOpt, 0, sizeof(CAHeaderOption_t) * optionNum);
+
+ int i;
+ for(i = 0 ; i < optionNum ; i++)
+ {
+ int optionID = 0;
+ printf("[%d] Option ID : ", i + 1);
+ scanf("%d", &optionID);
+ headerOpt[i].optionID = optionID;
+
+ memset(optionData, 0, sizeof(char) * MAX_OPT_LEN);
+ printf("[%d] Option Data : ", i + 1);
+ scanf("%s", optionData);
+ memcpy(headerOpt[i].optionData, optionData, strlen(optionData));
+ printf("[%d] inputed option : ID : %d, data : %s\n", i + 1, optionID, optionData );
+
+ headerOpt[i].optionLength = (uint16_t)strlen(optionData);
+ }
+ printf("\n=============================================\n");
+
+ CAAdvertiseResource(buf, headerOpt, (uint8_t)optionNum);
+
+ free(headerOpt);
- printf("=============================================\n");
+}
+
+void send_notification()
+{
+ char buf[MAX_BUF_LEN];
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+
+ printf("\n=============================================\n");
+ printf("10.11.12.13:4545/resource_uri ( for IP )\n");
+ printf("10:11:12:13:45:45/resource_uri ( for BT )\n");
+ printf("uri : ");
+
+ gets(buf);
+
+ // create remote endpoint
+ CARemoteEndpoint_t* endpoint = NULL;
+ CAResult_t res = CACreateRemoteEndpoint(buf, &endpoint);
+
+ if (res != CA_STATUS_OK)
+ {
+ printf("create remote endpoint error!!");
+ CADestroyRemoteEndpoint(endpoint);
+ return;
+ }
+
+ CAInfo_t respondeData;
+ memset(&respondeData, 0, sizeof(CAInfo_t));
+ respondeData.token = "client token";
+ respondeData.payload = "Temp Notification Data";
+
+ CAResponseInfo_t responseInfo;
+ memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
+ responseInfo.result = CA_CONTENT;
+ responseInfo.info = respondeData;
+
+ // send request
+ CASendNotification(endpoint, &responseInfo);
+
+ // destroy remote endpoint
+ if (endpoint != NULL)
+ {
+ CADestroyRemoteEndpoint(endpoint);
+ }
+ printf("\n=============================================\n");
}
void select_network()
printf("\n=============================================\n");
printf("\t\tMenu\n");
- printf("\ts : start listening server\n");
- printf("\td : start discovery server\n");
+ printf("\ts : start server\n");
+ printf("\tc : start client\n");
printf("\tf : find resource\n");
printf("\tr : send request\n");
printf("\ta : advertise resource\n");
+ printf("\tb : send notification\n");
printf("\tn : select network\n");
printf("\tx : unselect network\n");
printf("\th : handle request response\n");
CAHandleRequestResponse();
}
-void request_handler(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo)
+void request_handler(const CARemoteEndpoint_t* object, const CARequestInfo_t* requestInfo)
{
- printf("request_handler, uri : %s, data : %s\n", (object != NULL) ? object->resourceUri : "",
+ printf("[CALLBACK] request_handler, uri : %s, data : %s\n", (object != NULL) ? object->resourceUri : "",
(requestInfo != NULL) ? requestInfo->info.payload : "");
+ printf("[CALLBACK] request_handler, address : %s\n", (object != NULL) ? object->addressInfo.IP.ipAddress : "");
+
+ if(requestInfo->info.options)
+ {
+ uint32_t len = requestInfo->info.numOptions;
+ uint32_t i;
+ for(i = 0 ; i < len ; i++)
+ {
+ printf("[CALLBACK] request_handler, option ID : %d\n", requestInfo->info.options[i].optionID);
+ printf("[CALLBACK] request_handler, options data length : %d\n", requestInfo->info.options[i].optionLength);
+ printf("[CALLBACK] request_handler, options data : %s\n", requestInfo->info.options[i].optionData );
+ }
+ }
+
printf("send response with URI\n");
send_response(object, (requestInfo != NULL) ? requestInfo->info.token : "");
}
-void response_handler(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo)
+void response_handler(const CARemoteEndpoint_t* object, const CAResponseInfo_t* responseInfo)
{
- printf("response_handler, uri : %s, data : %s\n", (object != NULL) ? object->resourceUri : "",
+ printf("[CALLBACK] response_handler, uri : %s, data : %s\n", (object != NULL) ? object->resourceUri : "",
(responseInfo != NULL) ? responseInfo->info.payload : "");
- printf("send request after receivce response data\n");
- send_request_tmp(object, (responseInfo != NULL) ? responseInfo->info.token : "");
+ printf("[CALLBACK] response_handler, address : %s\n", (object != NULL) ? object->addressInfo.IP.ipAddress : "");
+
+ if(responseInfo->info.options)
+ {
+ uint32_t len = responseInfo->info.numOptions;
+ uint32_t i;
+ for(i = 0 ; i < len ; i++)
+ {
+ printf("[CALLBACK] response_handler, option ID : %d\n", responseInfo->info.options[i].optionID);
+ printf("[CALLBACK] response_handler, options data length : %d\n", responseInfo->info.options[i].optionLength);
+ printf("[CALLBACK] response_handler, options data : %s\n", responseInfo->info.options[i].optionData );
+ }
+ }
+
+ //printf("send request with URI\n");
+ //send_request_tmp(object, (responseInfo != NULL) ? responseInfo->info.token : "");
}
void send_response(CARemoteEndpoint_t* endpoint, CAToken_t request_token)
responseInfo.result = 203;
responseInfo.info = responseData;
- // send request
- endpoint->connectivityType = CA_WIFI;
+ // send request (connectivityType from remoteEndpoint of request Info)
CASendResponse(endpoint, &responseInfo);
printf("=============================================\n");
SRC_DIR := $(ROOT_DIR)/common/src/
CFLAGS = -Wall
COMPILEFLAGS = `pkg-config --cflags glib-2.0`
-LDFLAGS = `pkg-config --libs glib-2.0`
+LDFLAGS = `pkg-config --libs glib-2.0`
OUT = threadpool
all:
- $(CC) $(CFLAGS) $(INC_DIR) $(COMPILEFLAGS) $(SRC_DIR)uthreadpool.c $(SRC_DIR)umutex.c $(SRC_DIR)/../logger.c main.c -o $(OUT) $(LDFLAGS)
+ $(CC) $(CFLAGS) $(INC_DIR) $(COMPILEFLAGS) $(SRC_DIR)uthreadpool.c $(SRC_DIR)umutex.c $(SRC_DIR)/logger.c $(SRC_DIR)/oic_malloc.c main.c -o $(OUT) $(LDFLAGS)
clean:
rm -f $(OUT)
+/******************************************************************
+ *
+ * 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 <stdio.h>
#include <stdlib.h>
if (NULL == gMutex)
{
printf("[testThreadPool] Failed to create mutex!\n");
+ u_thread_pool_free(gThreadPoolHandle);
return;
}
if (NULL == gCond)
{
printf("[testThreadPool] Failed to create condition!\n");
-
+ u_thread_pool_free(gThreadPoolHandle);
u_mutex_free(gMutex);
return;
}
if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPoolHandle, task, (void *) string))
{
printf("[testThreadPool] thread_pool_add_task failed!\n");
-
+ u_thread_pool_free(gThreadPoolHandle);
u_mutex_unlock(gMutex);
u_mutex_free(gMutex);
u_cond_free(gCond);
--- /dev/null
+#
+# override with `make BUILD=debug`
+# override with `make PLATFORM=arduinomega` or `make PLATFORM=arduinodue`
+# default to release build
+# default to build for linux
+BUILD := release
+PLATFORM := linux
+
+ifeq ($(PLATFORM),linux)
+$(info *******************linux Build !!******************)
+
+CC=gcc
+
+ROOT_DIR = inc/
+INC_DIRS := -I$(ROOT_DIR)/
+
+#CFLAGS=$(INC_DIRS) -std=c99 -DWITH_POSIX
+#CFLAGS=-std=c99
+#CFLAGS=$(INC_DIRS) -std=c99 -DWITH_POSIX -g
+CFLAGS=$(INC_DIRS) -DWITH_POSIX -D__TIZEN__
+#COMPILEFLAG = `pkg-config --cflags --libs com.samsung.oicca com.samsung.oicca-devel`
+COMPILEFLAG = `pkg-config --cflags --libs com.samsung.oicca capi-network-wifi gobject-2.0 glib-2.0 dlog capi-network-bluetooth`
+
+OBJECTS := interfacesample.o casample.o
+
+all: $(OBJECTS)
+ $(CC) interfacesample.o -o interface_sample /usr/lib/liboicinterface.a -lm -lpthread -lrt -ldl -lstdc++ -lgobject-2.0 -lgio-2.0 -lglib-2.0 -lcapi-network-wifi -ldlog -lcapi-network-bluetooth
+ $(CC) casample.o -o ca_sample /usr/lib/liboicinterface.a -lm -lpthread -lrt -ldl -lstdc++ -lgobject-2.0 -lgio-2.0 -lglib-2.0 -lcapi-network-wifi -ldlog -lcapi-network-bluetooth
+interfacesample.o: interfacesample.c
+ $(CC) $(CFLAGS) $(COMPILEFLAG) -c interfacesample.c -o interfacesample.o
+casample.o: casample.c
+ $(CC) $(CFLAGS) $(COMPILEFLAG) -c casample.c -o casample.o
+pack:
+#$(CC) $(CFLAGS) $(COMPILEFLAG) wifi_interface.c bt_interface.c tc_interface.c sample_main.c -o sample /usr/lib/liboctbstack.a -lm
+ $(info **************************************TEST***************************)
+install:
+#cp -rf sample ./usr/apps/com.samsung.oicca/bin/sample
+
+clean:
+ rm -rf *.o interface_sample
+ rm -rf *.o ca_sample
+
+else ifeq ($(PLATFORM),arduinodue)
+$(info *********Arduinodue Build!!**********)
+
+#Make Compilation Script for arduino
+
+
+else
+ $(info *********error**********)
+ $(error Wrong value for PLATFORM !!)
+endif
--- /dev/null
+Compiling Interface APIs:
+=========================
+1) Get the latest interface APIs code.
+2) Copy the oic-resource code to linux machine.
+3) Change the ROOT_DIR in interface APIs makefile such that it points to oic-resource/csdk in local linux environment.
+4) Do "make" inside the interface APIs folder.
+
+Compiling Sample App FOR TIZEN:
+===============================
+1) Get the oic-resource code(Changes done for Logging by SRI-B) from SRI-B and build it in Tizen GBS
+2) Get the latest interface APIs code from repo and build it in Tizen GBS
+ To Build in Tizen GBS Platform, Use this command "sudo gbs build -A armv7l --include-all"
+3) For Verification, Build Sample Console App and execute in Tizen Device
+
+Procedure to Execute Sample App:
+=================================
+ 1) Copy the generated rpm(com.samsung.interfacesample-0.1-1.armv7l.rpm) to Tizen Device (say /opt/usr/media/xxx/)
+ 2) sdb shell,
+ 3) su
+ 4) cd /opt/usr/media/xxx/
+
+ 5) change-booting-mode.sh --update
+
+ 6) Install interfacesample(console app). It contains Interface API libs and OIC-CORE Libs
+ i) rpm -Uvh com.samsung.interfacesample-0.1-1.armv7l.rpm --force --nodeps
+
+ 7) Execute smack_reload.sh
+
+ 8) rpm will be installed in /usr/apps/ Execute the sample app by below commands
+ i) cd /usr/apps/com.samsung.interfacesample/bin
+ ii) ./sample
\ No newline at end of file
--- /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 <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "cacommon.h"
+#include "cainterface.h"
+
+static GMainLoop *mainloop;
+static GIOChannel *channel;
+static guint g_test_io_watch_id;
+static GError *g_err_Sample;
+
+pthread_t thread;
+
+#define MAX_BUF_LEN 1024
+#define MAX_OPT_LEN 16
+
+char get_menu();
+void process();
+
+void initialize();
+void start_listening_server();
+void start_discovery_server();
+void find_resource();
+void send_request();
+void send_response();
+void advertise_resource();
+void send_notification();
+void select_network();
+void unselect_network();
+void handle_request_response();
+
+void request_handler(const CARemoteEndpoint_t* object, const CARequestInfo_t* requestInfo);
+void response_handler(const CARemoteEndpoint_t* object, const CAResponseInfo_t* responseInfo);
+void send_request_tmp(CARemoteEndpoint_t *endpoint, CAToken_t token);
+void terminate();
+
+void pthread_func()
+{
+ g_main_loop_run(mainloop);
+}
+
+int main()
+{
+ system("clear");
+
+ printf("=============================================\n");
+ printf("\t\tsample main\n");
+ printf("=============================================\n");
+
+ process();
+
+ return 0;
+}
+
+void process()
+{
+ while (1)
+ {
+ char menu = toupper(get_menu());
+
+ switch (menu)
+ {
+ case 'Q': // quits the sample program
+ printf("quit..!!\n");
+ g_main_loop_quit(mainloop);
+ return;
+
+ case 'I': // Initialize interface
+ initialize();
+
+ case 'S': // start server
+ start_listening_server();
+ break;
+
+ case 'C': // start client
+ start_discovery_server();
+ break;
+
+ case 'F': // find resource
+ find_resource();
+ break;
+
+ case 'R': // send request
+ send_request();
+ break;
+
+ case 'A': // advertise resource
+ advertise_resource();
+ break;
+
+ case 'N': // select network
+ select_network();
+ break;
+
+ case 'X': // unselect network
+ unselect_network();
+ break;
+
+ case 'H': // handle request response
+ handle_request_response();
+ break;
+
+ case 'T': // Terminate interface
+ terminate();
+ break;
+
+ default:
+ printf("not supported menu!!\n");
+ break;
+ }
+ }
+
+}
+
+void initialize()
+{
+ mainloop = g_main_loop_new(NULL, FALSE);
+ pthread_create(&thread, NULL, (void *) &pthread_func, NULL);
+
+ CAInitialize();
+
+ // network enable
+ // default
+ printf("select default network(WIFI)\n");
+ CASelectNetwork(CA_WIFI);
+
+ // set handler.
+ CARegisterHandler(request_handler, response_handler);
+}
+
+void start_listening_server()
+{
+ printf("start listening server!!\n");
+
+ CAStartListeningServer();
+}
+
+void start_discovery_server()
+{
+ printf("start discovery server at client!!\n");
+
+ CAStartDiscoveryServer();
+}
+
+void find_resource()
+{
+ char buf[MAX_BUF_LEN];
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+
+ printf("\n=============================================\n");
+ printf("ex) a/light\n");
+ printf("reference uri : ");
+
+ gets(buf);
+
+ CAResult_t res = CAFindResource(buf);
+
+ if (res != CA_STATUS_OK)
+ {
+ printf("find resource error:%d !!\n", res);
+ }
+ else
+ {
+ printf("find resource for %s URI\n", buf);
+ }
+
+ printf("=============================================\n");
+}
+
+void send_request()
+{
+ char buf[MAX_BUF_LEN];
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+
+ printf("\n=============================================\n");
+ printf("10.11.12.13:4545/resource_uri ( for IP )\n");
+ printf("10:11:12:13:45:45/resource_uri ( for BT )\n");
+ printf("uri : ");
+
+ gets(buf);
+
+ // create remote endpoint
+ CARemoteEndpoint_t *endpoint = NULL;
+ CAResult_t res = CACreateRemoteEndpoint(buf, &endpoint);
+
+ if (res != CA_STATUS_OK)
+ {
+ printf("create remote endpoint error!!");
+ CADestroyRemoteEndpoint(endpoint);
+ return;
+ }
+
+ // create token
+ CAToken_t token = NULL;
+ res = CAGenerateToken(&token);
+
+ if (res != CA_STATUS_OK)
+ {
+ printf("token generate error!!");
+ token = NULL;
+ }
+
+ printf("generated token %s\n", (token != NULL) ? token : "");
+
+ CAInfo_t requestData;
+ memset(&requestData, 0, sizeof(CAInfo_t));
+ requestData.token = token;
+ requestData.payload = "Temp Json Payload";
+
+ CARequestInfo_t requestInfo;
+ memset(&requestInfo, 0, sizeof(CARequestInfo_t));
+ requestInfo.method = CA_GET;
+ requestInfo.info = requestData;
+
+ // send request
+ CASendRequest(endpoint, &requestInfo);
+
+ if (token != NULL)
+ {
+ CADestroyToken(token);
+ }
+
+ // destroy remote endpoint
+ if (endpoint != NULL)
+ {
+ CADestroyRemoteEndpoint(endpoint);
+ }
+
+ printf("=============================================\n");
+}
+
+void advertise_resource()
+{
+ char buf[MAX_BUF_LEN];
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+
+ printf("\n=============================================\n");
+ printf("uri : ");
+
+ scanf("%s", buf);
+
+ int optionNum = 0;
+ char optionData[MAX_OPT_LEN];
+
+ printf("Option Num : ");
+ scanf("%d", &optionNum);
+ CAHeaderOption_t *headerOpt;
+
+ if (optionNum > 0)
+ {
+ headerOpt = (CAHeaderOption_t *) malloc(sizeof(CAHeaderOption_t) * optionNum);
+ if (NULL == headerOpt)
+ {
+ printf("memory allocation failed!\n");
+ return;
+ }
+ memset(headerOpt, 0, sizeof(CAHeaderOption_t) * optionNum);
+ }
+
+ int i;
+ for (i = 0; i < optionNum; i++)
+ {
+ int optionID = 0;
+ printf("[%d] Option ID : ", i + 1);
+ scanf("%d", &optionID);
+ headerOpt[i].optionID = optionID;
+
+ memset(optionData, 0, sizeof(char) * MAX_OPT_LEN);
+ printf("[%d] Option Data : ", i + 1);
+ scanf("%s", optionData);
+ memcpy(headerOpt[i].optionData, optionData, MAX_OPT_LEN);
+ printf("[%d] inputed option : ID : %d, data : %s\n", i + 1, optionID, optionData);
+
+ headerOpt[i].optionLength = (uint16_t) strlen(optionData);
+ }
+ printf("\n=============================================\n");
+
+ CAAdvertiseResource(buf, headerOpt, (uint8_t) optionNum);
+
+ free(headerOpt);
+
+}
+
+void send_notification()
+{
+ char buf[MAX_BUF_LEN];
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+
+ printf("\n=============================================\n");
+ printf("10.11.12.13:4545/resource_uri ( for IP )\n");
+ printf("10:11:12:13:45:45/resource_uri ( for BT )\n");
+ printf("uri : ");
+
+ gets(buf);
+
+ // create remote endpoint
+ CARemoteEndpoint_t *endpoint = NULL;
+ CAResult_t res = CACreateRemoteEndpoint(buf, &endpoint);
+
+ if (res != CA_STATUS_OK)
+ {
+ printf("create remote endpoint error!!");
+ CADestroyRemoteEndpoint(endpoint);
+ return;
+ }
+
+ CAInfo_t respondeData;
+ memset(&respondeData, 0, sizeof(CAInfo_t));
+ respondeData.token = "client token";
+ respondeData.payload = "Temp Notification Data";
+
+ CAResponseInfo_t responseInfo;
+ memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
+ responseInfo.result = CA_CONTENT;
+ responseInfo.info = respondeData;
+
+ // send request
+ CASendNotification(endpoint, &responseInfo);
+
+ // destroy remote endpoint
+ if (endpoint != NULL)
+ {
+ CADestroyRemoteEndpoint(endpoint);
+ }
+ printf("\n=============================================\n");
+}
+
+void select_network()
+{
+ char buf[MAX_BUF_LEN];
+
+ printf("\n=============================================\n");
+ printf("\tselect network\n");
+ printf("ETHERNET : 0\n");
+ printf("WIFI : 1\n");
+ printf("EDR : 2\n");
+ printf("LE : 3\n");
+ printf("select : ");
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+ gets(buf);
+
+ int number = buf[0] - '0';
+
+ number = (number < 0 || number > 3) ? 1 : number;
+
+ CASelectNetwork(1 << number);
+
+ printf("=============================================\n");
+}
+
+void unselect_network()
+{
+ char buf[MAX_BUF_LEN];
+
+ printf("\n=============================================\n");
+ printf("\tunselect enabled network\n");
+ printf("ETHERNET : 0\n");
+ printf("WIFI : 1\n");
+ printf("EDR : 2\n");
+ printf("LE : 3\n");
+ printf("select : ");
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+ gets(buf);
+
+ int number = buf[0] - '0';
+
+ number = (number < 0 || number > 3) ? 1 : number;
+
+ CAUnSelectNetwork(1 << number);
+ printf("Terminating...\n");
+ CATerminate();
+ //pthread_join(thread, NULL);
+ printf("=============================================\n");
+}
+
+char get_menu()
+{
+ char buf[MAX_BUF_LEN];
+
+ printf("\n=============================================\n");
+ printf("\t\tMenu\n");
+ printf("\ti : Initialize\n");
+ printf("\ts : start server\n");
+ printf("\tc : start client\n");
+ printf("\tf : find resource\n");
+ printf("\tr : send request\n");
+ printf("\ta : advertise resource\n");
+ printf("\tn : select network\n");
+ printf("\tx : unselect network\n");
+ printf("\th : handle request response\n");
+ printf("\tt : terminate\n");
+ printf("\tq : quit\n");
+ printf("=============================================\n");
+ printf("select : ");
+
+ memset(buf, 0, sizeof(char) * MAX_BUF_LEN);
+
+ gets(buf);
+
+ return buf[0];
+}
+
+void handle_request_response()
+{
+ printf("handle_request_response\n");
+ CAHandleRequestResponse();
+}
+
+void request_handler(const CARemoteEndpoint_t* object, const CARequestInfo_t* requestInfo)
+{
+
+ printf("[CALLBACK] request_handler, uri : %s, data : %s\n",
+ (object != NULL) ? object->resourceUri : "",
+ (requestInfo != NULL) ? requestInfo->info.payload : "");
+
+ printf("[CALLBACK] request_handler, address : %s\n",
+ (object != NULL) ? object->addressInfo.IP.ipAddress : "");
+
+ if (requestInfo->info.options)
+ {
+ uint32_t len = requestInfo->info.numOptions;
+ uint32_t i;
+ for (i = 0; i < len; i++)
+ {
+ printf("[CALLBACK] request_handler, option ID : %d\n",
+ requestInfo->info.options[i].optionID);
+ printf("[CALLBACK] request_handler, options data length : %d\n",
+ requestInfo->info.options[i].optionLength);
+ printf("[CALLBACK] request_handler, options data : %s\n",
+ requestInfo->info.options[i].optionData);
+ }
+ }
+
+ printf("send response with URI\n");
+ send_response(object, (requestInfo != NULL) ? requestInfo->info.token : "");
+
+}
+
+void response_handler(const CARemoteEndpoint_t* object, const CAResponseInfo_t* responseInfo)
+{
+
+ printf("[CALLBACK] response_handler, uri : %s, data : %s\n",
+ (object != NULL) ? object->resourceUri : "",
+ (responseInfo != NULL) ? responseInfo->info.payload : "");
+
+ printf("[CALLBACK] response_handler, address : %s\n",
+ (object != NULL) ? object->addressInfo.IP.ipAddress : "");
+
+ if (responseInfo->info.options)
+ {
+ uint32_t len = responseInfo->info.numOptions;
+ uint32_t i;
+ for (i = 0; i < len; i++)
+ {
+ printf("[CALLBACK] response_handler, option ID : %d\n",
+ responseInfo->info.options[i].optionID);
+ printf("[CALLBACK] response_handler, options data length : %d\n",
+ responseInfo->info.options[i].optionLength);
+ printf("[CALLBACK] response_handler, options data : %s\n",
+ responseInfo->info.options[i].optionData);
+ }
+ }
+
+}
+
+void send_response(CARemoteEndpoint_t *endpoint, CAToken_t request_token)
+{
+
+ printf("\n=============================================\n");
+
+ CAInfo_t responseData;
+ //responseData = (CAInfo*) malloc(sizeof(CAInfo));
+ memset(&responseData, 0, sizeof(CAInfo_t));
+ responseData.token = request_token;
+ responseData.payload = "response payload";
+
+ CAResponseInfo_t responseInfo;
+ //responseInfo = (CAResponseInfo*) malloc(sizeof(CAResponseInfo));
+ memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
+ responseInfo.result = 203;
+ responseInfo.info = responseData;
+
+ // send request (connectivityType from remoteEndpoint of request Info)
+ CASendResponse(endpoint, &responseInfo);
+
+ printf("=============================================\n");
+
+}
+
+void send_request_tmp(CARemoteEndpoint_t *endpoint, CAToken_t token)
+{
+
+ printf("\n=============================================\n");
+
+ CAInfo_t requestData;
+ memset(&requestData, 0, sizeof(CAInfo_t));
+ requestData.token = token;
+ requestData.payload = "Temp Json Payload";
+
+ CARequestInfo_t requestInfo;
+ memset(&requestInfo, 0, sizeof(CARequestInfo_t));
+ requestInfo.method = CA_GET;
+ requestInfo.info = requestData;
+
+ // send request
+ endpoint->connectivityType = CA_WIFI;
+ CASendRequest(endpoint, &requestInfo);
+
+ printf("=============================================\n");
+
+}
+
+void terminate()
+{
+ unselect_network();
+}
--- /dev/null
+<manifest>
+ <define>
+ <domain name="interfacesample" />
+ <permit>
+ <smack permit="system::use_internet" type="rwx"/>
+ </permit>
+ <request>
+ <smack request="system::use_internet" type="rwx"/>
+ <smack request="bt-service" type="rwx"/>
+ <smack request="sap" type="rwx"/>
+ <smack request="bt-service::spp" type="rwx"/>
+ <smack request="bt-service::gap" type="rwx"/>
+ <smack request="bt-service::admin" type="rwx"/>
+ <smack request="bt-service::manager" type="rwx"/>
+ <smack request="bt-service::public" type="rwx"/>
+ <smack request="bt-service::platform" type="rwx"/>
+ </request>
+ </define>
+ <assign>
+ <filesystem path="/opt/apps/com.samsung.interfacesample/bin/sample" exec_label="sample" />
+ </assign>
+ <request>
+ <domain name="interfacesample" />
+ </request>
+</manifest>
--- /dev/null
+# all permissions
+#interfacesample system::vconf rwxat
+#interfacesample system::home rwxat
+#interfacesample system::media rwxat
+#interfacesample system::homedir rwxat
+#interfacesample system::share rwxat
+#interfacesample dali rwxat
+#interfacesample sys-assert::core rwxat
+#interfacesample dbus r
+#interfacesample system::media rwxat
+# system and device
+#interfacesample device::hwcodec rw
+#interfacesample device::video r
+#interfacesample device::camera r
+#interfacesample system::crash wx
+interfacesample system::use_internet rw
+# db
+#interfacesample libaccounts-svc::db rw
+#interfacesample ail::db rw
+#interfacesample media-data::db rw
+#interfacesample app-svc::db rw
+#interfacesample email-service::db rw
+#interfacesample cloud-content-sync::db rw
+#others
+#interfacesample media-server rwx
+#interfacesample mdm-server w
+#interfacesample xorg w
+#interfacesample isf rwx
+#interfacesample immvibed rw
+#interfacesample dbus rwx
+#interfacesample dali rx
+#interfacesample data-provider-master r
+#interfacesample smemo rx
+#interfacesample crash-worker rx
+#interfacesample msg-service w
+#interfacesample webkit2-efl rx
+#interfacesample ug-image-viewer-efl rx
+#interfacesample net.wifi-qs rwx
+#interfacesample sys-assert::info wx
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.interfacesample" version="0.1.12" install-location="internal-only">
+ <label>interfacesample</label>
+ <author email="oic" href="www.iotivity.org">OIC</author>
+ <description>interfacesample</description>
+ <ui-application appid="com.samsung.interfacesample" exec="/usr/apps/com.samsung.interfacesample/bin/sample" nodisplay="false" multiple="false" type="capp" taskmanage="true">
+ <icon>com.samsung.interfacesample.png</icon>
+ <label>interfacesample</label>
+ <label xml:lang="en-us">interfacesample</label>
+ <label xml:lang="nl-nl">interfacesample</label>
+ </ui-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/socket</privilege>
+ </privileges>
+
+</manifest>
--- /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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <wifi.h>
+#include <glib.h>
+
+#include "cacommon.h"
+#include "caadapterinterface.h"
+#include "uthreadpool.h"
+
+#define MOD_NAME "TizenSample"
+
+//Comment any below for blocking testing of specific adapters
+//#define WIFI_ADAPTER_TEST
+#define BT_ADAPTER_TEST
+//#define BLE_ADAPTER_TEST
+
+#if defined(WIFI_ADAPTER_TEST)
+#include "cawifiadapter.h"
+#include "caethernetadapter.h"
+static u_thread_pool_t gWiFiThreadPool = NULL;
+#elif defined(BT_ADAPTER_TEST)
+#include "caedradapter.h"
+static u_thread_pool_t gBTThreadPool = NULL;
+#elif defined(BLE_ADAPTER_TEST)
+#include "caleadapter.h"
+static u_thread_pool_t gLEThreadPool = NULL;
+#endif
+
+static GMainLoop *mainloop;
+static GIOChannel *channel;
+static guint g_test_io_watch_id;
+static GError *g_err_Sample;
+
+static CALocalConnectivity_t *localWifiEndpoint = NULL;
+//Hardcoded coap data for Test
+static char coapData[500] =
+ "{\"oc:\[{href\":\"/a/light\",\"ref\":{\"power\":\"20\",\"state\":\"true\"}}]}";
+
+void testInitializeBTInterface(void);
+void testTerminateBTInterface(void);
+void testInitializeWIFIInterface(void);
+void testTerminateWIFIInterface(void);
+void testInitializeBLEInterface(void);
+void testTerminateBLEInterface(void);
+
+typedef struct ConnectivityHandlerList
+{
+ CAConnectivityType_t type;
+ CAConnectivityHandler_t handler;
+ struct ConnectivityHandlerList *nextHandler;
+} ConnectivityHandlerList;
+
+static ConnectivityHandlerList *gConnectivityHandlers = NULL;
+
+void initializeThreadPool(CAConnectivityType_t type)
+{
+#ifdef BT_ADAPTER_TEST
+ if (CA_EDR == type && NULL == gBTThreadPool)
+ {
+ if (CA_STATUS_OK != u_thread_pool_init(3, &gBTThreadPool))
+ {
+ printf("Failed to create thread pool for BT adapter!\n");
+ return;
+ }
+ }
+#endif
+#ifdef WIFI_ADAPTER_TEST
+ if (CA_WIFI == type && NULL == gWiFiThreadPool)
+ {
+ if (CA_STATUS_OK != u_thread_pool_init(3, &gWiFiThreadPool))
+ {
+ printf("Failed to create thread pool for BT adapter!\n");
+ return;
+ }
+ }
+#endif
+#ifdef BLE_ADAPTER_TEST
+ if (CA_LE == type && NULL == gLEThreadPool)
+ {
+ if (CA_STATUS_OK != u_thread_pool_init(3, &gLEThreadPool))
+ {
+ printf("Failed to create thread pool for BT adapter!\n");
+ return;
+ }
+ }
+#endif
+}
+
+
+void storeInterfaceCallbacks(ConnectivityHandlerList *newHandler)
+{
+ printf("storeInterfaceCallbacks Entry in Sample\n");
+ newHandler->nextHandler = NULL;
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+
+ if (!tempConnectivityHandlers)
+ {
+ gConnectivityHandlers = newHandler;
+ printf("storeInterfaceCallbacks Exit in Sample\n");
+ return;
+ }
+
+ while (tempConnectivityHandlers->nextHandler)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ tempConnectivityHandlers->nextHandler = newHandler;
+ printf("storeInterfaceCallbacks Exit in Sample\n");
+}
+
+void interfaceRegisterCallback(CAConnectivityHandler_t handler,
+ CAConnectivityType_t connType)
+{
+ printf("interfaceRegisterCallback Entry in Sample\n");
+ ConnectivityHandlerList *newConnectivityHandler = (ConnectivityHandlerList *) malloc(sizeof(
+ ConnectivityHandlerList));
+ if (NULL == newConnectivityHandler)
+ {
+ printf("Memory allocation failed\n");
+ return;
+ }
+
+ newConnectivityHandler->type = connType;
+ newConnectivityHandler->handler = handler;
+ storeInterfaceCallbacks(newConnectivityHandler);
+ printf("interfaceRegisterCallback Exit in Sample\n");
+}
+
+void networkPacketHandler(CARemoteEndpoint_t *object, void *data, uint32_t dataLength)
+{
+ printf("networkPacketHandler Entry in Sample\n");
+ if (object == NULL || data == NULL)
+ {
+ printf("NULL Object\n");
+ return;
+ }
+
+ printf("Data Received from: ");
+ if (CA_EDR == object->connectivityType)
+ {
+ printf(object->addressInfo.BT.btMacAddress);
+ }
+ else if (CA_LE == object->connectivityType)
+ {
+ printf(object->addressInfo.LE.leMacAddress);
+ }
+ else if (CA_WIFI == object->connectivityType || CA_ETHERNET == object->connectivityType)
+ {
+ printf(object->addressInfo.IP.ipAddress);
+ }
+
+ printf("\nReceived Data [Length: %d]: %s\n",dataLength,(char *)data);
+ printf("networkPacketHandler Exit in Sample\n");
+}
+
+void networkInterfaceCallback(CALocalConnectivity_t *localEndPoint,
+ CANetworkStatus_t networkConnectivityState)
+{
+ printf("networkInterfaceCallback Entry in Sample\n");
+ if (localEndPoint == NULL)
+ {
+ printf("NULL Object\n");
+ return;
+ }
+
+ if (networkConnectivityState == CA_INTERFACE_UP)
+ {
+ printf("Network Status is UP\n");
+ }
+ else
+ {
+ printf("Network Status is DOWN\n");
+ }
+
+ printf("Address: ");
+ if (CA_EDR == localEndPoint->type)
+ {
+ printf("%s\n", localEndPoint->addressInfo.BT.btMacAddress);
+ }
+ else if (CA_LE == localEndPoint->type)
+ {
+ printf("%s\n", localEndPoint->addressInfo.LE.leMacAddress);
+ }
+ else if (CA_WIFI == localEndPoint->type || CA_ETHERNET == localEndPoint->type)
+ {
+ printf("%s\n", localEndPoint->addressInfo.IP.ipAddress);
+ }
+
+ printf("networkInterfaceCallback Exit in Sample\n");
+}
+
+
+void freeData(void *data)
+{
+ printf("freeData Entry in Sample\n");
+ if (data)
+ {
+ free(data);
+ }
+ printf("freeData Exit in Sample\n");
+}
+
+int16_t selectConnectivityType()
+{
+ int32_t cType;
+ printf("*******Select the Connectivity Type*******\n");
+ printf(" [1] WIFI \n");
+ printf(" [2] BT \n");
+ printf(" [3] BLE \n");
+
+ fflush(stdin);
+ scanf("%d", &cType);
+ if (cType < 1 && cType > 3)
+ {
+ printf("Invalid Selection!!!!\n");
+ return 0;
+ }
+ return (int16_t)cType;
+}
+
+int16_t interfaceStartAdapter(CAConnectivityType_t connType)
+{
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf("None of the interface is initialized\n");
+ return 0;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d", connType);
+ return 0;
+ }
+
+ if (CA_STATUS_OK != tempConnectivityHandlers->handler.startAdapter())
+ {
+ printf("Failed to Start adapter\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+int16_t interfaceMulticastStartServer(CAConnectivityType_t connType, int serverType)
+{
+ printf("interfaceMulticastStartServer Starting...\n");
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf("None of the interface is initialized\n");
+ return 0;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d", connType);
+ return 0;
+ }
+
+ CAAdapterStartDiscoveryServer startServer = NULL;
+ switch (serverType)
+ {
+ case 1: //Discovery server
+ startServer = tempConnectivityHandlers->handler.startDiscoverServer;
+ break;
+ case 2: //Listening server
+ startServer = tempConnectivityHandlers->handler.startListenServer;
+ break;
+ case 3: //Notification server
+ startServer = tempConnectivityHandlers->handler.startNotifyServer;
+ break;
+ }
+
+ if (startServer)
+ {
+ printf("Invoking start server method\n");
+ startServer();
+ }
+}
+
+int16_t interfaceSendUnicastData(CAConnectivityType_t connType)
+{
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf(" None of the interface is initialized \n");
+ return 0;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d", connType);
+ return 0;
+ }
+
+ if (CA_WIFI == connType)
+ {
+ CARemoteEndpoint_t endpoint;
+ char remoteIPAddress[CA_IPADDR_SIZE] = {0};
+ printf("\nEnter the Remote Endpoint IP: ");
+ scanf("%s", remoteIPAddress);
+ if (strlen(remoteIPAddress) == 0)
+ {
+ printf("Invalid device address\n");
+ return;
+ }
+ endpoint.connectivityType = CA_WIFI;
+ strncpy(endpoint.addressInfo.IP.ipAddress, remoteIPAddress, CA_IPADDR_SIZE);
+ endpoint.addressInfo.IP.port = 5283; /* Send the corresponding port here */
+
+ int sdatalen = tempConnectivityHandlers->handler.sendData(&endpoint, coapData,
+ strlen(coapData));
+ if (sdatalen == strlen(coapData))
+ {
+ printf("Send Unicast data success\n");
+ }
+ else
+ {
+ printf("Send Unicast data failed\n");
+ }
+ }
+ else if (CA_EDR == connType)
+ {
+ //create endpoint
+ CARemoteEndpoint_t endpoint;
+
+ //Get the device address from user
+ char deviceaddress[100] = {0};
+ printf("Enter the device address: \n");
+ scanf("%s", deviceaddress);
+
+ if (strlen(deviceaddress) == 0)
+ {
+ printf("Invlaid device address\n");
+ return;
+ }
+
+ endpoint.connectivityType = CA_EDR;
+ strncpy(endpoint.addressInfo.BT.btMacAddress, deviceaddress, CA_MACADDR_SIZE - 1);
+ endpoint.addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ endpoint.resourceUri = NULL;
+
+ printf("Sent Unicast data to device: %s\n", endpoint.addressInfo.BT.btMacAddress);
+ tempConnectivityHandlers->handler.sendData(&endpoint, coapData, strlen(coapData)+1);
+ }
+ else if (CA_LE == connType)
+ {
+ //create endpoint
+ CARemoteEndpoint_t endpoint;
+
+ //Get the device address from user
+ char deviceaddress[100] = {0};
+ printf("Enter the device address: \n");
+ scanf("%s", deviceaddress);
+
+ if (strlen(deviceaddress) == 0)
+ {
+ printf("Invlaid device address\n");
+ return;
+ }
+
+ //Get the service uuid from user
+ char uuid[100] = {0};
+ printf("Enter the service uuid: \n");
+ scanf("%s", uuid);
+
+ if (strlen(uuid) == 0)
+ {
+ printf("Invlaid service uuid\n");
+ return;
+ }
+
+ endpoint.connectivityType = CA_LE;
+ strncpy(endpoint.addressInfo.BT.btMacAddress, deviceaddress, CA_MACADDR_SIZE - 1);
+ endpoint.addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ endpoint.resourceUri = strdup(uuid);
+
+ tempConnectivityHandlers->handler.sendData(&endpoint, coapData, strlen(coapData));
+ printf("Sent Unicast data \n");
+ free(endpoint.resourceUri);
+ }
+
+ return 1;
+}
+
+void interfaceSendNotification(CAConnectivityType_t connType)
+{
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf(" None of the interface is initialized \n");
+ return;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d\n", connType);
+ return;
+ }
+
+ if (CA_WIFI == connType)
+ {
+ CARemoteEndpoint_t remoteEndpoint;
+ tempConnectivityHandlers->handler.sendNotification(&remoteEndpoint, coapData, strlen(coapData));
+ }
+ else if (CA_EDR == connType)
+ {
+ //create endpoint
+ CARemoteEndpoint_t endpoint;
+
+ //Get the device address from user
+ char deviceaddress[100] = {0};
+ printf("Enter the device address: \n");
+ scanf("%s", deviceaddress);
+
+ if (strlen(deviceaddress) == 0)
+ {
+ printf("Invlaid device address\n");
+ return;
+ }
+
+ //Get the service uuid from user
+ char uuid[100] = {0};
+ printf("Enter the service uuid: \n");
+ scanf("%s", uuid);
+
+ if (strlen(uuid) == 0)
+ {
+ printf("Invlaid service uuid\n");
+ return;
+ }
+
+ endpoint.connectivityType = CA_EDR;
+ strncpy(endpoint.addressInfo.BT.btMacAddress, deviceaddress, CA_MACADDR_SIZE - 1);
+ endpoint.addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ endpoint.resourceUri = strdup(uuid);
+
+ tempConnectivityHandlers->handler.sendNotification(&endpoint, coapData, strlen(coapData));
+ printf("Sent Unicast data \n");
+ free(endpoint.resourceUri);
+ }
+ else if (CA_LE == connType)
+ {
+ //create endpoint
+ CARemoteEndpoint_t endpoint;
+
+ //Get the device address from user
+ char deviceaddress[100] = {0};
+ printf("Enter the device address: \n");
+ scanf("%s", deviceaddress);
+
+ if (strlen(deviceaddress) == 0)
+ {
+ printf("Invlaid device address\n");
+ return;
+ }
+
+ //Get the service uuid from user
+ char uuid[100] = {0};
+ printf("Enter the service uuid: \n");
+ scanf("%s", uuid);
+
+ if (strlen(uuid) == 0)
+ {
+ printf("Invlaid service uuid\n");
+ return;
+ }
+
+ endpoint.connectivityType = CA_LE;
+ strncpy(endpoint.addressInfo.BT.btMacAddress, deviceaddress, CA_MACADDR_SIZE - 1);
+ endpoint.addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ endpoint.resourceUri = strdup(uuid);
+
+ tempConnectivityHandlers->handler.sendNotification(&endpoint, coapData, strlen(coapData));
+ printf("Sent Unicast data \n");
+ free(endpoint.resourceUri);
+ printf("Feature is not implemented !!\n");
+ }
+}
+
+int16_t interfaceSendMulticastData(CAConnectivityType_t connType)
+{
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf("None of the interface is initialized\n");
+ return 0;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d", connType);
+ return 0;
+ }
+
+ if (connType == CA_WIFI)
+ {
+ tempConnectivityHandlers->handler.sendDataToAll(coapData,
+ strlen(coapData) + 1);
+ }
+ else if (connType == CA_EDR || connType == CA_LE)
+ {
+ tempConnectivityHandlers->handler.sendDataToAll(coapData, strlen(coapData));
+ }
+}
+
+void interfaceReadData(CAConnectivityType_t connType)
+{
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf("None of the interface is initialized\n");
+ return;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d", connType);
+ return;
+ }
+
+ if (CA_STATUS_OK != tempConnectivityHandlers->handler.readData())
+ {
+ printf("Failed to Read Data\n");
+ return;
+ }
+
+ printf("Read Data is successfull\n");
+ return;
+}
+
+void interfaceGetNetworkInfo(CAConnectivityType_t connType)
+{
+ int i = 0;
+
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf("None of the interface is initialized\n");
+ return;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d", connType);
+ return;
+ }
+
+ //Get the network interface info
+ CALocalConnectivity_t *info = NULL;
+ uint32_t size = 0;
+ if (CA_STATUS_OK != tempConnectivityHandlers->handler.GetnetInfo(&info, &size))
+ {
+ printf("Failed to get network info\n");
+ return;
+ }
+
+ if (0 >= size || info == NULL)
+ {
+ printf("No network found !!!\n");
+ return;
+ }
+
+ printf("Network Information: \n");
+ for (; i < size; i++)
+ {
+ if (connType == CA_WIFI)
+ {
+ printf("Type : %s\n", (connType == CA_ETHERNET) ? "CA_ETHERNET" : "CA_WIFI");
+ printf("Address : %s\n", info[i].addressInfo.IP.ipAddress);
+ }
+ else
+ {
+ printf("Type : %s\n", (connType == CA_EDR) ? "CA_EDR" : "CA_LE");
+ printf("Address : %s\n\n", info[i].addressInfo.BT.btMacAddress);
+ }
+ }
+}
+
+int16_t interfaceStopAdapter(CAConnectivityType_t connType)
+{
+ ConnectivityHandlerList *tempConnectivityHandlers = gConnectivityHandlers;
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf("None of the interface is initialized\n");
+ return 0;
+ }
+
+ while (tempConnectivityHandlers && tempConnectivityHandlers->type != connType)
+ {
+ tempConnectivityHandlers = tempConnectivityHandlers->nextHandler;
+ }
+
+ if (NULL == tempConnectivityHandlers)
+ {
+ printf( "No interface handler for type %d", connType);
+ return 0;
+ }
+
+ if (CA_STATUS_OK != tempConnectivityHandlers->handler.stopAdapter())
+ {
+ printf("Failed to Stop adapter\n");
+ return 0;
+ }
+
+ printf("Stopped the adapter\n");
+ return 1;
+}
+
+void testInitializeInterface()
+{
+ printf("testInitializeInterface Entry\n");
+
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ testInitializeWIFIInterface();
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ testInitializeBTInterface();
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ testInitializeBLEInterface();
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testTerminateInterface()
+{
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+#ifdef WIFI_ADAPTER_TEST
+ if (1 == type) /* WIFI */
+ {
+ testTerminateWIFIInterface();
+ }
+#endif
+#ifdef BT_ADAPTER_TEST
+ if (2 == type) /*BT*/
+ {
+ testTerminateBTInterface();
+ }
+#endif
+#ifdef BLE_ADAPTER_TEST
+ if (3 == type) /*BLE*/
+ {
+ testTerminateBLEInterface();
+ }
+#endif
+
+ ConnectivityHandlerList *currentConnectivityHandler = gConnectivityHandlers;
+ ConnectivityHandlerList *prevConnectivityHandler = NULL;
+
+ printf("Linked list delete start\n");
+ while (currentConnectivityHandler != NULL)
+ {
+ printf("Iterating through the list to find the matching interface\n");
+ if (currentConnectivityHandler->type == type)
+ {
+ printf("Matching interface found\n");
+ if (prevConnectivityHandler == NULL)
+ {
+ currentConnectivityHandler = currentConnectivityHandler->nextHandler;
+ freeData(gConnectivityHandlers);
+ gConnectivityHandlers = NULL;
+ printf( "Node deleted with interface type %d", type);
+ }
+ else
+ {
+ prevConnectivityHandler->nextHandler = currentConnectivityHandler->nextHandler;
+ freeData(currentConnectivityHandler);
+ currentConnectivityHandler = prevConnectivityHandler->nextHandler;
+ printf( "Node deleted with interface type %d from linked list", type);
+ }
+ }
+ else
+ {
+ prevConnectivityHandler = currentConnectivityHandler;
+ currentConnectivityHandler = currentConnectivityHandler->nextHandler;
+ }
+ }
+ gConnectivityHandlers = NULL;
+ return;
+}
+
+void testStartAdapter()
+{
+ int type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceStartAdapter(CA_WIFI);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceStartAdapter(CA_EDR);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceStartAdapter(CA_LE);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testStartServer(int serverType)
+{
+ int type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceMulticastStartServer(CA_WIFI, serverType);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceMulticastStartServer(CA_EDR, serverType);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceMulticastStartServer(CA_LE, serverType);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testSendUnicastData()
+{
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceSendUnicastData(CA_WIFI);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceSendUnicastData(CA_EDR);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceSendUnicastData(CA_LE);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testSendNotification()
+{
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceSendNotification(CA_WIFI);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceSendNotification(CA_EDR);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceSendNotification(CA_LE);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testSendMulticastData()
+{
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceSendMulticastData(CA_WIFI);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceSendMulticastData(CA_EDR);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceSendMulticastData(CA_LE);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testReadData(void)
+{
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceReadData(CA_WIFI);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceReadData(CA_EDR);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceReadData(CA_LE);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testGetNetworkInfo(void)
+{
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceGetNetworkInfo(CA_WIFI);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceGetNetworkInfo(CA_EDR);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceGetNetworkInfo(CA_LE);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+void testStopAdapter()
+{
+ int16_t type = selectConnectivityType();
+ if (0 >= type || 3 < type)
+ {
+ printf("Invalid selection...\n");
+ return;
+ }
+
+ switch (type)
+ {
+#ifdef WIFI_ADAPTER_TEST
+ case 1: //WIFI
+ {
+ interfaceStopAdapter(CA_WIFI);
+ }
+ break;
+#endif
+#ifdef BT_ADAPTER_TEST
+ case 2: //BT
+ {
+ interfaceStopAdapter(CA_EDR);
+ }
+ break;
+#endif
+#ifdef BLE_ADAPTER_TEST
+ case 3: //BLE
+ {
+ interfaceStopAdapter(CA_LE);
+ }
+ break;
+#endif
+ default:
+ printf("Feature is not enabled or not implemented\n");
+ }
+}
+
+#ifdef BT_ADAPTER_TEST
+void testInitializeBTInterface(void)
+{
+ printf("Initiazing EDR\n");
+
+ printf("Initializing BT Adapter threadpool\n");
+ initializeThreadPool(CA_EDR);
+
+ //Start bluetooth communication adapter
+ CAResult_t err = CAInitializeEDR(interfaceRegisterCallback, networkPacketHandler,
+ networkInterfaceCallback, gBTThreadPool);
+ if (CA_STATUS_OK != err && CA_ADAPTER_NOT_ENABLED != err)
+ {
+ printf("Failed to initialize bluetooth communication adapter!\n");
+ }
+}
+
+void testTerminateBTInterface(void)
+{
+ printf("Terminating EDR\n");
+
+ //Terminate the Bluetooth communication adapter
+ CATerminateEDR();
+
+ printf( "Terminating BT Adapter thread pool");
+ u_thread_pool_free(gBTThreadPool);
+}
+#endif //BT_ADAPTER_TEST
+
+#ifdef WIFI_ADAPTER_TEST
+void testInitializeWIFIInterface(void)
+{
+ printf("testInitializeWIFIInterface IN\n");
+
+ printf("Initializing WIFI adapter threadpool\n");
+ initializeThreadPool(CA_WIFI);
+
+ //Start Wifi communication adapter
+ if (0 != CAInitializeWifi(interfaceRegisterCallback, networkPacketHandler,
+ networkInterfaceCallback, gWiFiThreadPool))
+ {
+ printf("testInitializeWIFIInterface Failed to initialize bluetooth communication adapter\n");
+ return;
+ }
+
+ printf("testInitializeWIFIInterface OUT\n");
+}
+
+void testTerminateWIFIInterface(void)
+{
+ printf("testTerminateWIFIInterface IN\n");
+
+ // Stop if Wifi communication adapter is running
+ interfaceStopAdapter(CA_WIFI);
+
+ // Freeing threadpool for wifi communication adapter
+ printf( "Terminating WIFI Adapter thread pool");
+ u_thread_pool_free(gWiFiThreadPool);
+
+ //Terminate the Wifi communication adapter
+ CATerminateWIfI();
+
+
+ printf("testTerminateWIFIInterface OUT\n");
+}
+#endif //WIFI_ADAPTER_TEST
+
+#ifdef BLE_ADAPTER_TEST
+void testInitializeBLEInterface(void)
+{
+ printf("testInitializeBLEInterface IN\n");
+
+ printf("Initializing BLE adapter threadpool\n");
+ initializeThreadPool(CA_LE);
+
+ //Start bluetooth communication adapter
+ if (0 != CAInitializeLE(interfaceRegisterCallback, networkPacketHandler,
+ networkInterfaceCallback, gLEThreadPool))
+ {
+ printf("testInitializeBLEInterface Failed due to CAInitializeLE\n");
+ return;
+ }
+
+ printf("testInitializeBLEInterface OUT\n");
+}
+
+void testTerminateBLEInterface(void)
+{
+ printf("testTerminateBLEInterface IN\n");
+
+ //Terminate the BLE server & Client
+ CATerminateLE();
+
+ printf( "Terminating BLE Adapter thread pool");
+ u_thread_pool_free(gLEThreadPool);
+
+ printf("testTerminateBLEInterface OUT\n");
+}
+#endif //BLE_ADAPTER_TEST
+
+static void testPrintHelp(void)
+{
+ printf(" =====================================================================\n");
+ printf("| Welcome to Connectivity Abstraction |\n");
+ printf("| - CA Unit Test v1.0 - |\n");
+ printf("|---------------------------------------------------------------------|\n");
+ printf("| ** Options ** |\n");
+ printf("| i - Initialize the Interface |\n");
+ printf("| d - Terminate the Interface |\n");
+ printf("| a - Start adapter |\n");
+ printf("| b - Stop adapter |\n");
+ printf("| sd- Start Discovery Server |\n");
+ printf("| sl- Start Listening Server |\n");
+ printf("| sn- Start Notification Server |\n");
+ printf("| u - Send Unicast Data |\n");
+ printf("| m - Send Multicast Data |\n");
+ printf("| n - Send Notification Data |\n");
+ printf("| g - Get Network Info |\n");
+ printf("| r - Read data synchronously |\n");
+ printf("| x - quit the test. |\n");
+ printf("| h - Help menu. |\n");
+ printf(" =====================================================================\n");
+}
+
+static gboolean testThread(GIOChannel *source, GIOCondition condition , gpointer data)
+{
+ gchar buf[10] = {'\0'};
+ gsize read = 0;
+
+
+ if (g_io_channel_read(channel, buf, 10, &read) != G_IO_ERROR_NONE)
+ {
+ printf("g_io_channel_read error!!!\n");
+ return 1;
+ }
+ buf[read] = '\0';
+ g_strstrip(buf);
+
+ /*if ((!has_register) && (((buf[0]!= 'i') && (buf[0]!= 'h') && (buf[0]!= 'q')) || (read != 2))) {
+ testPrintHelp();
+ printf("***Warning***: You should Register firstly!\n");
+ return 1;
+ }*/
+ switch (buf[0])
+ {
+ case 'i':
+ testInitializeInterface();
+ break;
+ case 'x':
+ testTerminateInterface();
+ if (g_source_remove(g_test_io_watch_id))
+ {
+ printf("g_source_remove() OK!!!\n");
+ g_io_channel_shutdown(channel, TRUE, &g_err_Sample);
+ g_io_channel_unref(channel);
+ g_main_loop_quit(mainloop);
+ }
+ break;
+ case 'd':
+ testTerminateInterface();
+ break;
+ case 'a':
+ testStartAdapter();
+ break;
+ case 'b':
+ testStopAdapter();
+ break;
+ case 's':
+ if (read == 3)
+ {
+ if (buf[1] == 'd')
+ {
+ testStartServer(1);
+ }
+ if (buf[1] == 'l')
+ {
+ testStartServer(2);
+ }
+ if (buf[1] == 'n')
+ {
+ testStartServer(3);
+ }
+ }
+ break;
+ case 'u':
+ testSendUnicastData();
+ break;
+ case 'm':
+ testSendMulticastData();
+ break;
+ case 'n':
+ testSendNotification();
+ break;
+ case 'r':
+ testReadData();
+ break;
+ case 'g':
+ testGetNetworkInfo();
+ break;
+ case 'h':
+ testPrintHelp();
+ }
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ printf("Starting sample\n");
+ mainloop = g_main_loop_new(NULL, FALSE);
+ channel = g_io_channel_unix_new(0);/* read from stdin */
+ g_test_io_watch_id = g_io_add_watch(channel,
+ (GIOCondition)(G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), testThread,
+ NULL);
+ printf("CM Test Thread created...\n");
+ testPrintHelp();
+ g_main_loop_run(mainloop);
+ return 0;
+}
+
--- /dev/null
+%define PREFIX /usr/apps/com.samsung.interfacesample
+%define ROOTDIR %{_builddir}/%{name}-%{version}
+
+Name: com.samsung.interfacesample
+Version: 0.1
+Release: 1
+Summary: Tizen interfacesample application
+URL: http://slp-source.sec.samsung.net
+Source: %{name}-%{version}.tar.gz
+License: SAMSUNG
+Group: Samsung/Application
+#BuildRequires: cmake
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: boost-devel
+BuildRequires: boost-thread
+BuildRequires: boost-system
+BuildRequires: boost-filesystem
+#BuildRequires: oic-core
+BuildRequires: pkgconfig(capi-network-wifi)
+BuildRequires: pkgconfig(capi-network-bluetooth)
+BuildRequires: com.samsung.oicca
+#BuildRequires: com.samsung.oicca-devel
+
+%description
+SLP interfacesample application
+
+%prep
+%setup -q
+
+%build
+
+make clean
+make PLATFORM=linux
+
+#make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+# remove later
+#%make_install
+mkdir -p %{buildroot}/usr/share/license
+mkdir -p %{buildroot}/usr/share/license
+mkdir -p %{buildroot}/usr/share/packages
+mkdir -p %{buildroot}/etc/smack/accesses2.d
+mkdir -p %{buildroot}/usr/apps/com.samsung.interfacesample/bin/
+mkdir -p %{buildroot}/usr/lib
+#cp -rf LICENSE %{buildroot}/usr/share/license/%{name}
+cp -rf %{ROOTDIR}/com.samsung.interfacesample.xml %{buildroot}/usr/share/packages
+cp -rf %{ROOTDIR}/com.samsung.interfacesample.rule %{buildroot}/etc/smack/accesses2.d
+cp -rf %{ROOTDIR}/interface_sample %{buildroot}/usr/apps/com.samsung.interfacesample/bin/
+cp -rf %{ROOTDIR}/ca_sample %{buildroot}/usr/apps/com.samsung.interfacesample/bin/
+#cp -rf %{ROOTDIR}/liboicinterface.a %{buildroot}/usr/lib
+
+%files
+%manifest com.samsung.interfacesample.manifest
+/etc/smack/accesses2.d/com.samsung.interfacesample.rule
+%defattr(-,root,root,-)
+%attr(-,inhouse,inhouse)
+/usr/apps/com.samsung.interfacesample/bin/interface_sample
+/usr/apps/com.samsung.interfacesample/bin/ca_sample
+#%{_libdir}/lib*.a*
+/usr/share/packages/com.samsung.interfacesample.xml
+#/opt/share/process-info/cmsample.ini
+#/usr/share/license/%{name}
--- /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 "caadapterutils.h"
+
+#include <string.h>
+#ifndef __ARDUINO__
+#include "oic_malloc.h"
+#endif //#ifndef __ARDUINO__
+#define CA_ADAPTER_UTILS_TAG "CA_ADAPTER_UTILS"
+
+CALocalConnectivity_t *CAAdapterCreateLocalEndpoint(CAConnectivityType_t type, const char *address,
+ const char *interfaceName)
+{
+ CALocalConnectivity_t *info = (CALocalConnectivity_t *) OICMalloc(
+ sizeof(CALocalConnectivity_t));
+ if (NULL == info)
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
+ return NULL;
+ }
+ memset(info, 0, sizeof(CALocalConnectivity_t));
+
+ info->type = type;
+ if (address && strlen(address))
+ {
+ if (CA_EDR == type)
+ {
+ strncpy(info->addressInfo.BT.btMacAddress, address, CA_MACADDR_SIZE - 1);
+ info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if (CA_LE == type)
+ {
+ strncpy(info->addressInfo.LE.leMacAddress, address, CA_MACADDR_SIZE - 1);
+ info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if (CA_WIFI == type || CA_ETHERNET == type)
+ {
+ strncpy(info->addressInfo.IP.ipAddress, address, CA_IPADDR_SIZE - 1);
+ info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
+ }
+ }
+
+ return info;
+}
+
+CALocalConnectivity_t *CAAdapterCopyLocalEndpoint(CALocalConnectivity_t *connectivity)
+{
+ VERIFY_NON_NULL_RET(connectivity, CA_ADAPTER_UTILS_TAG, "connectivity is NULL", NULL);
+
+ CALocalConnectivity_t *info = (CALocalConnectivity_t *) OICMalloc(
+ sizeof(CALocalConnectivity_t));
+ if (NULL == info)
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
+ return NULL;
+ }
+ memset(info, 0, sizeof(CALocalConnectivity_t));
+
+ info->type = connectivity->type;
+ if (CA_EDR == info->type && strlen(connectivity->addressInfo.BT.btMacAddress))
+ {
+ strncpy(info->addressInfo.BT.btMacAddress, connectivity->addressInfo.BT.btMacAddress,
+ CA_MACADDR_SIZE - 1);
+ info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if (CA_LE == info->type && strlen(connectivity->addressInfo.LE.leMacAddress))
+ {
+ strncpy(info->addressInfo.LE.leMacAddress, connectivity->addressInfo.LE.leMacAddress,
+ CA_MACADDR_SIZE - 1);
+ info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if ((CA_WIFI == info->type || CA_ETHERNET == info->type)
+ && strlen(connectivity->addressInfo.IP.ipAddress))
+ {
+ strncpy(info->addressInfo.IP.ipAddress, connectivity->addressInfo.IP.ipAddress,
+ CA_IPADDR_SIZE - 1);
+ info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
+ }
+
+ return info;
+}
+
+void CAAdapterFreeLocalEndpoint(CALocalConnectivity_t *localEndpoint)
+{
+ if (localEndpoint)
+ {
+ OICFree(localEndpoint);
+ }
+}
+
+CARemoteEndpoint_t *CAAdapterCreateRemoteEndpoint(CAConnectivityType_t type, const char *address,
+ const char *resourceUri)
+{
+ CARemoteEndpoint_t *info = (CARemoteEndpoint_t *) OICMalloc(sizeof(CARemoteEndpoint_t));
+ if (NULL == info)
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
+ return NULL;
+ }
+ memset(info, 0, sizeof(CARemoteEndpoint_t));
+
+ info->connectivityType = type;
+ if (address && strlen(address))
+ {
+ if (CA_EDR == type)
+ {
+ strncpy(info->addressInfo.BT.btMacAddress, address, CA_MACADDR_SIZE - 1);
+ info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if (CA_LE == info->connectivityType)
+ {
+ strncpy(info->addressInfo.LE.leMacAddress, address, CA_MACADDR_SIZE - 1);
+ info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if (CA_WIFI == type || CA_ETHERNET == type)
+ {
+ strncpy(info->addressInfo.IP.ipAddress, address, CA_IPADDR_SIZE - 1);
+ info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
+ }
+ }
+
+ if (resourceUri && strlen(resourceUri))
+ {
+ info->resourceUri = OICStrdup(resourceUri);
+ }
+
+ return info;
+}
+
+CARemoteEndpoint_t *CAAdapterCopyRemoteEndpoint(const CARemoteEndpoint_t *remoteEndpoint)
+{
+ VERIFY_NON_NULL_RET(remoteEndpoint, CA_ADAPTER_UTILS_TAG, "Remote endpoint is NULL", NULL);
+
+ CARemoteEndpoint_t *info = (CARemoteEndpoint_t *) OICMalloc(sizeof(CARemoteEndpoint_t));
+ if (NULL == info)
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
+ return NULL;
+ }
+ memset(info, 0, sizeof(CARemoteEndpoint_t));
+
+ info->connectivityType = remoteEndpoint->connectivityType;
+ if (CA_EDR == info->connectivityType && strlen(remoteEndpoint->addressInfo.BT.btMacAddress))
+ {
+ strncpy(info->addressInfo.BT.btMacAddress, remoteEndpoint->addressInfo.BT.btMacAddress,
+ CA_MACADDR_SIZE - 1);
+ info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if (CA_LE == info->connectivityType && strlen(remoteEndpoint->addressInfo.LE.leMacAddress))
+ {
+ strncpy(info->addressInfo.LE.leMacAddress, remoteEndpoint->addressInfo.LE.leMacAddress,
+ CA_MACADDR_SIZE - 1);
+ info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ }
+ else if ((CA_WIFI == info->connectivityType || CA_ETHERNET == info->connectivityType)
+ && strlen(remoteEndpoint->addressInfo.IP.ipAddress))
+ {
+ strncpy(info->addressInfo.IP.ipAddress, remoteEndpoint->addressInfo.IP.ipAddress,
+ CA_IPADDR_SIZE - 1);
+ info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
+ info->addressInfo.IP.port = remoteEndpoint->addressInfo.IP.port;
+ }
+
+ if (remoteEndpoint->resourceUri && strlen(remoteEndpoint->resourceUri))
+ {
+ info->resourceUri = OICStrdup(remoteEndpoint->resourceUri);
+ }
+
+ return info;
+}
+
+void CAAdapterFreeRemoteEndpoint(CARemoteEndpoint_t *remoteEndpoint)
+{
+ if (remoteEndpoint)
+ {
+ if (remoteEndpoint->resourceUri)
+ {
+ OICFree(remoteEndpoint->resourceUri);
+ }
+
+ OICFree(remoteEndpoint);
+ }
+}
+
--- /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 "camessagequeue.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "logger.h"
+#include "caadapterutils.h"
+#include "oic_malloc.h"
+
+#define TAG "CAAdapterUtil"
+
+CAResult_t CAAdapterInitializeMessageQueue(CAAdapterMessageQueue_t **queueHandle)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL(queueHandle, TAG, "Invalid queue handle container");
+
+ CAAdapterMessageQueue_t *queuePtr = (CAAdapterMessageQueue_t *) OICMalloc(
+ sizeof(CAAdapterMessageQueue_t));
+ if (!queuePtr)
+ {
+ OIC_LOG_V(ERROR, TAG, "Out of memory!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ memset((void *) queuePtr, 0, sizeof(CAAdapterMessageQueue_t));
+ // Initialize mutex utility
+ u_mutex_init();
+ queuePtr->queueMutex = u_mutex_new();
+ if (NULL == queuePtr->queueMutex)
+ {
+ OICFree(queuePtr);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ queuePtr->begin = NULL;
+ queuePtr->end = NULL;
+ *queueHandle = queuePtr;
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CAAdapterFreeMessage(CAAdapterMessage_t *message)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL_VOID(message, TAG, "Invalid message");
+
+ if (message->remoteEndpoint)
+ {
+ CAAdapterFreeRemoteEndpoint(message->remoteEndpoint);
+ }
+
+ if (message->data)
+ {
+ OICFree(message->data);
+ }
+ OICFree(message);
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CAAdapterTerminateMessageQueue(CAAdapterMessageQueue_t *queueHandle)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL_VOID(queueHandle, TAG, "Invalid queue handle");
+ VERIFY_NON_NULL_VOID(queueHandle->queueMutex, TAG, "Invalid queue mutex");
+ CAAdapterMessage_t *messagePtr = NULL;
+ CAAdapterMessage_t *toRemove = NULL;
+
+ u_mutex_lock(queueHandle->queueMutex);
+ messagePtr = queueHandle->begin;
+ while (messagePtr)
+ {
+ toRemove = messagePtr;
+ messagePtr = messagePtr->next;
+ CAAdapterFreeMessage(toRemove);
+ }
+
+ queueHandle->begin = NULL;
+ queueHandle->end = NULL;
+ u_mutex_unlock(queueHandle->queueMutex);
+ u_mutex_free(queueHandle->queueMutex);
+ queueHandle->queueMutex = NULL;
+ OICFree(queueHandle);
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+CAResult_t CAAdapterEnqueueMessage(CAAdapterMessageQueue_t *queueHandle,
+ const CARemoteEndpoint_t *remoteEndpoint, void *data, uint32_t dataLen)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL(queueHandle, TAG, "Invalid queue handle");
+ VERIFY_NON_NULL(queueHandle->queueMutex, TAG, "Invalid queue mutex");
+ VERIFY_NON_NULL(data, TAG, "Invalid data");
+
+ CAAdapterMessage_t *adapterMessage = (CAAdapterMessage_t *) OICMalloc(
+ sizeof(CAAdapterMessage_t));
+ if (!adapterMessage)
+ {
+ OIC_LOG_V(ERROR, TAG, "Out of memory!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memset((void *) adapterMessage, 0, sizeof(CAAdapterMessage_t));
+
+ // Copy data
+ adapterMessage->data = (void *) OICMalloc(dataLen);
+ if (adapterMessage->data == NULL)
+ {
+ OIC_LOG_V(ERROR, TAG, "Out of memory!!!");
+ CAAdapterFreeMessage(adapterMessage);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memcpy(adapterMessage->data, data, dataLen);
+ adapterMessage->dataLen = dataLen;
+
+ // Copy remote endpoint info
+ adapterMessage->remoteEndpoint = NULL;
+ if (remoteEndpoint)
+ {
+ adapterMessage->remoteEndpoint = CAAdapterCopyRemoteEndpoint(remoteEndpoint);
+ if (NULL == adapterMessage->remoteEndpoint)
+ {
+ OIC_LOG_V(ERROR, TAG, "Out of memory.!!");
+ OICFree(adapterMessage->data);
+ CAAdapterFreeMessage(adapterMessage);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ }
+ //Insert at end of queue
+ u_mutex_lock(queueHandle->queueMutex);
+ if (queueHandle->end)
+ {
+ queueHandle->end->next = adapterMessage;
+ queueHandle->end = adapterMessage;
+ }
+ else
+ {
+ queueHandle->begin = adapterMessage;
+ queueHandle->end = adapterMessage;
+ }
+ u_mutex_unlock(queueHandle->queueMutex);
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAAdapterDequeueMessage(CAAdapterMessageQueue_t *queueHandle,
+ CAAdapterMessage_t **message)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL(queueHandle, TAG, "Invalid queue handle");
+ VERIFY_NON_NULL(queueHandle->queueMutex, TAG, "Invalid queue mutex");
+ VERIFY_NON_NULL(message, TAG, "Invalid message handle");
+ u_mutex_lock(queueHandle->queueMutex);
+ if (queueHandle->begin)
+ {
+ *message = queueHandle->begin;
+ queueHandle->begin = queueHandle->begin->next;
+ if (queueHandle->begin == NULL)
+ {
+ queueHandle->end = NULL;
+ }
+ // keep next as NULL for upper layer
+ (*message)->next = NULL;
+ }
+ else
+ {
+ u_mutex_unlock(queueHandle->queueMutex);
+ return CA_STATUS_FAILED;
+ }
+ u_mutex_unlock(queueHandle->queueMutex);
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
#define TAG PCF("CA")
static CANetworkPacketReceivedCallback gEDRReceivedCallback = NULL;
+static u_thread_pool_t gThreadPoolHandle = NULL;
CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback)
+ CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle)
{
OIC_LOG_V(DEBUG, TAG, "CAInitializeEDR");
gEDRReceivedCallback = reqRespCallback;
+ gThreadPoolHandle = handle;
// register handlers
CAConnectivityHandler_t handler;
return 0;
}
-CAResult_t CAGetEDRInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size)
+CAResult_t CAGetEDRInterfaceInformation(CALocalConnectivity_t** info, uint32_t* size)
{
OIC_LOG_V(DEBUG, TAG, "CAGetEDRInterfaceInformation");
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtclient.c
+ * @brief This file provides the APIs to establish RFCOMM connection with remote bluetooth device
+ */
+
+#include "cabtclient.h"
+#include "caadapterutils.h"
+#include "cabtutils.h"
+#include "logger.h"
+
+CAResult_t CABTClientConnect(const char *remoteAddress, const char *serviceUUID)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+
+ VERIFY_NON_NULL(remoteAddress, BLUETOOTH_ADAPTER_TAG, "Remote address is null");
+ VERIFY_NON_NULL(serviceUUID, BLUETOOTH_ADAPTER_TAG, "Service UUID is null");
+
+ if (0 >= strlen(remoteAddress))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Empty remote address");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ if (0 >= strlen(serviceUUID))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Empty service uuid");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ if (BT_ERROR_NONE != (err = bt_socket_connect_rfcomm(remoteAddress, serviceUUID)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG,
+ "Failed to connect!, address [%s] uuid [%s] error num [%x]",
+ remoteAddress, serviceUUID, err);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtclient.h
+ * @brief This file provides the APIs to establish RFCOMM connection with remote bluetooth device
+ */
+
+#ifndef __CA_BT_CLIENT_H_
+#define __CA_BT_CLIENT_H_
+
+#include <string.h>
+#include <bluetooth.h>
+
+#include "cacommon.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @fn CABTClientConnect
+ * @brief Establishes RFCOMM connection with remote bluetooth device
+ *
+ * @param remoteAddress The address of remote bluetooth device to which connection needs to be established
+ * @param serviceUUID The UUID of service to which RFCOMM connection needs to established
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTClientConnect(const char *remoteAddress, const char *serviceUUID);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif //__CA_BT_CLIENT_H_
\ No newline at end of file
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtdevicelist.c
+ * @brief This file provides APIs to access the discovered bluetooth device list
+ */
+
+#include "cabtdevicelist.h"
+#include "caadapterutils.h"
+#include "cabtutils.h"
+#include "logger.h"
+
+CAResult_t CAAddBTDeviceToList(BTDeviceList **deviceList, BTDevice *device)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(deviceList, BLUETOOTH_ADAPTER_TAG, "Device list is null");
+ VERIFY_NON_NULL(device, BLUETOOTH_ADAPTER_TAG, "Device is null");
+
+ BTDeviceList *node = (BTDeviceList *) OICMalloc(sizeof(BTDeviceList));
+ if (NULL == node)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Out of memory (device list)!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ node->device = device;
+ node->next = NULL;
+
+ if (NULL == *deviceList) //Empty list
+ {
+ *deviceList = node;
+ }
+ else //Add at front end
+ {
+ node->next = *deviceList;
+ *deviceList = node;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveBTDeviceFromList(BTDeviceList **deviceList, const char *remoteAddress)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(deviceList, BLUETOOTH_ADAPTER_TAG, "Device list is null");
+ VERIFY_NON_NULL(remoteAddress, BLUETOOTH_ADAPTER_TAG, "Remote address is null");
+
+ BTDeviceList *cur = NULL;
+ BTDeviceList *prev = NULL;
+
+ cur = *deviceList;
+ while (cur != NULL)
+ {
+ if (!strcasecmp(cur->device->remoteAddress, remoteAddress))
+ {
+ if (cur == *deviceList)
+ {
+ *deviceList = cur->next;
+
+ cur->next = NULL;
+ CAFreeBTDeviceList(cur);
+ return CA_STATUS_OK;
+ }
+ else
+ {
+ prev->next = cur->next;
+
+ cur->next = NULL;
+ CAFreeBTDeviceList(cur);
+ return CA_STATUS_OK;
+ }
+ }
+ else
+ {
+ prev = cur;
+ cur = cur->next;
+ }
+ }
+
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Device not in the list !");
+ return CA_STATUS_FAILED;
+}
+
+CAResult_t CAGetBTDevice(BTDeviceList *deviceList, const char *remoteAddress, BTDevice **device)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(deviceList, BLUETOOTH_ADAPTER_TAG, "Device list is null");
+ VERIFY_NON_NULL(remoteAddress, BLUETOOTH_ADAPTER_TAG, "Remote address is null");
+ VERIFY_NON_NULL(device, BLUETOOTH_ADAPTER_TAG, "Device is null");
+
+ BTDeviceList *cur = deviceList;
+ *device = NULL;
+ while (cur != NULL)
+ {
+ if (!strcasecmp(cur->device->remoteAddress, remoteAddress))
+ {
+ *device = cur->device;
+ return CA_STATUS_OK;
+ }
+
+ cur = cur->next;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT [Device not found!]");
+ return CA_STATUS_FAILED;
+}
+
+CAResult_t CAGetBTDeviceBySocketId(BTDeviceList *deviceList, int32_t socketFd, BTDevice **device)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(deviceList, BLUETOOTH_ADAPTER_TAG, "Device list is null");
+ VERIFY_NON_NULL(device, BLUETOOTH_ADAPTER_TAG, "Device is null");
+
+ BTDeviceList *cur = deviceList;
+ *device = NULL;
+ while (cur != NULL)
+ {
+ if (cur->device->socketFD == socketFd)
+ {
+ *device = cur->device;
+ return CA_STATUS_OK;
+ }
+
+ cur = cur->next;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_FAILED;
+}
+
+CAResult_t CACreateBTDevice(const char *remoteAddress, const char *uuid, BTDevice **device)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(remoteAddress, BLUETOOTH_ADAPTER_TAG, "Remote address is null");
+ VERIFY_NON_NULL(uuid, BLUETOOTH_ADAPTER_TAG, "uuid is null");
+ VERIFY_NON_NULL(device, BLUETOOTH_ADAPTER_TAG, "Device is null");
+
+ *device = (BTDevice *) OICMalloc(sizeof(BTDevice));
+ if (NULL == *device)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Out of memory (device)!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ //Copy bluetooth address
+ if (remoteAddress && strlen(remoteAddress))
+ {
+ (*device)->remoteAddress = strndup(remoteAddress, strlen(remoteAddress));
+ if (NULL == (*device)->remoteAddress)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Out of memory (remote address)!");
+
+ OICFree(*device);
+ *device = NULL;
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ }
+
+ //Copy OIC service uuid
+ if (uuid && strlen(uuid))
+ {
+ (*device)->serviceUUID = strndup(uuid, strlen(uuid));
+ if (NULL == (*device)->serviceUUID)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG,
+ "[createBTDevice] Out of memory (service uuid)!");
+
+ OICFree((*device)->remoteAddress);
+ OICFree(*device);
+ *device = NULL;
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ }
+
+ (*device)->socketFD = -1;
+ (*device)->pendingDataList = NULL;
+ (*device)->serviceSearched = 0;
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CACreateAndAddToDeviceList(BTDeviceList **devicList, const char *remoteAddress,
+ const char *serviceUUID, BTDevice **device)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(devicList, BLUETOOTH_ADAPTER_TAG, "Device list is null");
+ VERIFY_NON_NULL(remoteAddress, BLUETOOTH_ADAPTER_TAG, "Remote address is null");
+ VERIFY_NON_NULL(device, BLUETOOTH_ADAPTER_TAG, "Device is null");
+
+ if (CA_STATUS_OK != CACreateBTDevice(remoteAddress, serviceUUID, device) || NULL == *device)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid or Not bonded device!");
+ return CA_STATUS_FAILED;
+ }
+
+ if (CA_STATUS_OK != CAAddBTDeviceToList(devicList, *device))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to add in list!");
+
+ //Remove created BTDevice
+ CAFreeBTDevice(*device);
+ *device = NULL;
+
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CAFreeBTDeviceList(BTDeviceList *deviceList)
+{
+ while (deviceList)
+ {
+ BTDeviceList *curList = deviceList;
+ deviceList = deviceList->next;
+
+ CAFreeBTDevice(curList->device);
+ OICFree(curList);
+ }
+}
+
+void CAFreeBTDevice(BTDevice *device)
+{
+ if (device)
+ {
+ if (device->remoteAddress)
+ {
+ OICFree(device->remoteAddress);
+ }
+
+ if (device->serviceUUID)
+ {
+ OICFree(device->serviceUUID);
+ }
+
+ if (device->pendingDataList)
+ {
+ CARemoveAllDataFromDevicePendingList(&device->pendingDataList);
+ }
+
+ OICFree(device);
+ }
+}
+
+CAResult_t CAAddDataToDevicePendingList(BTDataList **dataList, void *data, uint32_t dataLen)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(dataList, BLUETOOTH_ADAPTER_TAG, "Data list is null");
+ VERIFY_NON_NULL(data, BLUETOOTH_ADAPTER_TAG, "Data is null");
+
+ if (0 == dataLen)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: data length is zero!");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ BTDataList *pending_data = (BTDataList *) OICMalloc(sizeof(BTDataList));
+ if (NULL == pending_data)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "OICMalloc failed (data list)!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ pending_data->data = (BTData *) OICMalloc(sizeof(BTData));
+ if (NULL == pending_data->data)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "OICMalloc failed (data node)!");
+
+ OICFree(pending_data);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ pending_data->next = NULL;
+
+ pending_data->data->data = (void *) OICMalloc(dataLen); //data
+ if (NULL == pending_data->data->data)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "OICMalloc failed (data)!");
+
+ OICFree(pending_data->data);
+ OICFree(pending_data);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ memcpy(pending_data->data->data, data, dataLen);
+ pending_data->data->dataLength = dataLen;
+
+ if (NULL == *dataList) //Empty list
+ {
+ *dataList = pending_data;
+ }
+ else //Add at rear end
+ {
+ BTDataList *curList = *dataList;
+ while (curList->next != NULL)
+ {
+ curList = curList->next;
+ }
+
+ curList->next = pending_data;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveDataFromDevicePendingList(BTDataList **dataList)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(dataList, BLUETOOTH_ADAPTER_TAG, "Data list is null");
+
+ BTDataList *cur = NULL;
+ BTDataList *prev = NULL;
+
+ cur = *dataList;
+ if (NULL != cur->next) //next node present in list
+ {
+ prev = cur;
+ cur = cur->next;
+ CAFreeDataFromBTDataList(prev);
+ *dataList = cur;
+ }
+ else //last node
+ {
+ CAFreeDataFromBTDataList(cur);
+ *dataList = NULL;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveAllDataFromDevicePendingList(BTDataList **dataList)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(dataList, BLUETOOTH_ADAPTER_TAG, "Data list is null");
+
+ BTDataList *cur = NULL;
+ BTDataList *prev = NULL;
+
+ cur = *dataList;
+ while (cur)
+ {
+ prev = cur;
+ cur = cur->next;
+ CAFreeDataFromBTDataList(prev);
+ }
+
+ *dataList = NULL;
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CAFreeDataFromBTDataList(BTDataList *dataList)
+{
+ if (dataList)
+ {
+ if (dataList->data)
+ {
+ if (dataList->data->data)
+ {
+ OICFree(dataList->data->data);
+ }
+ OICFree(dataList->data);
+ }
+ OICFree(dataList);
+ dataList = NULL;
+ }
+}
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtdevicelist.h
+ * @brief This file provides APIs to access the discovered bluetooth device list
+ */
+
+#ifndef __CA_BT_DEVICE_LIST_H_
+#define __CA_BT_DEVICE_LIST_H_
+
+#include "cacommon.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @struct BTData
+ * @brief Structure to maintain the data needs to send to peer Bluetooth device.
+ */
+typedef struct
+{
+ void *data; /**< Data to be send to peer Bluetooth device. */
+ uint32_t dataLength; /**< Length of the data. */
+} BTData;
+
+/**
+ * @struct BTDataList
+ * @brief Structure to maintain list of data needs to send to peer Bluetooth device.
+ */
+typedef struct _BTDataList
+{
+ BTData *data; /**< Data to be send to peer Bluetooth device. */
+ struct _BTDataList *next;/**< Reference to next data in list. */
+} BTDataList;
+
+/**
+ * @struct BTDevice
+ * @brief Structure to maintain information of peer Bluetooth device.
+ */
+typedef struct
+{
+ char *remoteAddress; /**< Address of peer Bluetooth device. */
+ char *serviceUUID; /**< OIC service UUID running in peer Bluetooth device. */
+ int32_t socketFD; /**< RfComm connection socket FD. */
+ BTDataList *pendingDataList;/**< List of data needs to send to peer Bluetooth device. */
+ uint32_t serviceSearched; /**< Flag to indicate the status of service search. */
+} BTDevice;
+
+/**
+ * @struct BTDeviceList
+ * @brief Structure to maintain list of peer Bluetooth device information.
+ */
+typedef struct _BTDeviceList
+{
+ BTDevice *device; /**< Bluetooth device information. */
+ struct _BTDeviceList *next; /**< Reference to next device information. */
+} BTDeviceList;
+
+CAResult_t CAAddBTDeviceToList(BTDeviceList **deviceList, BTDevice *device);
+CAResult_t CARemoveBTDeviceFromList(BTDeviceList **deviceList, const char *remoteAddress);
+CAResult_t CAGetBTDevice(BTDeviceList *deviceList, const char *remoteAddress, BTDevice **device);
+CAResult_t CAGetBTDeviceBySocketId(BTDeviceList *deviceList, int32_t socket_id, BTDevice **device);
+CAResult_t CACreateBTDevice(const char *remoteAddress, const char *uuid, BTDevice **device);
+CAResult_t CACreateAndAddToDeviceList(BTDeviceList **deviceList, const char *remoteAddress,
+ const char *serviceUUID, BTDevice **device);
+void CAFreeBTDeviceList(BTDeviceList *deviceList);
+void CAFreeBTDevice(BTDevice *device);
+
+CAResult_t CAAddDataToDevicePendingList(BTDataList **dataList, void *data, uint32_t data_len);
+CAResult_t CARemoveDataFromDevicePendingList(BTDataList **dataList);
+CAResult_t CARemoveAllDataFromDevicePendingList(BTDataList **dataList);
+void CAFreeDataFromBTDataList(BTDataList *dataList);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif //__CA_BT_DEVICE_LIST_H_
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtendpoint.c
+ * @brief This file provides the APIs to send data on established RFCOMM connections.
+ */
+
+#include "cabtendpoint.h"
+#include "caadapterutils.h"
+#include "cabtutils.h"
+#include "logger.h"
+
+CAResult_t CABTSendData(const int32_t serverFD, const void *data, const uint32_t dataLength,
+ uint32_t *sentDataLen)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(data, BLUETOOTH_ADAPTER_TAG, "Data is null");
+ VERIFY_NON_NULL(sentDataLen, BLUETOOTH_ADAPTER_TAG, "Sent data length holder is null");
+
+ if (0 > serverFD)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Negative socket id");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ int dataLen = 0;
+ dataLen = bt_socket_send_data(serverFD, (const char *)data, dataLength);
+ if (dataLen == -1)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "sending data failed!, soketid [%d]", serverFD);
+ *sentDataLen = 0;
+ return CA_STATUS_FAILED;
+ }
+
+ *sentDataLen = dataLen;
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtendpoint.h
+ * @brief This file provides the APIs to send data on established RFCOMM connections.
+ */
+
+#ifndef __CA_BT_ENDPOINT_H_
+#define __CA_BT_ENDPOINT_H_
+
+#include <bluetooth.h>
+
+#include "cacommon.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @fn CABTSendData
+ * @brief Send data over RFCOMM connection
+ *
+ * @param serverFD The RFCOMM connection socket file descriptor
+ * @param data The data needs to be sent
+ * @param dataLength The length of data
+ * @param sentDataLen The length of data which actually sent successful
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTSendData(const int32_t serverFD, const void *data, const uint32_t dataLength,
+ uint32_t *sentDataLen);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif //__CA_BT_ENDPOINT_H_
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtmanager.c
+ * @brief This file provides the APIs to control Bluetooth transport
+ */
+
+#include "cabtmanager.h"
+#include "cabtclient.h"
+#include "cabtserver.h"
+#include "cabtendpoint.h"
+#include "cabtdevicelist.h"
+#include "cabtutils.h"
+#include "caadapterutils.h"
+#include "camessagequeue.h"
+
+
+typedef struct
+{
+ CALocalConnectivity_t *info;
+ CANetworkStatus_t status;
+} CABTNetworkEvent;
+
+typedef struct
+{
+ void *data;
+ int32_t dataLen;
+ CARemoteEndpoint_t *remoteEndpoint;
+} CABTMessage;
+
+/**
+ * @var gNetworkPacketReceivedCallback
+ * @brief Maintains the callback to be notified on receival of network packets from other
+ * Bluetooth devices.
+ */
+static CANetworkPacketReceivedCallback gNetworkPacketReceivedCallback = NULL;
+
+/**
+ * @var gNetworkChangeCallback
+ * @brief Maintains the callback to be notified on local bluetooth adapter status change.
+ */
+static CANetworkChangeCallback gNetworkChangeCallback = NULL;
+
+/**
+ * @var gBTDeviceListMutex
+ * @brief Mutex to synchronize the access to Bluetooth device information list.
+ */
+static u_mutex gBTDeviceListMutex = NULL;
+
+/**
+ * @var gBTDeviceList
+ * @brief Peer Bluetooth device information list.
+ */
+static BTDeviceList *gBTDeviceList = NULL;
+
+/**
+ * @var gLocalConnectivity
+ * @brief Information of local Bluetooth adapter.
+ */
+static CALocalConnectivity_t *gLocalConnectivity = NULL;
+
+/**
+ * @var gBTThreadPool
+ * @brief Reference to threadpool.
+ */
+static u_thread_pool_t gBTThreadPool = NULL;
+
+/**
+ * @var gSendDataQueue
+ * @brief Queue to maintain data to be send to remote Bluetooth devices.
+ */
+static CAAdapterMessageQueue_t *gSendDataQueue = NULL;
+
+/**
+ * @var gSendDataMutex
+ * @brief Mutex to synchronize access to data send queue.
+ */
+static u_mutex gSendDataMutex = NULL;
+
+/**
+ * @var gSendDataCond
+ * @brief Condition used for notifying handler the presence of data in send queue.
+ */
+static u_cond gSendDataCond = NULL;
+
+/**
+ * @var gDataSendHandlerState
+ * @brief Stop condition of sendhandler.
+ */
+static CABool_t gDataSendHandlerState = CA_FALSE;
+
+/**
+ * @fn CABTAdapterStateChangeCallback
+ * @brief This callback is registered to receive bluetooth adapter state changes.
+ */
+static void CABTAdapterStateChangeCallback(int result, bt_adapter_state_e adapterState,
+ void *userData);
+
+/**
+ * @fn CABTSocketConnectionStateCallback
+ * @brief This callback is registered to receive bluetooth RFCOMM connection state changes.
+ */
+static void CABTSocketConnectionStateCallback(int result,
+ bt_socket_connection_state_e connectionState,
+ bt_socket_connection_s *connection, void *userData);
+
+/**
+ * @fn CABTDataRecvCallback
+ * @brief This callback is registered to recieve data on any open RFCOMM connection.
+ */
+static void CABTDataRecvCallback(bt_socket_received_data_s *data, void *userData);
+
+/**
+ * @fn CABTDeviceDiscoveryCallback
+ * @brief This callback is registered to recieve all bluetooth nearby devices when device
+ * scan is initiated.
+ */
+static void CABTDeviceDiscoveryCallback(int result,
+ bt_adapter_device_discovery_state_e discoveryState,
+ bt_adapter_device_discovery_info_s *discoveryInfo, void *userData);
+
+/**
+ * @fn CABTServiceSearchedCallback
+ * @brief This callback is registered to recieve all the services remote bluetooth device supports
+ * when service search initiated.
+ */
+static void CABTServiceSearchedCallback(int result, bt_device_sdp_info_s *sdpInfo, void *userData);
+
+
+/**
+ * @fn CABTManagerInitializeQueues
+ * @brief This function creates send and receive message queues.
+ */
+static CAResult_t CABTManagerInitializeQueues(void);
+
+/**
+ * @fn CABTManagerTerminateQueues
+ * @brief This function releases send and receive message queues.
+ */
+static void CABTManagerTerminateQueues(void);
+
+/**
+ * @fn CABTManagerInitializeMutex
+ * @brief This function creates mutex.
+ */
+static void CABTManagerInitializeMutex(void);
+
+/**
+ * @fn CABTManagerTerminateMutex
+ * @brief This function frees mutex.
+ */
+static void CABTManagerTerminateMutex(void);
+
+/**
+ * @fn CABTManagerDataSendHandler
+ * @brief This function handles message from send queue.
+ */
+static void CABTManagerDataSendHandler(void *context);
+
+/**
+ * @fn CABTManagerSendUnicastData
+ * @brief This function send data to specified remote bluetooth device.
+ */
+static CAResult_t CABTManagerSendUnicastData(const char *remoteAddress, const char *serviceUUID,
+ void *data, uint32_t dataLength, uint32_t *sentLength);
+
+/**
+ * @fn CABTManagerSendMulticastData
+ * @brief This function send data to all bluetooth devices running OIC service.
+ */
+static CAResult_t CABTManagerSendMulticastData(const char *serviceUUID, void *data,
+ uint32_t dataLength,
+ uint32_t *sentLength);
+
+/**
+ * @fn CABTStartServiceSearch
+ * @brief This function search for OIC service for remote Bluetooth device.
+ */
+static CAResult_t CABTStartServiceSearch(const char *remoteAddress);
+
+/**
+ * @fn CABTNotifyNetworkStauts
+ * @brief This function creates notification task for network adapter status and add it to thread pool.
+ */
+static CAResult_t CABTNotifyNetworkStauts(CANetworkStatus_t status);
+
+/**
+ * @fn CABTOnNetworkStautsChanged
+ * @brief This is task callback function for notifying network adapter status to upper layer.
+ */
+static void CABTOnNetworkStautsChanged(void *context);
+
+/**
+ * @fn CABTCreateNetworkEvent
+ * @brief Creates instance of CABTNetworkEvent.
+ */
+static CABTNetworkEvent *CABTCreateNetworkEvent(CALocalConnectivity_t *connectivity,
+ CANetworkStatus_t status);
+
+/**
+ * @fn CABTFreeNetworkEvent
+ * @brief destroy instance of CABTNetworkEvent.
+ */
+static void CABTFreeNetworkEvent(CABTNetworkEvent *event);
+
+
+CAResult_t CABTManagerIntialize(u_thread_pool_t threadPool)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+
+ //Initialize Bluetooth service
+ if (BT_ERROR_NONE != (err = bt_initialize()))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Bluetooth initialization failed!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+
+ //Set bluetooth adapter sate change callback
+ if (BT_ERROR_NONE != (err = bt_adapter_set_state_changed_cb(CABTAdapterStateChangeCallback, NULL)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG,
+ "Setting bluetooth state change callback failed!, error num [%x]", err);
+
+ //Deinitialize the Bluetooth stack
+ bt_deinitialize();
+ return CA_STATUS_FAILED;
+ }
+
+ //Get Bluetooth adapter state
+ bt_adapter_state_e adapterState;
+ if (BT_ERROR_NONE != (err = bt_adapter_get_state(&adapterState)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Bluetooth get state failed!, error num [%x]",
+ err);
+
+ //Reset the adapter state change callback
+ bt_adapter_unset_state_changed_cb();
+
+ //Deinitialize the Bluetooth stack
+ bt_deinitialize();
+ return CA_STATUS_FAILED;
+ }
+
+ //Initialize Send/Receive data message queues
+ if (CA_STATUS_OK != CABTManagerInitializeQueues())
+ {
+ //Reset the adapter state change callback
+ bt_adapter_unset_state_changed_cb();
+
+ //Deinitialize the Bluetooth stack
+ bt_deinitialize();
+ return CA_STATUS_FAILED;
+ }
+
+ //Create and initialize the mutex
+ CABTManagerInitializeMutex();
+
+ if (NULL == gBTThreadPool)
+ {
+ gBTThreadPool = threadPool;
+ }
+
+ if (BT_ADAPTER_DISABLED == adapterState)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Bluetooth adapter is disabled!");
+ return CA_ADAPTER_NOT_ENABLED;
+ }
+
+ //Notity to upper layer
+ CABTNotifyNetworkStauts(CA_INTERFACE_UP);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CABTManagerTerminate(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ gNetworkPacketReceivedCallback = NULL;
+ gNetworkChangeCallback = NULL;
+
+ //Stop the adpater
+ CABTManagerStop();
+
+ //Unset bluetooth adapter callbacks
+ bt_adapter_unset_state_changed_cb();
+
+ //Terminate Bluetooth service
+ bt_deinitialize();
+
+ //Terminate thread pool
+ gBTThreadPool = NULL;
+
+ //Free LocalConnectivity information
+ CAAdapterFreeLocalEndpoint(gLocalConnectivity);
+ gLocalConnectivity = NULL;
+
+ //Free BTDevices list
+ if (gBTDeviceListMutex)
+ {
+ u_mutex_lock(gBTDeviceListMutex);
+ CAFreeBTDeviceList(gBTDeviceList);
+ gBTDeviceList = NULL;
+ u_mutex_unlock(gBTDeviceListMutex);
+ }
+
+ //Free the mutex
+ CABTManagerTerminateMutex();
+
+ //Terminate Send/Receive data messages queues
+ CABTManagerTerminateQueues();
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+CAResult_t CABTManagerStart(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+ bool isDiscoveryStarted = false;
+
+ //Get Bluetooth adapter state
+ bt_adapter_state_e adapterState;
+ if (BT_ERROR_NONE != (err = bt_adapter_get_state(&adapterState)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Bluetooth get state failed!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+
+ if (BT_ADAPTER_DISABLED == adapterState)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Bluetooth adapter is disabled!");
+ return CA_ADAPTER_NOT_ENABLED;
+ }
+
+ //Register for discovery and rfcomm socket connection callbacks
+ bt_adapter_set_device_discovery_state_changed_cb(CABTDeviceDiscoveryCallback, NULL);
+ bt_device_set_service_searched_cb(CABTServiceSearchedCallback, NULL);
+ bt_socket_set_connection_state_changed_cb(CABTSocketConnectionStateCallback, NULL);
+ bt_socket_set_data_received_cb(CABTDataRecvCallback, NULL);
+
+ if (BT_ERROR_NONE != (err = bt_adapter_is_discovering(&isDiscoveryStarted)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to get discovery state!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+
+ //Start device discovery if its not started
+ if (false == isDiscoveryStarted )
+ {
+ if (BT_ERROR_NONE != (err = bt_adapter_start_device_discovery()))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Device discovery failed!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ //Start data send and receive handlers
+ gDataSendHandlerState = CA_TRUE;
+ if (CA_STATUS_OK != u_thread_pool_add_task(gBTThreadPool, CABTManagerDataSendHandler, NULL))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to start data send handler!");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CABTManagerStop(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+ bool isDiscoveryStarted = false;
+
+ //Stop data send and receive handlers
+ if (gSendDataMutex && gSendDataCond && gDataSendHandlerState)
+ {
+ u_mutex_lock(gSendDataMutex);
+ gDataSendHandlerState = CA_FALSE;
+ u_cond_signal(gSendDataCond);
+ u_mutex_unlock(gSendDataMutex);
+ }
+
+ //Check discovery status
+ if (BT_ERROR_NONE != (err = bt_adapter_is_discovering(&isDiscoveryStarted)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to get discovery state!, error num [%x]",
+ err);
+ return;
+ }
+
+ //stop the device discovery process
+ if (true == isDiscoveryStarted)
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Stopping the device search process");
+ if (BT_ERROR_NONE != (err = bt_adapter_stop_device_discovery()))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to stop device discovery!, error num [%x]",
+ err);
+ }
+ }
+
+ //reset bluetooth adapter callbacks
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Resetting the callbacks");
+ bt_adapter_unset_device_discovery_state_changed_cb();
+ bt_device_unset_service_searched_cb();
+ bt_socket_unset_connection_state_changed_cb();
+ bt_socket_unset_data_received_cb();
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+void CABTManagerSetPacketReceivedCallback(CANetworkPacketReceivedCallback packetReceivedCallback)
+{
+ gNetworkPacketReceivedCallback = packetReceivedCallback;
+}
+
+void CABTManagerSetNetworkChangeCallback(CANetworkChangeCallback networkChangeCallback)
+{
+ gNetworkChangeCallback = networkChangeCallback;
+}
+
+CAResult_t CABTManagerSendData(const char *remoteAddress, const char *serviceUUID,
+ void *data, uint32_t dataLength, uint32_t *sentLength)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ //Input validation
+ VERIFY_NON_NULL(serviceUUID, BLUETOOTH_ADAPTER_TAG, "service UUID is null");
+ VERIFY_NON_NULL(data, BLUETOOTH_ADAPTER_TAG, "Data is null");
+ VERIFY_NON_NULL(sentLength, BLUETOOTH_ADAPTER_TAG, "Sent data length holder is null");
+
+ VERIFY_NON_NULL_RET(gSendDataQueue, BLUETOOTH_ADAPTER_TAG, "Send data queue is NULL",
+ CA_STATUS_FAILED);
+ VERIFY_NON_NULL_RET(gSendDataMutex, BLUETOOTH_ADAPTER_TAG, "Send data queue mutex is NULL",
+ CA_STATUS_FAILED);
+ VERIFY_NON_NULL_RET(gSendDataCond, BLUETOOTH_ADAPTER_TAG, "Send data queue condition is NULL",
+ CA_STATUS_FAILED);
+
+ //Add message to data queue
+ CARemoteEndpoint_t *remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_EDR, remoteAddress,
+ serviceUUID);
+ if (NULL == remoteEndpoint)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to create remote endpoint !");
+ return CA_STATUS_FAILED;
+ }
+
+ if (CA_STATUS_OK != CAAdapterEnqueueMessage(gSendDataQueue, remoteEndpoint, data, dataLength))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to add message to queue !");
+ return CA_STATUS_FAILED;
+ }
+
+ CAAdapterFreeRemoteEndpoint(remoteEndpoint);
+ *sentLength = dataLength;
+
+ //Signal message handler for processing data for sending
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Signalling message send handler");
+ u_mutex_lock(gSendDataMutex);
+ u_cond_signal(gSendDataCond);
+ u_mutex_unlock(gSendDataMutex);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CABTManagerStartServer(const char *serviceUUID, int32_t *serverID)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ return CABTServerStart(serviceUUID, serverID);
+}
+
+CAResult_t CABTManagerStopServer(const int32_t serverID)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ return CABTServerStop(serverID);
+}
+
+CAResult_t CABTManagerGetInterface(CALocalConnectivity_t **info)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+ char *localAddress = NULL;
+
+ //Input validation
+ VERIFY_NON_NULL(info, BLUETOOTH_ADAPTER_TAG, "LocalConnectivity info is null");
+
+ //Get the bluetooth adapter local address
+ if (BT_ERROR_NONE != (err = bt_adapter_get_address(&localAddress)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG,
+ "Getting local adapter address failed!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+
+ //Create network info
+ *info = CAAdapterCreateLocalEndpoint(CA_EDR, localAddress, NULL);
+ if (NULL == *info)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to create LocalConnectivity instance!");
+
+ OICFree(localAddress);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ OICFree(localAddress);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CABTManagerReadData(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CABTManagerInitializeQueues(void)
+{
+ if (NULL == gSendDataQueue)
+ {
+ if (CA_STATUS_OK != CAAdapterInitializeMessageQueue(&gSendDataQueue))
+ {
+ return CA_STATUS_FAILED;
+ }
+ }
+}
+
+void CABTManagerTerminateQueues(void)
+{
+ if (gSendDataQueue)
+ {
+ CAAdapterTerminateMessageQueue(gSendDataQueue);
+ gSendDataQueue = NULL;
+ }
+}
+
+void CABTManagerInitializeMutex(void)
+{
+ u_mutex_init();
+ if (NULL == gBTDeviceListMutex)
+ {
+ gBTDeviceListMutex = u_mutex_new();
+ }
+
+ if (NULL == gSendDataMutex)
+ {
+ gSendDataMutex = u_mutex_new();
+ }
+
+ if (NULL == gSendDataCond)
+ {
+ gSendDataCond = u_cond_new();
+ }
+}
+
+void CABTManagerTerminateMutex(void)
+{
+ if (gBTDeviceListMutex)
+ {
+ u_mutex_free(gBTDeviceListMutex);
+ gBTDeviceListMutex = NULL;
+ }
+
+ if (gSendDataMutex)
+ {
+ u_mutex_free(gSendDataMutex);
+ gSendDataMutex = NULL;
+ }
+
+ if (gSendDataCond)
+ {
+ u_cond_free(gSendDataCond);
+ gSendDataCond = NULL;
+ }
+}
+
+void CABTManagerDataSendHandler(void *context)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ u_mutex_lock(gSendDataMutex);
+ while (gDataSendHandlerState)
+ {
+ CAAdapterMessage_t *message = NULL;
+ const char *remoteAddress = NULL;
+ const char *serviceUUID = NULL;
+ uint32_t sentLength = 0;
+
+ //Extract the message from queue and send to remote bluetooth device
+ while (CA_STATUS_OK == CAAdapterDequeueMessage(gSendDataQueue, &message))
+ {
+ remoteAddress = message->remoteEndpoint->addressInfo.BT.btMacAddress;
+ serviceUUID = message->remoteEndpoint->resourceUri;
+ if (strlen(remoteAddress)) //Unicast data
+ {
+ if (CA_STATUS_OK != CABTManagerSendUnicastData(remoteAddress, serviceUUID,
+ message->data, message->dataLen, &sentLength))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to send unicast data !");
+ }
+ }
+ else //Multicast data
+ {
+ if (CA_STATUS_OK != CABTManagerSendMulticastData(serviceUUID, message->data,
+ message->dataLen, &sentLength))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to send multicast data !");
+ }
+ }
+
+ //Free message
+ CAAdapterFreeMessage(message);
+ }
+
+ //Wait for the data to be send
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Waitiing for data");
+ u_cond_wait(gSendDataCond, gSendDataMutex);
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Got the signal that data is pending");
+
+ if (CA_FALSE == gDataSendHandlerState)
+ {
+ break;
+ }
+ }
+
+ u_mutex_unlock(gSendDataMutex);
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+CAResult_t CABTManagerSendUnicastData(const char *remoteAddress, const char *serviceUUID,
+ void *data, uint32_t dataLength, uint32_t *sentLength)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ BTDevice *device = NULL;
+
+ //Input validation
+ VERIFY_NON_NULL(remoteAddress, BLUETOOTH_ADAPTER_TAG, "Remote address is null");
+ VERIFY_NON_NULL(serviceUUID, BLUETOOTH_ADAPTER_TAG, "service UUID is null");
+ VERIFY_NON_NULL(data, BLUETOOTH_ADAPTER_TAG, "Data is null");
+ VERIFY_NON_NULL(sentLength, BLUETOOTH_ADAPTER_TAG, "Sent data length holder is null");
+
+ if (0 >= dataLength)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Negative data length!");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ //Check the connection existence with remote device
+ u_mutex_lock(gBTDeviceListMutex);
+ if (CA_STATUS_OK != CAGetBTDevice(gBTDeviceList, remoteAddress, &device))
+ {
+ //Create new device and add to list
+ if (CA_STATUS_OK != CACreateAndAddToDeviceList(&gBTDeviceList, remoteAddress,
+ OIC_BT_SERVICE_ID, &device))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed create device and add to list!");
+
+ u_mutex_unlock(gBTDeviceListMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ //Start the OIC service search newly created device
+ if (CA_STATUS_OK != CABTStartServiceSearch(remoteAddress))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to initiate service search!");
+
+ //Remove device from list
+ CARemoveBTDeviceFromList(&gBTDeviceList, remoteAddress);
+
+ u_mutex_unlock(gBTDeviceListMutex);
+ return CA_STATUS_FAILED;
+ }
+ }
+ u_mutex_unlock(gBTDeviceListMutex);
+
+ if (-1 == device->socketFD)
+ {
+ //Adding to pending list
+ if (CA_STATUS_OK != CAAddDataToDevicePendingList(&device->pendingDataList, data,
+ dataLength))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to add data to pending list!");
+
+ //Remove device from list
+ CARemoveBTDeviceFromList(&gBTDeviceList, remoteAddress);
+ return CA_STATUS_FAILED;
+ }
+
+ //Make a rfcomm connection with remote BT Device
+ if (1 == device->serviceSearched &&
+ CA_STATUS_OK != CABTClientConnect(remoteAddress, serviceUUID))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to make RFCOMM connection!");
+
+ //Remove device from list
+ CARemoveBTDeviceFromList(&gBTDeviceList, remoteAddress);
+ return CA_STATUS_FAILED;
+ }
+ *sentLength = dataLength;
+ }
+ else
+ {
+ if (CA_STATUS_OK != CABTSendData(device->socketFD, data, dataLength, sentLength))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to send data!");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CABTManagerSendMulticastData(const char *serviceUUID, void *data, uint32_t dataLength,
+ uint32_t *sentLength)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ BTDeviceList *cur = NULL;
+
+ //Input validation
+ VERIFY_NON_NULL(serviceUUID, BLUETOOTH_ADAPTER_TAG, "service UUID is null");
+ VERIFY_NON_NULL(data, BLUETOOTH_ADAPTER_TAG, "Data is null");
+ VERIFY_NON_NULL(sentLength, BLUETOOTH_ADAPTER_TAG, "Sent data length holder is null");
+
+ if (0 >= dataLength)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Negative data length!");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ *sentLength = dataLength;
+
+ //Send the packet to all OIC devices
+ u_mutex_lock(gBTDeviceListMutex);
+ cur = gBTDeviceList;
+ while (cur != NULL)
+ {
+ BTDevice *device = cur->device;
+ cur = cur->next;
+
+ if (-1 == device->socketFD)
+ {
+ //Check if the device service search is finished
+ if (0 == device->serviceSearched)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Device services are still unknown!");
+ continue;
+ }
+
+ //Adding to pendding list
+ if (CA_STATUS_OK != CAAddDataToDevicePendingList(&device->pendingDataList, data,
+ dataLength))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to add data to pending list !");
+ continue;
+ }
+
+ //Make a rfcomm connection with remote BT Device
+ if (CA_STATUS_OK != CABTClientConnect(device->remoteAddress, device->serviceUUID))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to make RFCOMM connection !");
+
+ //Remove the data which added to pending list
+ CARemoveDataFromDevicePendingList(&device->pendingDataList);
+ continue;
+ }
+ }
+ else
+ {
+ if (CA_STATUS_OK != CABTSendData(device->socketFD, data, dataLength, sentLength))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to send data to [%s] !",
+ device->remoteAddress);
+ }
+ }
+ }
+ u_mutex_unlock(gBTDeviceListMutex);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CABTStartServiceSearch(const char *remoteAddress)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+
+ //Input validation
+ VERIFY_NON_NULL(remoteAddress, BLUETOOTH_ADAPTER_TAG, "Remote address is null");
+ if (0 == strlen(remoteAddress))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Remote address is empty!");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ //Start searching for OIC service
+ if (BT_ERROR_NONE != (err = bt_device_start_service_search(remoteAddress)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Get bonded device failed!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CABTAdapterStateChangeCallback(int result, bt_adapter_state_e adapterState, void *userData)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ if (BT_ADAPTER_ENABLED == adapterState)
+ {
+ //Notity to upper layer
+ CABTNotifyNetworkStauts(CA_INTERFACE_UP);
+ }
+ else if (BT_ADAPTER_DISABLED == adapterState)
+ {
+ //Notity to upper layer
+ CABTNotifyNetworkStauts(CA_INTERFACE_DOWN);
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+void CABTSocketConnectionStateCallback(int result, bt_socket_connection_state_e connectionState,
+ bt_socket_connection_s *connection, void *userData)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ BTDevice *device = NULL;
+
+ if (BT_ERROR_NONE != result || NULL == connection)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid connection state!, error num [%x]",
+ result);
+ return;
+ }
+
+ switch (connectionState)
+ {
+ case BT_SOCKET_CONNECTED:
+ {
+ u_mutex_lock(gBTDeviceListMutex);
+ if (CA_STATUS_OK != CAGetBTDevice(gBTDeviceList, connection->remote_address,
+ &device))
+ {
+ //Create the deviceinfo and add to list
+ if (CA_STATUS_OK != CACreateAndAddToDeviceList(&gBTDeviceList,
+ connection->remote_address, OIC_BT_SERVICE_ID, &device))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed add device to list!");
+ u_mutex_unlock(gBTDeviceListMutex);
+ return;
+ }
+
+ device->socketFD = connection->socket_fd;
+ u_mutex_unlock(gBTDeviceListMutex);
+ return;
+ }
+
+ device->socketFD = connection->socket_fd;
+ while (device->pendingDataList)
+ {
+ uint32_t sentData = 0;
+ BTData *btData = device->pendingDataList->data;
+ if (CA_STATUS_OK != CABTSendData(device->socketFD, btData->data,
+ btData->dataLength, &sentData))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to send pending data [%s]",
+ device->remoteAddress);
+
+ //Remove all the data from pending list
+ CARemoveAllDataFromDevicePendingList(&device->pendingDataList);
+ break;
+ }
+
+ //Remove the data which send from pending list
+ CARemoveDataFromDevicePendingList(&device->pendingDataList);
+ }
+ u_mutex_unlock(gBTDeviceListMutex);
+ }
+ break;
+
+ case BT_SOCKET_DISCONNECTED:
+ {
+ u_mutex_lock(gBTDeviceListMutex);
+ CARemoveBTDeviceFromList(&gBTDeviceList, connection->remote_address);
+ u_mutex_unlock(gBTDeviceListMutex);
+ }
+ break;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+void CABTDataRecvCallback(bt_socket_received_data_s *data, void *userData)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ BTDevice *device = NULL;
+
+ if (NULL == data || 0 >= data->data_size)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Data is null!");
+ return;
+ }
+
+ if (NULL == gNetworkPacketReceivedCallback)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Callback is not registered!");
+ return;
+ }
+
+ //Get BT device from list
+ u_mutex_lock(gBTDeviceListMutex);
+ if (CA_STATUS_OK != CAGetBTDeviceBySocketId(gBTDeviceList, data->socket_fd, &device))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Could not find the device!");
+
+ u_mutex_unlock(gBTDeviceListMutex);
+ return;
+ }
+ u_mutex_unlock(gBTDeviceListMutex);
+
+ //Create RemoteEndPoint
+ CARemoteEndpoint_t *remoteEndpoint = NULL;
+ remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_EDR, device->remoteAddress,
+ OIC_BT_SERVICE_ID);
+ if (NULL == remoteEndpoint)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to crate remote endpoint!");
+ return;
+ }
+
+ void *copyData = OICMalloc(data->data_size);
+ if (NULL == copyData)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed allocate memory!");
+ CAAdapterFreeRemoteEndpoint(remoteEndpoint);
+ return;
+ }
+ memcpy(copyData, data->data, data->data_size);
+
+ gNetworkPacketReceivedCallback(remoteEndpoint, copyData, (uint32_t)data->data_size);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+void CABTDeviceDiscoveryCallback(int result, bt_adapter_device_discovery_state_e discoveryState,
+ bt_adapter_device_discovery_info_s *discoveryInfo, void *userData)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ BTDevice *device = NULL;
+
+ if (BT_ERROR_NONE != result)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Received bad state!, error num [%x]",
+ result);
+ return;
+ }
+
+ switch (discoveryState)
+ {
+ case BT_ADAPTER_DEVICE_DISCOVERY_STARTED:
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Discovery started!");
+ }
+ break;
+
+ case BT_ADAPTER_DEVICE_DISCOVERY_FINISHED:
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Discovery finished!");
+ }
+ break;
+
+ case BT_ADAPTER_DEVICE_DISCOVERY_FOUND:
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Device discovered [%s]!",
+ discoveryInfo->remote_name);
+ if (CA_TRUE == CABTIsServiceSupported((const char **)discoveryInfo->service_uuid,
+ discoveryInfo->service_count,
+ OIC_BT_SERVICE_ID))
+ {
+ //Check if the deivce is already in the list
+ u_mutex_lock(gBTDeviceListMutex);
+ if (CA_STATUS_OK == CAGetBTDevice(gBTDeviceList, discoveryInfo->remote_address,
+ &device))
+ {
+ device->serviceSearched = 1;
+ u_mutex_unlock(gBTDeviceListMutex);
+ return;
+ }
+
+ //Create the deviceinfo and add to list
+ if (CA_STATUS_OK != CACreateAndAddToDeviceList(&gBTDeviceList,
+ discoveryInfo->remote_address, OIC_BT_SERVICE_ID, &device))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to add device to list!");
+ u_mutex_unlock(gBTDeviceListMutex);
+ return;
+ }
+
+ device->serviceSearched = 1;
+ u_mutex_unlock(gBTDeviceListMutex);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Device does not support OIC service!");
+ }
+ }
+ break;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+void CABTServiceSearchedCallback(int result, bt_device_sdp_info_s *sdpInfo, void *userData)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ if (NULL == sdpInfo)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "SDP info is null!");
+ return;
+ }
+
+ u_mutex_lock(gBTDeviceListMutex);
+
+ BTDevice *device = NULL;
+ if (CA_STATUS_OK == CAGetBTDevice(gBTDeviceList, sdpInfo->remote_address, &device)
+ && NULL != device)
+ {
+ if (1 == device->serviceSearched)
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Service is already searched for this device!");
+ u_mutex_unlock(gBTDeviceListMutex);
+ return;
+ }
+
+ if (CA_TRUE == CABTIsServiceSupported((const char **)sdpInfo->service_uuid,
+ sdpInfo->service_count, OIC_BT_SERVICE_ID))
+ {
+ device->serviceSearched = 1;
+ if (CA_STATUS_OK != CABTClientConnect(sdpInfo->remote_address, OIC_BT_SERVICE_ID))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to make rfcomm connection!");
+
+ //Remove the device from device list
+ CARemoveBTDeviceFromList(&gBTDeviceList, sdpInfo->remote_address);
+ }
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Device does not contain OIC service!");
+
+ //Remove device from list as it does not support OIC service
+ CARemoveBTDeviceFromList(&gBTDeviceList, sdpInfo->remote_address);
+ }
+ }
+
+ u_mutex_unlock(gBTDeviceListMutex);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+CAResult_t CABTNotifyNetworkStauts(CANetworkStatus_t status)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ //Create localconnectivity
+ if (NULL == gLocalConnectivity)
+ {
+ CABTManagerGetInterface(&gLocalConnectivity);
+ }
+
+ //Notity to upper layer
+ if (gNetworkChangeCallback && gLocalConnectivity && gBTThreadPool)
+ {
+ //Add notification task to thread pool
+ CABTNetworkEvent *event = CABTCreateNetworkEvent(gLocalConnectivity, status);
+ if (NULL != event)
+ {
+ if (CA_STATUS_OK != u_thread_pool_add_task(gBTThreadPool, CABTOnNetworkStautsChanged,
+ event))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to create threadpool!");
+ return CA_STATUS_FAILED;
+ }
+ }
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CABTOnNetworkStautsChanged(void *context)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ if (NULL == context)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "context is NULL!");
+ return;
+ }
+
+ CABTNetworkEvent *networkEvent = (CABTNetworkEvent *) context;
+
+ //Notity to upper layer
+ if (gNetworkChangeCallback)
+ {
+ gNetworkChangeCallback(networkEvent->info, networkEvent->status);
+ }
+
+ //Free the created Network event
+ CABTFreeNetworkEvent(networkEvent);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+CABTNetworkEvent *CABTCreateNetworkEvent(CALocalConnectivity_t *connectivity,
+ CANetworkStatus_t status)
+{
+ VERIFY_NON_NULL_RET(connectivity, BLUETOOTH_ADAPTER_TAG, "connectivity is NULL", NULL);
+
+ //Create CABTNetworkEvent
+ CABTNetworkEvent *event = (CABTNetworkEvent *) OICMalloc(sizeof(CABTNetworkEvent));
+ if (NULL == event)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to allocate memory to network event!");
+ return NULL;
+ }
+
+ //Create duplicate of Local connectivity
+ event->info = CAAdapterCopyLocalEndpoint(connectivity);
+ event->status = status;
+ return event;
+}
+
+void CABTFreeNetworkEvent(CABTNetworkEvent *event)
+{
+ if (event)
+ {
+ if (event->info)
+ {
+ CAAdapterFreeLocalEndpoint(event->info);
+ }
+
+ OICFree(event);
+ }
+}
+
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtmanager.h
+ * @brief This file provides the APIs to control Bluetooth transport
+ */
+
+#ifndef __CA_BT_MANAGER_H_
+#define __CA_BT_MANAGER_H_
+
+#include <pthread.h>
+#include <string.h>
+#include <bluetooth.h>
+
+#include "caedradapter.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @fn CABTManagerInitialize
+ * @brief Initializes Bluetooth adapter
+ *
+ * @param threadPool Thread pool for handling asynchronous tasks
+ *
+ * @return CA_STATUS_OK or CA_ADAPTER_NOT_ENABLED on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_ADAPTER_NOT_ENABLED Initialization is successful, but bluetooth adapter is
+ * not enabled.
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTManagerInitialize(u_thread_pool_t threadPool);
+
+/**
+ * @fn CABTManagerTerminate
+ * @brief Deinitialize with bluetooth adapter
+ *
+ * @see CABTManagerIntialize
+ *
+ */
+void CABTManagerTerminate(void);
+
+/**
+ * @fn CABTManagerStart
+ * @brief Start bluetooth adapter which includes start searching for nearby OIC devices
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ * @pre CABTManagerIntialize should be invoked before using this API
+ *
+ * @see CABTManagerIntialize
+ *
+ */
+CAResult_t CABTManagerStart(void);
+
+/**
+ * @fn CABTManagerStop
+ * @brief Stop bluetooth adapter which includes stoping searching for nearby OIC devices
+ *
+ * @pre CABTManagerIntialize should be invoked before using this API
+ *
+ * @see CABTManagerIntialize
+ * @see CABTManagerStart
+ *
+ */
+void CABTManagerStop(void);
+
+/**
+ * @fn CABTManagerSetPacketReceivedCallback
+ * @brief Register callback for receiving packets from remote Bluetooth device.
+ *
+ * @param packetReceivedCallback Callback function to register for receiving network packets
+ *
+ * @return none.
+ *
+ * @see CBNetworkPacketReceived
+ *
+ */
+void CABTManagerSetPacketReceivedCallback(CANetworkPacketReceivedCallback packetReceivedCallback);
+
+/**
+ * @fn CABTManagerSetNetworkChangeCallback
+ * @brief Register callback for receiving network chang state of local Bluetooth adapter.
+ *
+ * @param networkChangeCallback Callback function to register for receiving network adapter status
+ *
+ * @return none
+ *
+ * @see CBNetworkChange
+ *
+ */
+void CABTManagerSetNetworkChangeCallback(CANetworkChangeCallback networkChangeCallback);
+
+/**
+ * @fn CABTManagerSendData
+ * @brief Send unicast/multicast data to remote bluetooth device
+ *
+ * @param remoteAddress The address of remote bluetooth device to which data needs to be sent.
+ * This will be NULL in case of sending multicast data.
+ * @param serviceUUID The UUID of service to which RFCOMM connection needs to established
+ * @param data The data needs to be send to remote bluetooth device
+ * @param dataLength Length of data
+ * @param sentLength Length of data actually sent or added to pending list for sending
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTManagerSendData(const char *remoteAddress, const char *serviceUUID,
+ void *data, uint32_t dataLength, uint32_t *sentLength);
+
+/**
+ * @fn CABTManagerStartServer
+ * @brief Start RFCOMM server for given service UUID
+ *
+ * @param serviceUUID The UUID of service with which RFCOMM server needs to be started
+ * @param serverID The ID for the server which started
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_SERVER_STARTED_ALREADY Service on the specified UUID is already running.
+ * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTManagerStartServer(const char *serviceUUID, int32_t *serverID);
+
+/**
+ * @fn CABTManagerStopServer
+ * @brief Stop RFCOMM server
+ *
+ * @param serverID The ID of server which needs to be stopped
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTManagerStopServer(const int32_t serverID);
+
+/**
+ * @fn CABTManagerGetInterface
+ * @brief Get the local bluetooth adapter information.
+ *
+ * @param info Local bluetooth adapter information
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ * @see CALocalConnectivity_t
+ *
+ */
+CAResult_t CABTManagerGetInterface(CALocalConnectivity_t **info);
+
+/**
+ * @fn CABTManagerReadData
+ * @brief All received data will be notified to upper layer.
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTManagerReadData(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif //__CA_BT_MANAGER_H_
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtserver.c
+ * @brief This file provides the APIs to start and stop RFCOMM server.
+ */
+
+#include "cabtserver.h"
+#include "caadapterutils.h"
+#include "cabtutils.h"
+#include "logger.h"
+
+static int32_t gMaxPendingConnections = 10;
+
+CAResult_t CABTServerStart(const char *serviceUUID, int32_t *serverFD)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+ bool isRunning = false;
+ int socketFD;
+
+ VERIFY_NON_NULL(serviceUUID, BLUETOOTH_ADAPTER_TAG, "Service UUID is null");
+ VERIFY_NON_NULL(serverFD, BLUETOOTH_ADAPTER_TAG, "Server fd holder is null");
+
+ if (0 >= strlen(serviceUUID))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Empty service uuid!");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ if (BT_ERROR_NONE != bt_adapter_is_service_used(serviceUUID, &isRunning))
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG,
+ "Unable to find whether service is already running or not!");
+ return CA_STATUS_FAILED;
+ }
+
+ if (true == isRunning)
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Service is already running with this UUID!");
+ return CA_SERVER_STARTED_ALREADY;
+ }
+
+ //Registers a rfcomm socket with a specific service_uuid .
+ if (BT_ERROR_NONE != (err = bt_socket_create_rfcomm(serviceUUID, &socketFD)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to create rfcomm socket!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+
+ //Start listening and accepting
+ if (BT_ERROR_NONE != (err = bt_socket_listen_and_accept_rfcomm(socketFD,
+ gMaxPendingConnections)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed in listen rfcomm socket!, error num [%x]",
+ err);
+
+ bt_socket_destroy_rfcomm(socketFD);
+ return CA_STATUS_FAILED;
+ }
+
+ *serverFD = socketFD;
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CABTServerStop(const int32_t serverFD)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ int err = BT_ERROR_NONE;
+ if (BT_ERROR_NONE != (err = bt_socket_destroy_rfcomm(serverFD)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed close rfcomm server socket!, error num [%x]",
+ err);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtserver.h
+ * @brief This file provides the APIs to start and stop RFCOMM server.
+ */
+
+#ifndef __CA_BT_SERVER_H_
+#define __CA_BT_SERVER_H_
+
+#include <string.h>
+#include <bluetooth.h>
+
+#include "cacommon.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @fn CABTServerStart
+ * @brief Start RFCOMM server for given service UUID
+ *
+ * @param serviceUUID The UUID of service with which RFCOMM server needs to be started
+ * @param serverFD The RFCOMM server socket file descriptor
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTServerStart(const char *serviceUUID, int32_t *serverFD);
+
+/**
+ * @fn CABTServerStop
+ * @brief Stop RFCOMM server
+ *
+ * @param serverFD The RFCOMM server socket file descriptor which needs to be stopped
+ *
+ * @return CA_STATUS_OK on success otherwise proper error code.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_FAILED Operation failed
+ *
+ */
+CAResult_t CABTServerStop(const int32_t serverFD);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif //__CA_BT_SERVER_H_
\ No newline at end of file
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtutils.c
+ * @brief This file provides helper functions for EDR adapter.
+ */
+
+#include "cabtutils.h"
+#include "logger.h"
+
+#include <bluetooth.h>
+
+CABool_t CABTIsServiceSupported(const char **serviceUUID, const int32_t serviceCount,
+ const char *matchService)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ if (NULL == serviceUUID || 0 == serviceCount || NULL == matchService)
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Invalid input");
+ return CA_FALSE;
+ }
+
+ int i;
+ for (i = 0; i < serviceCount; i++)
+ {
+ if (!strcasecmp(serviceUUID[i], matchService))
+ {
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "Service found !");
+ return CA_TRUE;
+ }
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_FALSE;
+}
+
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file cabtutils.h
+ * @brief This file provides helper functions for EDR adapter.
+ */
+
+#ifndef __CA_BT_UTILS_H_
+#define __CA_BT_UTILS_H_
+
+#include <string.h>
+
+#include "cacommon.h"
+#include "oic_malloc.h"
+
+#ifndef BLUETOOTH_ADAPTER_TAG
+#define BLUETOOTH_ADAPTER_TAG "CA_BLUETOOTH"
+#endif //BLUETOOTH_ADAPTER_TAG
+
+#ifndef OIC_BT_SERVICE_ID
+#define OIC_BT_SERVICE_ID "12341234-1C25-481F-9DFB-59193D238280"
+#endif //OIC_BT_SERVICE_ID
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @fn CABTIsServiceSupported
+ * @brief Check if the specified list of service UUIDs contains OIC service UUID.
+ *
+ * @param serviceUUID Array of service UUIDs
+ * @param serviceCount Size of the service UUIDs array.
+ * @param matchService Service UUID to be checked in the given array of service UUIDs
+ *
+ * @return CA_TRUE if service UUID found otherwise CA_FALSE.
+ *
+ */
+CABool_t CABTIsServiceSupported(const char **serviceUUID, const int32_t serviceCount,
+ const char *matchService);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif //__CA_BT_UTILS_H_
+
--- /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.
+ *
+ ******************************************************************/
+
+/**
+ * @file caedradapter.c
+ * @brief This file contains the APIs for EDR adapters to be implemented
+ */
+
+#include "caedradapter.h"
+#include "cabtmanager.h"
+#include "cabtutils.h"
+#include "caadapterutils.h"
+#include "logger.h"
+
+static int32_t gDiscoveryServerID = -1;
+static int32_t gListeningServerID = -1;
+static int32_t gNotificationServerID = -1;
+
+static CAResult_t CAStartServer(const char *serviceUUID, int32_t *serverID);
+
+CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback,
+ CANetworkPacketReceivedCallback networkPacketCallback,
+ CANetworkChangeCallback netChangeCallback,
+ u_thread_pool_t handle)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ CAResult_t err = CA_STATUS_OK;
+
+ //Input validation
+ VERIFY_NON_NULL(registerCallback, BLUETOOTH_ADAPTER_TAG, "register callback is NULL");
+ VERIFY_NON_NULL(networkPacketCallback, BLUETOOTH_ADAPTER_TAG, "data receive callback is NULL");
+ VERIFY_NON_NULL(netChangeCallback, BLUETOOTH_ADAPTER_TAG, "network changge callback is NULL");
+ VERIFY_NON_NULL(handle, BLUETOOTH_ADAPTER_TAG, "Thread pool hanlde is NULL");
+
+ //Register the callbacks with BT Manager
+ CABTManagerSetPacketReceivedCallback(networkPacketCallback);
+ CABTManagerSetNetworkChangeCallback(netChangeCallback);
+
+ //Initialize BT Manager
+ err = CABTManagerIntialize(handle);
+ if (CA_STATUS_OK != err && CA_ADAPTER_NOT_ENABLED != err)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "BT Manger initialize failed!, error number [%d]",
+ err);
+ return err;
+ }
+
+ CAConnectivityHandler_t handler;
+ handler.startAdapter = CAStartEDR;
+ handler.startListenServer = CAStartEDRListeningServer;
+ handler.startDiscoverServer = CAStartEDRDiscoveryServer;
+ handler.sendData = CASendEDRUnicastData;
+ handler.sendDataToAll = CASendEDRMulticastData;
+ handler.startNotifyServer = CAStartEDRNotifyServer;
+ handler.sendNotification = CASendEDRNotification;
+ handler.GetnetInfo = CAGetEDRInterfaceInformation;
+ handler.readData = CAReadEDRData;
+ handler.stopAdapter = CAStopEDR;
+ handler.terminate = CATerminateEDR;
+ registerCallback(handler, CA_EDR);
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return err;
+}
+
+CAResult_t CAStartEDR(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ CAResult_t err = CA_STATUS_OK;
+
+ if (CA_STATUS_OK != (err = CABTManagerStart()))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "BT Manger start failed!, error number [%d] ",
+ err);
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return err;
+}
+
+CAResult_t CAStartEDRListeningServer(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ return CAStartServer(OIC_BT_SERVICE_ID, &gListeningServerID);
+}
+
+CAResult_t CAStartEDRDiscoveryServer(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ return CAStartServer(OIC_BT_SERVICE_ID, &gDiscoveryServerID);
+}
+
+uint32_t CASendEDRUnicastData(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ CAResult_t err = CA_STATUS_OK;
+ uint32_t sentLen = 0;
+ const char *serviceUUID = OIC_BT_SERVICE_ID;
+
+ //Input validation
+ VERIFY_NON_NULL_RET(endpoint, BLUETOOTH_ADAPTER_TAG, "Remote endpoint is null", 0);
+ VERIFY_NON_NULL_RET(data, BLUETOOTH_ADAPTER_TAG, "Data is null", 0);
+
+ if (0 == strlen(endpoint->addressInfo.BT.btMacAddress))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Address is empty!");
+ return 0;
+ }
+
+ if (0 == dataLen)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: data length is zero!");
+ return 0;
+ }
+
+ if (CA_STATUS_OK != (err = CABTManagerSendData(endpoint->addressInfo.BT.btMacAddress,
+ serviceUUID, data,
+ dataLen, &sentLen)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Send unicast data failed!, error num [%d]", err);
+ return 0;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return sentLen;
+}
+
+uint32_t CASendEDRMulticastData(void *data, uint32_t dataLen)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ CAResult_t err = CA_STATUS_OK;
+ uint32_t sentLen = 0;
+ const char *serviceUUID = OIC_BT_SERVICE_ID;
+
+ //Input validation
+ VERIFY_NON_NULL_RET(data, BLUETOOTH_ADAPTER_TAG, "Data is null", 0);
+
+ if (0 == dataLen)
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: data length is zero!");
+ return 0;
+ }
+
+ if (CA_STATUS_OK != (err = CABTManagerSendData(NULL, serviceUUID, data, dataLen,
+ &sentLen)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, " Send multicast data failed!, error num [%d]",
+ err);
+ return 0;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return sentLen;
+}
+
+CAResult_t CAStartEDRNotifyServer(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ return CAStartServer(OIC_BT_SERVICE_ID, &gNotificationServerID);
+}
+
+uint32_t CASendEDRNotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ return CASendEDRUnicastData(endpoint, data, dataLen);
+}
+
+CAResult_t CAGetEDRInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ VERIFY_NON_NULL(info, BLUETOOTH_ADAPTER_TAG, "LocalConnectivity info is null");
+
+ CAResult_t err = CA_STATUS_OK;
+ *size = 0;
+ if (CA_STATUS_OK != (err = CABTManagerGetInterface(info)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG,
+ "Failed to get local interface information!, error num [%d]", err);
+ return err;
+ }
+
+ *size = 1;
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return err;
+}
+
+CAResult_t CAReadEDRData(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ return CABTManagerReadData();
+}
+
+CAResult_t CAStopEDR(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ //Stop the Discovery server
+ if (-1 < gDiscoveryServerID)
+ {
+ CABTManagerStopServer(gDiscoveryServerID);
+ }
+
+ //Stop the Listening server
+ if (-1 < gListeningServerID)
+ {
+ CABTManagerStopServer(gListeningServerID);
+ }
+
+ //Stop the Notification server
+ if (-1 < gNotificationServerID)
+ {
+ CABTManagerStopServer(gNotificationServerID);
+ }
+
+ //Stop the adapter
+ CABTManagerStop();
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CATerminateEDR(void)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ //Terminate BT Manager
+ CABTManagerTerminate();
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+}
+
+CAResult_t CAStartServer(const char *serviceUUID, int32_t *serverID)
+{
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "IN");
+
+ CAResult_t err = CA_STATUS_OK;
+
+ //Input validation
+ VERIFY_NON_NULL(serviceUUID, BLUETOOTH_ADAPTER_TAG, "Service UUID is NULL");
+ VERIFY_NON_NULL(serverID, BLUETOOTH_ADAPTER_TAG, "Server ID is NULL");
+ if (0 == strlen(serviceUUID))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Invalid input: Service UUID is empty!");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ if (CA_STATUS_OK != (err = CABTManagerStartServer(serviceUUID, serverID)))
+ {
+ OIC_LOG_V(ERROR, BLUETOOTH_ADAPTER_TAG, "Failed to start RFCOMM server!, error num [%d]",
+ err);
+ return err;
+ }
+
+ OIC_LOG_V(DEBUG, BLUETOOTH_ADAPTER_TAG, "OUT");
+ return err;
+}
#include "cableserver.h"
#include "cableclient.h"
#include "cacommon.h"
+#include "umutex.h"
+#include "caadapterutils.h"
#else // __ARDUINO__
#include "BLEAdapterArduino.h"
#include "caadapterutils.h"
#define CALEADAPTER_TAG "CA_BLE_ADAPTER"
static CANetworkChangeCallback gNetworkCallback = NULL;
-static char gLocalBLEAddress[16] =
-{ 0, };
-static int gIsServer = 0;
+static char gLocalBLEAddress[16] = { 0, };
-int CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback);
+static CABool_t gIsServer = CA_FALSE;
-#ifdef __TIZEN__
-int CALEDeviceStateChangedCb(int result, bt_adapter_state_e adapter_state, void *user_data);
-#endif //#ifdef __TIZEN__
+static u_mutex gBleIsServerMutex = NULL;
+
+static u_mutex gBleNetworkCbMutex = NULL;
-pthread_mutex_t gBleIsServerMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static u_mutex gBleLocalAddressMutex = NULL;
-pthread_mutex_t gBleNetworkCbMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+int32_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback);
-pthread_mutex_t gBleLocalAddressMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+#ifdef __TIZEN__
+int32_t CALEDeviceStateChangedCb(int32_t result, bt_adapter_state_e adapter_state,
+ void *user_data);
+CAResult_t CAInitBleAdapterMutex();
+CAResult_t CATermiateBleAdapterMutex();
+
+#endif //#ifdef __TIZEN__
CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback)
+ CANetworkPacketReceivedCallback reqRespCallback,
+ CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle)
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
//Input validation
VERIFY_NON_NULL(registerCallback, NULL, "RegisterConnectivity callback is null");
VERIFY_NON_NULL(reqRespCallback, NULL, "PacketReceived Callback is null");
VERIFY_NON_NULL(netCallback, NULL, "NetworkChange Callback is null");
-#ifdef __TIZEN__
+ CAResult_t result = CAInitBleAdapterMutex();
- int ret = bt_initialize();
- if (0 != ret)
+ if (CA_STATUS_OK != result)
{
- OCLog(ERROR, CALEADAPTER_TAG, "bt_initialize failed!");
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleAdapterMutex failed!");
return CA_STATUS_FAILED;
}
+#ifdef __TIZEN__
+
+ bt_initialize();
+
#endif //#ifdef __TIZEN__
- CASetBLEReqRescallback(reqRespCallback);
+
+ CASetBleServerThreadPoolHandle(handle);
+ CASetBleClientThreadPoolHandle(handle);
+ CASetBLEReqRespServerCallback(reqRespCallback);
+ CASetBLEReqRespClientCallback(reqRespCallback);
CALERegisterNetworkNotifications(netCallback);
CAConnectivityHandler_t connHandler;
+ connHandler.startAdapter = NULL;
+ connHandler.stopAdapter = NULL;
connHandler.startListenServer = CAStartLEListeningServer;
connHandler.startDiscoverServer = CAStartLEDiscoveryServer;
connHandler.sendData = CASendLEUnicastData;
connHandler.terminate = CATerminateLE;
registerCallback(connHandler, CA_LE);
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
void CATerminateLE()
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- CASetBLEReqRescallback(NULL);
+ CASetBLEReqRespServerCallback(NULL);
+ CASetBLEReqRespClientCallback(NULL);
CALERegisterNetworkNotifications(NULL);
- pthread_mutex_lock(&gBleIsServerMutex);
- if (gIsServer == 1)
+ u_mutex_lock(gBleIsServerMutex);
+ if (CA_TRUE == gIsServer)
{
CAStopBleGattServer();
}
{
CAStopBLEGattClient();
}
- pthread_mutex_unlock(&gBleIsServerMutex);
+ u_mutex_unlock(gBleIsServerMutex);
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return;
}
-void CALEServerInitThreadFunc(void *param)
-{
- OCLog(DEBUG, CALEADAPTER_TAG, "[CALEServerInitThreadFunc]IN");
-
- CAStartBleGattServer();
-
- OCLog(DEBUG, CALEADAPTER_TAG, "[CALEServerInitThreadFunc] OUT");
-}
-
-void CALEClientInitThreadFunc(void *param)
-{
- OCLog(DEBUG, CALEADAPTER_TAG, "[CALEClientInitThreadFunc]IN");
-
- CAStartBLEGattClient();
-
- OCLog(DEBUG, CALEADAPTER_TAG, "[CALEClientInitThreadFunc] OUT");
-}
-
CAResult_t CAStartLEListeningServer()
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
-
- int init_pthread_status = 0;
- pthread_t pthread_id = 0;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- init_pthread_status = pthread_create(&pthread_id, &attr, CALEServerInitThreadFunc, NULL);
-
- if (init_pthread_status != 0)
- {
- OCLog(ERROR, CALEADAPTER_TAG, "pthread_create failed!");
- return CA_STATUS_FAILED;
- }
+ CAStartBleGattServer();
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
- pthread_mutex_lock(&gBleIsServerMutex);
- gIsServer = 1;
- pthread_mutex_unlock(&gBleIsServerMutex);
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
+ u_mutex_lock(gBleIsServerMutex);
+ gIsServer = CA_TRUE;
+ u_mutex_unlock(gBleIsServerMutex);
return CA_STATUS_OK;
}
CAResult_t CAStartLEDiscoveryServer()
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- int init_pthread_status = 0;
- pthread_t pthread_id = 0;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- init_pthread_status = pthread_create(&pthread_id, &attr, CALEClientInitThreadFunc, NULL);
-
- if (init_pthread_status != 0)
- {
- OCLog(ERROR, CALEADAPTER_TAG, "pthread_create failed!");
- return CA_STATUS_FAILED;
- }
+ CAStartBLEGattClient();
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
- pthread_mutex_lock(&gBleIsServerMutex);
- gIsServer = 0;
- pthread_mutex_unlock(&gBleIsServerMutex);
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
+ u_mutex_lock(gBleIsServerMutex);
+ gIsServer = CA_FALSE;
+ u_mutex_unlock(gBleIsServerMutex);
return CA_STATUS_OK;
}
CAResult_t CAStartLENotifyServer()
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
uint32_t CASendLENotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
CAResult_t CAReadLEData()
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
uint32_t CASendLEUnicastData(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
//Input validation
VERIFY_NON_NULL(endpoint, NULL, "Remote endpoint is null");
CAResult_t result = CA_STATUS_FAILED;
#ifdef __TIZEN__
- pthread_mutex_lock(&gBleIsServerMutex);
- if (gIsServer)
+ u_mutex_lock(gBleIsServerMutex);
+ if (CA_TRUE == gIsServer)
{
- result = CAUpdateCharacteristicsInGattServer(data, dataLen);
+ result = CABleServerSenderQueueEnqueueMessage(endpoint, data, dataLen);
if (CA_STATUS_OK != result)
{
- OCLogv(ERROR, CALEADAPTER_TAG,
- "[SendLEUnicastData] sending unicast data to [%s] failed\n", endpoint->addressInfo.BT.btMacAddress);
- pthread_mutex_unlock(&gBleIsServerMutex);
+ OIC_LOG(ERROR, CALEADAPTER_TAG,
+ "[SendLEUnicastData] CABleServerSenderQueueEnqueueMessage failed \n");
+ u_mutex_unlock(gBleIsServerMutex);
return 0;
}
}
else
{
- result = CAUpdateCharacteristicsToGattServer(endpoint->addressInfo.BT.btMacAddress, data,
- dataLen, UNICAST, 0);
+ result = CABleClientSenderQueueEnqueueMessage(endpoint, data, dataLen);
if (CA_STATUS_OK != result)
{
- OCLogv(ERROR, CALEADAPTER_TAG,
- "[SendLEUnicastData] sending unicast data to [%s] failed\n", endpoint->addressInfo.BT.btMacAddress);
- pthread_mutex_unlock(&gBleIsServerMutex);
+ OIC_LOG(ERROR, CALEADAPTER_TAG,
+ "[SendLEUnicastData] CABleClientSenderQueueEnqueueMessage failed \n");
+ u_mutex_unlock(gBleIsServerMutex);
return 0;
}
}
- pthread_mutex_unlock(&gBleIsServerMutex);
+ u_mutex_unlock(gBleIsServerMutex);
#else
char *tempPath = "temp_path";
updateCharacteristicsInGattServer(tempPath, (char *) data, dataLen);
#endif //#ifdef __TIZEN__
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return dataLen;
}
uint32_t CASendLEMulticastData(void *data, uint32_t dataLen)
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
//Input validation
VERIFY_NON_NULL(data, NULL, "Data is null");
if (0 >= dataLen)
{
- OCLog(ERROR, CALEADAPTER_TAG, "Invalid Parameter");
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "Invalid Parameter");
return 0;
}
CAResult_t result = CA_STATUS_FAILED;
#ifdef __TIZEN__
- pthread_mutex_lock(&gBleIsServerMutex);
- if (gIsServer)
+ u_mutex_lock(gBleIsServerMutex);
+ if (CA_TRUE == gIsServer)
{
- result = CAUpdateCharacteristicsInGattServer(data, dataLen);
+ result = CABleServerSenderQueueEnqueueMessage(NULL, data, dataLen);
if (CA_STATUS_OK != result)
{
- OCLogv(ERROR, CALEADAPTER_TAG,
- "[CASendLEMulticastData] updating data in server is failed");
- pthread_mutex_unlock(&gBleIsServerMutex);
+ OIC_LOG(ERROR, CALEADAPTER_TAG,
+ "[SendLEMulticastDataToAll] CABleServerSenderQueueEnqueueMessage failed" );
+ u_mutex_unlock(gBleIsServerMutex);
return 0;
}
}
else
{
- result = CAUpdateCharacteristicsToAllGattServers(data, dataLen);
+ result = CABleClientSenderQueueEnqueueMessage(NULL, data, dataLen);
if (CA_STATUS_OK != result)
{
- OCLogv(ERROR, CALEADAPTER_TAG,
- "[SendLEMulticastDataToAll] multicasting data to servers failed" );
- pthread_mutex_unlock(&gBleIsServerMutex);
+ OIC_LOG(ERROR, CALEADAPTER_TAG,
+ "[SendLEMulticastDataToAll] CABleClientSenderQueueEnqueueMessage failed" );
+ u_mutex_unlock(gBleIsServerMutex);
return 0;
}
}
- pthread_mutex_unlock(&gBleIsServerMutex);
+ u_mutex_unlock(gBleIsServerMutex);
#else
char *tempPath = "temp_path";
updateCharacteristicsInGattServer(tempPath, (char *) data, dataLen);
#endif //#ifdef __TIZEN__
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return dataLen;
}
-CAResult_t CAGetLEInterfaceInformation(CALocalConnectivityt_t **info, uint32_t *size)
+CAResult_t CAGetLEInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
VERIFY_NON_NULL(info, NULL, "CALocalConnectivity info is null");
-#ifdef OIC_ARDUINODUE
- OCLog(DEBUG, CALEADAPTER_TAG, "Info from ARDUINO");
- //1: call corresponding Arduino API
-#endif
-
#if __TIZEN__
char *local_address = NULL;
bt_adapter_get_address(&local_address);
if (NULL == local_address)
{
- OCLog(ERROR, CALEADAPTER_TAG, "Get local bt adapter address failed");
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "Get local bt adapter address failed");
return CA_STATUS_FAILED;
}
#endif //#if ARDUINODUE
*size = 0;
- (*info) = (CALocalConnectivityt_t *) OICMalloc(sizeof(CALocalConnectivityt_t));
+ (*info) = (CALocalConnectivity_t *) OICMalloc(sizeof(CALocalConnectivity_t));
if (NULL == (*info))
{
- OCLog(ERROR, CALEADAPTER_TAG, "Malloc failure!");
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failure!");
return CA_STATUS_FAILED;
}
- memset((*info), 0x0, sizeof(CALocalConnectivityt_t));
+ memset((*info), 0x0, sizeof(CALocalConnectivity_t));
strncpy((*info)->addressInfo.BT.btMacAddress, local_address, strlen(local_address));
- pthread_mutex_lock(&gBleLocalAddressMutex);
+ u_mutex_lock(gBleLocalAddressMutex);
strncpy(gLocalBLEAddress, local_address, sizeof(gLocalBLEAddress));
- pthread_mutex_unlock(&gBleLocalAddressMutex);
+ u_mutex_unlock(gBleLocalAddressMutex);
(*info)->type = CA_LE;
*size = 1;
OICFree(local_address);
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
-int CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback)
+int32_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback)
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- pthread_mutex_lock(&gBleNetworkCbMutex);
+ u_mutex_lock(gBleNetworkCbMutex);
gNetworkCallback = netCallback;
- pthread_mutex_unlock(&gBleNetworkCbMutex);
- int ret = 0;
+ u_mutex_unlock(gBleNetworkCbMutex);
+ int32_t ret = 0;
#ifdef __TIZEN__
if (netCallback)
{
ret = bt_adapter_set_state_changed_cb(CALEDeviceStateChangedCb, NULL);
- if(ret != 0)
+ if (ret != 0)
{
- OCLog(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!");
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!");
}
}
else
{
ret = bt_adapter_unset_state_changed_cb();
- if(ret != 0)
+ if (ret != 0)
{
- OCLog(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!");
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!");
}
}
#endif //#ifdef __TIZEN__
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
#ifdef __TIZEN__
-int CALEDeviceStateChangedCb(int result, bt_adapter_state_e adapter_state, void *user_data)
+int32_t CALEDeviceStateChangedCb(int32_t result, bt_adapter_state_e adapter_state, void *user_data)
{
- OCLog(DEBUG, CALEADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
bt_adapter_state_e btAdaptorState = BT_ADAPTER_DISABLED;
if (BT_ADAPTER_ENABLED == adapter_state)
btAdaptorState = BT_ADAPTER_ENABLED;
}
- CALocalConnectivityt_t localEndpoint;
+ CALocalConnectivity_t localEndpoint;
- pthread_mutex_lock(&gBleLocalAddressMutex);
+ u_mutex_lock(gBleLocalAddressMutex);
strncpy(localEndpoint.addressInfo.BT.btMacAddress, gLocalBLEAddress, strlen(gLocalBLEAddress));
- pthread_mutex_unlock(&gBleLocalAddressMutex);
+ u_mutex_unlock(gBleLocalAddressMutex);
- pthread_mutex_lock(&gBleNetworkCbMutex);
- if(NULL != gNetworkCallback)
+ u_mutex_lock(gBleNetworkCbMutex);
+ if (NULL != gNetworkCallback)
{
gNetworkCallback(&localEndpoint, adapter_state);
}
else
{
- OCLog(ERROR, CALEADAPTER_TAG, "gNetworkCallback is NULL");
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "gNetworkCallback is NULL");
}
- pthread_mutex_unlock(&gBleNetworkCbMutex);
- OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
+ u_mutex_unlock(gBleNetworkCbMutex);
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAInitBleAdapterMutex()
+{
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
+
+ u_mutex_init();
+ if (NULL == gBleIsServerMutex)
+ {
+ gBleIsServerMutex = u_mutex_new();
+ if (NULL == gBleIsServerMutex)
+ {
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleNetworkCbMutex)
+ {
+ gBleNetworkCbMutex = u_mutex_new();
+ if (NULL == gBleNetworkCbMutex)
+ {
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleLocalAddressMutex)
+ {
+ gBleLocalAddressMutex = u_mutex_new();
+ if (NULL == gBleLocalAddressMutex)
+ {
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
+ return CA_STATUS_OK;
+}
+CAResult_t CATermiateBleAdapterMutex()
+{
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
+ u_mutex_free(gBleIsServerMutex);
+ gBleIsServerMutex = NULL;
+ u_mutex_free(gBleNetworkCbMutex);
+ gBleNetworkCbMutex = NULL;
+ u_mutex_free(gBleLocalAddressMutex);
+ gBleLocalAddressMutex = NULL;
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
#endif //#ifdef OIC_TIZEN
#define TAG PCF("CA")
static CANetworkPacketReceivedCallback gLEReceivedCallback = NULL;
+static u_thread_pool_t gThreadPoolHandle = NULL;
CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback)
+ CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle)
{
OIC_LOG_V(DEBUG, TAG, "CAInitializeLE");
gLEReceivedCallback = reqRespCallback;
+ gThreadPoolHandle = handle;
// register handlers
CAConnectivityHandler_t handler;
return 0;
}
-CAResult_t CAGetLEInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size)
+CAResult_t CAGetLEInterfaceInformation(CALocalConnectivity_t** info, uint32_t* size)
{
OIC_LOG_V(DEBUG, TAG, "CAGetLEInterfaceInformation");
--- /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 "cableclient.h"
+
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<arpa/inet.h>
+#include<sys/types.h>
+#include<sys/socket.h>
+#include<netinet/in.h>
+#include <pthread.h>
+#include <gio/gio.h>
+
+#include "umutex.h"
+#include "camessagequeue.h"
+#include "caadapterutils.h"
+
+/**
+ * @def TZ_BLE_CLIENT_TAG
+ * @brief Logging tag for module name
+ */
+#define TZ_BLE_CLIENT_TAG "TZ_BLE_GATT_CLIENT"
+
+static BLEServiceList *gBLEServiceList = NULL;
+
+static CABool_t gIsBleGattClientStarted = CA_FALSE;
+
+static CAAdapterMessageQueue_t *gCABleClientSenderQueue = NULL;
+
+static CAAdapterMessageQueue_t *gCABleClientReceiverQueue = NULL;
+
+static u_mutex gBleServiceListMutex = NULL;
+
+static u_mutex gBleReqRespClientCbMutex = NULL;
+
+static u_mutex gBleClientStateMutex = NULL;
+
+static u_mutex gBleClientSendDataMutex = NULL;
+
+static u_cond gBleClientSendCondWait = NULL;
+
+static u_mutex gBleClientReceiveDataMutex = NULL;
+
+static u_mutex gBleClientThreadPoolMutex = NULL;
+
+static CANetworkPacketReceivedCallback gReqRespClientCallback = NULL;
+
+static CABool_t gClientUp = CA_FALSE;
+
+static GMainLoop *g_event_loop = NULL;
+
+static u_thread_pool_t gBleClientThreadPool = NULL;
+
+typedef struct gattService
+{
+ bt_gatt_attribute_h serviceInfo;
+ char *address;
+} stGattServiceInfo_t;
+
+void CABleGattCharacteristicWriteCb(bt_gatt_attribute_h handle)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
+}
+
+void *CABleClientSenderQueueProcessor()
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
+
+ while (gClientUp)
+ {
+ CAAdapterMessage_t *senderData = NULL;
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, " conditional wait");
+
+ u_mutex_lock(gBleClientSendDataMutex);
+ u_cond_wait(gBleClientSendCondWait, gBleClientSendDataMutex);
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "wait unlocked");
+
+ CAResult_t result = CA_STATUS_FAILED;
+
+ while (CA_STATUS_OK == CAAdapterDequeueMessage(gCABleClientSenderQueue, &senderData))
+ {
+ if (NULL == senderData)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "senderData is NULL");
+ continue;
+ }
+ if (NULL != senderData->remoteEndpoint)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Sending Unicast data");
+ const char *bdAddress = senderData->remoteEndpoint->addressInfo.LE.leMacAddress;
+
+ if (NULL == bdAddress)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "bdAddress is NULL");
+ continue;
+ }
+
+ result = CAUpdateCharacteristicsToGattServer(bdAddress, senderData->data,
+ senderData->dataLen, UNICAST, 0);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "Failed to UpdateCharacteristicsToGattServer [%s]", bdAddress);
+ }
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Sending Multicast data");
+ result = CAUpdateCharacteristicsToAllGattServers(senderData->data,
+ senderData->dataLen);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "Failed to UpdateCharacteristicsToAllGattServers !");
+ }
+ }
+
+ CAAdapterFreeMessage(senderData);
+ }
+
+ u_mutex_unlock(gBleClientSendDataMutex);
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
+ return NULL;
+}
+
+CAResult_t CASetCharacteristicDescriptorValue(stGattCharDescriptor_t *stGattCharDescriptorInfo)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ uint8_t desc[stGattCharDescriptorInfo->total];
+ unsigned char noti[4] =
+ { 0, };
+ char *strUUID = NULL;
+
+ memcpy(desc, (uint8_t *) stGattCharDescriptorInfo->descriptor, stGattCharDescriptorInfo->total);
+
+ strUUID = (char *) OICMalloc(sizeof(char) * 5);
+ if (NULL == strUUID)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "malloc failure!");
+ return CA_STATUS_FAILED;
+ }
+ memset(strUUID, 0x0, sizeof(char) * 5);
+ snprintf(strUUID, 4, "%x%x", desc[3], desc[2]);
+ noti[0] = desc[0];
+ noti[1] = desc[1];
+ noti[2] = 0x01;
+ noti[3] = 0x00;
+
+ if (!strncmp(strUUID, "2902", 2))
+ {
+ int32_t ret = 0;
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "setting notification/indication for descriptor");
+
+ ret = bt_gatt_set_characteristic_desc_value_request(
+ stGattCharDescriptorInfo->characteristic, noti, 4, CABleGattCharacteristicWriteCb);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_gatt_set_characteristic_desc_value_request failed with return[%s] \n",
+ CABTGetErrorMsg(ret));
+ OICFree(strUUID);
+ return CA_STATUS_FAILED;
+ }
+ }
+ bt_gatt_destroy_attribute_handle(stGattCharDescriptorInfo->characteristic);
+ bt_gatt_destroy_attribute_handle(stGattCharDescriptorInfo->descriptor);
+ OICFree(stGattCharDescriptorInfo);
+ OICFree(strUUID);
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void *CASetCharacteristicDescriptorValueThread(void *stServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == stServiceInfo)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param stServiceInfo is NULL");
+ return NULL;
+ }
+
+ stGattCharDescriptor_t *stTemp = (stGattCharDescriptor_t *) stServiceInfo;
+
+ if (NULL == stTemp)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "stTemp is NULL");
+ return NULL;
+ }
+
+ CAResult_t result = CASetCharacteristicDescriptorValue(stTemp);
+
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG , "CASetCharacteristicDescriptorValue failed!");
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return NULL;
+}
+
+void CABleGattDescriptorDiscoveredCb(int result, unsigned char format, int total,
+ bt_gatt_attribute_h descriptor, bt_gatt_attribute_h characteristic, void *userData)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ stGattCharDescriptor_t *stTemp = (stGattCharDescriptor_t *) OICMalloc(
+ sizeof(stGattCharDescriptor_t));
+
+ if (NULL == stTemp)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "stTemp is NULL");
+ return;
+ }
+ bt_gatt_clone_attribute_handle(&(stTemp->descriptor), descriptor);
+
+ bt_gatt_clone_attribute_handle(&(stTemp->characteristic), characteristic);
+
+ stTemp->total = total;
+ u_mutex_lock(gBleClientThreadPoolMutex);
+ if (NULL == gBleClientThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleClientThreadPool is NULL");
+ OICFree(stTemp);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return;
+ }
+
+ CAResult_t ret = u_thread_pool_add_task(gBleClientThreadPool,
+ (void *) CASetCharacteristicDescriptorValueThread, (void *) stTemp);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+ OICFree(stTemp);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ //CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo, bleServiceInfo->bdAddress);
+ return;
+ }
+
+ sleep(2);
+ ret = u_thread_pool_add_task(gBleClientThreadPool, (void *) CABleClientSenderQueueProcessor,
+ (void *) NULL);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ //CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo, bleServiceInfo->bdAddress);
+ return;
+ }
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG,
+ "LE Client initialization complete. Enabling gClientUp state to TRUE ");
+ gClientUp = CA_TRUE;
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return;
+}
+
+void *CADiscoverDescriptorThread(void *stServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, " IN");
+
+ if (NULL == stServiceInfo)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "stServiceInfo is NULL");
+ return NULL;
+ }
+ stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *) stServiceInfo;
+
+ int32_t ret = bt_gatt_discover_characteristic_descriptor(stTemp->serviceInfo,
+ CABleGattDescriptorDiscoveredCb, NULL);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_gatt_discover_characteristic_descriptor failed with returns[%s] \n",
+ CABTGetErrorMsg(ret));
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return NULL;
+}
+
+void *CADiscoverCharThread(void *stServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == stServiceInfo)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param stServiceInfo is NULL");
+ return NULL;
+ }
+
+ stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *) stServiceInfo;
+
+ if (NULL == stTemp)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "stTemp is NULL");
+ return NULL;
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "remote address [%s]", stTemp->address);
+
+ CAResult_t result = CABleDiscoverCharacteristics(stTemp->serviceInfo, stTemp->address);
+
+ bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
+
+ OICFree(stTemp->address);
+
+ OICFree(stTemp);
+
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG , "CABleDiscoverCharacteristics failed!");
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return NULL;
+}
+
+void CABtGattBondCreatedCb(int32_t result, bt_device_info_s *device_info, void *user_data)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+ if (result == BT_ERROR_NONE)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "A bond with chat_server is created.");OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Callback: The number of service : %d.",
+ device_info->service_count);
+
+ int32_t i = 0;
+
+ char *bdAddress = device_info->remote_address;
+
+ int32_t len = strlen(bdAddress);
+
+ char *addr = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == addr)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ return;
+ }
+ memset(addr, 0x0, len + 1);
+
+ strncpy(addr, bdAddress, len);
+
+ BLEServiceInfo *bleServiceInfo = NULL;
+
+ u_mutex_lock(gBleServiceListMutex);
+ CAResult_t retVal = CAGetBLEServiceInfo(gBLEServiceList, addr, &bleServiceInfo);
+
+ u_mutex_unlock(gBleServiceListMutex);
+ OICFree(addr);
+
+ if (CA_STATUS_OK != retVal)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CAGetBLEServiceInfo failed! ");
+ bleServiceInfo = NULL;
+ return;
+ }
+
+ int32_t ret = CAVerifyOICService(bleServiceInfo->service_clone);
+
+ if (CA_STATUS_OK == ret)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Its OIC service");
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG ,
+ " serviceInfo remote address [%s]", bleServiceInfo->bdAddress);
+
+ stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *) OICMalloc(
+ sizeof(stGattServiceInfo_t));
+ if (NULL == stTemp)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ return;
+ }
+
+ bt_gatt_clone_attribute_handle(&(stTemp->serviceInfo), bleServiceInfo->service_clone);
+
+ len = strlen(bleServiceInfo->bdAddress);
+
+ stTemp->address = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == stTemp->address)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
+ OICFree(stTemp);
+ return;
+ }
+ memset(stTemp->address, 0x0, len + 1);
+
+ strncpy(stTemp->address, bleServiceInfo->bdAddress, len);
+
+ u_mutex_lock(gBleClientThreadPoolMutex);
+ if (NULL == gBleClientThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleClientThreadPool is NULL");
+ bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
+ OICFree(stTemp->address);
+ OICFree(stTemp);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ /*CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo,
+ * bleServiceInfo->bdAddress); */
+ return;
+ }
+
+ CAResult_t ret = u_thread_pool_add_task(gBleClientThreadPool,
+ (void *) CADiscoverCharThread, (void *) stTemp);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "u_thread_pool_add_task failed with ret [%d]", ret);
+ bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
+ OICFree(stTemp->address);
+ OICFree(stTemp);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return;
+ }
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Its not OIC service!! ");
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
+ "Callback: is_bonded - %d.", device_info->is_bonded);OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
+ "Callback: is_connected - %d.", device_info->is_connected);
+
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ " create_bond Failed as [%s ]", CABTGetErrorMsg(result));
+ }OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+void *CAGATTCreateBondThread(void *stServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == stServiceInfo)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param stServiceInfo is NULL");
+ return NULL;
+ }
+
+ stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *) stServiceInfo;
+
+ if (NULL == stTemp)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "stTemp is NULL");
+ return NULL;
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "remote address [%s]",
+ stTemp->address);
+
+ CAResult_t result = CABleGATTCreateBond(stTemp->address);
+
+ OICFree(stTemp->address);
+
+ OICFree(stTemp);
+
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG ,
+ "CABleDiscoverCharacteristics failed!");
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return NULL;
+}
+
+void CABleGattCharacteristicChangedCb(bt_gatt_attribute_h characteristic, unsigned char *value,
+ int32_t valueLen, void *userData)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ int32_t i = 0;
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Changed characteristic is [%s]", (char *)characteristic);
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Changed characteristic value length [%d]", valueLen);
+
+ for (i = 0; i < valueLen; i++)
+ {
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Changed characteristic value %c", value[i]);
+ }
+
+ CARemoteEndpoint_t *remoteEndPoint = (CARemoteEndpoint_t *) OICMalloc(
+ sizeof(CARemoteEndpoint_t));
+ if (NULL == remoteEndPoint)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "Malloc Failure!");
+ return;
+ }
+ memset(remoteEndPoint, 0x0, sizeof(CARemoteEndpoint_t));
+
+ ///TODO: Currently Empty endpoint is being sent.
+ ///TODO:Later proper remote address has to be added when tizen team changed their code
+#if 0
+ VERIFY_NON_NULL(gCABleClientReceiverQueue, TZ_BLE_CLIENT_TAG,
+ "BleClientReceiverQueue is NULL");
+ u_mutex_lock(gBleClientReceiveDataMutex);
+ CAResult_t retVal = CAAdapterEnqueueMessage(gCABleClientReceiverQueue,
+ remoteEndPoint, value,
+ valueLen);
+ if (CA_STATUS_OK != retVal )
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CAAdapterEnqueueMessage failed!");
+ u_mutex_unlock(gBleClientReceiveDataMutex);
+ CATerminateBLEGattClient();
+ return;
+ }
+ u_mutex_unlock(gBleClientReceiveDataMutex);
+#endif
+
+ char *data = (char *) OICMalloc(sizeof(char) * valueLen + 1);
+ if (NULL == data)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "Malloc failed!");
+ OICFree(remoteEndPoint);
+ return;
+ }
+
+ memset(data, 0x0, valueLen + 1);
+
+ strncpy(data, value, valueLen);
+
+ u_mutex_lock(gBleReqRespClientCbMutex);
+ if (NULL == gReqRespClientCallback)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gReqRespCallback is NULL!");
+ OICFree(value);
+ OICFree(remoteEndPoint);
+ u_mutex_unlock(gBleReqRespClientCbMutex);
+ return;
+ }
+
+ gReqRespClientCallback(remoteEndPoint, data, valueLen);
+
+ u_mutex_unlock(gBleReqRespClientCbMutex);
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return;
+}
+
+CABool_t CABleGattPrimaryServiceCb(bt_gatt_attribute_h service, void *userData)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == service || NULL == userData)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param service or userData is NULL");
+ return false;
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Service info [%s]", (char *)service);
+
+ int32_t ret = CAVerifyOICService(service);
+
+ if (CA_STATUS_OK == ret)
+ {
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Its OIC service");
+
+ char *bdAddress = (char *) userData;
+
+ int32_t len = strlen(bdAddress);
+
+ char *addr = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == addr)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "malloc failed! ");
+ return false;
+ }
+ memset(addr, 0x0, len + 1);
+
+ strncpy(addr, bdAddress, len);
+
+ BLEServiceInfo *bleServiceInfo = NULL;
+
+ CAResult_t result = CACreateBLEServiceInfo(addr, service, &bleServiceInfo);
+
+ OICFree(addr);
+
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CACreateBLEServiceInfo failed! ");
+ bleServiceInfo = NULL;
+ return false;
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG ,
+ " serviceInfo remote address [%s]", bleServiceInfo->bdAddress);
+
+ u_mutex_lock(gBleServiceListMutex);
+ result = CAAddBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo);
+
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG , "CAAddBLEServiceInfoToList failed!");
+ bleServiceInfo = NULL;
+ u_mutex_unlock(gBleServiceListMutex);
+ return false;
+ }
+ u_mutex_unlock(gBleServiceListMutex);
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG , "Registering to watch characteristics changes \n");
+
+ int32_t ret = bt_gatt_watch_characteristic_changes(bleServiceInfo->service_clone);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_gatt_watch_characteristic_changes failed with [%s] \n", CABTGetErrorMsg(ret));
+ u_mutex_lock(gBleServiceListMutex);
+ CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo,
+ bleServiceInfo->bdAddress);
+ u_mutex_unlock(gBleServiceListMutex);
+ return false;
+ }
+
+ stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *) OICMalloc(
+ sizeof(stGattServiceInfo_t));
+
+ if (NULL == stTemp)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ u_mutex_lock(gBleServiceListMutex);
+ CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo,
+ bleServiceInfo->bdAddress);
+ u_mutex_unlock(gBleServiceListMutex);
+ return false;
+ }
+
+ memset(stTemp, 0x0, sizeof(stGattServiceInfo_t));
+
+ len = strlen(bleServiceInfo->bdAddress);
+
+ stTemp->address = (char *) OICMalloc(sizeof(char) * len + 1);
+
+ if (NULL == stTemp->address)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ u_mutex_lock(gBleServiceListMutex);
+ CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo,
+ bleServiceInfo->bdAddress);
+ u_mutex_unlock(gBleServiceListMutex);
+ OICFree(stTemp);
+ return false;
+ }
+
+ memset(stTemp->address, 0x0, len + 1);
+
+ strncpy(stTemp->address, bleServiceInfo->bdAddress, len);
+
+ u_mutex_lock(gBleClientThreadPoolMutex);
+ if (NULL == gBleClientThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleClientThreadPool is NULL");
+ OICFree(stTemp->address);
+ OICFree(stTemp);
+ u_mutex_lock(gBleServiceListMutex);
+ CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo,
+ bleServiceInfo->bdAddress);
+ u_mutex_unlock(gBleServiceListMutex);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return false;
+ }
+
+ result = u_thread_pool_add_task(gBleClientThreadPool, (void *) CAGATTCreateBondThread,
+ (void *) stTemp);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "u_thread_pool_add_task failed with ret [%d]", result);
+ OICFree(stTemp->address);
+ OICFree(stTemp);
+ u_mutex_lock(gBleServiceListMutex);
+ CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo,
+ bleServiceInfo->bdAddress);
+ u_mutex_unlock(gBleServiceListMutex);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return false;
+ }
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Its not OIC service!! ");
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
+ return true;;
+}
+
+CABool_t CABleGattCharacteristicsDiscoveredCb(int32_t result, int32_t inputIndex, int32_t total,
+ bt_gatt_attribute_h characteristic, void *userData)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == characteristic || NULL == userData)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param characteristic and userData is NULL");
+ return false;
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
+ "result [%d] input_index [%d] total [%d]",
+ result, inputIndex, total);
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
+ "new characteristic found is [%s]", (char *)characteristic);
+
+ char *bdAddress = (char *) userData;
+
+ BLEServiceInfo *bleServiceInfo = NULL;
+
+ u_mutex_lock(gBleServiceListMutex);
+
+ CAGetBLEServiceInfo(gBLEServiceList, bdAddress, &bleServiceInfo);
+
+ u_mutex_unlock(gBleServiceListMutex);
+
+ if (1 == inputIndex)
+ {
+ CAResult_t retVal = CAAppendBLECharInfo(characteristic, READ_CHAR, bleServiceInfo);
+ if (CA_STATUS_OK != retVal)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG , "CAAppendBLECharInfo failed ");
+ return false;
+ }
+ }
+ else if (2 == inputIndex)
+ {
+ CAResult_t retVal = CAAppendBLECharInfo(characteristic, WRITE_CHAR, bleServiceInfo);
+ if (CA_STATUS_OK != retVal)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG , "CAAppendBLECharInfo failed! ");
+ return false;
+ }
+
+ }
+
+ stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *) OICMalloc(sizeof(stGattServiceInfo_t));
+
+ if (NULL == stTemp)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ return false;
+ }
+
+ memset(stTemp, 0x0, sizeof(stGattServiceInfo_t));
+
+ bt_gatt_clone_attribute_handle(&(stTemp->serviceInfo), characteristic);
+
+ int32_t len = strlen(bleServiceInfo->bdAddress);
+
+ stTemp->address = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == stTemp->address)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
+ OICFree(stTemp);
+ return false;
+ }
+ memset(stTemp->address, 0x0, len + 1);
+
+ strncpy(stTemp->address, bleServiceInfo->bdAddress, len);
+
+ u_mutex_lock(gBleClientThreadPoolMutex);
+ if (NULL == gBleClientThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleClientThreadPool is NULL");
+ bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
+ OICFree(stTemp->address);
+ OICFree(stTemp);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return false;
+ }
+
+ CAResult_t ret = u_thread_pool_add_task(gBleClientThreadPool,
+ (void *) CADiscoverDescriptorThread, (void *) stTemp);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+ bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
+ OICFree(stTemp->address);
+ OICFree(stTemp);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ //CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo, bleServiceInfo->bdAddress);
+ return false;
+ }
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return true;
+
+}
+
+CAResult_t CABleClientSenderQueueEnqueueMessage(CARemoteEndpoint_t *remoteEndpoint, void *data,
+ uint32_t dataLen)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
+
+ VERIFY_NON_NULL(data, NULL, "Param data is NULL");
+
+ VERIFY_NON_NULL_RET(gCABleClientSenderQueue, TZ_BLE_CLIENT_TAG,
+ "BleClientReceiverQueue is NULL", CA_STATUS_FAILED);
+ VERIFY_NON_NULL_RET(gBleClientSendDataMutex, TZ_BLE_CLIENT_TAG,
+ "BleClientSendDataMutex is NULL", CA_STATUS_FAILED);
+ VERIFY_NON_NULL_RET(gBleClientSendCondWait, TZ_BLE_CLIENT_TAG, "BleClientSendCondWait is NULL",
+ CA_STATUS_FAILED);
+
+ u_mutex_lock(gBleClientSendDataMutex);
+ CAResult_t retVal = CAAdapterEnqueueMessage(gCABleClientSenderQueue, remoteEndpoint, data,
+ dataLen);
+ if (CA_STATUS_OK != retVal)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CAAdapterEnqueueMessage failed!");
+ u_mutex_unlock(gBleClientSendDataMutex);
+ return CA_STATUS_FAILED;
+ }OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Sending signal for the sender processor ");
+ u_mutex_unlock(gBleClientSendDataMutex);
+ u_cond_signal(gBleClientSendCondWait);
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CALEReadDataFromLEClient()
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
+#if 0
+ CAAdapterMessage_t *receiverData = NULL;
+
+ u_mutex_lock(gBleClientReceiveDataMutex);
+ CAResult_t result = CAAdapterDequeueMessage(gCABleClientReceiverQueue, &receiverData);
+
+ if (CA_STATUS_OK != result)
+ {
+ u_mutex_lock(gBleReqRespClientCbMutex);
+ if (NULL == gReqRespClientCallback)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gReqRespClientCallback is NULL!");
+ CAAdapterFreeMessage(receiverData);
+ u_mutex_unlock(gBleReqRespClientCbMutex);
+ u_mutex_unlock(gBleClientReceiveDataMutex);
+ return;
+ }
+
+ gReqRespClientCallback(receiverData->remoteEndpoint, receiverData->data, receiverData->dataLen);
+
+ CAAdapterFreeMessage(receiverData);
+ }
+ u_mutex_unlock(gBleClientReceiveDataMutex);
+
+#endif
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
+
+ return CA_STATUS_OK;
+}
+
+void *CAGattConnectThread(void *remoteAddress)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
+
+ if (NULL == remoteAddress)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param remoteAddress is NULL ");
+ return NULL;
+ }
+
+ char *address = (char *) remoteAddress;
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "remote address is [%s]", address);
+
+ CAResult_t result = bt_gatt_connect(address, true);
+
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_gatt_connect failed for [%s]", address);
+ return NULL;
+ }
+
+ OICFree(address);
+ address = NULL;
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return NULL;
+}
+
+void CAPrintDiscoveryInformation(bt_adapter_le_device_discovery_info_s *discoveryInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == discoveryInfo)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "discoveryInfo is NULL ");
+ return;
+ }
+
+ if (discoveryInfo->remote_address)
+ {
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Remote Address [%s]", discoveryInfo->remote_address);
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
+ " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
+ discoveryInfo->adv_data_len, discoveryInfo->scan_data_len, discoveryInfo->rssi,
+ discoveryInfo->address_type);OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+void CABtAdapterLeDeviceDiscoveryStateChangedCb(int32_t result,
+ bt_adapter_le_device_discovery_state_e discoveryState,
+ bt_adapter_le_device_discovery_info_s *discoveryInfo, void *userData)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (discoveryInfo == NULL && discoveryState == BT_ADAPTER_LE_DEVICE_DISCOVERY_FOUND)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "discoveryInfo is NULL");
+ return;
+ }
+
+ if (discoveryState != BT_ADAPTER_LE_DEVICE_DISCOVERY_FOUND)
+ {
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
+ " LE Discovery state is [%s]",
+ discoveryState == BT_ADAPTER_LE_DEVICE_DISCOVERY_STARTED ? "Started" : "Finished" );
+ }
+ else
+ {
+
+ CAPrintDiscoveryInformation(discoveryInfo);
+
+ if (NULL == discoveryInfo->remote_address)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "discoveryInfo->remote_address is NULL");
+ return;
+ }
+
+ int32_t len = strlen(discoveryInfo->remote_address);
+
+ char *addr = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == addr)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ return;
+ }
+ memset(addr, 0x0, len + 1);
+
+ strncpy(addr, discoveryInfo->remote_address, len);
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
+ "Trying to do Gatt connection to [%s] ", addr);
+
+ u_mutex_lock(gBleClientThreadPoolMutex);
+ if (NULL == gBleClientThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleClientThreadPool is NULL");
+ OICFree(addr);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return;
+ }
+
+ CAResult_t ret = u_thread_pool_add_task(gBleClientThreadPool, (void *) CAGattConnectThread,
+ (void *) addr);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+ OICFree(addr);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return;
+ }
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ if (discoveryInfo->adv_data_len > 31 || discoveryInfo->scan_data_len > 31)
+ {
+ bt_adapter_le_stop_device_discovery();
+ return;
+ }
+
+ }OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+void *CADiscoverBLEServicesThread(void *remoteAddress)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == remoteAddress)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param remoteAddress is NULL ");
+ return NULL;
+ }
+
+ char *address = (char *) remoteAddress;
+
+ CAResult_t result = CABleDiscoverServices(remoteAddress);
+
+ OICFree(address);
+ address = NULL;
+
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "CABleDiscoverServices Failed");
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
+ return NULL;
+}
+
+void CABleGattConnectionStateChangedCb(int32_t result, bool connected, const char *remoteAddress,
+ void *userData)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "CABleGattConnectionStateChangedCb result[%d] ", result);
+
+ if (NULL == remoteAddress)
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Param remoteAddress is NULL ");
+ return;
+ }
+
+ if (connected)
+ {
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Connected to [%s] ", remoteAddress);
+
+ int32_t len = strlen(remoteAddress);
+
+ char *addr = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == addr)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ return;
+ }
+ memset(addr, 0x0, len + 1);
+
+ strncpy(addr, remoteAddress, len);
+
+ u_mutex_lock(gBleClientThreadPoolMutex);
+ if (NULL == gBleClientThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleClientThreadPool is NULL");
+ OICFree(addr);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return;
+ }
+
+ CAResult_t ret = u_thread_pool_add_task(gBleClientThreadPool,
+ (void *) CADiscoverBLEServicesThread, (void *) addr);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+ OICFree(addr);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return;
+ }
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "DisConnected from [%s] ", remoteAddress);
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+CAResult_t CABleGATTCreateBond(const char *remoteAddress)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ if (NULL == remoteAddress)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "remoteAddress is NULL! ");
+ return CA_STATUS_FAILED;
+ }
+
+ VERIFY_NON_NULL(remoteAddress, NULL, "Param remoteAddress is NULL");
+
+ int32_t ret = bt_device_create_bond(remoteAddress);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_device_create_bond Failed with ret value [%d] ", ret);
+ return CA_STATUS_FAILED;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ " bt_device_create_bond query success for address [%s]", remoteAddress);
+ }OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+
+ return CA_STATUS_OK;
+
+}
+
+CAResult_t CABleDiscoverServices(const char *remoteAddress)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ VERIFY_NON_NULL(remoteAddress, NULL, "Param remoteAddress is NULL");
+
+ sleep(2);
+
+ int32_t len = strlen(remoteAddress);
+
+ char *addr = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == addr)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ return CA_STATUS_FAILED;
+ }
+ memset(addr, 0x0, len + 1);
+
+ strncpy(addr, remoteAddress, len);
+
+ int32_t ret = bt_gatt_foreach_primary_services(remoteAddress, CABleGattPrimaryServiceCb,
+ (void *) addr); //addr memory will be free in callback.
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_gatt_foreach_primary_services Failed with ret value [%d] ",
+ ret);
+ OICFree(addr);
+ return CA_STATUS_FAILED;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_gatt_foreach_primary_services success for address [%s]", remoteAddress);
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+
+ return CA_STATUS_OK;
+
+}
+
+CAResult_t CABleDiscoverCharacteristics(bt_gatt_attribute_h service, const char *remoteAddress)
+{
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ VERIFY_NON_NULL(service, NULL, "service is NULL");
+
+ VERIFY_NON_NULL(remoteAddress, NULL, "remoteAddress is NULL");
+
+ int32_t len = strlen(remoteAddress);
+
+ char *addr = (char *) OICMalloc(sizeof(char) * len + 1);
+ if (NULL == addr)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed! ");
+ return CA_STATUS_FAILED;
+ }
+ memset(addr, 0x0, len + 1);
+
+ strncpy(addr, remoteAddress, len);
+
+ int32_t ret = bt_gatt_discover_characteristics(service, CABleGattCharacteristicsDiscoveredCb,
+ (void *) addr); // addr will be freed in callback.
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_gatt_discover_characteristics failed with error [%d]", ret);
+ OICFree(addr);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+
+ return CA_STATUS_OK;
+
+}
+
+CAResult_t CAStartBLEGattClient()
+{
+ CAResult_t retVal = CAInitGattClientMutexVaraibles();
+
+ if (retVal != CA_STATUS_OK)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CAInitGattClientMutexVaraibles failed!");
+ CATerminateGattClientMutexVariables();
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ if (NULL == gBleClientThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleServerThreadPool is NULL");
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ CAResult_t ret = u_thread_pool_add_task(gBleClientThreadPool,
+ (void *) CAStartBleGattClientThread, (void *) NULL);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return CA_STATUS_FAILED;
+ }
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ return CA_STATUS_OK;
+}
+
+void *CAStartBleGattClientThread(void *data)
+{
+ u_mutex_lock(gBleClientStateMutex);
+
+ if (CA_TRUE == gIsBleGattClientStarted)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "Gatt Client is already running");
+ u_mutex_unlock(gBleClientStateMutex);
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+
+ bt_adapter_le_scan_params_s scan_param =
+ { 0, };
+ scan_param.type = BT_ADAPTER_LE_PASSIVE_SCAN;
+ scan_param.interval = 1560;
+ scan_param.window = 160;
+
+ int32_t ret = bt_adapter_le_set_scan_parameter(&scan_param);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_set_scan_parameter Failed");
+ u_mutex_unlock(gBleClientStateMutex);
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+
+ ret = bt_gatt_set_connection_state_changed_cb(CABleGattConnectionStateChangedCb, NULL);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_gatt_set_connection_state_changed_cb Failed");
+ u_mutex_unlock(gBleClientStateMutex);
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+
+ ret = bt_adapter_le_set_device_discovery_state_changed_cb(
+ CABtAdapterLeDeviceDiscoveryStateChangedCb, NULL);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_adapter_le_set_device_discovery_state_changed_cb Failed");
+ u_mutex_unlock(gBleClientStateMutex);
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Setting characteristic_changed cb \n");
+
+ ret = bt_gatt_set_characteristic_changed_cb(CABleGattCharacteristicChangedCb, NULL);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_gatt_set_characteristic_changed_cb Failed as [%s ]",
+ CABTGetErrorMsg(ret));
+ u_mutex_unlock(gBleClientStateMutex);
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Setting bt_device_set_bond_created_cb \n");
+
+ ret = bt_device_set_bond_created_cb(CABtGattBondCreatedCb, NULL);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, " bt_device_set_bond_created_cb Failed as [%s ]",
+ CABTGetErrorMsg(ret));
+ u_mutex_unlock(gBleClientStateMutex);
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Starting LE device discovery");
+
+ ret = bt_adapter_le_start_device_discovery();
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_start_device_discovery Failed");
+ u_mutex_unlock(gBleClientStateMutex);
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG,
+ "bt_adapter_le_start_device_discovery Success");
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+
+ u_mutex_unlock(gBleClientStateMutex);
+
+ CAResult_t retVal = CAAdapterInitializeMessageQueue(&gCABleClientSenderQueue);
+ if (CA_STATUS_OK != retVal)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CAAdapterInitializeMessageQueue failed!");
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+
+ retVal = CAAdapterInitializeMessageQueue(&gCABleClientReceiverQueue);
+ if (CA_STATUS_OK != retVal)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CAAdapterInitializeMessageQueue failed!");
+ CATerminateBLEGattClient();
+ return NULL;
+ }
+ gIsBleGattClientStarted = CA_TRUE;
+ GMainContext *thread_context = NULL;
+
+ thread_context = g_main_context_new();
+
+ g_event_loop = g_main_loop_new(thread_context, FALSE);
+
+ g_main_context_push_thread_default(thread_context);
+
+ g_main_loop_run(g_event_loop);
+
+ return NULL;
+
+}
+
+void CAStopBLEGattClient()
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ u_mutex_lock(gBleClientStateMutex);
+
+ if (CA_FALSE == gIsBleGattClientStarted)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "Gatt Client is not running to stop");
+
+ u_mutex_unlock(gBleClientStateMutex);
+ return;
+ }
+ u_mutex_unlock(gBleClientStateMutex);
+
+ CATerminateBLEGattClient();
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+void CATerminateBLEGattClient()
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ u_mutex_lock(gBleClientStateMutex);
+
+ // Required for waking up the thread which is running in gmain loop
+
+ GMainContext *context_event_loop = g_main_loop_get_context(g_event_loop);
+
+ if (context_event_loop)
+ {
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "g_event_loop context %x", context_event_loop);
+
+ g_main_context_wakeup(context_event_loop);
+
+ }
+ else
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "g_event_loop context is NULL");
+ }
+
+ // Kill g main loops and kill threads
+ g_main_loop_quit(g_event_loop);
+
+ gClientUp = CA_FALSE;
+
+ bt_gatt_unset_connection_state_changed_cb();
+
+ bt_adapter_le_stop_device_discovery();
+
+ bt_gatt_unset_characteristic_changed_cb();
+
+ bt_adapter_le_unset_device_discovery_state_changed_cb();
+
+ bt_gatt_unset_connection_state_changed_cb();
+
+ bt_adapter_le_disable();
+
+ bt_device_unset_bond_created_cb();
+ bt_gatt_unset_characteristic_changed_cb();
+ u_mutex_lock(gBleServiceListMutex);
+
+ CAFreeBLEServiceList(gBLEServiceList);
+
+ gBLEServiceList = NULL;
+
+ u_mutex_unlock(gBleServiceListMutex);
+
+ gIsBleGattClientStarted = CA_FALSE;
+
+ u_mutex_unlock(gBleClientStateMutex);
+
+ CAResetRegisteredServiceCount();
+
+ u_mutex_lock(gBleClientSendDataMutex);
+ if (NULL != gCABleClientSenderQueue)
+ {
+ CAAdapterTerminateMessageQueue(gCABleClientSenderQueue);
+ gCABleClientSenderQueue = NULL;
+ }
+ u_mutex_unlock(gBleClientSendDataMutex);
+
+ u_mutex_lock(gBleClientReceiveDataMutex);
+ if (NULL != gCABleClientReceiverQueue)
+ {
+ CAAdapterTerminateMessageQueue(gCABleClientReceiverQueue);
+ gCABleClientReceiverQueue = NULL;
+
+ }
+ u_mutex_unlock(gBleClientReceiveDataMutex);
+
+ CATerminateGattClientMutexVaraibles();
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+CAResult_t CAInitGattClientMutexVaraibles()
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+ u_mutex_init();
+ if (NULL == gBleClientStateMutex)
+ {
+ gBleClientStateMutex = u_mutex_new();
+ if (NULL == gBleClientStateMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleServiceListMutex)
+ {
+ gBleServiceListMutex = u_mutex_new();
+ if (NULL == gBleServiceListMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleReqRespClientCbMutex)
+ {
+ gBleReqRespClientCbMutex = u_mutex_new();
+ if (NULL == gBleReqRespClientCbMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleClientSendDataMutex)
+ {
+ gBleClientSendDataMutex = u_mutex_new();
+ if (NULL == gBleClientSendDataMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleClientReceiveDataMutex)
+ {
+ gBleClientReceiveDataMutex = u_mutex_new();
+ if (NULL == gBleClientReceiveDataMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleClientThreadPoolMutex)
+ {
+ gBleClientThreadPoolMutex = u_mutex_new();
+ if (NULL == gBleClientThreadPoolMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleClientSendCondWait)
+ {
+ gBleClientSendCondWait = u_cond_new();
+ if (NULL == gBleClientSendCondWait)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "u_cond_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CATerminateGattClientMutexVariables()
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+ u_mutex_free(gBleClientReceiveDataMutex);
+ gBleClientReceiveDataMutex = NULL;
+ u_mutex_free(gBleClientStateMutex);
+ gBleClientStateMutex = NULL;
+ u_mutex_free(gBleServiceListMutex);
+ gBleServiceListMutex = NULL;
+ u_mutex_free(gBleReqRespClientCbMutex);
+ gBleReqRespClientCbMutex = NULL;
+ u_mutex_free(gBleClientSendDataMutex);
+ gBleClientSendDataMutex = NULL;
+ u_mutex_free(gBleClientThreadPoolMutex);
+ gBleClientThreadPoolMutex = NULL;
+ u_mutex_free(gBleClientSendCondWait);
+ gBleClientSendCondWait = NULL;
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+void CASetBleClientThreadPoolHandle(u_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ gBleClientThreadPool = handle;
+ u_mutex_unlock(gBleClientThreadPoolMutex);
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+}
+
+CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const char *data,
+ int32_t dataLen, TRANSFER_TYPE type, int32_t position)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ VERIFY_NON_NULL(data, NULL, "data is NULL");
+
+ if (0 >= dataLen)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "dataLen is less than or equal zero. Invalid input!");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ BLEServiceInfo *bleServiceInfo = NULL;
+ if (UNICAST == type)
+ {
+ VERIFY_NON_NULL(remoteAddress, NULL, "remoteAddress is NULL");
+ u_mutex_lock(gBleServiceListMutex);
+ CAResult_t ret = CAGetBLEServiceInfo(gBLEServiceList, remoteAddress, &bleServiceInfo);
+
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "CAGetBLEServiceInfo is failed!");
+ u_mutex_unlock(gBleServiceListMutex);
+ return CA_STATUS_FAILED;
+ }
+ u_mutex_unlock(gBleServiceListMutex);
+ }
+ else if (MULTICAST == type)
+ {
+ u_mutex_lock(gBleServiceListMutex);
+ CAResult_t ret = CAGetBLEServiceInfoByPosition(gBLEServiceList, position, &bleServiceInfo);
+
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "CAGetBLEServiceInfoByPosition is failed");
+ u_mutex_unlock(gBleServiceListMutex);
+ return CA_STATUS_FAILED;
+ }
+ u_mutex_unlock(gBleServiceListMutex);
+ }
+
+ VERIFY_NON_NULL(bleServiceInfo, NULL, "bleServiceInfo is NULL");
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Updating the data of length [%d] to [%s] ", dataLen,
+ bleServiceInfo->bdAddress);
+
+ char *value = (char *) OICMalloc(sizeof(char) * (dataLen + 1));
+
+ if (NULL == value)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "malloc failed!");
+ return CA_STATUS_FAILED;
+ }
+ memset(value, 0x0, (dataLen + 1));
+
+ strncpy(value, data, dataLen);
+
+ int32_t ret = bt_gatt_set_characteristic_value_request(bleServiceInfo->write_char, value,
+ dataLen, CABleGattCharacteristicWriteCb);
+
+ OICFree(value);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "bt_gatt_set_characteristic_value_request Failed with return val [%d]",
+ ret);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAUpdateCharacteristicsToAllGattServers(const char *data, int32_t dataLen)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ VERIFY_NON_NULL(data, NULL, "data is NULL");
+
+ if (0 >= dataLen)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "dataLen is less than or equal zero. Invalid input !");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ int32_t pos = 0;
+
+ int32_t NumberOfServersConnected = CAGetRegisteredServiceCount();
+
+ for (pos = 0; pos < NumberOfServersConnected; pos++)
+ {
+ /*remoteAddress will be NULL.
+ Since we have to send to all the address. pos will be used for getting remote address.
+ */
+ int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, MULTICAST, pos);
+
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
+ "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
+ }
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
+
+ return CA_STATUS_OK;
+}
+void CASetBLEReqRespClientCallback(CANetworkPacketReceivedCallback callback)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
+
+ u_mutex_lock(gBleReqRespClientCbMutex);
+
+ gReqRespClientCallback = callback;
+
+ u_mutex_unlock(gBleReqRespClientCbMutex);
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_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.
+*
+******************************************************************/
+#ifndef _BLE_CLIENT_
+#define _BLE_CLIENT_
+
+#include <bluetooth.h>
+#include <bluetooth_type.h>
+#include <bluetooth_product.h>
+
+#include "cacommon.h"
+#include "caadapterutils.h"
+#include "cableclientutil.h"
+#include "caadapterinterface.h"
+#include "logger.h"
+#include "uthreadpool.h"
+
+
+/**
+* @fn CAStartBLEGattClient
+* @brief Used to start CAStartBleGattClientThread for initializing Gatt Client
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAStartBLEGattClient();
+
+/**
+* @fn CAStartBleGattClientThread
+* @brief This is thread which will be used to initialize the Gatt Client and start device discovery.
+* 1. Set scan parameters 2.Setting neccessary callbacks for connection, characteristics changed and discovery and bond creation.
+* 3. Start device discovery
+*
+* @param[in] data - Currently it will be NULL(no parameter)
+*
+* @return NULL on success or failure.
+*
+*/
+void *CAStartBleGattClientThread(void *data);
+
+/**
+* @fn CAStopBLEGattClient
+* @brief Used to stop Gatt Client gracefully in turn it will call CATerminateBLEGattClient function.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+void CAStopBLEGattClient();
+
+/**
+* @fn CATerminateBLEGattClient
+* @brief Used to unset all the callbacks and stop service discovery
+*
+* @return void
+*
+*/
+void CATerminateBLEGattClient();
+
+/**
+* @fn CAInitGattClientMutexVaraibles
+* @brief Used to initialize all required mutex variable for Gatt Client implementation.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAInitGattClientMutexVaraibles();
+
+/**
+* @fn CATerminateGattClientMutexVaraibles
+* @brief Used to terminate all required mutex variable for Gatt Client implementation.
+*
+* @return void
+*
+*/
+void CATerminateGattClientMutexVariables();
+
+/**
+* @fn CASetBleClientThreadPoolHandle
+* @brief Used to Set the gThreadPool handle which is required for spawning new thread.
+*
+* @param[in] handle - Thread pool handle which is given by above layer for using thread creation task.
+*
+* @return void
+*
+*/
+void CASetBleClientThreadPoolHandle(u_thread_pool_t handle);
+
+
+/**
+* @fn CABleGATTCreateBond
+* @brief Used to make LE bond with remote device(pairng the device) using bt_device_create_bond api.
+*
+* @param[in] remoteAddress - mac address of remote device which we want to bond with
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CABleGATTCreateBond(const char *remoteAddress);
+
+
+/**
+* @fn CABleDiscoverServices
+* @brief Used to discover the services that is advertised by Gatt Server asynchrounously.
+*
+* @param[in] remoteAddress - mac address of remote device inwhich we want to discover the services.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CABleDiscoverServices(const char *remoteAddress);
+
+/**
+* @fn CABleDiscoverCharacteristics
+* @brief Used to discover the characteristics in specific service in remote device.
+*
+* @param[in] service -The attribute handle of service. Unique identifier for service.
+* @param[in] remoteAddress - mac address of remote device inwhich we want to discover the services.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CABleDiscoverCharacteristics(bt_gatt_attribute_h service, const char *remoteAddress);
+
+/**
+* @fn CARegisterForChangeInCharacterstics
+* @brief Used to register a callback function that will be invoked when a characteristic value is changed.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CARegisterForChangeInCharacterstics();
+
+/**
+* @fn CABleGattPrimaryServiceCb
+* @brief This is the callback which will be called when we get the primary services repeatedly.
+*
+* @param[in] service -The attribute handle of service. Unique identifier for service.
+* @param[in] userData - user data
+*
+* @return 0 on failure and 1 on success.
+*
+*/
+CABool_t CABleGattPrimaryServiceCb(bt_gatt_attribute_h service, void *userData);
+
+/**
+* @fn CABtGattCharacteristicsDiscoveredCb
+* @brief This is the callback which will be called after the characteristics are discovered by bt_gatt_discover_characteristics()
+*
+* @param[in] result The result of discovering
+* @param[in] inputIndex The index of characteristics in a service, starts from 0
+* @param[in] total The total number of characteristics in a service
+* @param[in] characteristic The attribute handle of characteristic
+* @param[in] userData The user data passed from the request function
+*
+* @return 0 on failure and 1 on success.
+*
+*/
+int32_t CABtGattCharacteristicsDiscoveredCb(int32_t result, int32_t inputIndex, int32_t total,
+ bt_gatt_attribute_h characteristic, void *userData);
+
+
+/**
+* @fn CAUpdateCharacteristicsToGattServer
+* @brief Sets the value of characteristic and update the value to GATTServer(unicast).
+*
+* @param[in] remoteAddress The address of the remote device
+* @param[in] data The value of characteristic (byte array)
+* @param[in] dataLen The length of value
+* @param[in] TRANSFER_TYPE (UNICAST/MULTICAST)
+* @param[in] position The unique index of each ble server. Used for multicast feature.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*/
+CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const char *data,
+ int32_t dataLen, TRANSFER_TYPE type, int32_t position);
+
+/**
+ * @fn CAUpdateCharacteristicsToGattServer
+ * @brief Sets the value of characteristic and update the value to All registered GATTServer -> Multicast
+ *
+ * @param[in] data The value of characteristic (byte array)
+ * @param[in] dataLen The length of value
+ *
+ * @return 0 on success otherwise a positive error value.
+ * @retval CA_STATUS_OK Successful
+ * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+ * @retval CA_STATUS_FAILED Operation failed
+ */
+CAResult_t CAUpdateCharacteristicsToAllGattServers(const char *data, int32_t dataLen);
+
+/**
+ * @fn CASetBLEReqRespClientCallback
+ * @brief used to store upper layer callback locally which will be used to send the data to application
+ *
+ * @param[in] CANetworkPacketReceivedCallback - upper layer callback function to pass the data to CA layer.
+ *
+ * @return void
+ *
+ */
+void CASetBLEReqRespClientCallback(CANetworkPacketReceivedCallback callback);
+
+/**
+* @fn CALEReadDataFromLEClient
+* @brief synchronous function for reading characteristic value.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CALEReadDataFromLEClient();
+
+/**
+* @fn CABleClientSenderQueueEnqueueMessage
+* @brief Used to enqueue the message into sender queue using CAAdapterEnqueueMessage and make signal to the thread to process.
+*
+* @param[in] remoteEndpoint Remote device information
+* @param[in] data data which we wants to send to remote device
+* @param[in] dataLen Length of data.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CABleClientSenderQueueEnqueueMessage(CARemoteEndpoint_t *remoteEndpoint,
+ void *data, uint32_t dataLen);
+
+/**
+* @fn CABleGattCharacteristicWriteCb
+* @brief This is the callback which will be called after the characteristics changed.
+*
+* @param[in] handle The attribute handle of characteristic
+*
+* @return void
+*
+*/
+void CABleGattCharacteristicWriteCb(bt_gatt_attribute_h handle);
+
+/**
+* @fn CABleClientSenderQueueProcessor
+* @brief This is the thread which will be used for processing sender queue.
+*
+* @return NULL on success or failure.
+*
+*/
+void *CABleClientSenderQueueProcessor();
+
+/**
+* @fn CABleGattDescriptorDiscoveredCb
+* @brief This is the callback which will be called when descriptor of characteristics is found.
+*
+* @param[in] result The result of discovering
+* @param[in] format format of descriptor.
+* @param[in] total The total number of descriptor in a characteristic
+* @param[in] descriptor The attribute handle of descriptor
+* @param[in] characteristic The attribute handle of characteristic
+* @param[in] userData The user data passed from the request function
+*
+* @return void
+*
+*/
+void CABleGattDescriptorDiscoveredCb(int32_t result, unsigned char format, int32_t total,
+ bt_gatt_attribute_h descriptor, bt_gatt_attribute_h characteristic, void *userData);
+/**
+* @fn CADiscoverDescriptorThread
+* @brief This is the thread which will be used for finding descriptor of characteristic.
+*
+* @param[in] stServiceInfo Service Information which contains the remote address and service handle, characteristic handle.
+*
+* @return NULL on success or failure.
+*
+*/
+void *CADiscoverDescriptorThread(void *stServiceInfo);
+
+/**
+* @fn CADiscoverCharThread
+* @brief This is the thread which will be used for finding characteristic of a service.
+*
+* @param[in] stServiceInfo Service Information which contains the remote address and service handle, characteristic handle.
+*
+* @return NULL on success or failure.
+*
+*/
+void *CADiscoverCharThread(void *stServiceInfo);
+
+/**
+* @fn CABtGattBondCreatedCb
+* @brief This is the callback which will be called when bond created with remote device.
+*
+* @param[in] result The result of bond creation.
+* @param[in] device_info remote device information
+* @param[in] userData The user data passed from the request function
+*
+* @return void
+*
+*/
+void CABtGattBondCreatedCb(int32_t result, bt_device_info_s *device_info, void *user_data);
+
+/**
+* @fn CAGATTCreateBondThread
+* @brief This is the thread which will be used for creating bond with remote device.
+*
+* @param[in] stServiceInfo Service Information which contains the remote address and service handle, characteristic handle.
+*
+* @return NULL on success or failure.
+*
+*/
+void *CAGATTCreateBondThread(void *stServiceInfo);
+
+/**
+* @fn CABleGattCharacteristicChangedCb
+* @brief This is the callback which will be called after the characteristic value changes happen.
+*
+* @param[in] characteristic The attribute handle of characteristic
+* @param[in] value Value of the characteristics of a service.
+* @param[in] valueLen length of data.
+* @param[in] userData The user data passed from the request function
+*
+* @return 0 on failure and 1 on success.
+*
+*/
+void CABleGattCharacteristicChangedCb(bt_gatt_attribute_h characteristic, unsigned char *value,
+ int32_t valueLen, void *userData);
+
+/**
+* @fn CABleGattCharacteristicsDiscoveredCb
+* @brief This is the callback which will be called after the characteristics are discovered by bt_gatt_discover_characteristics()
+*
+* @param[in] result The result of discovering
+* @param[in] inputIndex The index of characteristics in a service, starts from 0
+* @param[in] total The total number of characteristics in a service
+* @param[in] characteristic The attribute handle of characteristic
+* @param[in] userData The user data passed from the request function
+*
+* @return 0 on failure and 1 on success.
+*
+*/
+CABool_t CABleGattCharacteristicsDiscoveredCb(int32_t result, int32_t inputIndex, int32_t total,
+ bt_gatt_attribute_h characteristic, void *userData);
+
+/**
+* @fn CAGATTCreateBondThread
+* @brief This is the thread which will be used for making gatt connection with remote devices
+*
+* @param[in] remoteAddress Mac address of remote device which wants to connect with.
+*
+* @return NULL on success or failure.
+*
+*/
+void *CAGattConnectThread (void *remoteAddress);
+/**
+* @fn CAPrintDiscoveryInformation
+* @brief Used to print device information(Util method)
+*
+* @param[in] discoveryInfo Device information structure.
+*
+* @return void
+*
+*/
+void CAPrintDiscoveryInformation(bt_adapter_le_device_discovery_info_s *discoveryInfo);
+/**
+* @fn CABtAdapterLeDeviceDiscoveryStateChangedCb
+* @brief This is the callback which will be called when the device discovery state changes.
+*
+* @param[in] result The result of discovering
+* @param[in] discoveryState State of the discovery(FOUND/STARTED/ FINISHED)
+* @param[in] discoveryInfo Remote Device information.
+* @param[in] userData The user data passed from the request function
+*
+* @return void
+*
+*/
+void CABtAdapterLeDeviceDiscoveryStateChangedCb(int32_t result,
+ bt_adapter_le_device_discovery_state_e discoveryState,
+ bt_adapter_le_device_discovery_info_s *discoveryInfo,
+ void *userData);
+/**
+* @fn CADiscoverBLEServicesThread
+* @brief This is thread which will be spawned for discovering ble services. Once called discover api, then it will be terminated.
+*
+* @param[in] remoteAddress Mac address of the remote device in which we want to search services.
+*
+* @return NULL for success or failure.
+*
+*/
+void *CADiscoverBLEServicesThread (void *remoteAddress);
+
+/**
+* @fn CABleGattConnectionStateChangedCb
+* @brief This is the callback which will be called whenever there is change in gatt connection with server(Connected/Disconnected)
+*
+* @param[in] result The result of discovering
+* @param[in] connected State of connection
+* @param[in] remoteAddress Mac address of the remote device in which we made connection.
+* @param[in] userData The user data passed from the request function
+*
+* @return void
+*
+*/
+void CABleGattConnectionStateChangedCb(int32_t result, bool connected, const char *remoteAddress,
+ void *userData);
+
+
+
+#endif //#ifndef _BLE_CLIENT_
--- /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 "cableclientutil.h"
+
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<arpa/inet.h>
+#include<sys/types.h>
+#include<sys/socket.h>
+#include<netinet/in.h>
+
+
+#include "caadapterutils.h"
+
+#define TZ_BLE_CLIENT_UTIL_TAG "TZ_BLE_GATT_CLIENT_UTIL"
+
+#define OIC_BLE_SERVICE_ID "000018f3-0000-1000-8000-00805f9b34fb"
+///TODO: OIC_BLE_SERVICE_ID will be generated by invoking API in future.
+
+static BLEServiceList *gBLEServiceList = NULL;
+
+static int32_t gNumberOfServiceConnected = 0;
+
+void CAIncrementRegisteredServiceCount()
+{
+ gNumberOfServiceConnected++;
+}
+
+void CADecrementRegisteredServiceCount()
+{
+ gNumberOfServiceConnected--;
+}
+
+void CAResetRegisteredServiceCount()
+{
+ gNumberOfServiceConnected = 0;
+}
+
+int32_t CAGetRegisteredServiceCount()
+{
+ return gNumberOfServiceConnected ;
+}
+
+CAResult_t CACreateBLEServiceInfo(const char *bdAddress, bt_gatt_attribute_h service,
+ BLEServiceInfo **bleServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+
+ VERIFY_NON_NULL(bdAddress, NULL, " Param bdAddress is NULL");
+ VERIFY_NON_NULL(service, NULL, " Param service is NULL");
+
+ *bleServiceInfo = (BLEServiceInfo *) OICMalloc(sizeof(BLEServiceInfo));
+ if (NULL == *bleServiceInfo)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_UTIL_TAG, " Malloc failed!");
+ return CA_STATUS_FAILED;
+ }
+ memset(*bleServiceInfo, 0x0, sizeof(BLEServiceInfo));
+
+ int32_t len = strlen(bdAddress);
+ (*bleServiceInfo)->bdAddress = (char *) OICMalloc(sizeof(char) * len + 1);
+
+ if (NULL == (*bleServiceInfo)->bdAddress)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_UTIL_TAG, " Malloc failed!");
+
+ OICFree(*bleServiceInfo);
+ return CA_STATUS_FAILED;
+ }
+ memset((*bleServiceInfo)->bdAddress, 0x0, len + 1);
+
+ strncpy((*bleServiceInfo)->bdAddress, bdAddress, len);
+
+ if (service)
+ {
+
+ int32_t ret = bt_gatt_clone_attribute_handle(&((*bleServiceInfo)->service_clone), service);
+
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_UTIL_TAG, " service handle clone failed with ret [%d]",
+ ret);
+ OICFree((*bleServiceInfo)->bdAddress);
+ OICFree(*bleServiceInfo);
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAAppendBLECharInfo( bt_gatt_attribute_h characteristic, CHAR_TYPE type,
+ BLEServiceInfo *bleServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+
+ VERIFY_NON_NULL(characteristic, NULL, " Param characteristic is NULL");
+ VERIFY_NON_NULL(bleServiceInfo, NULL, " Param bleServiceInfo is NULL");
+
+ if (READ_CHAR == type )
+ {
+ int32_t ret = bt_gatt_clone_attribute_handle(&((bleServiceInfo)->read_char), characteristic);
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_UTIL_TAG, " read_char clone failed with ret [%d]",
+ ret);
+ return CA_STATUS_FAILED;
+ }
+ }
+ else if (WRITE_CHAR == type)
+ {
+ int32_t ret = bt_gatt_clone_attribute_handle(&((bleServiceInfo)->write_char), characteristic);
+ if (BT_ERROR_NONE != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_CLIENT_UTIL_TAG, " write_char clone failed with ret [%d]",
+ ret);
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAAddBLEServiceInfoToList(BLEServiceList **serviceList, BLEServiceInfo *bleServiceInfo)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+
+ VERIFY_NON_NULL(serviceList, NULL, " Param serviceList is NULL");
+ VERIFY_NON_NULL(bleServiceInfo, NULL, " Param bleServiceInfo is NULL");
+
+ BLEServiceList *node = (BLEServiceList *) OICMalloc(sizeof(BLEServiceList));
+ if (NULL == node)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_UTIL_TAG, "[ERROR]Malloc failed!");
+ OICFree(bleServiceInfo->bdAddress);
+ OICFree(bleServiceInfo);
+ return CA_STATUS_FAILED;
+ }
+ memset(node, 0x0, sizeof(BLEServiceList));
+
+ node->serviceInfo = bleServiceInfo;
+ node->next = NULL;
+
+ if (*serviceList == NULL) //Empty list
+ {
+ *serviceList = node;
+ }
+ else //Add at front end
+ {
+ node->next = *serviceList;
+ *serviceList = node;
+ }
+
+ CAIncrementRegisteredServiceCount();
+
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "Device [%s] added to list", bleServiceInfo->bdAddress);
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveBLEServiceInfoToList(BLEServiceList **serviceList,
+ BLEServiceInfo *bleServiceInfo,
+ const char *bdAddress)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+
+ VERIFY_NON_NULL(serviceList, NULL, "Param serviceList is NULL");
+ VERIFY_NON_NULL(*serviceList, NULL, "Param *serviceList is NULL");
+ VERIFY_NON_NULL(bdAddress, NULL, "Param bdAddress is NULL");
+
+ BLEServiceList *cur = NULL;
+ BLEServiceList *prev = NULL;
+
+ cur = *serviceList;
+ while (cur != NULL)
+ {
+ if (!strcasecmp(cur->serviceInfo->bdAddress, bdAddress))
+ {
+ if (cur == *serviceList)
+ {
+ *serviceList = cur->next;
+
+ cur->next = NULL;
+ CAFreeBLEServiceList(cur);
+ CADecrementRegisteredServiceCount();
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+ return CA_STATUS_OK;
+ }
+ else
+ {
+ prev->next = cur->next;
+
+ cur->next = NULL;
+ CAFreeBLEServiceList(cur);
+ CADecrementRegisteredServiceCount();
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+ return CA_STATUS_OK;
+ }
+ }
+ else
+ {
+ prev = cur;
+ cur = cur->next;
+ }
+ }
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, " OUT");
+ return CA_STATUS_FAILED;
+
+}
+
+CAResult_t CAGetBLEServiceInfo(BLEServiceList *serviceList, const char *bdAddress,
+ BLEServiceInfo **bleServiceInfo)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+
+ VERIFY_NON_NULL(serviceList, NULL, "Param serviceList is NULL");
+ VERIFY_NON_NULL(bleServiceInfo, NULL, "Param bleServiceInfo is NULL");
+ VERIFY_NON_NULL(bdAddress, NULL, "Param bdAddress is NULL");
+
+
+ BLEServiceList *cur = serviceList;
+ *bleServiceInfo = NULL;
+ while (cur != NULL)
+ {
+ if (!strcasecmp(cur->serviceInfo->bdAddress, bdAddress))
+ {
+ *bleServiceInfo = cur->serviceInfo;
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+ return CA_STATUS_OK;
+ }
+
+ cur = cur->next;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, " OUT");
+ return CA_STATUS_FAILED;
+}
+
+CAResult_t CAGetBLEServiceInfoByPosition(BLEServiceList *serviceList, int32_t position,
+ BLEServiceInfo **bleServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+
+ VERIFY_NON_NULL(serviceList, NULL, "Param serviceList is NULL");
+ VERIFY_NON_NULL(bleServiceInfo, NULL, "Param bleServiceInfo is NULL");
+
+ if (0 > position)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_UTIL_TAG, "Position Invalid input !");
+ return CA_STATUS_INVALID_PARAM;
+ }
+ BLEServiceList *cur = serviceList;
+ *bleServiceInfo = NULL;
+ int32_t count = 0;
+
+ while (cur != NULL)
+ {
+ if (position == count)
+ {
+ *bleServiceInfo = cur->serviceInfo;
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+ return CA_STATUS_OK;
+ }
+ count++;
+ cur = cur->next;
+ }
+ return CA_STATUS_FAILED;
+}
+
+void CAFreeBLEServiceList(BLEServiceList *serviceList)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+ while (serviceList)
+ {
+ BLEServiceList *temp = serviceList;
+ serviceList = serviceList->next;
+ CAFreeBLEServiceInfo(temp->serviceInfo);
+ OICFree(temp);
+ }
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+ return ;
+}
+
+void CAFreeBLEServiceInfo(BLEServiceInfo *bleServiceInfo)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+ if (bleServiceInfo)
+ {
+ if (bleServiceInfo->bdAddress)
+ {
+ bt_device_destroy_bond(bleServiceInfo->bdAddress);
+ bt_gatt_disconnect(bleServiceInfo->bdAddress);
+ OICFree(bleServiceInfo->bdAddress);
+ bt_gatt_destroy_attribute_handle(bleServiceInfo->service_clone);
+ bt_gatt_destroy_attribute_handle(bleServiceInfo->read_char);
+ bt_gatt_destroy_attribute_handle(bleServiceInfo->write_char);
+ }
+ OICFree(bleServiceInfo);
+ }
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+ return ;
+}
+
+
+CAResult_t CAVerifyOICService(bt_gatt_attribute_h serviceHandle)
+{
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "IN");
+
+ VERIFY_NON_NULL(serviceHandle, NULL, "Param serviceHandle is NULL");
+
+ int32_t ret = 0;
+ char *uuid = NULL;
+
+ ret = bt_gatt_get_service_uuid(serviceHandle, &uuid);
+
+ if (0 != ret)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_UTIL_TAG, "bt_gatt_get_service_uuid failed !");
+ return CA_STATUS_FAILED;
+ }
+
+ if (strcasecmp(uuid, OIC_BLE_SERVICE_ID) != 0)
+ {
+ OIC_LOG(ERROR, TZ_BLE_CLIENT_UTIL_TAG, "It is not OIC service!");
+ return CA_STATUS_FAILED;
+ }
+ OIC_LOG(DEBUG, TZ_BLE_CLIENT_UTIL_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+const char *CABTGetErrorMsg(bt_error_e err)
+{
+ const char *errStr = NULL;
+
+ switch (err)
+ {
+ case BT_ERROR_NONE:
+ errStr = "BT_ERROR_NONE";
+ break;
+ case BT_ERROR_CANCELLED:
+ errStr = "BT_ERROR_CANCELLED";
+ break;
+ case BT_ERROR_INVALID_PARAMETER:
+ errStr = "BT_ERROR_INVALID_PARAMETER";
+ break;
+ case BT_ERROR_OUT_OF_MEMORY:
+ errStr = "BT_ERROR_OUT_OF_MEMORY";
+ break;
+ case BT_ERROR_RESOURCE_BUSY:
+ errStr = "BT_ERROR_RESOURCE_BUSY";
+ break;
+ case BT_ERROR_TIMED_OUT:
+ errStr = "BT_ERROR_TIMED_OUT";
+ break;
+ case BT_ERROR_NOW_IN_PROGRESS:
+ errStr = "BT_ERROR_NOW_IN_PROGRESS";
+ break;
+ case BT_ERROR_NOT_INITIALIZED:
+ errStr = "BT_ERROR_NOT_INITIALIZED";
+ break;
+ case BT_ERROR_NOT_ENABLED:
+ errStr = "BT_ERROR_NOT_ENABLED";
+ break;
+ case BT_ERROR_ALREADY_DONE:
+ errStr = "BT_ERROR_ALREADY_DONE";
+ break;
+ case BT_ERROR_OPERATION_FAILED:
+ errStr = "BT_ERROR_OPERATION_FAILED";
+ break;
+ case BT_ERROR_NOT_IN_PROGRESS:
+ errStr = "BT_ERROR_NOT_IN_PROGRESS";
+ break;
+ case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
+ errStr = "BT_ERROR_REMOTE_DEVICE_NOT_BONDED";
+ break;
+ case BT_ERROR_AUTH_REJECTED:
+ errStr = "BT_ERROR_AUTH_REJECTED";
+ break;
+ case BT_ERROR_AUTH_FAILED:
+ errStr = "BT_ERROR_AUTH_FAILED";
+ break;
+ case BT_ERROR_REMOTE_DEVICE_NOT_FOUND:
+ errStr = "BT_ERROR_REMOTE_DEVICE_NOT_FOUND";
+ break;
+ case BT_ERROR_SERVICE_SEARCH_FAILED:
+ errStr = "BT_ERROR_SERVICE_SEARCH_FAILED";
+ break;
+ case BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED:
+ errStr = "BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED";
+ break;
+ case BT_ERROR_PERMISSION_DENIED:
+ errStr = "BT_ERROR_PERMISSION_DENIED";
+ break;
+ case BT_ERROR_SERVICE_NOT_FOUND:
+ errStr = "BT_ERROR_SERVICE_NOT_FOUND";
+ break;
+ case BT_ERROR_NOT_SUPPORTED:
+ errStr = "BT_ERROR_NOT_SUPPORTED";
+ break;
+ default:
+ errStr = "NOT Defined";
+ break;
+ }
+
+ return errStr;
+}
+
--- /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.
+*
+******************************************************************/
+#ifndef _BLE_CLIENT_UTIL
+#define _BLE_CLIENT_UTIL
+
+#include <bluetooth.h>
+
+#include "cacommon.h"
+#include "logger.h"
+
+
+/**
+ * @struct BLEServiceInfo
+ * @brief Info regarding the GATTServer
+ *
+ * This structure holds the infomation about the GATTServer
+* in the service and the characteristic level
+ */
+typedef struct
+{
+ bt_gatt_attribute_h service_clone; /**< gatt_attribute handler for the OIC service. */
+ bt_gatt_attribute_h
+ read_char; /**< gatt_attribute handler for the OIC read characteristic. */
+ bt_gatt_attribute_h
+ write_char; /**< gatt_attribute handler for the OIC write characteristic. */
+ char *bdAddress; /**< BD address where OIC service is running. */
+} BLEServiceInfo;
+
+/**
+ * @struct BLEServiceList
+ * @brief List of the BLEServiceInfo structures.
+ *
+ * A list of BLEServiceInfo and gives the info about all the
+ * the registered services from the client side.
+ */
+typedef struct _BLEServiceList
+{
+ BLEServiceInfo *serviceInfo; /**< BLEServiceInfo strucutre from an OIC Server */
+ struct _BLEServiceList *next; /**< next pointer */
+} BLEServiceList;
+
+/**
+ * @ENUM CHAR_TYPE
+ * @brief different characteristics types.
+ *
+ * This ENUM provides information of different characteristics
+ * which will be added to OIC service.
+ */
+typedef enum
+{
+ WRITE_CHAR, /**< write_char This will be used to get the unicast response */
+ READ_CHAR, /**< read_char This will be used update value to OIC server */
+ NOTIFY_CHAR /**< reserved char for the time being. */
+} CHAR_TYPE;
+
+/**
+ * @ENUM TRANSFER_TYPE
+ * @brief Provide info about different mode of data transfer
+ *
+ * This enum is used to differentiate between unicast and multicast data transfer.
+ */
+typedef enum
+{
+ MULTICAST, /**< When this enum is selected, data will be updated to all OIC servers. */
+ UNICAST /**< When this enum is selected, data will be updated to desired OIC Server. */
+} TRANSFER_TYPE;
+
+typedef struct gattCharDescriptor
+{
+ bt_gatt_attribute_h descriptor;
+ bt_gatt_attribute_h characteristic;
+ int total;
+} stGattCharDescriptor_t;
+
+/**
+* @fn CAIncrementRegisteredServiceCount
+* @brief Used to increment the registered service count.
+*
+* @return void.
+*
+*/
+void CAIncrementRegisteredServiceCount();
+
+/**
+* @fn CADecrementRegisteredServiceCount
+* @brief Used to decrement the registered service count.
+*
+* @return void.
+*
+*/
+void CADecrementRegisteredServiceCount();
+
+/**
+* @fn CAResetRegisteredServiceCount
+* @brief Used to reset the registered service count.
+*
+* @return void.
+*
+*/
+void CAResetRegisteredServiceCount();
+
+/**
+* @fn CAGetRegisteredServiceCount
+* @brief Used to get the total registered service count.
+*
+* @return total registered service count.
+*
+*/
+int32_t CAGetRegisteredServiceCount();
+
+/**
+* @fn CACreateBLEServiceInfo
+* @brief Used to create BLEServiceInfo structure with server handler and BD address will be created.
+*
+* @param[in] bdAddress - BD address of the device where GATTServer is running.
+* @param[in] service - service attribute handler.
+* @param[in] bleServiceInfo - Pointer where serviceInfo structure needs to be stored.
+* Memory will be allocated here and needs to be cleared by user.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CACreateBLEServiceInfo(const char *bdAddress, bt_gatt_attribute_h service,
+ BLEServiceInfo **bleServiceInfo);
+
+/**
+* @fn CAAppendBLECharInfo
+* @brief Used to append the characteristic info to the already created serviceInfo structure.
+*
+* @param[in] characteristic charecteristic attribute handler.
+* @param[in] type specifies whether its READ_CHAR or WRITE_CHAR
+* @param[in] bleServiceInfo Pointer where serviceInfo structure needs to be appended with char info.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAAppendBLECharInfo(bt_gatt_attribute_h characteristic, CHAR_TYPE type,
+ BLEServiceInfo *bleServiceInfo);
+
+/**
+* @fn CAAddBLEServiceInfoToList
+* @brief Used to add the ServiceInfo structure to the Service List.
+*
+* @param[in] serviceList Pointer to the ble service list which holds the info of list of service registered from client.
+* @param[in] bleServiceInfo Pointer where serviceInfo structure needs to be appended with char info.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAAddBLEServiceInfoToList(BLEServiceList **serviceList, BLEServiceInfo *bleServiceInfo);
+
+/**
+* @fn CARemoveBLEServiceInfoToList
+* @brief Used to remove the ServiceInfo structure from the Service List.
+*
+* @param[in] serviceList Pointer to the ble service list which holds the info of list of service registered from client.
+* @param[in] bleServiceInfo Pointer where serviceInfo structure needs to be appended with char info.
+* @param[in] bdAddress BD address of the device where GATTServer is disconnected.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CARemoveBLEServiceInfoToList(BLEServiceList **serviceList,
+ BLEServiceInfo *bleServiceInfo,
+ const char *bdAddress);
+
+/**
+* @fn CAGetBLEServiceInfo
+* @brief Used to get the serviceInfo from the list.
+*
+* @param[in] serviceList Pointer to the ble service list which holds the info of list of service registered from client.
+* @param[in] bdAddress BD address of the device where GATTServer information is required.
+* @param[out] bleServiceInfo Pointer where serviceInfo structure needs to provide the service and char info.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAGetBLEServiceInfo(BLEServiceList *serviceList, const char *bdAddress,
+ BLEServiceInfo **bleServiceInfo);
+
+/**
+* @fn CAGetBLEServiceInfoByPosition
+* @brief Used to get the serviceInfo from the list by position.
+*
+* @param[in] serviceList Pointer to the ble service list which holds the info of list of service registered from client.
+* @param[in] position The service information of particular position in the list.
+* @param[out] bleServiceInfo Pointer where serviceInfo structure needs to provide the service and char info.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAGetBLEServiceInfoByPosition(BLEServiceList *serviceList, int32_t position,
+ BLEServiceInfo **bleServiceInfo);
+
+/**
+* @fn CAFreeBLEServiceList
+* @brief Used to get clear ble service list
+*
+* @param[in] serviceList Pointer to the ble service list which holds the info of list of service registered from client.
+*
+* @return void
+*
+*/
+void CAFreeBLEServiceList(BLEServiceList *serviceList);
+
+/**
+* @fn CAFreeBLEServiceInfo
+* @brief Used to get remove particular ble service info from list
+*
+* @param[in] serviceinfo Pointer to the structure which needs to be cleared.
+*
+* @return void
+*
+*/
+void CAFreeBLEServiceInfo(BLEServiceInfo *bleServiceInfo);
+
+/**
+* @fn CAVerifyOICService
+* @brief Used to check whether found handle is OIC service handle or not.
+*
+* @param[in] serviceHandle - Discovered service handle(unique identifier for service)
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAVerifyOICService(bt_gatt_attribute_h serviceHandle);
+
+#endif //#ifndef _BLE_CLIENT_UTIL
--- /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 "cableserver.h"
+#include <pthread.h>
+#include "cacommon.h"
+#include "caadapterutils.h"
+#include <gio/gio.h>
+#include "umutex.h"
+#include "camessagequeue.h"
+#include "caadapterutils.h"
+
+/**
+ * @def TZ_BLE_SERVER_TAG
+ * @brief Logging tag for module name
+ */
+#define TZ_BLE_SERVER_TAG "TZ_BLE_GATT_SERVER"
+
+///TODO:: Currently keeping as single service. Later service path will be added in list for supporting multiple services.
+
+static char *gGattSvcPath = NULL;
+
+static char *gGattReadCharPath = NULL;
+
+static char *gGattWriteCharPath = NULL;
+
+static bt_advertiser_h hAdvertiser = NULL;
+
+static CANetworkPacketReceivedCallback gReqRespCallback = NULL;
+
+static CAAdapterMessageQueue_t *gCABleServerSenderQueue = NULL;
+
+static CAAdapterMessageQueue_t *gCABleServerReceiverQueue = NULL;
+
+static CABool_t gIsBleGattServerStarted = CA_FALSE;
+
+/**
+ * @var gServiceStateMutex
+ * @brief Mutex to synchronize the process of starting Gatt Server.
+ */
+static u_mutex gBleServerStateMutex = NULL;
+
+static u_mutex gBleCharacteristicMutex = NULL;
+
+static u_mutex gBleServiceMutex = NULL;
+
+static u_mutex gBleReqRespCbMutex = NULL;
+
+static u_mutex gBleServerSendDataMutex = NULL;
+
+static u_mutex gBleServerThreadPoolMutex = NULL;
+
+static u_cond gBleServerSendCondWait = NULL;
+
+static u_mutex gBleServerReceiveDataMutex = NULL;
+
+static GMainLoop *g_event_loop = NULL;
+
+static u_thread_pool_t gBleServerThreadPool = NULL;
+
+static CABool_t gServerUp = CA_FALSE;
+
+
+void *CABleServerSenderQueueProcessor()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN ");
+
+ while (gServerUp)
+ {
+ CAAdapterMessage_t *senderData = NULL;
+
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, " conditional wait");
+
+ u_mutex_lock(gBleServerSendDataMutex);
+ u_cond_wait(gBleServerSendCondWait, gBleServerSendDataMutex);
+
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "wait unlocked");
+
+ CAResult_t result = CA_STATUS_FAILED;
+
+ while (CA_STATUS_OK == CAAdapterDequeueMessage(gCABleServerSenderQueue, &senderData))
+ {
+ if (senderData == NULL)
+ {
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "senderData is NULL");
+ continue;
+ }
+ result = CAUpdateCharacteristicsInGattServer(senderData->data, senderData->dataLen);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Failed to CAUpdateCharacteristicsInGattServer");
+ }
+ else
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Failed to CAUpdateCharacteristicsInGattServer !");
+ }
+ CAAdapterFreeMessage(senderData);
+ }
+
+ u_mutex_unlock(gBleServerSendDataMutex);
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT ");
+ return NULL;
+}
+
+
+CAResult_t CAStartBleGattServer()
+{
+ ///TODO:: Check BT adapter is enabled or not ..if its not enabled, enable bt adapter.
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ CAResult_t ret = CAInitGattServerMutexVaraibles();
+
+ if (CA_STATUS_OK != ret )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAInitGattServerMutexVaraibles failed!");
+ CATerminateGattServerMutexVaraibles();
+ return CA_SERVER_NOT_STARTED;
+ }
+
+
+ u_mutex_lock(gBleServerThreadPoolMutex);
+ if (NULL == gBleServerThreadPool)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "gBleServerThreadPool is NULL");
+ u_mutex_unlock(gBleServerThreadPoolMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ ret = u_thread_pool_add_task(gBleServerThreadPool, (void *) CAStartBleGattServerThread,
+ (void *) NULL);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+ u_mutex_unlock(gBleServerThreadPoolMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ ret = CAAdapterInitializeMessageQueue(&gCABleServerSenderQueue);
+ if (CA_STATUS_OK != ret )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAdapterInitializeMessageQueue failed!");
+ CATerminateBleGattServer();
+ u_mutex_unlock(gBleServerThreadPoolMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ ret = CAAdapterInitializeMessageQueue(&gCABleServerReceiverQueue);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAdapterInitializeMessageQueue failed!");
+ CATerminateBleGattServer();
+ u_mutex_unlock(gBleServerThreadPoolMutex);
+ return CA_STATUS_FAILED;
+ }
+ gServerUp = CA_TRUE;
+ ret = u_thread_pool_add_task(gBleServerThreadPool, (void *) CABleServerSenderQueueProcessor,
+ (void *) NULL);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
+
+ //CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo, bleServiceInfo->bdAddress);
+ u_mutex_unlock(gBleServerThreadPoolMutex);
+ return CA_STATUS_FAILED;
+ }
+ u_mutex_unlock(gBleServerThreadPoolMutex);
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void *CAStartBleGattServerThread(void *data)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+ u_mutex_lock(gBleServerStateMutex);
+ if (CA_TRUE == gIsBleGattServerStarted)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Gatt Server is already running");
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ CAResult_t ret = CAInitBleGattService();
+
+ if (CA_STATUS_OK != ret )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "_bt_gatt_init_service failed");
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ sleep(5); // Sleep is must. otherwise its crashing
+
+ char *serviceUUID = "000018f3-0000-1000-8000-00805f9b34fb";
+
+ ret = CAAddNewBleServiceInGattServer(serviceUUID);
+
+ if (CA_STATUS_OK != ret )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAddNewBleServiceInGattServer failed");
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ char *charReadUUID = "00002af5-0000-1000-8000-00805f9b34fb";
+
+ char charReadValue[4] = {33, 44, 55, 66};
+
+ ret = CAAddNewCharacteristicsToGattServer(gGattSvcPath, charReadUUID, charReadValue, 512 ,
+ 0); // For Read Characteristics.
+
+ if (CA_STATUS_OK != ret )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAddNewCharacteristicsToGattServer failed");
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ char *charWriteUUID = "00002af6-0000-1000-8000-00805f9b34fb";
+
+ char charWriteValue[4] = {33, 44, 55, 66};
+
+
+ ret = CAAddNewCharacteristicsToGattServer(gGattSvcPath, charWriteUUID, charWriteValue, 512 ,
+ 1); // For Write Characteristics.
+ if (CA_STATUS_OK != ret )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAddNewCharacteristicsToGattServer failed");
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ ret = CARegisterBleServicewithGattServer(gGattSvcPath);
+
+ if (CA_STATUS_OK != ret )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CARegisterBleServicewithGattServer failed");
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ bt_adapter_le_create_advertiser(&hAdvertiser);
+
+ if (NULL == hAdvertiser)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "hAdvertiser is NULL");
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ int32_t retVal = bt_adapter_le_start_advertising(hAdvertiser, NULL, NULL, NULL);
+
+ if (BT_ERROR_NONE != retVal)
+ {
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "bt_adapter_le_start_advertising failed with ret [%d] ",
+ retVal);
+ u_mutex_unlock(gBleServerStateMutex);
+ CATerminateBleGattServer();
+ return NULL;
+ }
+
+ gIsBleGattServerStarted = CA_TRUE;
+
+ u_mutex_unlock(gBleServerStateMutex);
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG,
+ "LE Server initialization complete. Enabling gServerUp state to TRUE ");
+ gServerUp = CA_TRUE;
+
+ GMainContext *thread_context = NULL;
+
+ thread_context = g_main_context_new();
+
+ g_event_loop = g_main_loop_new(thread_context, FALSE);
+
+ g_main_context_push_thread_default(thread_context);
+
+ g_main_loop_run(g_event_loop);
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+
+ return NULL;
+
+}
+
+CAResult_t CAStopBleGattServer()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ u_mutex_lock(gBleServerStateMutex);
+
+ if (CA_FALSE == gIsBleGattServerStarted)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Gatt Server is not running to stop");
+
+ u_mutex_unlock(gBleServerStateMutex);
+ return CA_STATUS_OK;
+ }
+ u_mutex_unlock(gBleServerStateMutex);
+
+ CATerminateBleGattServer();
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+void CATerminateBleGattServer()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ int32_t ret = 0;
+
+ u_mutex_lock(gBleServerStateMutex);
+ // Required for waking up the thread which is running in gmain loop
+ GMainContext *context_event_loop = g_main_loop_get_context(g_event_loop);
+
+ if (context_event_loop)
+ {
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "g_event_loop context %x", context_event_loop);
+ g_main_context_wakeup(context_event_loop);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "g_event_loop context is NULL");
+ }
+
+ // Kill g main loops and kill threads
+ g_main_loop_quit(g_event_loop);
+
+ if (NULL != hAdvertiser )
+ {
+ ret = bt_adapter_le_stop_advertising(hAdvertiser);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_adapter_le_stop_advertising failed with ret [%d]", ret);
+ }
+
+ ret = bt_adapter_le_destroy_advertiser(hAdvertiser);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_adapter_le_destroy_advertiser failed with ret [%d]", ret);
+ }
+ hAdvertiser = NULL;
+ }
+
+ ret = CARemoveAllBleServicesFromGattServer();
+ if (ret != 0)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "removeAllBleServicesFromGattServer failed");
+ }
+
+ ret = CADeInitBleGattService();
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "_bt_gatt_deinit_service failed with ret [%d]", ret);
+ }
+
+ // free service Path(unique identifier for ble service)
+ u_mutex_lock(gBleServiceMutex);
+ OICFree(gGattSvcPath);
+ gGattSvcPath = NULL;
+ u_mutex_unlock(gBleServiceMutex);
+
+ // freeing characteristics
+ u_mutex_lock(gBleCharacteristicMutex);
+ OICFree(gGattReadCharPath);
+ gGattReadCharPath = NULL;
+ OICFree(gGattWriteCharPath);
+ gGattWriteCharPath = NULL;
+ u_mutex_unlock(gBleCharacteristicMutex);
+
+ gIsBleGattServerStarted = CA_FALSE;
+ gServerUp = CA_FALSE;
+ u_mutex_unlock(gBleServerStateMutex);
+
+ // Terminating gCABleServerSenderQueue
+ u_mutex_lock(gBleServerSendDataMutex);
+ if (NULL != gCABleServerSenderQueue)
+ {
+ CAAdapterTerminateMessageQueue(gCABleServerSenderQueue);
+ gCABleServerSenderQueue = NULL;
+ }
+ u_mutex_unlock(gBleServerSendDataMutex);
+
+ // Terminating gCABleServerReceiverQueue
+ u_mutex_lock(gBleServerReceiveDataMutex);
+ if (NULL != gCABleServerReceiverQueue)
+ {
+ CAAdapterTerminateMessageQueue(gCABleServerReceiverQueue);
+ gCABleServerReceiverQueue = NULL;
+ }
+ u_mutex_unlock(gBleServerReceiveDataMutex);
+
+ // Terminating all mutex variables.
+ CATerminateGattServerMutexVaraibles();
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+}
+
+CAResult_t CAInitGattServerMutexVaraibles()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+ u_mutex_init();
+ if (NULL == gBleServerStateMutex)
+ {
+ gBleServerStateMutex = u_mutex_new();
+ if (NULL == gBleServerStateMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleServiceMutex)
+ {
+ gBleServiceMutex = u_mutex_new();
+ if (NULL == gBleServiceMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleCharacteristicMutex)
+ {
+ gBleCharacteristicMutex = u_mutex_new();
+ if (NULL == gBleCharacteristicMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleReqRespCbMutex)
+ {
+ gBleReqRespCbMutex = u_mutex_new();
+ if (NULL == gBleReqRespCbMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleServerSendDataMutex)
+ {
+ gBleServerSendDataMutex = u_mutex_new();
+ if (NULL == gBleServerSendDataMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleServerReceiveDataMutex)
+ {
+ gBleServerReceiveDataMutex = u_mutex_new();
+ if (NULL == gBleServerReceiveDataMutex)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ if (NULL == gBleServerSendCondWait)
+ {
+ gBleServerSendCondWait = u_cond_new();
+ if (NULL == gBleServerSendCondWait)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_mutex_new failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ return CA_STATUS_OK;
+}
+void CATerminateGattServerMutexVaraibles()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+ u_mutex_free(gBleServerStateMutex);
+ gBleServerStateMutex = NULL;
+
+ u_mutex_free(gBleServerReceiveDataMutex);
+ gBleServerReceiveDataMutex = NULL;
+ u_mutex_free(gBleServerSendDataMutex);
+ gBleServerSendDataMutex = NULL;
+
+ gBleServerStateMutex = NULL;
+ u_mutex_free(gBleServiceMutex);
+ gBleServiceMutex = NULL;
+ u_mutex_free(gBleCharacteristicMutex);
+ gBleCharacteristicMutex = NULL;
+ u_mutex_free(gBleReqRespCbMutex);
+ gBleReqRespCbMutex = NULL;
+
+ u_mutex_free(gBleServerSendCondWait);
+ gBleServerSendCondWait = NULL;
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+}
+CAResult_t CAInitBleGattService()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+ int32_t ret = _bt_gatt_init_service();
+
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "_bt_gatt_deinit_service failed with ret [%d]", ret);
+ return CA_STATUS_FAILED;
+ }
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+
+CAResult_t CADeInitBleGattService()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+ int32_t ret = _bt_gatt_deinit_service();
+
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "_bt_gatt_deinit_service failed with ret [%d]", ret);
+ return CA_STATUS_FAILED;
+ }
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CASetBleServerThreadPoolHandle(u_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+ u_mutex_lock(gBleServerThreadPoolMutex);
+ gBleServerThreadPool = handle;
+ u_mutex_unlock(gBleServerThreadPoolMutex);
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+}
+
+
+CAResult_t CALEReadDataFromLEServer()
+{
+#if 0
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN ");
+
+ CAAdapterMessage_t *receiverData = NULL;
+
+ CAResult_t result = CAAdapterDequeueMessage(gCABleServerReceiverQueue, &receiverData);
+
+ if (CA_STATUS_OK != result)
+ {
+ u_mutex_lock(gBleReqRespCbMutex);
+ if (NULL == gReqRespCallback)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "gReqRespCallback is NULL!");
+ u_mutex_unlock(gBleReqRespCbMutex);
+ return;
+ }
+
+ gReqRespCallback(receiverData->remoteEndpoint, receiverData->data, receiverData->dataLen);
+
+ u_mutex_unlock(gBleReqRespCbMutex);
+
+ CAAdapterFreeMessage(receiverData);
+ }
+#endif
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT ");
+}
+
+CAResult_t CAAddNewBleServiceInGattServer(const char *serviceUUID)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ VERIFY_NON_NULL(serviceUUID, NULL, "Param serviceUUID is NULL");
+
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "service uuid %s", serviceUUID);
+
+ char *svcPath = NULL;
+
+ int32_t ret = bt_gatt_add_service(serviceUUID, &svcPath);
+
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_gatt_add_service failed with ret [%d]", ret);
+ return CA_STATUS_FAILED;
+ }
+
+ if (NULL != svcPath)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "AddNewBleServiceInGattServer ServicePath obtained is %s",
+ svcPath);
+
+ u_mutex_lock(gBleServiceMutex);
+
+ if (NULL != gGattSvcPath)
+ {
+ OICFree(gGattSvcPath);
+ gGattSvcPath = NULL;
+ }
+ gGattSvcPath = svcPath;
+
+ u_mutex_unlock(gBleServiceMutex);
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveBleServiceFromGattServer(const char *svcPath)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ VERIFY_NON_NULL(svcPath, NULL, "Param svcPath is NULL");
+
+ int32_t ret = bt_gatt_remove_service(svcPath);
+
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_gatt_remove_service failed [%d]", ret);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveAllBleServicesFromGattServer()
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+ int32_t ret = bt_gatt_delete_services();
+
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_gatt_delete_services failed with ret [%d]", ret);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+void CABleGattRemoteCharacteristicWriteCb(char *charPath,
+ unsigned char *charValue,
+ int32_t charValueLen, void *userData)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ if (NULL == charPath || NULL == charValue)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Param callback values are NULL");
+ return;
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "charPath = [%s] charValue = [%s] len [%d]", charPath,
+ charValue, charValueLen);
+ CARemoteEndpoint_t *remoteEndPoint = (CARemoteEndpoint_t *) OICMalloc(sizeof(CARemoteEndpoint_t));
+ if (NULL == remoteEndPoint)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Malloc Failure!");
+ return;
+ }
+ memset(remoteEndPoint, 0x0, sizeof(CARemoteEndpoint_t));
+ ///TODO: Currently Empty endpoint is being sent.
+ ///TODO:Later proper remote address has to be added when tizen team changed their code
+#if 0
+ VERIFY_NON_NULL(gCABleServerReceiverQueue, TZ_BLE_SERVER_TAG, "BleServerReceiverQueue is NULL");
+
+ CAResult_t retVal = CAAdapterEnqueueMessage(gCABleServerReceiverQueue, remoteEndPoint, charValue,
+ charValueLen);
+ if (CA_STATUS_OK != retVal )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAdapterEnqueueMessage failed!");
+ return;
+ }
+#endif
+
+ char *data = (char *)OICMalloc(sizeof(char) * charValueLen + 1);
+ if (NULL == data)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Malloc failed!");
+ OICFree(remoteEndPoint);
+ return;
+ }
+
+ memset(data, 0x0, charValueLen + 1);
+
+ strncpy(data, charValue, charValueLen);
+
+ u_mutex_lock(gBleReqRespCbMutex);
+ if (NULL == gReqRespCallback)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "gReqRespCallback is NULL!");
+ OICFree(charValue);
+ OICFree(remoteEndPoint);
+ u_mutex_unlock(gBleReqRespCbMutex);
+ return;
+ }
+
+ gReqRespCallback(remoteEndPoint, data, charValueLen);
+ u_mutex_unlock(gBleReqRespCbMutex);
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+}
+
+CAResult_t CABleServerSenderQueueEnqueueMessage(CARemoteEndpoint_t *remoteEndpoint,
+ void *data, uint32_t dataLen)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN ");
+
+ VERIFY_NON_NULL(data, NULL, "Param data is NULL");
+
+ VERIFY_NON_NULL_RET(gCABleServerSenderQueue, TZ_BLE_SERVER_TAG, "BleServerReceiverQueue is NULL",
+ CA_STATUS_FAILED);
+ VERIFY_NON_NULL_RET(gBleServerSendDataMutex, TZ_BLE_SERVER_TAG, "BleServerSendDataMutex is NULL",
+ CA_STATUS_FAILED);
+ VERIFY_NON_NULL_RET(gBleServerSendCondWait, TZ_BLE_SERVER_TAG, "BleServerSendCondWait is NULL",
+ CA_STATUS_FAILED);
+
+ u_mutex_lock(gBleServerSendDataMutex);
+ CAResult_t retVal = CAAdapterEnqueueMessage(gCABleServerSenderQueue, remoteEndpoint, data, dataLen);
+ if (CA_STATUS_OK != retVal )
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAdapterEnqueueMessage failed!");
+ u_mutex_unlock(gBleServerSendDataMutex);
+ return CA_STATUS_FAILED;
+ }
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "Sending signal for the sender processor ");
+ u_mutex_unlock(gBleServerSendDataMutex);
+ u_cond_signal(gBleServerSendCondWait);
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT ");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARegisterBleServicewithGattServer(const char *svcPath)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ VERIFY_NON_NULL(svcPath, NULL, "Param svcPath is NULL");
+
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "svcPath:%s", svcPath);
+
+ int32_t ret = bt_gatt_register_service(svcPath, CABleGattRemoteCharacteristicWriteCb, NULL);
+
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_gatt_register_service failed with ret [%d]", ret);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, char *charUUID, char *charValue,
+ int32_t charValueLen, int32_t read)
+{
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ const char *charFlags[4] = {"read", "write", "notify", "indicate"};
+
+ char *charPath = NULL;
+
+ int32_t flagLen = 4;
+
+ int32_t ret = bt_gatt_add_characteristic(charUUID, charValue, charValueLen, charFlags, flagLen,
+ svcPath, &charPath);
+
+ if (ret != 0 || charPath == NULL)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_gatt_add_characteristic failed with ret [%d]", ret);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "bt_gatt_add_characteristic charPath obtained: %s", charPath);
+
+ u_mutex_lock(gBleCharacteristicMutex);
+
+ if (read == 0)
+ {
+ if (NULL != gGattReadCharPath)
+ {
+ OICFree(gGattReadCharPath);
+ gGattReadCharPath = NULL;
+ }
+ gGattReadCharPath = charPath;
+
+ }
+ else
+ {
+ if (NULL != gGattWriteCharPath)
+ {
+ OICFree(gGattWriteCharPath);
+ gGattWriteCharPath = NULL;
+ }
+ gGattWriteCharPath = charPath;
+ }
+
+ u_mutex_unlock(gBleCharacteristicMutex);
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveCharacteristicsFromGattServer(const char *charPath)
+{
+ ///TODO: There is no api provided in bluetooth.h for removing characteristics.
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAUpdateCharacteristicsInGattServer(const char *charValue, int32_t charValueLen)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ VERIFY_NON_NULL(charValue, NULL, "Param charValue is NULL");
+
+ u_mutex_lock(gBleCharacteristicMutex);
+
+ if (NULL == gGattWriteCharPath)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "gGattWriteCharPath is NULL");
+ u_mutex_unlock(gBleCharacteristicMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ char *data = (char *) OICMalloc(sizeof(char) * (charValueLen + 1));
+
+ if (NULL == data)
+ {
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "malloc failed!");
+ u_mutex_unlock(gBleCharacteristicMutex);
+ return CA_STATUS_FAILED;
+ }
+ memset(data, 0x0, (charValueLen + 1));
+
+ strncpy(data, charValue, charValueLen);
+
+ int32_t ret = bt_gatt_update_characteristic(gGattWriteCharPath, data, charValueLen);
+
+ OICFree(data);
+ data = NULL;
+
+ if (0 != ret)
+ {
+ OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_gatt_update_characteristic failed with return [%d]", ret);
+ u_mutex_unlock(gBleCharacteristicMutex);
+ return CA_STATUS_FAILED;
+ }
+
+ u_mutex_unlock(gBleCharacteristicMutex);
+
+ OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "OUT");
+
+ return CA_STATUS_OK;
+}
+
+void CASetBLEReqRespServerCallback(CANetworkPacketReceivedCallback callback)
+{
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+ u_mutex_lock(gBleReqRespCbMutex);
+
+ gReqRespCallback = callback;
+
+ u_mutex_unlock(gBleReqRespCbMutex);
+
+ OIC_LOG(DEBUG, TZ_BLE_SERVER_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.
+*
+******************************************************************/
+#ifndef __TZ_BLE_SERVER_H_
+#define __TZ_BLE_SERVER_H_
+
+#include <bluetooth.h>
+#include <bluetooth_type.h>
+#include <bluetooth_product.h>
+
+#include "caadapterinterface.h"
+#include "logger.h"
+#include "uthreadpool.h"
+
+/**
+* @fn CAStartBleGattServer
+* @brief Used to start Gatt Server thread for service creation and advertise ble service.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAStartBleGattServer();
+
+/**
+* @fn CAStartBleGattServerThread
+* @brief This is thread which will be used for creating ble service and advertise ble service.
+* 1. Create New OIC Service 2. Add two read & write characteristics to service.
+* 3. Register Service 4. Advertise service.
+*
+* @param[in] data - Currently it will be NULL.
+*
+* @return NULL on sucess or failure.
+*
+*/
+void *CAStartBleGattServerThread(void *data);
+
+/**
+* @fn CAStopBleGattServer
+* @brief Used to terminate BLE Gatt Service.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAStopBleGattServer();
+
+/**
+* @fn CATerminateBleGattServer
+* @brief Used to stop Gatt Server thread and remove service registration, stop advertising.
+*
+* @return void
+*
+*/
+void CATerminateBleGattServer();
+
+/**
+* @fn CAInitBleGattService
+* @brief Used to initialize gatt service using _bt_gatt_init_service api.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAInitBleGattService();
+
+/**
+* @fn CADeInitBleGattService
+* @brief Used to de-initialize gatt service using _bt_gatt_deinit_service api.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CADeInitBleGattService();
+
+/**
+* @fn CAInitGattServerMutexVaraibles
+* @brief Used to initialize all required mutex varaibles for GATT server implementation.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAInitGattServerMutexVaraibles();
+
+
+/**
+* @fn CATerminateGattServerMutexVaraibles
+* @brief Used to terminate all required mutex varaibles for GATT server implementation.
+*
+* @return void
+*
+*/
+void CATerminateGattServerMutexVaraibles();
+
+/**
+* @fn CASetBleServerThreadPoolHandle
+* @brief Used to Set the gThreadPool handle which is required for spawning new thread.
+*
+* @param[in] handle - Thread pool handle which is given by above layer for using thread creation task.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+void CASetBleServerThreadPoolHandle(u_thread_pool_t handle);
+
+/**
+* @fn CAAddNewBleServiceInGattServer
+* @brief Used to add new OIC service in GATT server using bt_gatt_add_service api and
+* internally store service path(outparam) in global variable
+*
+* @param[in] serviceUUID - unique identifier for BLE OIC service.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAAddNewBleServiceInGattServer(const char *serviceUUID);
+
+/**
+* @fn CARemoveBleServiceFromGattServer
+* @brief Used to remove already registered service from Gatt Server using bt_gatt_remove_service api.
+*
+* @param[in] svcPath - unique identifier for BLE OIC service which is outparam of bt_gatt_add_service api.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CARemoveBleServiceFromGattServer(const char *svcPath);
+
+/**
+* @fn CARemoveAllBleServicesFromGattServer
+* @brief Used to remove all the registered service from Gatt Server using bt_gatt_delete_services api.
+*
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CARemoveAllBleServicesFromGattServer();
+
+/**
+* @fn CARegisterBleServicewithGattServer
+* @brief Used to register the service in Gatt Server using bt_gatt_register_service api.
+*
+* @param[in] svcPath - unique identifier for BLE OIC service which is outparam of bt_gatt_add_service api.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CARegisterBleServicewithGattServer(const char *svcPath);
+
+/**
+* @fn CAAddNewCharacteristicsToGattServer
+* @brief Used to add new characteristics(Read/Write) to the service in Gatt Server using bt_gatt_add_characteristic api.
+*
+* @param[in] svcPath service path to which this characteristic belongs to.
+* @param[in] charUUID - Gatt characteristic uuid.
+* @param[in] charValue -Gatt characteristic value.
+* @param[in] charValueLen - Caracteristic value length.
+* @param[in] read - boolean varaible for checking whether read characteristics or write characteristics.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, char *charUUID, char *charValue,
+ int32_t charValueLen, int32_t read);
+
+/**
+* @fn CARemoveCharacteristicsFromGattServer
+* @brief Used to remove characteristics(Read/Write) from the service in Gatt Server.
+*
+* @param[in] charPath characteristic path registered on the interface and unique identifier for added characteristics.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CARemoveCharacteristicsFromGattServer(const char *charPath);
+
+/**
+* @fn CAUpdateCharacteristicsInGattServer
+* @brief Used to update characteristics(Read/Write) value that we want to send to particular client.
+* Both unicast and multicast will use the same api. In mulicast, we will be sending in loop to all clients.
+*
+* @param[in] charValue - data that we want to send to client(unicast)/clients(multicast)
+* @param[in] charValueLen - length of the data.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CAUpdateCharacteristicsInGattServer(const char *charValue, int32_t charValueLen);
+
+/**
+* @fn CABleGattRemoteCharacteristicWriteCb
+* @brief This is the callback which will be called when client update one of the characteristics with data.
+*
+* @param[in] charPath - characteristic path registered on the interface and unique identifier for added characteristics.
+* @param[in] charValue - data which is send by client.
+* @param[in] charValueLen - length of the data.
+* @param[in] userData - user data
+*
+* @return void
+*
+*/
+void CABleGattRemoteCharacteristicWriteCb(char *charPath,
+ unsigned char *charValue, int32_t charValueLen, void *userData);
+
+/**
+* @fn CASetBLEReqRespServerCallback
+* @brief used to store upper layer callback locally which will be used to send the data to application
+*
+* @param[in] CANetworkPacketReceivedCallback - upper layer callback function to pass the data to CA layer.
+*
+* @return void
+*
+*/
+void CASetBLEReqRespServerCallback(CANetworkPacketReceivedCallback callback);
+
+/**
+* @fn CALEReadDataFromLEServer
+* @brief synchronous function for reading characteristic value.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CALEReadDataFromLEServer();
+
+/**
+* @fn CABleServerSenderQueueEnqueueMessage
+* @brief Used to enqueue the message into sender queue using CAAdapterEnqueueMessage and make signal to the thread to process.
+*
+* @param[in] remoteEndpoint Remote device information
+* @param[in] data data which we wants to send to remote device
+* @param[in] dataLen Length of data.
+*
+* @return 0 on success otherwise a positive error value.
+* @retval CA_STATUS_OK Successful
+* @retval CA_STATUS_INVALID_PARAM Invalid input argumets
+* @retval CA_STATUS_FAILED Operation failed
+*
+*/
+CAResult_t CABleServerSenderQueueEnqueueMessage(CARemoteEndpoint_t *remoteEndpoint,
+ void *data, uint32_t dataLen);
+
+/**
+* @fn CABleServerSenderQueueProcessor
+* @brief This is the thread which will be used for processing receiver queue.
+*
+* @return NULL on success or failure.
+*
+*/
+void *CABleServerSenderQueueProcessor();
+
+#endif //#ifndef __TZ_BLE_SERVER_H_
#include "cainterface.h"
#include "caremotehandler.h"
#include "camessagehandler.h"
+#include "caprotocolmessage.h"
#include "canetworkconfigurator.h"
#include "cainterfacecontroller.h"
#include "logger.h"
#define TAG PCF("CA")
-static void CAMessageHandler(int32_t id, CADetachErrorCode code)
-{
-}
-
CAResult_t CAInitialize()
{
OIC_LOG_V(DEBUG, TAG, "CAInitialize");
- CASetMessageHandlerCallback(CAMessageHandler);
-
CAResult_t res = CAInitializeMessageHandler();
if (res != CA_STATUS_OK)
CADestroyTokenInternal(token);
}
-CAResult_t CAGetNetworkInformation(CALocalConnectivityt_t **info, uint32_t* size)
+CAResult_t CAGetNetworkInformation(CALocalConnectivity_t **info, uint32_t* size)
{
OIC_LOG_V(DEBUG, TAG, "CAGetNetworkInformation");
- return CA_NOT_SUPPORTED;
+ return CAGetNetworkInformationInternal(info, size);
}
CAResult_t CAFindResource(const CAURI_t resourceUri)
{
OIC_LOG_V(DEBUG, TAG, "CAFindResource");
- int32_t actionId = -1;
-
- actionId = CADetachMessageResourceUri(resourceUri);
+ return CADetachMessageResourceUri(resourceUri, NULL, 0);
- if (actionId == -1)
- return CA_SEND_FAILED;
-
- OIC_LOG_V(DEBUG, TAG, "action id : %d", actionId);
-
- return CA_STATUS_OK;
}
CAResult_t CASendRequest(const CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo)
{
OIC_LOG_V(DEBUG, TAG, "CASendGetRequest");
- int32_t actionId = -1;
-
- actionId = CADetachRequestMessage(object, requestInfo);
-
- if (actionId == -1)
- return CA_SEND_FAILED;
-
- OIC_LOG_V(DEBUG, TAG, "action id : %d", actionId);
-
- return CA_STATUS_OK;
+ return CADetachRequestMessage(object, requestInfo);
}
CAResult_t CASendNotification(const CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo)
{
OIC_LOG_V(DEBUG, TAG, "CASendNotification");
- return CA_NOT_SUPPORTED;
+ return CADetachResponseMessage(object, responseInfo);
+
}
CAResult_t CASendResponse(const CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo)
{
OIC_LOG_V(DEBUG, TAG, "CASendResponse");
- int32_t actionId = -1;
-
- actionId = CADetachResponseMessage(object, responseInfo);
+ return CADetachResponseMessage(object, responseInfo);
- if (actionId == -1)
- return CA_SEND_FAILED;
-
- OIC_LOG_V(DEBUG, TAG, "action id : %d", actionId);
-
- return CA_STATUS_OK;
}
-CAResult_t CAAdvertiseResource(const CAURI_t uri, CAHeaderOption_t* options, uint8_t numOptions)
+CAResult_t CAAdvertiseResource(const CAURI_t resourceUri, CAHeaderOption_t* options,
+ uint8_t numOptions)
{
OIC_LOG_V(DEBUG, TAG, "CAAdvertiseResource");
- return CA_NOT_SUPPORTED;
+ return CADetachMessageResourceUri(resourceUri, options, numOptions);
+
}
CAResult_t CASelectNetwork(const uint32_t interestedNetwork)
#include <stdint.h>
#include "cainterfacecontroller.h"
+#include "cawifiadapter.h"
+#include "caethernetadapter.h"
#include "caedradapter.h"
#include "caleadapter.h"
-#include "cawifiethernetadapter.h"
+#include "cawifiadapter.h"
+#include "caethernetadapter.h"
#include "canetworkconfigurator.h"
+#include "caremotehandler.h"
+#include "oic_malloc.h"
#include "logger.h"
+#include "uthreadpool.h"
#define TAG PCF("CA")
+#define CA_MEMORY_ALLOC_CHECK(arg) { if (arg == NULL) {OIC_LOG_V(DEBUG, TAG, "memory error"); goto memory_error_exit;} }
+
#define CA_CONNECTIVITY_TYPE_NUM 4
static CAConnectivityHandler_t gAdapterHandler[CA_CONNECTIVITY_TYPE_NUM];
static CANetworkPacketReceivedCallback gNetworkPacketReceivedCallback = NULL;
+static CANetworkChangeCallback gNetworkChangeCallback = NULL;
+
static int8_t CAGetAdapterIndex(CAConnectivityType_t cType)
{
switch (cType)
static void CARegisterCallback(CAConnectivityHandler_t handler, CAConnectivityType_t cType)
{
+ OIC_LOG(DEBUG, TAG, "CARegisterCallback - Entry");
int8_t index = -1;
index = CAGetAdapterIndex(cType);
}
}
-static void CANetworkChangedCallback(CALocalConnectivityt_t* info, CANetworkStatus_t status)
+static void CANetworkChangedCallback(CALocalConnectivity_t* info, CANetworkStatus_t status)
{
OIC_LOG(DEBUG, TAG, "Network Changed callback");
+
+ // Call the callback.
+ if (gNetworkChangeCallback != NULL)
+ {
+ gNetworkChangeCallback(info, status);
+ }
}
-void CAInitializeAdapters()
+void CAInitializeAdapters(u_thread_pool_t handle)
{
OIC_LOG(DEBUG, TAG, "initialize adapters..");
// Initialize adapters and register callback.
#ifdef ETHERNET_ADAPTER
- CAInitializeEthernet(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback);
+ CAInitializeEthernet(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback, handle);
#endif /* ETHERNET_ADAPTER */
#ifdef WIFI_ADAPTER
- CAInitializeWifi(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback);
+ CAInitializeWifi(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback, handle);
#endif /* WIFI_ADAPTER */
#ifdef EDR_ADAPTER
- CAInitializeEDR(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback);
+ CAInitializeEDR(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback, handle);
#endif /* EDR_ADAPTER */
#ifdef LE_ADAPTER
- CAInitializeLE(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback);
+ CAInitializeLE(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback, handle);
#endif /* LE_ADAPTER */
}
gNetworkPacketReceivedCallback = callback;
}
+void CASetNetworkChangeCallback(CANetworkChangeCallback callback)
+{
+ OIC_LOG(DEBUG, TAG, "Set network change callback");
+
+ gNetworkChangeCallback = callback;
+}
+
void CAStartAdapter(CAConnectivityType_t cType)
{
OIC_LOG_V(DEBUG, TAG, "Start the adapter of CAConnectivityType[%d]", cType);
}
}
+CAResult_t CAGetNetworkInfo(CALocalConnectivity_t **info, uint32_t* size)
+{
+ CAResult_t res = CA_STATUS_FAILED;
+ int8_t index = 0;
+ int8_t i = 0;
+
+ CALocalConnectivity_t* resInfo = NULL;
+ uint32_t resSize = 0;
+
+ CALocalConnectivity_t* tempInfo[CA_CONNECTIVITY_TYPE_NUM];
+ uint32_t tempSize[CA_CONNECTIVITY_TYPE_NUM];
+
+ memset(tempInfo, 0, sizeof(CALocalConnectivity_t*) * CA_CONNECTIVITY_TYPE_NUM);
+ memset(tempSize, 0, sizeof(int8_t) * CA_CONNECTIVITY_TYPE_NUM);
+
+ // #1. get information each adapter
+ for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++)
+ {
+ if (gAdapterHandler[index].GetnetInfo != NULL)
+ {
+ res = gAdapterHandler[index].GetnetInfo(&tempInfo[index], &tempSize[index]);
+
+ OIC_LOG_V(DEBUG, TAG, "%d adapter network info size is %d res:%d", index,
+ tempSize[index], res);
+ }
+ }
+
+ resSize = 0;
+ for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++)
+ {
+ // check information
+ if (tempInfo[index] == NULL || tempSize[index] <= 0)
+ {
+ continue;
+ }
+
+ // #2. total size
+ resSize += tempSize[index];
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "network info total size is %d!", resSize);
+
+ if (resSize <= 0)
+ {
+ return res;
+ }
+
+ // #3. add data into result
+ // memory allocation
+ resInfo = (CALocalConnectivity_t*) OICMalloc(sizeof(CALocalConnectivity_t) * resSize);
+ CA_MEMORY_ALLOC_CHECK(resInfo);
+ memset(resInfo, 0, sizeof(CALocalConnectivity_t) * resSize);
+
+ i = 0;
+ for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++)
+ {
+ // check information
+ if (tempInfo[index] == NULL || tempSize[index] <= 0)
+ {
+ continue;
+ }
+
+ memcpy(resInfo + i, tempInfo[index], sizeof(CALocalConnectivity_t) * tempSize[index]);
+
+ i += tempSize[index];
+
+ // free adapter data
+ OICFree(tempInfo[index]);
+ }
+
+ // #5. save data
+ *info = resInfo;
+ *size = resSize;
+
+ OIC_LOG_V(DEBUG, TAG, "each network info save success!");
+
+ return res;
+
+ // memory error label.
+ memory_error_exit:
+
+ return CA_MEMORY_ALLOC_FAILED;
+}
+
CAResult_t CASendUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t length)
{
OIC_LOG(DEBUG, TAG, "Send unicast data to enabled interface..");
#include "camessagehandler.h"
#include "caremotehandler.h"
#include "cainterfacecontroller.h"
+#include "caprotocolmessage.h"
#include "uqueue.h"
#include "logger.h"
#include "config.h" /* for coap protocol */
#include "coap.h"
#include "uthreadpool.h" /* for thread pool */
+#include "caqueueingthread.h"
#include "umutex.h"
#include "oic_malloc.h"
#define TAG PCF("CA")
#define MEMORY_ALLOCK_CHECK(arg) { if (arg == NULL) {OIC_LOG_V(DEBUG, TAG, "memory error"); goto memory_error_exit;} }
-#define MAX_ACTION_NUM 300
#define MAX_THREAD_POOL_SIZE 10
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
+typedef enum
+{
+ SEND_TYPE_MULTICAST = 0, SEND_TYPE_UNICAST
+} CASendDataType_t;
typedef struct
{
- int32_t actionId;
+ CASendDataType_t type;
CARemoteEndpoint_t* remoteEndpoint;
CARequestInfo_t* requestInfo;
CAResponseInfo_t* responseInfo;
+ CAHeaderOption_t* options;
+ uint8_t numOptions;
} CAData_t;
-typedef void (*CAThreadTask)(CAData_t* data);
-
-typedef struct
-{
- u_mutex threadMutex;
- u_cond threadCond;
- CAThreadTask threadTask;
- int32_t isStop;
- u_queue_t* dataQueue;
-} CAThread_t;
-
// thread pool handle
static u_thread_pool_t gThreadPoolHandle = NULL;
// message handler main thread
-static CAThread_t gSendThread;
-
-// message handler callback
-static int32_t gCurrentActionId = 0;
-static CAMessageHandlerCallback gHandlerCallback = NULL;
+static CAQueueingThread_t gSendThread;
+static CAQueueingThread_t gReceiveThread;
// handler field
static CARequestCallback gRequestHandler = NULL;
static CAResponseCallback gResponseHandler = NULL;
-static u_queue_t* gMessageQueue = NULL;
-static u_mutex gMessageQueueMutex = NULL;
-
-static void CAAddReceiveData(CAData_t* data)
+static void CAReceiveThreadProcess(void* threadData)
{
- OIC_LOG_V(DEBUG, TAG, "CAAddReceiveData");
-
- // create thread data
- u_queue_message_t* message = (u_queue_message_t*) OICMalloc(sizeof(u_queue_message_t));
-
- if (message == NULL)
- {
- OIC_LOG_V(DEBUG, TAG, "memory error!!");
- return;
- }
- memset(message, 0, sizeof(u_queue_message_t));
-
- message->msg = data;
- message->size = sizeof(CAData_t);
-
- // mutex lock
- u_mutex_lock(gMessageQueueMutex);
-
- // add thread data into list
- u_queue_add_element(gMessageQueue, message);
-
- // mutex unlock
- u_mutex_unlock(gMessageQueueMutex);
+ // TODO
+ // currently not support.
+ // CAHandleRequestResponseCallbacks codes will move to this function.
}
-static void CAAddSendData(CAData_t* data)
+static void CASendThreadProcess(void* threadData)
{
- OIC_LOG_V(DEBUG, TAG, "CAAddSendData!!");
+ CAData_t* data = (CAData_t*) threadData;
- // create thread data
- u_queue_message_t* message = (u_queue_message_t*) OICMalloc(sizeof(u_queue_message_t));
-
- if (message == NULL)
- {
- OIC_LOG_V(DEBUG, TAG, "memory error!!");
- return;
- }
- memset(message, 0, sizeof(u_queue_message_t));
-
- message->msg = data;
- message->size = sizeof(CAData_t);
-
- // mutex lock
- u_mutex_lock(gSendThread.threadMutex);
-
- // add thread data into list
- u_queue_add_element(gSendThread.dataQueue, message);
-
- // notity the thread
- u_cond_signal(gSendThread.threadCond);
-
- // mutex unlock
- u_mutex_unlock(gSendThread.threadMutex);
-}
-
-static void CAStopSendThread()
-{
- OIC_LOG_V(DEBUG, TAG, "CAStopSendThread request!!");
-
- // mutex lock
- u_mutex_lock(gSendThread.threadMutex);
-
- // set stop flag
- gSendThread.isStop = TRUE;
-
- // notity the thread
- u_cond_signal(gSendThread.threadCond);
-
- // mutex unlock
- u_mutex_unlock(gSendThread.threadMutex);
-}
-
-static void CASendThreadProcess(CAData_t* data)
-{
if (data == NULL)
{
OIC_LOG(DEBUG, TAG, "thread data error!!");
return;
}
- OIC_LOG_V(DEBUG, TAG, "thread action id : %d", data->actionId);
+ CAResult_t res = CA_STATUS_FAILED;
- CADetachErrorCode code = FAIL;
- int32_t res = 0;
+ CASendDataType_t type = data->type;
- if (data->requestInfo != NULL)
+ if (type == SEND_TYPE_UNICAST)
{
- OIC_LOG(DEBUG, TAG, "requestInfo is available");
-
coap_pdu_t* pdu = NULL;
- pdu = CAGeneratePdu(data->remoteEndpoint->resourceUri, data->requestInfo->method,
- data->requestInfo->info);
- // interface controller function call.
- if (NULL != pdu)
+ if (data->requestInfo != NULL)
{
- OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data);
-
- OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code);
+ OIC_LOG_V(DEBUG, TAG, "requestInfo is available..");
- OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %s", pdu->hdr);
-
- res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length);
+ pdu = (coap_pdu_t*) CAGeneratePdu(data->remoteEndpoint->resourceUri,
+ data->requestInfo->method, data->requestInfo->info);
}
- }
- else if (data->responseInfo != NULL)
- {
- OIC_LOG_V(DEBUG, TAG, "responseInfo is available..");
-
- coap_pdu_t* pdu = NULL;
+ else if (data->responseInfo != NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "responseInfo is available..");
- pdu = CAGeneratePdu(data->remoteEndpoint->resourceUri, data->responseInfo->result,
- data->responseInfo->info);
+ pdu = (coap_pdu_t*) CAGeneratePdu(data->remoteEndpoint->resourceUri,
+ data->responseInfo->result, data->responseInfo->info);
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TAG, "request info, response info is empty");
+ }
// interface controller function call.
if (NULL != pdu)
OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code);
- OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %x", pdu->hdr);
+ OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %s", pdu->hdr);
res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length);
}
+
}
- else
+ else if (type == SEND_TYPE_MULTICAST)
{
OIC_LOG(DEBUG, TAG, "both requestInfo & responseInfo is not available");
coap_pdu_t* pdu = NULL;
CAInfo_t info;
memset(&info, 0, sizeof(CAInfo_t));
- pdu = CAGeneratePdu(data->remoteEndpoint->resourceUri, CA_GET, info);
+
+ info.options = data->options;
+ info.numOptions = data->numOptions;
+
+ pdu = (coap_pdu_t*) CAGeneratePdu(data->remoteEndpoint->resourceUri, CA_GET, info);
if (NULL != pdu)
{
OIC_LOG_V(DEBUG, TAG, "PDU Maker - id : %d", pdu->hdr->id);
- OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %x", pdu->hdr);
+ OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %s", pdu->hdr);
res = CASendMulticastData(pdu->hdr, pdu->length);
}
-
- }
-
- if (res)
- {
- code = SUCCESS;
- }
-
- if (gHandlerCallback != NULL)
- {
- gHandlerCallback(data->actionId, code);
- }
-}
-
-static void* CAThreadBaseRoutine(void* treadData)
-{
- OIC_LOG_V(DEBUG, TAG, "message handler main thread start..");
-
- CAThread_t* thread = (CAThread_t*) treadData;
-
- if (thread == NULL)
- {
- OIC_LOG_V(DEBUG, TAG, "thread data passing error!!");
-
- return NULL;
}
-
- while (!thread->isStop)
+ else
{
- // mutex lock
- u_mutex_lock(thread->threadMutex);
-
- // if queue is empty, thread will wait
- if (u_queue_get_size(thread->dataQueue) <= 0)
- {
- OIC_LOG_V(DEBUG, TAG, "wait..");
- // wait
- u_cond_wait(thread->threadCond, thread->threadMutex);
-
- OIC_LOG_V(DEBUG, TAG, "wake up..");
- }
-
- // mutex unlock
- u_mutex_unlock(thread->threadMutex);
-
- // check stop flag
- if (thread->isStop)
- continue;
-
- // get data
- u_queue_message_t* message = u_queue_get_element(thread->dataQueue);
-
- CAData_t* data = (CAData_t*) message->msg;
-
- // process data
- thread->threadTask(data);
+ OIC_LOG(DEBUG, TAG, "unknown type!");
}
- OIC_LOG_V(DEBUG, TAG, "message handler main thread end..");
-
- return NULL;
-}
-
-static int32_t CAIncreaseActionId()
-{
- ++gCurrentActionId;
-
- gCurrentActionId = (gCurrentActionId > MAX_ACTION_NUM) ? 0 : gCurrentActionId;
-
- return gCurrentActionId;
}
static void CAReceivedPacketCallback(CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen)
coap_pdu_t* pdu;
uint32_t code = CA_NOT_FOUND;
- pdu = CAParsePDU(data, &code);
+ pdu = (coap_pdu_t*) CAParsePDU((const char*) data, &code);
+ OICFree(data);
+
+ char uri[CA_MAX_URI_LENGTH] =
+ { 0, };
if (code == CA_GET || code == CA_POST || code == CA_PUT || code == CA_DELETE)
{
- CARequestInfo_t ReqInfo;
- memset(&ReqInfo, 0, sizeof(CARequestInfo_t));
- CAGetRequestInfoFromPdu(pdu, &ReqInfo);
+ CARequestInfo_t* ReqInfo;
+ ReqInfo = (CARequestInfo_t*) OICMalloc(sizeof(CARequestInfo_t));
+ memset(ReqInfo, 0, sizeof(CARequestInfo_t));
+ CAGetRequestInfoFromPdu(pdu, ReqInfo, uri);
- if (NULL != ReqInfo.info.options && NULL != endpoint)
+ if (NULL != ReqInfo->info.options && NULL != endpoint)
{
- OIC_LOG_V(DEBUG, TAG, "Request PDU - optionID: %d", ReqInfo.info.options->optionID);
+ uint32_t i;
+ for (i = 0; i < ReqInfo->info.numOptions; i++)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Request- optionID: %d", ReqInfo->info.options[i].optionID);
- OIC_LOG_V(DEBUG, TAG, "Request PDU - optionlist: %s", ReqInfo.info.options->optionData);
+ OIC_LOG_V(DEBUG, TAG, "Request- list: %s", ReqInfo->info.options[i].optionData);
+ }
- OIC_LOG_V(DEBUG, TAG, "Request PDU - payload: %s", ReqInfo.info.payload);
+ OIC_LOG_V(DEBUG, TAG, "Request- payload: %s", ReqInfo->info.payload);
- OIC_LOG_V(DEBUG, TAG, "Request PDU - code: %d", ReqInfo.method);
+ OIC_LOG_V(DEBUG, TAG, "Request- code: %d", ReqInfo->method);
- endpoint->resourceUri = (char*) OICMalloc(strlen(ReqInfo.info.options->optionData) + 1);
- memcpy(endpoint->resourceUri, ReqInfo.info.options->optionData,
- strlen(ReqInfo.info.options->optionData));
+ endpoint->resourceUri = (char*) OICMalloc(strlen(uri) + 1);
+ memset(endpoint->resourceUri, 0, strlen(uri) + 1);
+ memcpy(endpoint->resourceUri, uri, strlen(uri));
OIC_LOG_V(DEBUG, TAG, "added resource URI : %s", endpoint->resourceUri);
}
CAData_t* cadata = NULL;
cadata = (CAData_t*) OICMalloc(sizeof(CAData_t));
memset(cadata, 0, sizeof(CAData_t));
- cadata->actionId = 1;
+
+ cadata->type = SEND_TYPE_UNICAST;
cadata->remoteEndpoint = endpoint;
- cadata->requestInfo = &ReqInfo;
+ cadata->requestInfo = ReqInfo;
cadata->responseInfo = NULL;
- CAAddReceiveData(cadata);
-
+ CAQueueingThreadAddData(&gReceiveThread, cadata, sizeof(CAData_t));
}
else
{
- CAResponseInfo_t ResInfo;
- memset(&ResInfo, 0, sizeof(CARequestInfo_t));
- CAGetResponseInfoFromPdu(pdu, &ResInfo);
+ CAResponseInfo_t* ResInfo;
+ ResInfo = (CAResponseInfo_t*) OICMalloc(sizeof(CAResponseInfo_t));
+ memset(ResInfo, 0, sizeof(CAResponseInfo_t));
+ CAGetResponseInfoFromPdu(pdu, ResInfo, uri);
- if (NULL != ResInfo.info.options && NULL != endpoint)
+ if (NULL != ResInfo->info.options && NULL != endpoint)
{
- OIC_LOG_V(DEBUG, TAG, "Response PDU - optionID: %d", ResInfo.info.options->optionID);
+ uint32_t i;
+ for (i = 0; i < ResInfo->info.numOptions; i++)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Response- optionID: %d", ResInfo->info.options[i].optionID);
- OIC_LOG_V(DEBUG, TAG, "Response PDU - optionlist: %s", ResInfo.info.options->optionData);
+ OIC_LOG_V(DEBUG, TAG, "Response- list: %s", ResInfo->info.options[i].optionData);
+ }
- OIC_LOG_V(DEBUG, TAG, "Response PDU - payload: %s", ResInfo.info.payload);
+ OIC_LOG_V(DEBUG, TAG, "Response- payload: %s", ResInfo->info.payload);
- OIC_LOG_V(DEBUG, TAG, "Response PDU - code: %d", ResInfo.result);
+ OIC_LOG_V(DEBUG, TAG, "Response- code: %d", ResInfo->result);
- endpoint->resourceUri = (char*) OICMalloc(strlen(ResInfo.info.options->optionData) + 1);
- memcpy(endpoint->resourceUri, ResInfo.info.options->optionData,
- strlen(ResInfo.info.options->optionData));
+ endpoint->resourceUri = (char*) OICMalloc(strlen(uri) + 1);
+ memset(endpoint->resourceUri, 0, strlen(uri) + 1);
+ memcpy(endpoint->resourceUri, uri, strlen(uri));
OIC_LOG_V(DEBUG, TAG, "added resource URI : %s", endpoint->resourceUri);
}
CAData_t* cadata = NULL;
cadata = (CAData_t*) OICMalloc(sizeof(CAData_t));
memset(cadata, 0, sizeof(CAData_t));
- cadata->actionId = 1;
+
+ cadata->type = SEND_TYPE_UNICAST;
cadata->remoteEndpoint = endpoint;
cadata->requestInfo = NULL;
- cadata->responseInfo = &ResInfo;
- CAAddReceiveData(cadata);
+ cadata->responseInfo = ResInfo;
+
+ CAQueueingThreadAddData(&gReceiveThread, cadata, sizeof(CAData_t));
}
}
+static void CANetworkChangedCallback(CALocalConnectivity_t* info, CANetworkStatus_t status)
+{
+ OIC_LOG(DEBUG, TAG, "networkChangeCallback in message handler!!");
+}
+
void CAHandleRequestResponseCallbacks()
{
OIC_LOG_V(DEBUG, TAG, "CAHandleRequestResponseCallbacks");
// #1 parse the data
// #2 get endpoint
- u_mutex_lock(gMessageQueueMutex);
+ u_mutex_lock(gReceiveThread.threadMutex);
- u_queue_message_t* item = u_queue_get_element(gMessageQueue);
+ u_queue_message_t* item = u_queue_get_element(gReceiveThread.dataQueue);
- u_mutex_unlock(gMessageQueueMutex);
+ u_mutex_unlock(gReceiveThread.threadMutex);
if (item == NULL)
return;
// get endpoint
CAData_t* td = (CAData_t*) msg;
-
CARemoteEndpoint_t* rep = td->remoteEndpoint;
if (rep == NULL)
{
if (gRequestHandler)
{
- gRequestHandler(rep, NULL);
+ gRequestHandler(rep, td->requestInfo);
+ }
+
+ if(NULL != td->requestInfo->info.options)
+ {
+ OICFree(td->requestInfo->info.options);
+ }
+
+ if(NULL != td->requestInfo->info.payload)
+ {
+ OICFree(td->requestInfo->info.payload);
}
+
+ if(NULL != td->requestInfo->info.token)
+ {
+ OICFree(td->requestInfo->info.token);
+ }
+ OICFree(td->requestInfo);
}
if (td->responseInfo != NULL)
{
if (gResponseHandler)
{
- gResponseHandler(rep, NULL);
+ gResponseHandler(rep, td->responseInfo);
}
+
+ if(NULL != td->responseInfo->info.options)
+ {
+ OICFree(td->responseInfo->info.options);
+ }
+
+ if(NULL != td->responseInfo->info.payload)
+ {
+ OICFree(td->responseInfo->info.payload);
+ }
+
+ if(NULL != td->responseInfo->info.token)
+ {
+ OICFree(td->responseInfo->info.token);
+ }
+ OICFree(td->responseInfo);
}
- u_queue_remove_element(gMessageQueue);
+ if(NULL != rep->resourceUri)
+ {
+ OICFree(rep->resourceUri);
+ }
+ OICFree(rep);
}
-int32_t CADetachRequestMessage(const CARemoteEndpoint_t* object, const CARequestInfo_t* request)
+CAResult_t CADetachRequestMessage(const CARemoteEndpoint_t* object, const CARequestInfo_t* request)
{
OIC_LOG_V(DEBUG, TAG, "CADetachRequestMessage");
if (object == NULL || request == NULL)
{
- return -1;
+ return CA_STATUS_FAILED;
}
- int32_t id = 0;
-
- // create action id
- id = CAIncreaseActionId();
-
CAData_t* data = (CAData_t*) OICMalloc(sizeof(CAData_t));
MEMORY_ALLOCK_CHECK(data);
MEMORY_ALLOCK_CHECK(requestInfo);
// save data
- data->actionId = id;
+ data->type = SEND_TYPE_UNICAST;
data->remoteEndpoint = remoteEndpoint;
data->requestInfo = requestInfo;
data->responseInfo = NULL;
// add thread
- CAAddSendData(data);
+ CAQueueingThreadAddData(&gSendThread, data, sizeof(CAData_t));
- return id;
+ return CA_STATUS_OK;
// memory error label.
memory_error_exit:
OICFree(data);
}
- return -1;
+ return CA_MEMORY_ALLOC_FAILED;
}
-int32_t CADetachResponseMessage(const CARemoteEndpoint_t* object, const CAResponseInfo_t* response)
+CAResult_t CADetachResponseMessage(const CARemoteEndpoint_t* object,
+ const CAResponseInfo_t* response)
{
OIC_LOG_V(DEBUG, TAG, "CADetachResponseMessage");
if (object == NULL || response == NULL)
{
- return -1;
+ return CA_STATUS_FAILED;
}
- int32_t id = 0;
-
- // create action id
- id = CAIncreaseActionId();
-
CAData_t* data = (CAData_t*) OICMalloc(sizeof(CAData_t));
MEMORY_ALLOCK_CHECK(data);
MEMORY_ALLOCK_CHECK(responseInfo);
// save data
- data->actionId = id;
+ data->type = SEND_TYPE_UNICAST;
data->remoteEndpoint = remoteEndpoint;
data->requestInfo = NULL;
data->responseInfo = responseInfo;
// add thread
- CAAddSendData(data);
+ CAQueueingThreadAddData(&gSendThread, data, sizeof(CAData_t));
- return id;
+ return CA_STATUS_OK;
// memory error label.
memory_error_exit:
OICFree(data);
}
- return -1;
+ return CA_MEMORY_ALLOC_FAILED;
}
-int32_t CADetachMessageResourceUri(const CAURI_t resourceUri)
+CAResult_t CADetachMessageResourceUri(const CAURI_t resourceUri, const CAHeaderOption_t* options,
+ uint8_t numOptions)
{
if (resourceUri == NULL)
{
- return -1;
+ return CA_STATUS_FAILED;
}
- int32_t id = 0;
-
- // create action id
- id = CAIncreaseActionId();
-
CAData_t* data = (CAData_t*) OICMalloc(sizeof(CAData_t));
MEMORY_ALLOCK_CHECK(data);
CA_ETHERNET | CA_WIFI | CA_EDR | CA_LE);
// save data
- data->actionId = id;
+ data->type = SEND_TYPE_MULTICAST;
data->remoteEndpoint = remoteEndpoint;
data->requestInfo = NULL;
data->responseInfo = NULL;
+ data->options = NULL;
+ data->numOptions = 0;
+
+ if (options != NULL && numOptions > 0)
+ {
+ // copy data
+ CAHeaderOption_t* temp = (CAHeaderOption_t*) OICMalloc(
+ sizeof(CAHeaderOption_t) * numOptions);
+
+ MEMORY_ALLOCK_CHECK(temp);
+
+ memset(temp, 0, sizeof(CAHeaderOption_t) * numOptions);
+ memcpy(temp, options, sizeof(CAHeaderOption_t) * numOptions);
+
+ data->options = temp;
+ data->numOptions = numOptions;
+ }
// add thread
- CAAddSendData(data);
+ CAQueueingThreadAddData(&gSendThread, data, sizeof(CAData_t));
- return id;
+ return CA_STATUS_OK;
// memory error label.
memory_error_exit:
OICFree(data);
}
- return -1;
-}
-
-void CASetMessageHandlerCallback(CAMessageHandlerCallback callback)
-{
- OIC_LOG_V(DEBUG, TAG, "set message handler callback.");
-
- gHandlerCallback = callback;
+ return CA_MEMORY_ALLOC_FAILED;
}
void CASetRequestResponseCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler)
CAResult_t CAInitializeMessageHandler()
{
+ OIC_LOG(DEBUG, TAG, "CAInitializeMessageHandler - Entry");
CASetPacketReceivedCallback(CAReceivedPacketCallback);
+ CASetNetworkChangeCallback(CANetworkChangedCallback);
+
// create thread pool
CAResult_t res;
res = u_thread_pool_init(MAX_THREAD_POOL_SIZE, &gThreadPoolHandle);
}
// send thread initialize
- memset(&gSendThread, 0, sizeof(CAThread_t));
-
- // mutex init
- u_mutex_init();
-
- // set send thread data
- gSendThread.dataQueue = u_queue_create();
- gSendThread.threadMutex = u_mutex_new();
- gSendThread.threadCond = u_cond_new();
- gSendThread.isStop = FALSE;
- gSendThread.threadTask = CASendThreadProcess;
+ CAQueueingThreadInitialize(&gSendThread, gThreadPoolHandle, CASendThreadProcess);
// start send thread
- res = u_thread_pool_add_task(gThreadPoolHandle, CAThreadBaseRoutine, &gSendThread);
+ res = CAQueueingThreadStart(&gSendThread);
if (res != CA_STATUS_OK)
{
- OIC_LOG_V(DEBUG, TAG, "thread pool add task error.");
+ OIC_LOG_V(DEBUG, TAG, "thread start error(send thread).");
return res;
}
- // set receive queue
- gMessageQueue = u_queue_create();
- gMessageQueueMutex = u_mutex_new();
+ // receive thread initialize
+ CAQueueingThreadInitialize(&gReceiveThread, gThreadPoolHandle, CAReceiveThreadProcess);
+
+ // start receive thread
+ // TODO
+ // currently not support.
+// res = CAThreadStart(gReceiveThread);
+//
+// if (res != CA_STATUS_OK)
+// {
+// OIC_LOG_V(DEBUG, TAG, "thread start error(receive thread).");
+// return res;
+// }
// initialize interface adapters by controller
- CAInitializeAdapters();
+ CAInitializeAdapters(gThreadPoolHandle);
return CA_STATUS_OK;
}
CATerminateAdapters();
// stop thread
- CAStopSendThread();
+ // delete thread data
+ CAQueueingThreadStop(&gSendThread);
+ CAQueueingThreadDestroy(&gSendThread);
+ // stop thread
// delete thread data
- u_mutex_free(gSendThread.threadMutex);
- u_cond_free(gSendThread.threadCond);
- u_queue_delete(gSendThread.dataQueue);
+ CAQueueingThreadStop(&gReceiveThread);
+ CAQueueingThreadDestroy(&gReceiveThread);
// destroy thread pool
u_thread_pool_free(gThreadPoolHandle);
OIC_LOG_V(DEBUG, TAG, "message handler terminate completed!");
-
- u_queue_delete(gMessageQueue);
- u_mutex_free(gMessageQueueMutex);
}
case CA_LE:
-#ifdef LE_ADAPTER
+#ifndef LE_ADAPTER
OIC_LOG_V(DEBUG, TAG, "Add network type(LE) - Not Supported");
return CA_NOT_SUPPORTED;
#endif /* LE_ADAPTER */
u_arraylist_t* CAGetSelectedNetworkList()
{
+ OIC_LOG(DEBUG, TAG, "IN");
if (gSelectedNetworkList == NULL)
{
OIC_LOG_V(DEBUG, TAG, "Selected network not found");
return NULL;
}
-
+ OIC_LOG(DEBUG, TAG, "OUT");
return gSelectedNetworkList;
}
+
+CAResult_t CAGetNetworkInformationInternal(CALocalConnectivity_t **info, uint32_t* size)
+{
+ OIC_LOG_V(DEBUG, TAG, "get network information.");
+
+ return CAGetNetworkInfo(info, size);
+}
#define TAG PCF("CA")
-#define CA_MAX_TOKEN_LEN 8
+#define CA_MAX_TOKEN_LEN (8)
#define CA_FLAGS_BLOCK 0x01
-#define CA_URI_MAX_SIZE 256
-#define CA_BUFSIZE 40
+#define CA_BUFSIZE 128
+#define CA_COAP_MESSAGE_CON 0
-uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t* outReqInfo)
+uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t* outReqInfo, char* outUri)
{
OIC_LOG(DEBUG, TAG, "get request info from PDU");
if (NULL == pdu)
return 0;
uint32_t code = CA_NOT_FOUND;
- CAGetRequestPDUInfo(pdu, &code, &(outReqInfo->info));
+ CAGetRequestPDUInfo(pdu, &code, &(outReqInfo->info), outUri);
outReqInfo->method = code;
return 1;
}
-uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t* outResInfo)
+uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t* outResInfo, char* outUri)
{
OIC_LOG(DEBUG, TAG, "get response info from PDU");
if (NULL == pdu)
return 0;
uint32_t code = CA_NOT_FOUND;
- CAGetRequestPDUInfo(pdu, &code, &(outResInfo->info));
+ CAGetRequestPDUInfo(pdu, &code, &(outResInfo->info), outUri);
outResInfo->result = code;
return 1;
return NULL;
length = strlen(uri);
+ if (CA_MAX_URI_LENGTH < length)
+ {
+ OIC_LOG(DEBUG, TAG, "check URI length..");
+ return NULL;
+ }
+
coapUri = (char*) OICMalloc(length + coapHeaderLength + 1);
memset(coapUri, 0, length + coapHeaderLength + 1);
if (NULL != coapUri)
{
-
memcpy(coapUri, "coap://[::]/", coapHeaderLength);
memcpy(coapUri + coapHeaderLength, uri, length);
CAParseURI(coapUri, &optlist);
// parsing options in HeadOption
- if (NULL != &info)
- {
- CAParseHeadOption(code, info, &optlist);
- }
+ CAParseHeadOption(code, info, &optlist);
OICFree(coapUri);
}
- if (NULL != info.payload)
+ if (NULL != info.payload) // payload is include in request / response
{
if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload)))
return NULL;
}
- else
+ else // payload is not include in request / response
{
if (!(pdu = CACreatePDUforRequest((code_t) code, optlist)))
return NULL;
str the_token =
{ 0, _token_data };
+ uint32_t CAFlags = 0;
+ coap_block_t CABlock =
+ { .num = 0, .m = 0, .szx = 6 };
+
if (!(pdu = coap_new_pdu()))
return NULL;
/* initialize message id */
unsigned short message_id;
- prng((unsigned char *)&message_id, sizeof(unsigned short));
+ prng((unsigned char * )&message_id, sizeof(unsigned short));
- pdu->hdr->type = msgtype;
+ pdu->hdr->type = CA_COAP_MESSAGE_CON;
pdu->hdr->id = htons(++message_id);
pdu->hdr->code = code;
pdu->hdr->token_length = the_token.length;
if (!coap_add_token(pdu, the_token.length, the_token.s))
{
- OIC_LOG(DEBUG, TAG,"cannot add token to request");
+ OIC_LOG(DEBUG, TAG, "cannot add token to request");
}
for (opt = options; opt; opt = opt->next)
{
- coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data),
- COAP_OPTION_LENGTH(*(coap_option *)opt->data),
- COAP_OPTION_DATA(*(coap_option *)opt->data));
+ coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
+ COAP_OPTION_LENGTH(*(coap_option * )opt->data),
+ COAP_OPTION_DATA(*(coap_option * )opt->data));
}
if (NULL != payload)
{
uint32_t len = strlen(payload);
- if ((flags & CA_FLAGS_BLOCK) == 0)
+ if ((CAFlags & CA_FLAGS_BLOCK) == 0)
{
OIC_LOG_V(DEBUG, TAG, "coap_add_data, payload: %s", payload);
- coap_add_data(pdu, len, payload);
+ coap_add_data(pdu, len, (const unsigned char *) payload);
}
else
{
OIC_LOG_V(DEBUG, TAG, "coap_add_block, payload: %s", payload);
- coap_add_block(pdu, len, payload, block.num, block.szx);
+ coap_add_block(pdu, len, (const unsigned char *) payload, CABlock.num, CABlock.szx);
}
}
return pdu;
/* initialize message id */
unsigned short message_id;
- prng((unsigned char *)&message_id, sizeof(unsigned short));
+ prng((unsigned char * )&message_id, sizeof(unsigned short));
- pdu->hdr->type = msgtype;
+ pdu->hdr->type = CA_COAP_MESSAGE_CON;
pdu->hdr->id = htons(++message_id);
pdu->hdr->code = code;
for (opt = options; opt; opt = opt->next)
{
- coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data),
- COAP_OPTION_LENGTH(*(coap_option *)opt->data),
- COAP_OPTION_DATA(*(coap_option *)opt->data));
+ coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
+ COAP_OPTION_LENGTH(*(coap_option * )opt->data),
+ COAP_OPTION_DATA(*(coap_option * )opt->data));
}
return pdu;
uint32_t i;
for (i = 0; i < info.numOptions; i++)
{
- coap_insert(optlist,
- CACreateNewOptionNode(info.options->optionID, info.options->optionLength,
- info.options->optionData), CAOrderOpts);
+ uint32_t id = info.options[i].optionID;
+ if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
+ {
+ OIC_LOG_V(DEBUG, TAG, "it is not Header Option : %d", id);
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "Head Option ID: %d", info.options[i].optionID);
+ OIC_LOG_V(DEBUG, TAG, "Head Option data: %s", info.options[i].optionData);
+ OIC_LOG_V(DEBUG, TAG, "Head Option length: %d", info.options[i].optionLength);
+
+ coap_insert(optlist,
+ CACreateNewOptionNode(info.options[i].optionID, info.options[i].optionLength,
+ info.options[i].optionData), CAOrderOpts);
+ }
}
}
return node;
error: perror("new_option_node: malloc");
- coap_free( option);
+ coap_free(option);
return NULL;
}
if (!a || !b)
return a < b ? -1 : 1;
- if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option *)b))
+ if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))
return -1;
- return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option *)b);
+ return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);
+}
+
+uint32_t getOptionCount(coap_opt_iterator_t opt_iter)
+{
+ uint32_t count = 0;
+ coap_opt_t *option;
+
+ while ((option = coap_option_next(&opt_iter)))
+ {
+ count++;
+ }
+
+ return count;
}
-void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t* outCode, CAInfo_t* outInfo)
+void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t* outCode, CAInfo_t* outInfo, char* outUri)
{
unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */
uint32_t encode = 0;
coap_opt_iterator_t opt_iter;
coap_opt_t *option;
- char optionResult[CA_URI_MAX_SIZE] =
+ char optionResult[CA_MAX_URI_LENGTH] =
{ 0, };
- uint32_t count = 0;
+ uint32_t count = 0, idx = 0;
+ uint32_t optionLength = 0;
uint32_t isfirstsetflag = 0;
- /* show options, if any */
coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
memset(optionResult, 0, sizeof(optionResult));
+
+ count = getOptionCount(opt_iter);
+
+ // set code
+ (*outCode) = (uint32_t) pdu->hdr->code;
+
+ // init HeaderOption list
+ memset(outInfo, 0, sizeof(CAInfo_t));
+ outInfo->numOptions = count;
+ outInfo->options = (CAHeaderOption_t*) OICMalloc(sizeof(CAHeaderOption_t) * count);
+ memset(outInfo->options, 0, sizeof(CAHeaderOption_t) * count);
+
while ((option = coap_option_next(&opt_iter)))
{
if (print_readable(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), buf, sizeof(buf),
encode))
{
- if (opt_iter.type == COAP_OPTION_URI_PATH || opt_iter.type == COAP_OPTION_URI_QUERY)
+ if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
{
if (0 == isfirstsetflag)
{
isfirstsetflag = 1;
- memcpy(optionResult + count, buf, strlen(buf));
- count += strlen(buf);
+ memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
+ optionLength += strlen((const char *) buf);
}
else
{
- if (opt_iter.type == COAP_OPTION_URI_PATH)
+ if (COAP_OPTION_URI_PATH == opt_iter.type)
{
- memcpy(optionResult + count, "/", 1);
- count++;
+ memcpy(optionResult + optionLength, "/", 1);
+ optionLength++;
}
- else if (opt_iter.type == COAP_OPTION_URI_QUERY)
+ else if (COAP_OPTION_URI_QUERY == opt_iter.type)
{
- memcpy(optionResult + count, "?", 1);
- count++;
+ memcpy(optionResult + optionLength, "?", 1);
+ optionLength++;
}
- memcpy(optionResult + count, buf, strlen(buf));
- count += strlen(buf);
+ memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
+ optionLength += strlen((const char *) buf);
+ }
+ }
+
+ if (idx < count)
+ {
+ uint32_t length = (uint32_t) strlen((const char *) buf);
+
+ if(length <= CA_MAX_HEADER_OPTION_DATA_LENGTH) {
+ outInfo->options[idx].optionID = opt_iter.type;
+ outInfo->options[idx].optionLength = length;
+ outInfo->options[idx].protocolID = CA_COAP_ID;
+ memcpy(outInfo->options[idx].optionData, buf, length);
+ idx++;
}
}
}
}
- OIC_LOG(DEBUG, TAG, "set CAInfo_t after parsing");
-
- // set pdu info
- (*outCode) = (uint32_t) pdu->hdr->code;
- memset(outInfo, 0, sizeof(CAInfo_t));
-
- outInfo->options = (CAHeaderOption_t*) OICMalloc(sizeof(CAHeaderOption_t));
- memset(outInfo->options, 0, sizeof(CAHeaderOption_t));
-
- outInfo->options->optionID = opt_iter.type;
- outInfo->options->optionLength = count;
- memcpy(outInfo->options->optionData, optionResult, CA_MAX_HEADER_OPTION_DATA_LENGTH);
-
+ // set token data
if (pdu->hdr->token_length > 0)
{
outInfo->token = (char*) OICMalloc(pdu->hdr->token_length);
memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length);
}
+ // set payload data
if (NULL != pdu->data)
{
- outInfo->payload = (char*) OICMalloc(strlen(pdu->data) + 1);
- memcpy(outInfo->payload, pdu->data, strlen(pdu->data) + 1);
+ outInfo->payload = (char*) OICMalloc(strlen((const char *) pdu->data) + 1);
+ memcpy(outInfo->payload, pdu->data, strlen((const char *) pdu->data) + 1);
}
+
+ // set uri info
+ memcpy(outUri, optionResult, strlen(optionResult));
}
CAResult_t CAGenerateTokenInternal(CAToken_t* token)
{
- OIC_LOG(DEBUG, TAG, "generate the token");
+ if (token == NULL)
+ {
+ return CA_STATUS_FAILED;
+ }
+
+ // memory allocation
+ char* temp = (char*) OICMalloc(sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
+
+ if (temp == NULL)
+ {
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memset(temp, 0, sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
+
+ // set random byte
+ uint32_t index;
+ for (index = 0; index < CA_MAX_TOKEN_LEN; index++)
+ {
+ temp[index] = rand() & 0xFF;
+ }
+
+ // save token
+ *token = temp;
+
+ OIC_LOG_V(DEBUG, TAG, "generate the token(%s)!!", *token);
return CA_STATUS_OK;
}
void CADestroyTokenInternal(CAToken_t token)
{
- OIC_LOG(DEBUG, TAG, "destroy the token!!");
-
if (token != NULL)
{
+ OIC_LOG_V(DEBUG, TAG, "destroy the token(%s)!!", token);
+
OICFree(token);
}
}
+
+void CADeinitialize(CAInfo_t* info)
+{
+ OIC_LOG(DEBUG, TAG, "CADeinitialize!!");
+
+ if (NULL != info)
+ {
+ if (NULL != info->options)
+ {
+ OIC_LOG(DEBUG, TAG, "free options in CAInfo");
+ OICFree(info->options);
+ }
+
+ if (NULL != info->token)
+ {
+ OIC_LOG(DEBUG, TAG, "free token in CAInfo");
+ OICFree(info->token);
+ }
+
+ if (NULL != info->payload)
+ {
+ OIC_LOG(DEBUG, TAG, "free payload in CAInfo");
+ OICFree(info->payload);
+ }
+ }
+}
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "caqueueingthread.h"
+#include "oic_malloc.h"
+#include "logger.h"
+
+#define TAG PCF("CA")
+
+static void CAQueueingThreadBaseRoutine(void* treadValue)
+{
+ OIC_LOG_V(DEBUG, TAG, "message handler main thread start..");
+
+ CAQueueingThread_t* thread = (CAQueueingThread_t*) treadValue;
+
+ if (thread == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread data passing error!!");
+
+ return;
+ }
+
+ while (!thread->isStop)
+ {
+ // mutex lock
+ u_mutex_lock(thread->threadMutex);
+
+ // if queue is empty, thread will wait
+ if (u_queue_get_size(thread->dataQueue) <= 0)
+ {
+ OIC_LOG_V(DEBUG, TAG, "wait..");
+ // wait
+ u_cond_wait(thread->threadCond, thread->threadMutex);
+
+ OIC_LOG_V(DEBUG, TAG, "wake up..");
+ }
+
+ // mutex unlock
+ u_mutex_unlock(thread->threadMutex);
+
+ // check stop flag
+ if (thread->isStop)
+ continue;
+
+ // get data
+ u_queue_message_t* message = u_queue_get_element(thread->dataQueue);
+
+ void* data = message->msg;
+
+ // process data
+ thread->threadTask(data);
+
+ // free
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "message handler main thread end..");
+}
+
+CAResult_t CAQueueingThreadInitialize(CAQueueingThread_t* thread, u_thread_pool_t handle,
+ CAThreadTask task)
+{
+ if (thread == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread instance is empty..");
+ return CA_STATUS_FAILED;
+ }
+
+ if (handle == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread pool handle is empty..");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "thread initialize..");
+
+ memset(thread, 0, sizeof(CAQueueingThread_t));
+
+ // mutex init
+ u_mutex_init();
+
+ // set send thread data
+ thread->threadPool = handle;
+ thread->dataQueue = u_queue_create();
+ thread->threadMutex = u_mutex_new();
+ thread->threadCond = u_cond_new();
+ thread->isStop = CA_FALSE;
+ thread->threadTask = task;
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAQueueingThreadStart(CAQueueingThread_t* thread)
+{
+ if (thread == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread instance is empty..");
+ return CA_STATUS_FAILED;
+ }
+
+ if (thread->threadPool == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread pool handle is empty..");
+ return CA_STATUS_FAILED;
+ }
+
+ CAResult_t res = u_thread_pool_add_task(thread->threadPool, CAQueueingThreadBaseRoutine,
+ thread);
+
+ if (res != CA_STATUS_OK)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread pool add task error(send thread).");
+ return res;
+ }
+
+ return res;
+}
+
+CAResult_t CAQueueingThreadAddData(CAQueueingThread_t* thread, void* data, uint32_t size)
+{
+ if (thread == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread instance is empty..");
+ return CA_STATUS_FAILED;
+ }
+
+ if (data == NULL || size == 0)
+ {
+ OIC_LOG_V(DEBUG, TAG, "data is empty..");
+
+ return CA_STATUS_FAILED;
+ }
+
+ // create thread data
+ u_queue_message_t* message = (u_queue_message_t*) OICMalloc(sizeof(u_queue_message_t));
+
+ if (message == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "memory error!!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memset(message, 0, sizeof(u_queue_message_t));
+
+ message->msg = data;
+ message->size = sizeof(size);
+
+ // mutex lock
+ u_mutex_lock(thread->threadMutex);
+
+ // add thread data into list
+ u_queue_add_element(thread->dataQueue, message);
+
+ // notity the thread
+ u_cond_signal(thread->threadCond);
+
+ // mutex unlock
+ u_mutex_unlock(thread->threadMutex);
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAQueueingThreadDestroy(CAQueueingThread_t* thread)
+{
+ if (thread == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread instance is empty..");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "thread destroy..");
+
+ u_mutex_free(thread->threadMutex);
+ u_cond_free(thread->threadCond);
+ u_queue_delete(thread->dataQueue);
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAQueueingThreadStop(CAQueueingThread_t* thread)
+{
+ if (thread == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "thread instance is empty..");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "thread stop request!!");
+
+ // mutex lock
+ u_mutex_lock(thread->threadMutex);
+
+ // set stop flag
+ thread->isStop = CA_TRUE;
+
+ // notity the thread
+ u_cond_signal(thread->threadCond);
+
+ // mutex unlock
+ u_mutex_unlock(thread->threadMutex);
+
+ return CA_STATUS_OK;
+}
+
int32_t isIp = 0;
int32_t ipLen = 0;
- int32_t port = 0;
int i = 0;
for (i = 0; i < len; i++)
if (ipLen > 0)
outAddress->IP.port = atoi(pAddress + ipLen + 1);
- OIC_LOG_V(DEBUG, TAG, "ip: %s,port: %d", outAddress->IP.ipAddress, outAddress->IP.port);
+ OIC_LOG_V(DEBUG, TAG, "ip: %s, port: %d", outAddress->IP.ipAddress, outAddress->IP.port);
}
else
{
#include <string.h>
#include "caethernetadapter.h"
+//#include "config.h"
+//#include "coap.h"
+#include "caethernetcore.h"
#include "logger.h"
+#include "oic_malloc.h"
#define TAG PCF("CA")
+// received packet callback
static CANetworkPacketReceivedCallback gEthernetReceivedCallback = NULL;
+static u_thread_pool_t gThreadPoolHandle = NULL;
+
+static void CAEthernetPacketReceiveCallback(const char* address, const char* data)
+{
+ OIC_LOG_V(DEBUG, TAG, "CAethernetPacketReceiveCallback, from: %s, data: %s", address, data);
+
+ // call the callback
+ if (gEthernetReceivedCallback != NULL)
+ {
+ CARemoteEndpoint_t* endpoint = NULL;
+ endpoint = (CARemoteEndpoint_t*) OICMalloc(sizeof(CARemoteEndpoint_t));
+
+ // set address
+ memset((void*) endpoint->addressInfo.IP.ipAddress, 0, CA_IPADDR_SIZE);
+ if (CA_IPADDR_SIZE > strlen(address))
+ {
+ strcpy((char*) endpoint->addressInfo.IP.ipAddress, address);
+ }
+ free(address);
+
+ // set connectivity type
+ endpoint->connectivityType = CA_ETHERNET;
+
+ gEthernetReceivedCallback(endpoint, (void *) data, strlen(data));
+ }
+}
CAResult_t CAInitializeEthernet(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback)
+ CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle)
{
- OIC_LOG_V(DEBUG, TAG, "CAInitializeEthernet");
+ OIC_LOG(DEBUG, TAG, "IntializeEthernet");
gEthernetReceivedCallback = reqRespCallback;
+ gThreadPoolHandle = handle;
// register handlers
CAConnectivityHandler_t handler;
handler.startDiscoverServer = CAStartEthernetDiscoveryServer;
handler.sendData = CASendEthernetUnicastData;
handler.sendDataToAll = CASendEthernetMulticastData;
- handler.startNotifyServer = CAStartEthernetNotifyServer;
+ handler.startNotifyServer = CAStartEthernetNotifyRecvServers;
handler.sendNotification = CASendEthernetNotification;
handler.GetnetInfo = CAGetEthernetInterfaceInformation;
handler.readData = CAReadEthernetData;
registerCallback(handler, CA_ETHERNET);
+ CAEthernetSetCallback(CAEthernetPacketReceiveCallback);
+
return CA_STATUS_OK;
}
+void CATerminateEthernet()
+{
+ OIC_LOG(DEBUG, TAG, "TerminateEthernet");
+
+ CAEthernetTerminate();
+}
+
CAResult_t CAStartEthernet()
{
- OIC_LOG_V(DEBUG, TAG, "CAStartEthernet");
+ OIC_LOG(DEBUG, TAG, "CAStartEthernet");
+ //CAEthernetInitialize();
+ CAEthernetInitialize(gThreadPoolHandle);
+
+ OIC_LOG(DEBUG, TAG, "CAEthernetStartUnicastServer");
+ int32_t res = CAEthernetStartUnicastServer();
+
+ if (res < 0)
+ return CA_STATUS_FAILED;
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStopEthernet()
+{
+ OIC_LOG(DEBUG, TAG, "CAStopEthernet");
+
+ // ToDo:
return CA_STATUS_OK;
}
CAResult_t CAStartEthernetListeningServer()
{
- OIC_LOG_V(DEBUG, TAG, "CAStartEthernetListeningServer");
+ OIC_LOG(DEBUG, TAG, "StartEthernetListeningServer");
+
+ int32_t res = CAEthernetStartMulticastServer();
+
+ if (res < 0)
+ return CA_STATUS_FAILED;
return CA_STATUS_OK;
}
CAResult_t CAStartEthernetDiscoveryServer()
{
- OIC_LOG_V(DEBUG, TAG, "CAStartEthernetDiscoveryServer");
+ OIC_LOG(DEBUG, TAG, "StartEthernetDiscoveryServer");
+
+ int32_t res = CAEthernetStartMulticastServer();
+
+ if (res < 0)
+ return CA_STATUS_FAILED;
return CA_STATUS_OK;
}
uint32_t CASendEthernetUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CASendEthernetUnicastData");
+ OIC_LOG(DEBUG, TAG, "SendEthernetUnicastData");
+
+ CAEthernetSendUnicastMessage(endpoint->addressInfo.IP.ipAddress, data, dataLen);
return 0;
}
uint32_t CASendEthernetMulticastData(void* data, uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CASendEthernetMulticastData");
+ OIC_LOG(DEBUG, TAG, "CASendEthernetMulticastData");
+
+ CAEthernetSendMulticastMessage("0.0.0.0", (char*) data);
return 0;
}
-CAResult_t CAStartEthernetNotifyServer()
+CAResult_t CAStartEthernetNotifyRecvServers()
{
- OIC_LOG_V(DEBUG, TAG, "CAStartEthernetNotifyServer");
+ OIC_LOG(DEBUG, TAG, "StartEthernetNotifyRecvServers");
+
+ // ToDo:
return CA_STATUS_OK;
}
uint32_t CASendEthernetNotification(const CARemoteEndpoint_t* endpoint, void* data,
uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CASendEthernetNotification");
+ OIC_LOG(DEBUG, TAG, "SendEthernetNotification");
+
+ // ToDo:
return 0;
}
-CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size)
+CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivity_t** info, uint32_t* size)
{
- OIC_LOG_V(DEBUG, TAG, "CAGetEthernetInterfaceInformation");
+ OIC_LOG(DEBUG, TAG, "GetEthernetInterfaceInformation");
+
+ // ToDo:
return CA_STATUS_OK;
}
CAResult_t CAReadEthernetData()
{
- OIC_LOG_V(DEBUG, TAG, "Read Ethernet Data");
+ OIC_LOG(DEBUG, TAG, "Read Ethernet Data");
- return CA_STATUS_OK;
-}
-
-CAResult_t CAStopEthernet()
-{
- OIC_LOG_V(DEBUG, TAG, "CAStopEthernet");
+ // ToDo:
return CA_STATUS_OK;
}
-void CATerminateEthernet()
-{
- OIC_LOG_V(DEBUG, TAG, "CATerminateEthernet");
-}
--- /dev/null
+#include <stdio.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "caethernetcore.h"
+#include "logger.h"
+#include "uthreadpool.h" /* for thread pool */
+#include "umutex.h"
+#include "caqueueingthread.h"
+#include "oic_malloc.h"
+
+#define TAG PCF("CA")
+
+#define CA_MAX_BUFFER_SIZE 512 // Max length of buffer
+#define CA_UNICAST_PORT 5383 // The port on which to listen for incoming data
+#define CA_MULTICAST_ADDR "224.0.1.187"
+#define CA_MULTICAST_PORT 5683
+typedef enum
+{
+ CA_UNICAST = 1, CA_MULTICAST
+} CATransmissionType_t;
+
+typedef struct
+{
+ CATransmissionType_t transmissionType; // 0: none, 1: unicast, 2: multicast
+ char* address;
+ int port;
+ void* data;
+} CAThreadData_t;
+
+typedef struct
+{
+ u_mutex threadMutex;
+ u_cond threadCond;
+ CABool_t isStop;
+ int32_t status; // 0: stopped, 1: running
+} CATask_t;
+
+int32_t unicast_receive_socket;
+struct sockaddr_in multicast_send_interface_addr;
+int32_t multicast_receive_socket;
+struct sockaddr_in multicast_receive_interface_addr;
+
+static CAPacketReceiveCallback gPacketReceiveCallback = NULL;
+
+static u_thread_pool_t gThreadPoolHandle = NULL;
+
+// message handler main thread
+static CAQueueingThread_t gSendThread;
+static CAQueueingThread_t gReceiveThread;
+
+CATask_t unicastListenTask;
+CATask_t multicastListenTask;
+
+static void CAEthernetSendProcess(void* threadData)
+{
+ OIC_LOG(DEBUG, TAG, "CAEthernetSendThreadProcess");
+
+ CAThreadData_t* data = (CAThreadData_t*) threadData;
+ if (data == NULL)
+ {
+ OIC_LOG(DEBUG, TAG, "thread data is error!");
+ return;
+ }
+
+ if (data->transmissionType == CA_UNICAST)
+ {
+ // unicast
+ CAEthernetSendUnicastMessageImpl(data->address, (char*) (data->data));
+ }
+ else if (data->transmissionType == CA_MULTICAST)
+ {
+ // multicast
+ CAEthernetSendMulticastMessageImpl((char*) (data->data));
+ }
+}
+
+static void CAEthernetReceiveProcess(void* threadData)
+{
+ OIC_LOG(DEBUG, TAG, "CAEthernetReceiveProcess");
+
+ CAThreadData_t* data = (CAThreadData_t*) threadData;
+ if (data == NULL)
+ {
+ OIC_LOG(DEBUG, TAG, "thread data is error!");
+ return;
+ }
+
+ if (gPacketReceiveCallback != NULL)
+ {
+ gPacketReceiveCallback(data->address, (char*) (data->data));
+ }
+}
+
+static void CAUnicastListenThread(void* threadData)
+{
+ OIC_LOG(DEBUG, TAG, "CAUnicastListenThread");
+
+ char buf[CA_MAX_BUFFER_SIZE];
+ int32_t recv_len;
+
+ struct sockaddr_in si_other;
+ int32_t slen = sizeof(si_other);
+
+ while (!unicastListenTask.isStop)
+ {
+ OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, Waiting for data...");
+ fflush(stdout);
+
+ memset(buf, 0, sizeof(char) * CA_MAX_BUFFER_SIZE);
+
+ // try to receive some data, this is a blocking call
+ if ((recv_len = recvfrom(unicast_receive_socket, buf, CA_MAX_BUFFER_SIZE, 0,
+ (struct sockaddr *) &si_other, (socklen_t *) &slen)) == -1)
+ {
+ OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, recv_len() error");
+ continue;
+ }
+
+ // print details of the client/peer and the data received
+ OIC_LOG_V(DEBUG, TAG, "CAUnicastListenThread, Received packet from %s:%d",
+ inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
+ OIC_LOG_V(DEBUG, TAG, "CAUnicastListenThread, Data: %s", buf);
+
+ // store the data at queue.
+ CAThreadData_t* td = NULL;
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
+ memset(td, 0, sizeof(CAThreadData_t));
+ td->transmissionType = 1; // unicast
+
+ char* _address = inet_ntoa(si_other.sin_addr);
+ int len = strlen(_address);
+ td->address = (char*) OICMalloc(sizeof(char) * (len + 1));
+ memset(td->address, 0, len + 1);
+ memcpy(td->address, _address, len);
+ td->port = ntohs(si_other.sin_port);
+
+ td->data = (void*) OICMalloc(sizeof(void) * CA_MAX_BUFFER_SIZE);
+ memset(td->data, 0, CA_MAX_BUFFER_SIZE);
+ memcpy(td->data, buf, sizeof(buf));
+
+ CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));
+ }
+
+ OIC_LOG(DEBUG, TAG, "end of CAUnicastListenThread");
+}
+
+static void CAMulticastListenThread(void* threadData)
+{
+ OIC_LOG(DEBUG, TAG, "CAMulticastListenThread");
+
+ char msgbuf[CA_MAX_BUFFER_SIZE];
+
+ struct sockaddr_in client;
+ int32_t addrlen = sizeof(client);
+
+ OIC_LOG(DEBUG, TAG, "CAMulticastListenThread, waiting for input...");
+
+ while (!multicastListenTask.isStop)
+ {
+ int32_t recv_bytes = recvfrom(multicast_receive_socket, msgbuf, CA_MAX_BUFFER_SIZE, 0,
+ (struct sockaddr *) &client, (socklen_t *) &addrlen);
+ if (recv_bytes < 0)
+ {
+ if (errno != EAGAIN)
+ {
+ OIC_LOG(DEBUG, TAG, "CAMulticastListenThread, error recvfrom");
+
+ return;
+ }
+
+ continue;
+ }
+
+ msgbuf[recv_bytes] = 0;
+
+ OIC_LOG_V(DEBUG, TAG, "Received msg: %s, size: %d", msgbuf, recv_bytes);
+
+ char* sender = inet_ntoa(client.sin_addr);
+ char local[INET_ADDRSTRLEN];
+ CAEthernetGetLocalAddress(local);
+ if (strcmp(sender, local) == 0)
+ {
+ OIC_LOG_V(DEBUG, TAG, "skip the local request (via multicast)");
+ continue;
+ }
+ else
+ {
+ // store the data at queue.
+ CAThreadData_t* td = NULL;
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
+ memset(td, 0, sizeof(CAThreadData_t));
+ td->transmissionType = 2; // multicast
+
+ char* _address = inet_ntoa(client.sin_addr);
+ int len = strlen(_address);
+ td->address = (char*) OICMalloc(sizeof(char) * (len + 1));
+ memset(td->address, 0, len + 1);
+ memcpy(td->address, _address, len);
+ td->port = ntohs(client.sin_port);
+
+ td->data = (void*) OICMalloc(sizeof(void) * CA_MAX_BUFFER_SIZE);
+ memset(td->data, 0, CA_MAX_BUFFER_SIZE);
+ memcpy(td->data, msgbuf, sizeof(msgbuf));
+
+ CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));
+ }
+
+ }
+
+ OIC_LOG(DEBUG, TAG, "end of CAMulticastListenThread");
+}
+
+void CAEthernetInitialize(u_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, TAG, "CAEthernetInitialize");
+
+ gThreadPoolHandle = handle;
+
+ // unicast/multicast send queue
+ CAQueueingThreadInitialize(&gSendThread, gThreadPoolHandle, CAEthernetSendProcess);
+
+ // start send thread
+ CAResult_t res = CAQueueingThreadStart(&gSendThread);
+ if (res != CA_STATUS_OK)
+ {
+ OIC_LOG(DEBUG, TAG, "thread start is error (send thread)");
+ // return res;
+ return;
+ }
+
+ // unicast/multicast receive queue
+ CAQueueingThreadInitialize(&gReceiveThread, gThreadPoolHandle, CAEthernetReceiveProcess);
+
+ // start send thread
+ res = CAQueueingThreadStart(&gReceiveThread);
+ if (res != CA_STATUS_OK)
+ {
+ OIC_LOG(DEBUG, TAG, "thread start is error (receive thread)");
+ // return res;
+ return;
+ }
+
+ unicastListenTask.threadMutex = u_mutex_new();
+ unicastListenTask.threadCond = u_cond_new();
+ unicastListenTask.isStop = CA_FALSE;
+ unicastListenTask.status = 0; // stopped
+
+ multicastListenTask.threadMutex = u_mutex_new();
+ multicastListenTask.threadCond = u_cond_new();
+ multicastListenTask.isStop = CA_FALSE;
+ multicastListenTask.status = 0; // stopped
+
+ // [UDP Server]
+ struct sockaddr_in si_me;
+
+ // create a UDP socket
+ if ((unicast_receive_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+ {
+ OIC_LOG_V(DEBUG, TAG, "CAEthernetInit, creating socket failed");
+
+ return;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "CAEthernetInit, socket created");
+
+ // [multicast sender]
+ uint32_t multiTTL = 1;
+
+ // zero out the structure
+ memset((char *) &si_me, 0, sizeof(si_me));
+
+ si_me.sin_family = AF_INET;
+ si_me.sin_port = htons(CA_UNICAST_PORT);
+ si_me.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ int32_t ret_val = setsockopt(unicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL,
+ sizeof(multiTTL));
+ if (ret_val < 0)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetInit, Failed to set REUSEADDR");
+ }
+
+ // bind socket to port
+ if (bind(unicast_receive_socket, (struct sockaddr*) &si_me, sizeof(si_me)) == -1)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetInit, binding socket failed");
+ close(unicast_receive_socket);
+ return;
+ }
+
+ OIC_LOG(DEBUG, TAG, "CAEthernetInit, socket binded");
+
+ memset(&multicast_send_interface_addr, 0, sizeof(multicast_send_interface_addr));
+ multicast_send_interface_addr.sin_family = AF_INET;
+ multicast_send_interface_addr.sin_addr.s_addr = inet_addr(CA_MULTICAST_ADDR);
+ multicast_send_interface_addr.sin_port = htons(CA_MULTICAST_PORT);
+
+ // [multicast receiver]
+ // 1. Create a typical UDP socket and set Non-blocking for reading
+ multicast_receive_socket = socket(AF_INET, SOCK_DGRAM, 0);
+ if (multicast_receive_socket < 0)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetInit, Socket error");
+ close(unicast_receive_socket);
+ return;
+ }
+
+ // 2. Allow multiple sockets to use the same port number
+ ret_val = setsockopt(multicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL,
+ sizeof(multiTTL));
+ if (ret_val < 0)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetInit, Failed to set REUSEADDR");
+ }
+
+ // 3. Set up the interface
+ memset(&multicast_receive_interface_addr, 0, sizeof(multicast_receive_interface_addr));
+ multicast_receive_interface_addr.sin_family = AF_INET;
+ multicast_receive_interface_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ multicast_receive_interface_addr.sin_port = htons(CA_MULTICAST_PORT);
+
+ // 4. Bind to the interface
+ ret_val = bind(multicast_receive_socket, (struct sockaddr *) &multicast_receive_interface_addr,
+ sizeof(multicast_receive_interface_addr));
+ if (ret_val < 0)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetInit, Failed to bind socket");
+
+ return;
+ }
+
+ // 5. Join the multicast group
+ struct ip_mreq mreq;
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.imr_multiaddr.s_addr = inet_addr(CA_MULTICAST_ADDR);
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ ret_val = setsockopt(multicast_receive_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq));
+ if (ret_val < 0)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetInit, Failed to join multicast group");
+
+ return;
+ }
+}
+
+void CAEthernetTerminate()
+{
+ OIC_LOG(DEBUG, TAG, "CAEthernetTerminate");
+
+ close(unicast_receive_socket);
+ close(multicast_receive_socket);
+
+ shutdown(unicast_receive_socket, 2);
+ shutdown(multicast_receive_socket, 2);
+
+ CAEthernetStopUnicastServer(0);
+
+ CAEthernetStopMulticastServer(0);
+
+ // stop thread
+ CAQueueingThreadStop(&gSendThread);
+ // delete thread data
+ CAQueueingThreadDestroy(&gSendThread);
+
+ // stop thread
+ CAQueueingThreadStop(&gReceiveThread);
+ // delete thread data
+ CAQueueingThreadDestroy(&gReceiveThread);
+
+ u_mutex_free(unicastListenTask.threadMutex);
+ u_cond_free(unicastListenTask.threadCond);
+
+ u_mutex_free(multicastListenTask.threadMutex);
+ u_cond_free(multicastListenTask.threadCond);
+
+}
+
+int32_t CAEthernetSendUnicastMessage(const char* address, const char* data, int lengh)
+{
+ // store the data at queue.
+ CAThreadData_t* td = NULL;
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
+ if (td == NULL)
+ {
+ OICFree(data);
+ return 0;
+ }
+ memset(td, 0, sizeof(CAThreadData_t));
+ td->transmissionType = CA_UNICAST; // unicast type
+ int len = strlen(address);
+ td->address = (char*) OICMalloc(sizeof(char) * (len + 1));
+ if (td->address != NULL)
+ {
+ memset(td->address, 0, len + 1);
+ memcpy(td->address, address, len);
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "Memory Full");
+ OICFree(td);
+ OICFree(data);
+ return 0;
+ }
+ td->data = data;
+
+ CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));
+
+ return 0;
+}
+
+int32_t CAEthernetSendMulticastMessage(const char* m_address, const char* data)
+{
+ // store the data at queue.
+ CAThreadData_t* td = NULL;
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
+ if (td == NULL)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Memory Full");
+ OICFree(data);
+ return 0;
+ }
+ memset(td, 0, sizeof(CAThreadData_t));
+ td->transmissionType = CA_MULTICAST; // unicast
+ td->address = NULL;
+ td->data = data;
+
+ CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));
+
+ return 0;
+}
+
+int32_t CAEthernetStartUnicastServer()
+{
+ OIC_LOG_V(DEBUG, TAG, "CAEthernetStartUnicastServer(%s, %d)", "0.0.0.0", CA_UNICAST_PORT);
+
+ // check the server status
+ if (unicastListenTask.status == 1)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetStartUnicastServer, already running");
+
+ return 0;
+ }
+
+ // unicast listen thread
+ CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAUnicastListenThread, NULL);
+ if (res != CA_STATUS_OK)
+ {
+ OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (unicast listen thread)");
+ return res;
+ }
+
+ unicastListenTask.status = 1; // running
+
+ return 0;
+}
+
+int32_t CAEthernetStartMulticastServer()
+{
+ OIC_LOG_V(DEBUG, TAG, "CAEthernetStartMulticastServer(%s, %d)", "0.0.0.0", CA_MULTICAST_PORT);
+
+ // check the server status
+ if (multicastListenTask.status == 1)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetStartMulticastServer, already running");
+
+ return 0;
+ }
+
+ // multicast listen thread
+ CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAMulticastListenThread, NULL);
+ if (res != CA_STATUS_OK)
+ {
+ OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (multicast listen thread)");
+ return res;
+ }
+
+ multicastListenTask.status = 1;
+
+ return 0;
+}
+
+int32_t CAEthernetStopUnicastServer()
+{
+ OIC_LOG(DEBUG, TAG, "CAEthernetStopUnicastServer");
+
+ // mutex lock
+ u_mutex_lock(unicastListenTask.threadMutex);
+
+ // set stop flag
+ unicastListenTask.isStop = CA_TRUE;
+
+ // notity the thread
+ u_cond_signal(unicastListenTask.threadCond);
+
+ // mutex unlock
+ u_mutex_unlock(unicastListenTask.threadMutex);
+
+ unicastListenTask.status = 0; // stopped
+
+ return 0;
+}
+
+int32_t CAEthernetStopMulticastServer()
+{
+ OIC_LOG(DEBUG, TAG, "CAEthernetStopMulticastServer");
+
+ // mutex lock
+ u_mutex_lock(multicastListenTask.threadMutex);
+
+ // set stop flag
+ multicastListenTask.isStop = CA_TRUE;
+
+ // notity the thread
+ u_cond_signal(multicastListenTask.threadCond);
+
+ // mutex unlock
+ u_mutex_unlock(multicastListenTask.threadMutex);
+
+ multicastListenTask.status = 0; // stopped
+
+ return 0;
+}
+
+void CAEthernetSetCallback(CAPacketReceiveCallback callback)
+{
+ gPacketReceiveCallback = callback;
+}
+
+void CAEthernetGetLocalAddress(char* addressBuffer)
+{
+ //char addressBuffer[INET_ADDRSTRLEN];
+ memset(addressBuffer, 0, INET_ADDRSTRLEN);
+
+ struct ifaddrs* ifAddrStruct = NULL;
+ struct ifaddrs* ifa = NULL;
+ void* tmpAddrPtr = NULL;
+
+ getifaddrs(&ifAddrStruct);
+
+ for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ if (!ifa->ifa_addr)
+ {
+ continue;
+ }
+
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ { // check it is IP4
+ // is a valid IP4 Address
+ tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
+
+ memset(addressBuffer, 0, INET_ADDRSTRLEN);
+ inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
+
+ if (strcmp(addressBuffer, "127.0.0.1") == 0)
+ continue;
+ }
+ }
+
+ if (ifAddrStruct != NULL)
+ freeifaddrs(ifAddrStruct);
+}
+
+int32_t CAEthernetSendUnicastMessageImpl(const char* address, const char* data)
+{
+ OIC_LOG_V(DEBUG, TAG, "CAEthernetSendUnicastMessageImpl, address: %s, data: %s", address, data);
+
+ // [UDP Client]
+
+ struct sockaddr_in si_other;
+ int32_t slen = sizeof(si_other);
+
+ memset((char *) &si_other, 0, sizeof(si_other));
+
+ si_other.sin_family = AF_INET;
+ si_other.sin_port = htons(CA_UNICAST_PORT);
+ if (inet_aton(address, &si_other.sin_addr) == 0)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetSendUnicastMessageImpl, inet_aton, error...");
+ return 0;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "CAEthernetSendUnicastMessageImpl, sendto, to: %s, data: %s", address,
+ data);
+ if (sendto(unicast_receive_socket, data, strlen(data), 0, (struct sockaddr *) &si_other, slen)
+ == -1)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetSendUnicastMessageImpl, sendto, error...");
+
+ return 0;
+ }
+
+ return 0;
+}
+
+int32_t CAEthernetSendMulticastMessageImpl(const char* msg)
+{
+ OIC_LOG_V(DEBUG, TAG, "CAEthernetSendMulticastMessageImpl, sendto, data: %s", msg);
+
+ int32_t result = sendto(unicast_receive_socket, msg, strlen(msg), 0,
+ (struct sockaddr *) &multicast_send_interface_addr,
+ sizeof(multicast_send_interface_addr));
+ if (result < 0)
+ {
+ OIC_LOG(DEBUG, TAG, "CAEthernetSendMulticastMessageImpl, sending message error...");
+
+ return -1;
+ }
+
+ return 0;
+}
+++ /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 "cawifiethernetadapter.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include "caadapterutils.h"
-#include "umutex.h"
-
-#ifdef __TIZEN__
-#include "cawifiserver.h"
-#include "cawificlient.h"
-#include "cawifimonitor.h"
-#elif defined(OIC_ARDUINODUE)
-#include <logger.h>
-#include <string.h>
-#include "cawifiadapter.h"
-#endif //#ifdef __TIZEN__
-/**
- * @def WIFI_ETHERNET_ADAPTER_TAG
- * @brief Logging tag for module name
- */
-#define WIFI_ETHERNET_ADAPTER_TAG "WIFI_ETHERNET_ADAPTER"
-
-/**
- * @def CA_PORT
- * @brief Port to listen for incoming data
- */
-#define CA_PORT 5283
-
-#define CA_MCAST_PORT 5298
-
-/**
- * @def CA_MULTICAST_IP
- * @brief Multicast IP Address
- */
-#define CA_MULTICAST_IP "224.0.1.187"
-
-/**
- * @var gNetworkCallback
- * @brief Network callback
- */
-static CANetworkChangeCallback gNetworkCallback = NULL;
-
-/**
- * @var gIsMulticastServerStarted
- * @brief Flag to check if multicast server is started
- */
-static int gIsMulticastServerStarted = 0;
-static u_mutex gMutexIsMulticastServerStarted = NULL;
-
-void CAInitializeMutex()
-{
- u_mutex_init();
- gMutexIsMulticastServerStarted = u_mutex_new();
-}
-
-int CAWIFIRegisterNetworkNotifications(CANetworkChangeCallback netCallback)
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- gNetworkCallback = netCallback; //TODO: Remove and set using API define in arduino specific file
-#ifdef __TIZEN__
- if (netCallback != NULL)
- {
- CAInitializeWIFIAdapter();
- CASetWIFINetworkChangeCallback(netCallback);
- }
- else
- {
- CADeinitializeWIFIAdapter();
- }
-#endif
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback)
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
- CAResult_t ret = CA_STATUS_OK;
-
- VERIFY_NON_NULL(registerCallback, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument");
- VERIFY_NON_NULL(reqRespCallback, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument");
- VERIFY_NON_NULL(netCallback, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument");
-
- CAConnectivityHandler_t wifiHandler;
- wifiHandler.startAdapter = CAStartWIFI;
- wifiHandler.startListenServer = CAStartWIFIListeningServer;
- wifiHandler.startDiscoverServer = CAStartWIFIDiscoveryServer;
- wifiHandler.sendData = CASendWIFIUnicastData;
- wifiHandler.sendDataToAll = CASendWIFIMulticastData;
- wifiHandler.startNotifyServer = CAStartWIFINotifyRecvServers;
- wifiHandler.sendNotification = CASendWIFINotification;
- wifiHandler.GetnetInfo = CAGetWIFIInterfaceInformation;
- wifiHandler.readData = CAReadWIFIData;
- wifiHandler.stopAdapter = CAStopWIFI;
- wifiHandler.terminate = CATerminateWifi;
- registerCallback(wifiHandler, CA_WIFI);
-
- CASetWIFINetworkPacketCallback(reqRespCallback);
- CAWIFIRegisterNetworkNotifications(netCallback);
- CAInitializeMutex();
- CAInitializeServerMutex();
- //ret = CAStartWIFIUnicastServer();
-
- OCLog(INFO, WIFI_ETHERNET_ADAPTER_TAG, "IntializeWifi Success");
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return ret;
-}
-
-CAResult_t CAStartWIFI()
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
- int16_t unicastPort = CA_PORT;
- CAResult_t ret = CA_STATUS_OK;
-
-#ifdef __TIZEN__
- CASetIsStartServerInvoked();
- int retVal = CAIsWIFIConnected();
- if(retVal == 0)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "WIFI is not Connected");
- return ret;
- }
-#endif
- /*Address is hardcoded as we are using Single Interface*/
- ret = CAStartUnicastServer("0.0.0.0", &unicastPort);
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return ret;
-}
-
-CAResult_t CAStartWIFIListeningServer()
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- CAResult_t ret = CA_STATUS_OK;
- int16_t multicastPort = CA_MCAST_PORT;
-
- if (gIsMulticastServerStarted == 1)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Server is already Started");
- return CA_STATUS_OK;
- }
-#ifdef __TIZEN__
- int retVal = CAIsWIFIConnected();
- if(retVal == 0)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "WIFI is not Connected");
- return CA_STATUS_FAILED;
- }
-#endif
- ret = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", &multicastPort);
- if (ret == CA_STATUS_OK)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Multicast Server is Started Successfully");
- u_mutex_lock(gMutexIsMulticastServerStarted);
- gIsMulticastServerStarted = 1;
- u_mutex_unlock(gMutexIsMulticastServerStarted);
- }
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return ret;
-}
-
-CAResult_t CAStartWIFIDiscoveryServer()
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- CAResult_t ret = CA_STATUS_OK;
- int16_t multicastPort = CA_MCAST_PORT;
-
- if (gIsMulticastServerStarted == 1)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Server is already Started");
- return CA_STATUS_OK;
- }
-#ifdef __TIZEN__
- /*int retVal = CAIsWIFIConnected();
- if(retVal == 0)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "WIFI is not Connected");
- return CA_STATUS_FAILED;
- }*/ //VV
-#endif
- ret = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", &multicastPort);
- if (ret == CA_STATUS_OK)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Multicast Server is Started Successfully");
- u_mutex_lock(gMutexIsMulticastServerStarted);
- gIsMulticastServerStarted = 1;
- u_mutex_unlock(gMutexIsMulticastServerStarted);
- }
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return ret;
-}
-
-uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t *remoteEndpoint, void *data,
- uint32_t dataLen)
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- uint32_t dataSize = 0;
-
- VERIFY_NON_NULL_RET(remoteEndpoint, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument", dataSize);
- VERIFY_NON_NULL_RET(data, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument", dataSize);
-
- if (dataLen <= 0)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Data Length is 0");
- return dataSize;
-
- }
-
- dataSize = CAWIFISendData(remoteEndpoint->addressInfo.IP.ipAddress,
- remoteEndpoint->addressInfo.IP.port, data, dataLen, 0);
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return dataSize;
-}
-
-uint32_t CASendWIFIMulticastData(void *data, uint32_t dataLength)
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- uint32_t dataSize = 0;
-
- VERIFY_NON_NULL_RET(data, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument", dataSize);
-
- if (dataLength <= 0)
- {
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Data Length is 0");
- return 0;
-
- }
- dataSize = CAWIFISendData(CA_MULTICAST_IP, CA_MCAST_PORT, data, dataLength, 1);
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return dataSize;
-}
-
-CAResult_t CAStartWIFINotifyRecvServers()
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen)
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t **info, uint32_t* size)
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-
- VERIFY_NON_NULL(info, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument");
- //VERIFY_NON_NULL(size, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument");
- char localIpAddress[CA_IPADDR_SIZE];
- int32_t localIpAddressLen = sizeof(localIpAddress);
-#ifdef __TIZEN__
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Getting WIFI address");
- CAGetInterfaceAddress(localIpAddress, localIpAddressLen);
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Got WIFI address");
-#else
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Getting shield address");
- arduinoGetInterfaceAddress(localIpAddress, localIpAddressLen);
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Got shield address");
-#endif //#if __ARDUINO__
- /**
- * Create local endpoint using util function
- */
- (*info) = CreateLocalEndpoint(CA_WIFI, localIpAddress, "WiFi");
- if (NULL == (*info))
- {
- OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG, "Error while Createing Memory");
- return CA_STATUS_FAILED;
- }
-
- (*size) = 1;
-
- OCLog(INFO, WIFI_ETHERNET_ADAPTER_TAG, "GetWIFIInterfaceInformation success");
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CAReadWIFIData()
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
-#ifdef __ARDUINO__
- arduoinoCheckServerData();
-#endif //#ifdef __ARDUINO__
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CAStopWIFI()
-{
- CAResult_t result = CA_STATUS_FAILED;
- result = CAStopUnicastServer();
- if (result != CA_STATUS_OK)
- {
- OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG, "Error while stopping UnicastServer");
- return CA_STATUS_FAILED;
- }
-#ifdef __TIZEN__
- CAUnsetIsStartServerInvoked();
-#endif
- result = CAStopMulticastServer();
- if (result != CA_STATUS_OK)
- {
- OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG, "Error while stopping MulticastServer");
- return CA_STATUS_FAILED;
- }
- else
- {
- u_mutex_lock(gMutexIsMulticastServerStarted);
- gIsMulticastServerStarted = 0;
- u_mutex_unlock(gMutexIsMulticastServerStarted);
- }
- return CA_STATUS_OK;
-}
-
-void CATerminateWifi()
-{
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN");
- CAResult_t result = CA_STATUS_FAILED;
-
- CASetWIFINetworkPacketCallback(NULL);
- result = CAWIFIRegisterNetworkNotifications(NULL);
- if (result != CA_STATUS_OK)
- {
- OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG,
- "Error while wifiRegisterNetworkNotifications(NULL)");
- }
-
- OCLog(INFO, WIFI_ETHERNET_ADAPTER_TAG, "TerminateWifi Success");
-
- OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT");
- return;
-}
#include <string.h>
#include "cawifiadapter.h"
-
#include "config.h"
#include "coap.h"
-
#include "cawificore.h"
-
#include "logger.h"
+#include "oic_malloc.h"
#define TAG PCF("CA")
// received packet callback
static CANetworkPacketReceivedCallback gWifiReceivedCallback = NULL;
+static u_thread_pool_t gThreadPoolHandle = NULL;
-static void CAWiFiPacketReceiveCallback(const char* address, const char* data)
+static void CAWiFiPacketReceiveCallback(char* address, const char* data)
{
OIC_LOG_V(DEBUG, TAG,
"CAWiFiPacketReceiveCallback, from: %s, data: %s", address, data);
// set address
memset((void*) endpoint->addressInfo.IP.ipAddress, 0, CA_IPADDR_SIZE);
- if (CA_IPADDR_SIZE > strlen(address))
+ if (CA_IPADDR_SIZE > strlen(address)) {
strcpy((char*) endpoint->addressInfo.IP.ipAddress, address);
+ }
+ OICFree(address);
// set connectivity type
endpoint->connectivityType = CA_WIFI;
- gWifiReceivedCallback(endpoint, data, strlen(data));
+ gWifiReceivedCallback(endpoint, (void *) data, strlen(data));
}
}
CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback,
- CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback)
+ CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle)
{
OIC_LOG(DEBUG, TAG, "IntializeWifi");
gWifiReceivedCallback = reqRespCallback;
+ gThreadPoolHandle = handle;
// register handlers
CAConnectivityHandler_t handler;
CAWiFiSetCallback(CAWiFiPacketReceiveCallback);
- return 0;
+ return CA_STATUS_OK;
}
void CATerminateWIfI()
CAResult_t CAStartWIFI()
{
OIC_LOG(DEBUG, TAG, "CAStartWIFI");
- CAWiFiInitialize();
+ //CAWiFiInitialize();
+ CAWiFiInitialize(gThreadPoolHandle);
OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer");
- CAWiFiStartUnicastServer("0.0.0.0", atoi("5283"));
+ int32_t res = CAWiFiStartUnicastServer("0.0.0.0", atoi("5283"));
- return 0;
+ if (res < 0)
+ return CA_STATUS_FAILED;
+
+ return CA_STATUS_OK;
}
CAResult_t CAStopWIFI()
// ToDo:
- return 0;
+ return CA_STATUS_OK;
}
CAResult_t CAStartWIFIListeningServer()
{
OIC_LOG(DEBUG, TAG, "StartWIFIListeningServer");
- CAWiFiStartMulticastServer("0.0.0.0", atoi("5283"));
+ int32_t res = CAWiFiStartMulticastServer("0.0.0.0", atoi("5283"));
- return 0;
+ if (res < 0)
+ return CA_STATUS_FAILED;
+
+ return CA_STATUS_OK;
}
CAResult_t CAStartWIFIDiscoveryServer()
{
OIC_LOG(DEBUG, TAG, "StartWIFIDiscoveryServer");
- CAWiFiStartMulticastServer("0.0.0.0", atoi("5283"));
+ int32_t res = CAWiFiStartMulticastServer("0.0.0.0", atoi("5283"));
- return 0;
+ if (res < 0)
+ return CA_STATUS_FAILED;
+
+ return CA_STATUS_OK;
}
uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen)
// ToDo:
- return 0;
+ return CA_STATUS_OK;
}
uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen)
return 0;
}
-CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size)
+CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivity_t** info, uint32_t* size)
{
OIC_LOG(DEBUG, TAG, "GetWIFIInterfaceInformation");
// ToDo:
- return 0;
+ return CA_STATUS_OK;
}
CAResult_t CAReadWIFIData()
// ToDo:
- return 0;
+ return CA_STATUS_OK;
}
-#include <stdio.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-#include "cawificore.h"
-#include <errno.h>
-#include <sys/types.h>
-#include <ifaddrs.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include "logger.h"
-
-#define TAG PCF("CA")
-
-#define CA_MAX_BUFFER_SIZE 512 // Max length of buffer
-#define CA_UNICAST_PORT 5283 // The port on which to listen for incoming data
-int32_t unicast_socket;
-pthread_t pthread_unicast_server;
-pthread_t pthread_unicast_client;
-pthread_mutex_t mutex_unicast;
-pthread_cond_t sync_cond_unicast;
-int32_t unicast_send_thread_flag = 0; // 0: run, 1: stop
-
-char* target = NULL;
-void* list = NULL;
-
-#define CA_MULTICAST_ADDR "224.0.1.187"
-#define CA_MULTICAST_PORT 5683
-
-int32_t multicast_send_socket;
-struct sockaddr_in multicast_send_interface_addr;
-
-pthread_t pthread_multicast_server;
-pthread_t pthread_multicast_client;
-
-int32_t multicast_receive_socket;
-struct sockaddr_in multicast_receive_interface_addr;
-
-void* data_list = NULL;
-
-pthread_mutex_t mutex_multicast;
-pthread_cond_t sync_cond_multicast;
-int32_t multicast_send_thread_flag = 0; // 0: run, 1: stop
-
-CAPacketReceiveCallback gPacketReceiveCallback = NULL;
-
-void CAWiFiInitialize()
-{
- OIC_LOG(DEBUG, TAG, "CAWiFiInitialize");
-
- pthread_mutex_init(&mutex_unicast, NULL);
-
- pthread_mutex_init(&mutex_multicast, NULL);
-
- // [UDP Server]
- struct sockaddr_in si_me;
-
- // create a UDP socket
- if ((unicast_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
- {
- OIC_LOG_V(DEBUG, TAG, "CAWiFiInit, creating socket failed");
-
- return;
- }
-
- OIC_LOG_V(DEBUG, TAG, "CAWiFiInit, socket created");
-
- // zero out the structure
- memset((char *) &si_me, 0, sizeof(si_me));
-
- si_me.sin_family = AF_INET;
- si_me.sin_port = htons(CA_UNICAST_PORT);
- si_me.sin_addr.s_addr = htonl(INADDR_ANY);
-
- // bind socket to port
- if (bind(unicast_socket, (struct sockaddr*) &si_me, sizeof(si_me)) == -1)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiInit, binding socket failed");
-
- return;
- }
-
- OIC_LOG(DEBUG, TAG, "CAWiFiInit, socket binded");
-
- // [multicast sender]
- uint32_t multiTTL = 1;
-
- // 1. Set up a typical UDP socket
- multicast_send_socket = socket(AF_INET, SOCK_DGRAM, 0);
- if (multicast_send_socket < 0)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiInit, Socket error");
-
- return;
- }
-
- memset(&multicast_send_interface_addr, 0, sizeof(multicast_send_interface_addr));
- multicast_send_interface_addr.sin_family = AF_INET;
- multicast_send_interface_addr.sin_addr.s_addr = inet_addr(CA_MULTICAST_ADDR);
- multicast_send_interface_addr.sin_port = htons(CA_MULTICAST_PORT);
-
- // [multicast receiver]
- // 1. Create a typical UDP socket and set Non-blocking for reading
- multicast_receive_socket = socket(AF_INET, SOCK_DGRAM, 0);
- if (multicast_receive_socket < 0)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiInit, Socket error");
-
- return;
- }
-
- // 2. Allow multiple sockets to use the same port number
- int32_t ret_val = setsockopt(multicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL,
- sizeof(multiTTL));
- if (ret_val < 0)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR");
- }
-
- // 3. Set up the interface
- memset(&multicast_receive_interface_addr, 0, sizeof(multicast_receive_interface_addr));
- multicast_receive_interface_addr.sin_family = AF_INET;
- multicast_receive_interface_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- multicast_receive_interface_addr.sin_port = htons(CA_MULTICAST_PORT);
-
- // 4. Bind to the interface
- ret_val = bind(multicast_receive_socket, (struct sockaddr *) &multicast_receive_interface_addr,
- sizeof(multicast_receive_interface_addr));
- if (ret_val < 0)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to bind socket");
-
- return;
- }
-
- // 5. Join the multicast group
- struct ip_mreq mreq;
- memset(&mreq, 0, sizeof(mreq));
- mreq.imr_multiaddr.s_addr = inet_addr(CA_MULTICAST_ADDR);
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- ret_val = setsockopt(multicast_receive_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
- sizeof(mreq));
- if (ret_val < 0)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to join multicast group");
-
- return;
- }
-}
-
-void CAWiFiTerminate()
-{
- OIC_LOG(DEBUG, TAG, "CAWiFiTerminate");
-
- pthread_mutex_destroy(&mutex_unicast);
-
- pthread_mutex_destroy(&mutex_multicast);
-
- close(unicast_socket);
-
- close(multicast_send_socket);
-
- close(multicast_receive_socket);
-}
-
-int32_t CAWiFiSendUnicastMessage(const char* address, const char* data, int lengh)
-{
- CASendUnicastMessage(address, data);
-
- return 0;
-}
-
-int32_t CAWiFiSendMulticastMessage(const char* m_address, const char* data)
-{
- CASendMulticastMessage(data);
-
- return 0;
-}
-
-int32_t CAWiFiStartUnicastServer(const char* address, int port)
-{
- OIC_LOG_V(DEBUG, TAG, "CAWiFiStartUnicastServer(%s, %d)", address, port);
-
- int32_t result = pthread_create(&pthread_unicast_server, NULL, (void *) &CAUnicastReceiveThread,
- (void *) NULL);
- if (result < 0)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, creating unicast_receive_thread failed");
-
- return -1;
- }
-
- result = pthread_create(&pthread_unicast_client, NULL, (void *) &CAUnicastSendThread,
- (void *) NULL);
- if (result < 0)
- {
- OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, creating unicast_send_thread failed");
-
- return -1;
- }
-
- OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, receive & send thread created");
-
- return 0;
-}
-
-int32_t CAWiFiStartMulticastServer(const char* m_address, int port)
-{
- OIC_LOG_V(DEBUG, TAG, "CAWiFiStartMulticastServer(%s, %d)", m_address, port);
-
- int32_t result = pthread_create(&pthread_multicast_server, NULL,
- (void *) &CAMulticastReceiveThread, (void *) NULL);
- if (result < 0)
- {
-
- return -1;
- }
-
- result = pthread_create(&pthread_multicast_client, NULL, (void *) &CAMulticastSendThread,
- (void *) NULL);
- if (result < 0)
- {
- OIC_LOG(DEBUG, TAG, "creating receive_thread failed");
-
- return -1;
- }
-
- return 0;
-}
-
-int32_t CAWiFiStopUnicastServer(int32_t server_id)
-{
-
- CAStopUnicastSendThread();
-
- return 0;
-}
-
-int32_t CAWiFiStopMulticastServer(int32_t server_id)
-{
-
- CAStopMulticastSendThread();
-
- return 0;
-}
-
-void CAWiFiSetCallback(CAPacketReceiveCallback callback)
-{
- gPacketReceiveCallback = callback;
-}
-
-void* CAUnicastReceiveThread(void* data)
-{
- OIC_LOG(DEBUG, TAG, "CAUnicastReceiveThread");
-
- char buf[CA_MAX_BUFFER_SIZE];
- int32_t recv_len;
-
- struct sockaddr_in si_other;
- int32_t slen = sizeof(si_other);
-
- // keep listening for data
- while (1)
- {
- OIC_LOG(DEBUG, TAG, "CAUnicastReceiveThread, Waiting for data...");
- fflush(stdout);
-
- memset(buf, 0, sizeof(char) * CA_MAX_BUFFER_SIZE);
-
- // try to receive some data, this is a blocking call
- if ((recv_len = recvfrom(unicast_socket, buf, CA_MAX_BUFFER_SIZE, 0,
- (struct sockaddr *) &si_other, &slen)) == -1)
- {
- OIC_LOG(DEBUG, TAG, "CAUnicastReceiveThread, recv_len() error");
- continue;
- }
-
- // print details of the client/peer and the data received
- OIC_LOG_V(DEBUG, TAG, "CAUnicastReceiveThread, Received packet from %s:%d",
- inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
- OIC_LOG_V(DEBUG, TAG, "CAUnicastReceiveThread, Data: %s", buf);
-
- if (gPacketReceiveCallback != NULL)
- {
- gPacketReceiveCallback(inet_ntoa(si_other.sin_addr), buf);
- }
- }
-
- return (void*) 0;
-}
-
-void* CAUnicastSendThread(void* data)
-{
- OIC_LOG(DEBUG, TAG, "CAUnicastSendThread");
-
- while (!unicast_send_thread_flag)
- {
- pthread_mutex_lock(&mutex_unicast);
-
- pthread_cond_wait(&sync_cond_unicast, &mutex_unicast);
-
- pthread_mutex_unlock(&mutex_unicast);
-
- if (unicast_send_thread_flag)
- return (void*) 0;
-
- CASendUnicastMessageImpl(target, list, strlen(list));
- }
-
- return (void*) 0;
-}
-
-void CASendUnicastMessage(char* address, void* data)
-{
- target = address;
- list = data;
- unicast_send_thread_flag = 0;
-
- pthread_cond_signal(&sync_cond_unicast);
-}
-
-int32_t CASendUnicastMessageImpl(const char* address, const char* data, int32_t lengh)
-{
- OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, address: %s, data: %s", address, data);
-
- // [UDP Client]
- struct sockaddr_in si_other;
- int32_t slen = sizeof(si_other);
-
- memset((char *) &si_other, 0, sizeof(si_other));
-
- si_other.sin_family = AF_INET;
- si_other.sin_port = htons(CA_UNICAST_PORT);
- if (inet_aton(address, &si_other.sin_addr) == 0)
- {
- OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, inet_aton, error...");
- return 0;
- }
-
- OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, to: %s, data: %s", address, data);
- if (sendto(unicast_socket, data, strlen(data), 0, (struct sockaddr *) &si_other, slen) == -1)
- {
- OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, error...");
-
- return 0;
- }
-
- return 0;
-}
-
-void CAStopUnicastSendThread()
-{
- unicast_send_thread_flag = 1;
-
- pthread_cond_signal(&sync_cond_unicast);
-}
-
-void* CAMulticastReceiveThread(void* data)
-{
- OIC_LOG(DEBUG, TAG, "CAMulticastReceiveThread");
-
- // 6. Read from the socket and print out a message when one is received
- char msgbuf[CA_MAX_BUFFER_SIZE];
-
- struct sockaddr_in client;
- int32_t addrlen = sizeof(client);
-
- OIC_LOG(DEBUG, TAG, "CAMulticastReceiveThread, waiting for input...");
-
- while (1)
- {
- int32_t recv_bytes = recvfrom(multicast_receive_socket, msgbuf, CA_MAX_BUFFER_SIZE, 0,
- (struct sockaddr *) &client, (socklen_t *) &addrlen);
- if (recv_bytes < 0)
- {
- if (errno != EAGAIN)
- {
- OIC_LOG(DEBUG, TAG, "CAMulticastReceiveThread, error recvfrom");
-
- return (void*) 0;
- }
-
- continue;
- }
-
- msgbuf[recv_bytes] = 0;
-
- OIC_LOG_V(DEBUG, TAG, "Received msg: %s, size: %d", msgbuf, recv_bytes);
-
- char* sender = inet_ntoa(client.sin_addr);
- char local[INET_ADDRSTRLEN];
- CAGetLocalAddress(local);
- if (strcmp(sender, local) == 0)
- {
- OIC_LOG_V(DEBUG, TAG, "skip the local request (via multicast)");
- }
- else
- {
- if (gPacketReceiveCallback != NULL)
- {
- gPacketReceiveCallback(inet_ntoa(client.sin_addr), msgbuf);
- }
- }
-
- }
-
- return (void*) 0;
-}
-
-void* CAMulticastSendThread(void* data)
-{
- OIC_LOG(DEBUG, TAG, "CAMulticastSendThread");
-
- while (!multicast_send_thread_flag)
- {
- pthread_mutex_lock(&mutex_multicast);
-
- pthread_cond_wait(&sync_cond_multicast, &mutex_multicast);
-
- pthread_mutex_unlock(&mutex_multicast);
-
- if (multicast_send_thread_flag)
- return (void*) 0;
-
- CASendMulticastMessageImpl(data_list);
- }
-
- return (void*) 0;
-}
-
-void CASendMulticastMessage(void* data)
-{
- data_list = data;
- multicast_send_thread_flag = 0;
-
- pthread_cond_signal(&sync_cond_multicast);
-}
-
-int32_t CASendMulticastMessageImpl(const char* msg)
-{
- OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, sendto, data: %s", msg);
-
- int32_t result = sendto(multicast_send_socket, msg, strlen(msg), 0,
- (struct sockaddr *) &multicast_send_interface_addr,
- sizeof(multicast_send_interface_addr));
- if (result < 0)
- {
- OIC_LOG(DEBUG, TAG, "CASendMulticastMessageImpl, sending message error...");
-
- return -1;
- }
-
- return 0;
-}
-
-void CAStopMulticastSendThread()
-{
- multicast_send_thread_flag = 1;
-
- pthread_cond_signal(&sync_cond_multicast);
-}
-
-void CAGetLocalAddress(char* addressBuffer)
-{
- //char addressBuffer[INET_ADDRSTRLEN];
- memset(addressBuffer, 0, INET_ADDRSTRLEN);
-
- struct ifaddrs* ifAddrStruct = NULL;
- struct ifaddrs* ifa = NULL;
- void* tmpAddrPtr = NULL;
-
- getifaddrs(&ifAddrStruct);
-
- for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
- {
- if (!ifa->ifa_addr)
- {
- continue;
- }
-
- if (ifa->ifa_addr->sa_family == AF_INET)
- { // check it is IP4
- // is a valid IP4 Address
- tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
-
- memset(addressBuffer, 0, INET_ADDRSTRLEN);
- inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
-
- if (strcmp(addressBuffer, "127.0.0.1") == 0)
- continue;
- }
- }
-
- if (ifAddrStruct != NULL)
- freeifaddrs(ifAddrStruct);
-}
-
+#include <stdio.h>\r
+#include <sys/socket.h>\r
+#include <arpa/inet.h>\r
+#include <string.h>\r
+#include <pthread.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <sys/types.h>\r
+#include <ifaddrs.h>\r
+#include <netinet/in.h>\r
+#include <string.h>\r
+#include <arpa/inet.h>\r
+\r
+#include "cawificore.h"\r
+#include "logger.h"\r
+#include "uthreadpool.h" /* for thread pool */\r
+#include "umutex.h"\r
+#include "caqueueingthread.h"\r
+#include "oic_malloc.h"\r
+\r
+#define TAG PCF("CA")\r
+\r
+#define CA_MAX_BUFFER_SIZE 512 // Max length of buffer\r#define CA_UNICAST_PORT 5383 // The port on which to listen for incoming data\r#define CA_MULTICAST_ADDR "224.0.1.187"\r
+#define CA_MULTICAST_PORT 5683\r
+\r
+typedef enum\r
+{\r
+ CA_UNICAST = 1, CA_MULTICAST\r
+} CATransmissionType_t;\r
+\r
+typedef struct\r
+{\r
+ CATransmissionType_t transmissionType; // 0: none, 1: unicast, 2: multicast\r
+ char* address;\r
+ int port;\r
+ void* data;\r
+} CAThreadData_t;\r
+\r
+typedef struct\r
+{\r
+ u_mutex threadMutex;\r
+ u_cond threadCond;\r
+ int32_t isStop;\r
+ int32_t status; // 0: stopped, 1: running\r
+} CATask_t;\r
+\r
+int32_t unicast_receive_socket;\r
+struct sockaddr_in multicast_send_interface_addr;\r
+int32_t multicast_receive_socket;\r
+struct sockaddr_in multicast_receive_interface_addr;\r
+\r
+static CAPacketReceiveCallback gPacketReceiveCallback = NULL;\r
+\r
+static u_thread_pool_t gThreadPoolHandle = NULL;\r
+\r
+// message handler main thread\r
+static CAQueueingThread_t gSendThread;\r
+static CAQueueingThread_t gReceiveThread;\r
+\r
+CATask_t unicastListenTask;\r
+CATask_t multicastListenTask;\r
+\r
+static void CASendProcess(void* threadData)\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CASendThreadProcess");\r
+\r
+ CAThreadData_t* data = (CAThreadData_t*) threadData;\r
+ if (data == NULL)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "thread data is error!");\r
+ return;\r
+ }\r
+\r
+ if (data->transmissionType == CA_UNICAST)\r
+ {\r
+ // unicast\r
+ CASendUnicastMessageImpl(data->address, (char*) (data->data));\r
+ }\r
+ else if (data->transmissionType == CA_MULTICAST)\r
+ {\r
+ // multicast\r
+ CASendMulticastMessageImpl((char*) (data->data));\r
+ }\r
+}\r
+\r
+static void CAReceiveProcess(void* threadData)\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CAReceiveProcess");\r
+\r
+ CAThreadData_t* data = (CAThreadData_t*) threadData;\r
+ if (data == NULL)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "thread data is error!");\r
+ return;\r
+ }\r
+\r
+ if (gPacketReceiveCallback != NULL)\r
+ {\r
+ gPacketReceiveCallback(data->address, (char*) (data->data));\r
+ }\r
+}\r
+\r
+static void CAUnicastListenThread(void* threadData)\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CAUnicastListenThread");\r
+\r
+ char buf[CA_MAX_BUFFER_SIZE];\r
+ int32_t recv_len;\r
+\r
+ struct sockaddr_in si_other;\r
+ int32_t slen = sizeof(si_other);\r
+\r
+ while (!unicastListenTask.isStop)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, Waiting for data...");\r
+ fflush(stdout);\r
+\r
+ memset(buf, 0, sizeof(char) * CA_MAX_BUFFER_SIZE);\r
+\r
+ // try to receive some data, this is a blocking call\r
+ if ((recv_len = recvfrom(unicast_receive_socket, buf, CA_MAX_BUFFER_SIZE, 0,\r
+ (struct sockaddr *) &si_other, (socklen_t *) &slen)) == -1)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, recv_len() error");\r
+ continue;\r
+ }\r
+\r
+ // print details of the client/peer and the data received\r
+ OIC_LOG_V(DEBUG, TAG, "CAUnicastListenThread, Received packet from %s:%d",\r
+ inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));\r
+ OIC_LOG_V(DEBUG, TAG, "CAUnicastListenThread, Data: %s", buf);\r
+\r
+ // store the data at queue.\r
+ CAThreadData_t* td = NULL;\r
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));\r
+ memset(td, 0, sizeof(CAThreadData_t));\r
+ td->transmissionType = 1; // unicast\r
+\r
+ char* _address = inet_ntoa(si_other.sin_addr);\r
+ int len = strlen(_address);\r
+ td->address = (char*) OICMalloc(sizeof(char) * (len + 1));\r
+ memset(td->address, 0, len + 1);\r
+ memcpy(td->address, _address, len);\r
+ td->port = ntohs(si_other.sin_port);\r
+\r
+ td->data = (void*) OICMalloc(sizeof(void) * CA_MAX_BUFFER_SIZE);\r
+ memset(td->data, 0, CA_MAX_BUFFER_SIZE);\r
+ memcpy(td->data, buf, sizeof(buf));\r
+\r
+ CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));\r
+ }\r
+\r
+ OIC_LOG(DEBUG, TAG, "end of CAUnicastListenThread");\r
+}\r
+\r
+static void CAMulticastListenThread(void* threadData)\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CAMulticastListenThread");\r
+\r
+ char msgbuf[CA_MAX_BUFFER_SIZE];\r
+\r
+ struct sockaddr_in client;\r
+ int32_t addrlen = sizeof(client);\r
+\r
+ OIC_LOG(DEBUG, TAG, "CAMulticastListenThread, waiting for input...");\r
+\r
+ while (!multicastListenTask.isStop)\r
+ {\r
+ int32_t recv_bytes = recvfrom(multicast_receive_socket, msgbuf, CA_MAX_BUFFER_SIZE, 0,\r
+ (struct sockaddr *) &client, (socklen_t *) &addrlen);\r
+ if (recv_bytes < 0)\r
+ {\r
+ if (errno != EAGAIN)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAMulticastListenThread, error recvfrom");\r
+\r
+ return;\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ msgbuf[recv_bytes] = 0;\r
+\r
+ OIC_LOG_V(DEBUG, TAG, "Received msg: %s, size: %d", msgbuf, recv_bytes);\r
+\r
+ char* sender = inet_ntoa(client.sin_addr);\r
+ char local[INET_ADDRSTRLEN];\r
+ CAGetLocalAddress(local);\r
+ if (strcmp(sender, local) == 0)\r
+ {\r
+ OIC_LOG_V(DEBUG, TAG, "skip the local request (via multicast)");\r
+ }\r
+ else\r
+ {\r
+ // store the data at queue.\r
+ CAThreadData_t* td = NULL;\r
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));\r
+ memset(td, 0, sizeof(CAThreadData_t));\r
+ td->transmissionType = 2; // multicast\r
+\r
+ char* _address = inet_ntoa(client.sin_addr);\r
+ int len = strlen(_address);\r
+ td->address = (char*) OICMalloc(sizeof(char) * (len + 1));\r
+ memset(td->address, 0, len + 1);\r
+ memcpy(td->address, _address, len);\r
+ td->port = ntohs(client.sin_port);\r
+\r
+ td->data = (void*) OICMalloc(sizeof(void) * CA_MAX_BUFFER_SIZE);\r
+ memset(td->data, 0, CA_MAX_BUFFER_SIZE);\r
+ memcpy(td->data, msgbuf, sizeof(msgbuf));\r
+\r
+ CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));\r
+ }\r
+\r
+ }\r
+\r
+ OIC_LOG(DEBUG, TAG, "end of CAMulticastListenThread");\r
+}\r
+\r
+void CAWiFiInitialize(u_thread_pool_t handle)\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInitialize");\r
+\r
+ gThreadPoolHandle = handle;\r
+\r
+ // unicast/multicast send queue\r
+ CAQueueingThreadInitialize(&gSendThread, gThreadPoolHandle, CASendProcess);\r
+\r
+ // start send thread\r
+ CAResult_t res = CAQueueingThreadStart(&gSendThread);\r
+ if (res != CA_STATUS_OK)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "thread start is error (send thread)");\r
+ // return res;\r
+ return;\r
+ }\r
+\r
+ // unicast/multicast receive queue\r
+ CAQueueingThreadInitialize(&gReceiveThread, gThreadPoolHandle, CAReceiveProcess);\r
+\r
+ // start send thread\r
+ res = CAQueueingThreadStart(&gReceiveThread);\r
+ if (res != CA_STATUS_OK)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "thread start is error (receive thread)");\r
+ // return res;\r
+ return;\r
+ }\r
+\r
+ unicastListenTask.threadMutex = u_mutex_new();\r
+ unicastListenTask.threadCond = u_cond_new();\r
+ unicastListenTask.isStop = FALSE;\r
+ unicastListenTask.status = 0; // stopped\r
+\r
+ multicastListenTask.threadMutex = u_mutex_new();\r
+ multicastListenTask.threadCond = u_cond_new();\r
+ multicastListenTask.isStop = FALSE;\r
+ multicastListenTask.status = 0; // stopped\r
+\r
+ // [UDP Server]\r
+ struct sockaddr_in si_me;\r
+\r
+ // create a UDP socket\r
+ if ((unicast_receive_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)\r
+ {\r
+ OIC_LOG_V(DEBUG, TAG, "CAWiFiInit, creating socket failed");\r
+\r
+ return;\r
+ }\r
+\r
+ OIC_LOG_V(DEBUG, TAG, "CAWiFiInit, socket created");\r
+\r
+ // [multicast sender]\r
+ uint32_t multiTTL = 1;\r
+\r
+ // zero out the structure\r
+ memset((char *) &si_me, 0, sizeof(si_me));\r
+\r
+ si_me.sin_family = AF_INET;\r
+ si_me.sin_port = htons(CA_UNICAST_PORT);\r
+ si_me.sin_addr.s_addr = htonl(INADDR_ANY);\r
+\r
+ int32_t ret_val = setsockopt(unicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL,\r
+ sizeof(multiTTL));\r
+ if (ret_val < 0)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR");\r
+ }\r
+\r
+ // bind socket to port\r
+ if (bind(unicast_receive_socket, (struct sockaddr*) &si_me, sizeof(si_me)) == -1)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInit, binding socket failed");\r
+\r
+ return;\r
+ }\r
+\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInit, socket binded");\r
+\r
+ memset(&multicast_send_interface_addr, 0, sizeof(multicast_send_interface_addr));\r
+ multicast_send_interface_addr.sin_family = AF_INET;\r
+ multicast_send_interface_addr.sin_addr.s_addr = inet_addr(CA_MULTICAST_ADDR);\r
+ multicast_send_interface_addr.sin_port = htons(CA_MULTICAST_PORT);\r
+\r
+ // [multicast receiver]\r
+ // 1. Create a typical UDP socket and set Non-blocking for reading\r
+ multicast_receive_socket = socket(AF_INET, SOCK_DGRAM, 0);\r
+ if (multicast_receive_socket < 0)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInit, Socket error");\r
+\r
+ return;\r
+ }\r
+\r
+ // 2. Allow multiple sockets to use the same port number\r
+ ret_val = setsockopt(multicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL,\r
+ sizeof(multiTTL));\r
+ if (ret_val < 0)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR");\r
+ }\r
+\r
+ // 3. Set up the interface\r
+ memset(&multicast_receive_interface_addr, 0, sizeof(multicast_receive_interface_addr));\r
+ multicast_receive_interface_addr.sin_family = AF_INET;\r
+ multicast_receive_interface_addr.sin_addr.s_addr = htonl(INADDR_ANY);\r
+ multicast_receive_interface_addr.sin_port = htons(CA_MULTICAST_PORT);\r
+\r
+ // 4. Bind to the interface\r
+ ret_val = bind(multicast_receive_socket, (struct sockaddr *) &multicast_receive_interface_addr,\r
+ sizeof(multicast_receive_interface_addr));\r
+ if (ret_val < 0)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to bind socket");\r
+\r
+ return;\r
+ }\r
+\r
+ // 5. Join the multicast group\r
+ struct ip_mreq mreq;\r
+ memset(&mreq, 0, sizeof(mreq));\r
+ mreq.imr_multiaddr.s_addr = inet_addr(CA_MULTICAST_ADDR);\r
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);\r
+ ret_val = setsockopt(multicast_receive_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,\r
+ sizeof(mreq));\r
+ if (ret_val < 0)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to join multicast group");\r
+\r
+ return;\r
+ }\r
+}\r
+\r
+void CAWiFiTerminate()\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiTerminate");\r
+\r
+ close(unicast_receive_socket);\r
+ close(multicast_receive_socket);\r
+\r
+ shutdown(unicast_receive_socket, 2);\r
+ shutdown(multicast_receive_socket, 2);\r
+\r
+ CAWiFiStopUnicastServer(0);\r
+\r
+ CAWiFiStopMulticastServer(0);\r
+\r
+ // stop thread\r
+ CAQueueingThreadStop(&gSendThread);\r
+ // delete thread data\r
+ CAQueueingThreadDestroy(&gSendThread);\r
+\r
+ // stop thread\r
+ CAQueueingThreadStop(&gReceiveThread);\r
+ // delete thread data\r
+ CAQueueingThreadDestroy(&gReceiveThread);\r
+\r
+ u_mutex_free(unicastListenTask.threadMutex);\r
+ u_cond_free(unicastListenTask.threadCond);\r
+\r
+ u_mutex_free(multicastListenTask.threadMutex);\r
+ u_cond_free(multicastListenTask.threadCond);\r
+\r
+}\r
+\r
+int32_t CAWiFiSendUnicastMessage(const char* address, const char* data, int lengh)\r
+{\r
+ // store the data at queue.\r
+ CAThreadData_t* td = NULL;\r
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));\r
+ if (td == NULL)\r
+ {\r
+ return 0;\r
+ }\r
+ memset(td, 0, sizeof(CAThreadData_t));\r
+ td->transmissionType = CA_UNICAST; // unicast type\r
+ int len = strlen(address);\r
+ td->address = (char*) OICMalloc(sizeof(char) * (len + 1));\r
+ if (td->address != NULL)\r
+ {\r
+ memset(td->address, 0, len + 1);\r
+ memcpy(td->address, address, len);\r
+ }\r
+ else\r
+ {\r
+ OIC_LOG_V(DEBUG, TAG, "Memory Full");\r
+ OICFree(td);\r
+ return 0;\r
+ }\r
+\r
+ td->data = data;\r
+\r
+ CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));\r
+\r
+ return 0;\r
+}\r
+\r
+int32_t CAWiFiSendMulticastMessage(const char* m_address, const char* data)\r
+{\r
+ // store the data at queue.\r
+ CAThreadData_t* td = NULL;\r
+ td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));\r
+ if (td == NULL)\r
+ {\r
+ OICFree(data);\r
+ return 0;\r
+ }\r
+ memset(td, 0, sizeof(CAThreadData_t));\r
+ td->transmissionType = CA_MULTICAST; // multicast type\r
+ td->address = NULL;\r
+ td->data = data;\r
+\r
+ CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));\r
+\r
+ return 0;\r
+}\r
+\r
+int32_t CAWiFiStartUnicastServer()\r
+{\r
+ OIC_LOG_V(DEBUG, TAG, "CAWiFiStartUnicastServer(%s, %d)", "0.0.0.0", CA_UNICAST_PORT);\r
+\r
+ // check the server status\r
+ if (unicastListenTask.status == 1)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, already running");\r
+\r
+ return 0;\r
+ }\r
+\r
+ // unicast listen thread\r
+ CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAUnicastListenThread, NULL);\r
+ if (res != CA_STATUS_OK)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (unicast listen thread)");\r
+ return res;\r
+ }\r
+\r
+ unicastListenTask.status = 1; // running\r
+\r
+ return 0;\r
+}\r
+\r
+int32_t CAWiFiStartMulticastServer()\r
+{\r
+ OIC_LOG_V(DEBUG, TAG, "CAWiFiStartMulticastServer(%s, %d)", "0.0.0.0", CA_MULTICAST_PORT);\r
+\r
+ // check the server status\r
+ if (multicastListenTask.status == 1)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiStartMulticastServer, already running");\r
+\r
+ return 0;\r
+ }\r
+\r
+ // multicast listen thread\r
+ CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAMulticastListenThread, NULL);\r
+ if (res != CA_STATUS_OK)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (multicast listen thread)");\r
+ return res;\r
+ }\r
+\r
+ multicastListenTask.status = 1;\r
+\r
+ return 0;\r
+}\r
+\r
+int32_t CAWiFiStopUnicastServer()\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiStopUnicastServer");\r
+\r
+ // mutex lock\r
+ u_mutex_lock(unicastListenTask.threadMutex);\r
+\r
+ // set stop flag\r
+ unicastListenTask.isStop = TRUE;\r
+\r
+ // notity the thread\r
+ u_cond_signal(unicastListenTask.threadCond);\r
+\r
+ // mutex unlock\r
+ u_mutex_unlock(unicastListenTask.threadMutex);\r
+\r
+ unicastListenTask.status = 0; // stopped\r
+\r
+ return 0;\r
+}\r
+\r
+int32_t CAWiFiStopMulticastServer()\r
+{\r
+ OIC_LOG(DEBUG, TAG, "CAWiFiStopMulticastServer");\r
+\r
+ // mutex lock\r
+ u_mutex_lock(multicastListenTask.threadMutex);\r
+\r
+ // set stop flag\r
+ multicastListenTask.isStop = TRUE;\r
+\r
+ // notity the thread\r
+ u_cond_signal(multicastListenTask.threadCond);\r
+\r
+ // mutex unlock\r
+ u_mutex_unlock(multicastListenTask.threadMutex);\r
+\r
+ multicastListenTask.status = 0; // stopped\r
+\r
+ return 0;\r
+}\r
+\r
+void CAWiFiSetCallback(CAPacketReceiveCallback callback)\r
+{\r
+ gPacketReceiveCallback = callback;\r
+}\r
+\r
+void CAGetLocalAddress(char* addressBuffer)\r
+{\r
+ //char addressBuffer[INET_ADDRSTRLEN];\r
+ memset(addressBuffer, 0, INET_ADDRSTRLEN);\r
+\r
+ struct ifaddrs* ifAddrStruct = NULL;\r
+ struct ifaddrs* ifa = NULL;\r
+ void* tmpAddrPtr = NULL;\r
+\r
+ getifaddrs(&ifAddrStruct);\r
+\r
+ for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)\r
+ {\r
+ if (!ifa->ifa_addr)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ if (ifa->ifa_addr->sa_family == AF_INET)\r
+ { // check it is IP4\r
+ // is a valid IP4 Address\r
+ tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;\r
+\r
+ memset(addressBuffer, 0, INET_ADDRSTRLEN);\r
+ inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);\r
+\r
+ if (strcmp(addressBuffer, "127.0.0.1") == 0)\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (ifAddrStruct != NULL)\r
+ freeifaddrs(ifAddrStruct);\r
+}\r
+\r
+int32_t CASendUnicastMessageImpl(const char* address, const char* data)\r
+{\r
+ OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, address: %s, data: %s", address, data);\r
+\r
+ // [UDP Client]\r
+\r
+ struct sockaddr_in si_other;\r
+ int32_t slen = sizeof(si_other);\r
+\r
+ memset((char *) &si_other, 0, sizeof(si_other));\r
+\r
+ si_other.sin_family = AF_INET;\r
+ si_other.sin_port = htons(CA_UNICAST_PORT);\r
+ if (inet_aton(address, &si_other.sin_addr) == 0)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, inet_aton, error...");\r
+ return 0;\r
+ }\r
+\r
+ OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, to: %s, data: %s", address, data);\r
+ if (sendto(unicast_receive_socket, data, strlen(data), 0, (struct sockaddr *) &si_other, slen)\r
+ == -1)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, error...");\r
+\r
+ return 0;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int32_t CASendMulticastMessageImpl(const char* msg)\r
+{\r
+ OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, sendto, data: %s", msg);\r
+\r
+ int32_t result = sendto(unicast_receive_socket, msg, strlen(msg), 0,\r
+ (struct sockaddr *) &multicast_send_interface_addr,\r
+ sizeof(multicast_send_interface_addr));\r
+ if (result < 0)\r
+ {\r
+ OIC_LOG(DEBUG, TAG, "CASendMulticastMessageImpl, sending message error...");\r
+\r
+ return -1;\r
+ }\r
+\r
+ return 0;\r
+}\r
--- /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 "caethernetadapter.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include "logger.h"
+
+/**
+ * @def WIFI_ETHERNET_ADAPTER_TAG
+ * @brief Logging tag for module name
+ */
+#define ETHERNET_ADAPTER_TAG "ETHERNET_ADAPTER"
+
+CAResult_t CAInitializeEthernet(CARegisterConnectivityCallback registerCallback,
+ CANetworkPacketReceivedCallback networkPacketCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAStartEthernet()
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAStartEthernetListeningServer()
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+
+}
+
+CAResult_t CAStartEthernetDiscoveryServer()
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+uint32_t CASendEthernetUnicastData(const CARemoteEndpoint_t *remoteEndpoint, void *data,
+ uint32_t dataLen)
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return 0;
+}
+
+uint32_t CASendEthernetMulticastData(void *data, uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return 0;
+}
+
+CAResult_t CAStartEthernetNotifyServer()
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+uint32_t CASendEthernetNotification(const CARemoteEndpoint_t *endpoint, void *data,
+ uint32_t dataLen)
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAReadEthernetData()
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAStopEthernet()
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
+ return CA_NOT_SUPPORTED;
+}
+
+void CATerminateEthernet()
+{
+ OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
+ OIC_LOG(DEBUG, ETHERNET_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 "cawifiadapter.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include "caadapterutils.h"
+#include "umutex.h"
+#include "logger.h"
+#include "cawifiserver.h"
+#include "cawificlient.h"
+#include "cawifimonitor.h"
+#include "camessagequeue.h"
+
+/**
+ * @def WIFI_ETHERNET_ADAPTER_TAG
+ * @brief Logging tag for module name
+ */
+#define WIFI_ADAPTER_TAG "WIFI_ADAPTER"
+
+/**
+ * @def CA_PORT
+ * @brief Port to listen for incoming data
+ */
+#define CA_PORT 5283
+
+/**
+ * @def CA_MCAST_PORT
+ * @brief Multicast Port Number
+ */
+#define CA_MCAST_PORT 5298
+
+/**
+ * @def CA_MULTICAST_IP
+ * @brief Multicast IP Address
+ */
+#define CA_MULTICAST_IP "224.0.1.187"
+
+/* Skip Queue */
+/**
+ * @var gNetworkPacketCallback
+ * @brief Network Packet Received Callback
+ */
+static CANetworkPacketReceivedCallback gNetworkPacketCallback = NULL;
+
+/**
+ * @var gIsMulticastServerStarted
+ * @brief Flag to check if multicast server is started
+ */
+static int gIsMulticastServerStarted = 0;
+
+/**
+ * @var gMutexIsMulticastServerStarted
+ * @brief Mutex for gIsMulticastServerStarted
+ */
+static u_mutex gMutexIsMulticastServerStarted = NULL;
+
+/**
+ * @var gSendQueueHandle
+ * @brief Queue handle for Send Data
+ */
+static CAAdapterMessageQueue_t *gSendQueueHandle = NULL;
+
+/**
+ * @var gRecvQueueHandle
+ * @brief Queue handle for Receive Data
+ */
+static CAAdapterMessageQueue_t *gRecvQueueHandle = NULL;
+
+/**
+ * @var gSendDataCond
+ * @brief Condition for Send Data
+ */
+static u_cond gSendDataCond = NULL;
+
+void CAInitializeMutex()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ u_mutex_init();
+ if (NULL == gMutexIsMulticastServerStarted)
+ {
+ gMutexIsMulticastServerStarted = u_mutex_new();
+ }
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+}
+
+int CAWIFIRegisterNetworkNotifications(CANetworkChangeCallback netCallback)
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ if (netCallback != NULL)
+ {
+ CAInitializeWIFIAdapter();
+ CASetWIFINetworkChangeCallback(netCallback);
+ }
+ else
+ {
+ CADeinitializeWIFIAdapter();
+ }
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAInitializeQueueHandles()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ if (CA_STATUS_OK != CAAdapterInitializeMessageQueue(&gSendQueueHandle))
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Failed to Initialize Send queue Handle");
+ return CA_STATUS_FAILED;
+ }
+ gSendDataCond = u_cond_new();
+ CASetSendQueueHandle(gSendQueueHandle, CA_TRUE, gSendDataCond);
+
+ if (CA_STATUS_OK != CAAdapterInitializeMessageQueue(&gRecvQueueHandle))
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Failed to Initialize Receive queue Handle");
+ return CA_STATUS_FAILED;
+ }
+ CASetRecvQueueHandle(gRecvQueueHandle);
+ return CA_STATUS_OK;
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+}
+
+void CADeinitializeSendQueueHandle()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ CASetSendQueueHandle(NULL, CA_FALSE, NULL);
+ CAAdapterTerminateMessageQueue(gSendQueueHandle);
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+}
+
+void CADeinitializeRecvQueueHandle()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ CAAdapterTerminateMessageQueue(gRecvQueueHandle);
+ CASetRecvQueueHandle(NULL);
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+}
+
+#if 0 /* Skip Queue */
+void CASetWIFINetworkPacketCallback(CANetworkPacketReceivedCallback callback)
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ gNetworkPacketCallback = callback;
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+}
+#endif //#if 0
+CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback,
+ CANetworkPacketReceivedCallback networkPacketCallback, CANetworkChangeCallback netCallback,
+ u_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ VERIFY_NON_NULL(registerCallback, WIFI_ADAPTER_TAG,
+ "Invalid argument : registerCallback is NULL");
+ VERIFY_NON_NULL(networkPacketCallback, WIFI_ADAPTER_TAG,
+ "Invalid argument : networkPacketCallback is NULL");
+ VERIFY_NON_NULL(netCallback, WIFI_ADAPTER_TAG, "Invalid argument : netCallback is NULL");
+
+ CAConnectivityHandler_t wifiHandler;
+ wifiHandler.startAdapter = CAStartWIFI;
+ wifiHandler.startListenServer = CAStartWIFIListeningServer;
+ wifiHandler.startDiscoverServer = CAStartWIFIDiscoveryServer;
+ wifiHandler.sendData = CASendWIFIUnicastData;
+ wifiHandler.sendDataToAll = CASendWIFIMulticastData;
+ wifiHandler.startNotifyServer = CAStartWIFINotifyRecvServers;
+ wifiHandler.sendNotification = CASendWIFINotification;
+ wifiHandler.GetnetInfo = CAGetWIFIInterfaceInformation;
+ wifiHandler.readData = CAReadWIFIData;
+ wifiHandler.stopAdapter = CAStopWIFI;
+ wifiHandler.terminate = CATerminateWIfI;
+ registerCallback(wifiHandler, CA_WIFI);
+
+ CASetWIFINetworkPacketCallback(networkPacketCallback);
+ CAWIFIRegisterNetworkNotifications(netCallback);
+ CAInitializeMutex();
+ CAInitializeServerMutex();
+ CASetThreadHandle(handle);
+ CASetMulticastData(CA_MULTICAST_IP, CA_MCAST_PORT);
+
+ if (CA_STATUS_OK != CAInitializeQueueHandles())
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Failed to Initialize Queue Handle");
+ return CA_STATUS_FAILED;
+ }
+ if (CA_STATUS_OK != CAStartSendDataThread(handle))
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Failed to Start Send Data Thread");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(INFO, WIFI_ADAPTER_TAG, "IntializeWifi is Success");
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartWIFI()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ int16_t unicastPort = CA_PORT;
+ CAResult_t ret = CA_STATUS_OK;
+
+ CASetIsStartServerInvoked();
+ CABool_t retVal = CAIsWIFIConnected();
+ if (retVal == CA_FALSE)
+ {
+ OIC_LOG(INFO, WIFI_ADAPTER_TAG, "WIFI is not Connected");
+ return ret;
+ }
+
+ // Address is hardcoded as we are using Single Interface
+ ret = CAStartUnicastServer("0.0.0.0", &unicastPort);
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return ret;
+}
+
+CAResult_t CAStartWIFIListeningServer()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ CAResult_t ret = CA_STATUS_OK;
+ int16_t multicastPort = CA_MCAST_PORT;
+
+ if (gIsMulticastServerStarted == 1)
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG,
+ "Failed to Start Listening Server, Already Started! Return code[%d]",
+ CA_SERVER_STARTED_ALREADY);
+ return CA_SERVER_STARTED_ALREADY;
+ }
+
+ CABool_t retVal = CAIsWIFIConnected();
+ if (retVal == CA_FALSE)
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG,
+ "Failed to Start Listening Server, WIFI is not Connected! Return code[%d]",
+ CA_ADAPTER_NOT_ENABLED);
+ return CA_ADAPTER_NOT_ENABLED;
+ }
+
+ ret = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", &multicastPort);
+ if (ret == CA_STATUS_OK)
+ {
+ OIC_LOG(INFO, WIFI_ADAPTER_TAG, "Multicast Server is Started Successfully");
+ u_mutex_lock(gMutexIsMulticastServerStarted);
+ gIsMulticastServerStarted = 1;
+ u_mutex_unlock(gMutexIsMulticastServerStarted);
+ }
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return ret;
+}
+
+CAResult_t CAStartWIFIDiscoveryServer()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ CAResult_t ret = CA_STATUS_OK;
+ int16_t multicastPort = CA_MCAST_PORT;
+
+ if (gIsMulticastServerStarted == 1)
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG,
+ "Failed to Start Discovery Server, Already Started! Return code[%d]",
+ CA_SERVER_STARTED_ALREADY);
+ return CA_SERVER_STARTED_ALREADY;
+ }
+
+ CABool_t retVal = CAIsWIFIConnected();
+ if (retVal == CA_FALSE)
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG,
+ "Failed to Start Discovery Server, WIFI is not Connected! Return code[%d]",
+ CA_ADAPTER_NOT_ENABLED);
+ return CA_ADAPTER_NOT_ENABLED;
+ }
+
+ ret = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", &multicastPort);
+ if (ret == CA_STATUS_OK)
+ {
+ OIC_LOG(INFO, WIFI_ADAPTER_TAG, "Multicast Server is Started Successfully");
+ u_mutex_lock(gMutexIsMulticastServerStarted);
+ gIsMulticastServerStarted = 1;
+ u_mutex_unlock(gMutexIsMulticastServerStarted);
+ }
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return ret;
+}
+
+uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t *remoteEndpoint, void *data,
+ uint32_t dataLen)
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ uint32_t dataSize = 0;
+
+ VERIFY_NON_NULL_RET(remoteEndpoint, WIFI_ADAPTER_TAG,
+ "Invalid argument : remoteEndpoint is NULL", dataSize);
+ VERIFY_NON_NULL_RET(data, WIFI_ADAPTER_TAG, "Invalid argument : data is NULL", dataSize);
+
+ if (dataLen <= 0)
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Invalid argument : Data Length is 0");
+ return dataSize;
+
+ }
+
+ if (NULL == gSendQueueHandle)
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Queue Handle is not Initialized");
+ return dataSize;
+ }
+ CAAdapterEnqueueMessage(gSendQueueHandle, remoteEndpoint, data, dataLen);
+ u_cond_signal(gSendDataCond);
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return dataLen;
+}
+
+uint32_t CASendWIFIMulticastData(void *data, uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ uint32_t dataSize = 0;
+
+ VERIFY_NON_NULL_RET(data, WIFI_ADAPTER_TAG, "Invalid argument : data is NULL", dataSize);
+
+ if (dataLength <= 0)
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Invalid argument : Data Length is 0");
+ return 0;
+
+ }
+
+ if (NULL == gSendQueueHandle)
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Queue Handle is not Initialized");
+ return dataSize;
+ }
+ CAAdapterEnqueueMessage(gSendQueueHandle, NULL, data, dataLength);
+ u_cond_signal(gSendDataCond);
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return dataLength;
+}
+
+CAResult_t CAStartWIFINotifyRecvServers()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+uint32_t CASendWIFINotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+
+ CABool_t retVal = CAIsWIFIConnected();
+ if (retVal == CA_FALSE)
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG,
+ "Failed to get interface address, WIFI is not Connected! Return code[%d]",
+ CA_ADAPTER_NOT_ENABLED);
+ return CA_ADAPTER_NOT_ENABLED;
+ }
+
+ VERIFY_NON_NULL(info, WIFI_ADAPTER_TAG, "Invalid argument : info is NULL");
+ char localIpAddress[CA_IPADDR_SIZE];
+ int32_t localIpAddressLen = sizeof(localIpAddress);
+
+ CAGetInterfaceAddress(localIpAddress, localIpAddressLen);
+
+ // Create local endpoint using util function
+ (*info) = CAAdapterCreateLocalEndpoint(CA_WIFI, localIpAddress, "WiFi");
+ if (NULL == (*info))
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG, "Failed to create Local Endpoint! Return code[%d]",
+ CA_MEMORY_ALLOC_FAILED);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ (*size) = 1;
+
+ OIC_LOG(INFO, WIFI_ADAPTER_TAG, "GetWIFIInterfaceInformation success");
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAReadWIFIData()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ if (NULL == gRecvQueueHandle)
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "QueueHandle is NULL");
+ return CA_STATUS_FAILED;
+ }
+ CAAdapterMessage_t *messageReceived;
+ if (CA_STATUS_OK != CAAdapterDequeueMessage(gRecvQueueHandle, &messageReceived))
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Dequeue Message failed");
+ return CA_STATUS_FAILED;
+ }
+
+ if (gNetworkPacketCallback && (NULL != messageReceived))
+ {
+ gNetworkPacketCallback(messageReceived->remoteEndpoint, messageReceived->data,
+ messageReceived->dataLen);
+ }
+
+ CAAdapterFreeMessage(messageReceived);
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStopWIFI()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ CAResult_t result = CA_STATUS_FAILED;
+ result = CAStopUnicastServer();
+ if (result != CA_STATUS_OK)
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG, "Failed to Stop Unicast Server! Return code[%d]",
+ result);
+ return result;
+ }
+ CAUnsetIsStartServerInvoked();
+ result = CAStopMulticastServer();
+ if (result != CA_STATUS_OK)
+ {
+ OIC_LOG_V(ERROR, WIFI_ADAPTER_TAG, "Failed to Stop Multicast Server! Return code[%d]",
+ result);
+ return result;
+ }
+ else
+ {
+ u_mutex_lock(gMutexIsMulticastServerStarted);
+ gIsMulticastServerStarted = 0;
+ u_mutex_unlock(gMutexIsMulticastServerStarted);
+ }
+ CADeinitializeRecvQueueHandle();
+ CADeinitializeSendQueueHandle();
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CATerminateWIfI()
+{
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "IN");
+ CAResult_t result = CA_STATUS_FAILED;
+
+ CASetWIFINetworkPacketCallback(NULL);
+ result = CAWIFIRegisterNetworkNotifications(NULL);
+ if (result != CA_STATUS_OK)
+ {
+ OIC_LOG(ERROR, WIFI_ADAPTER_TAG, "Failed to Unregister Network Notifications");
+ }
+ OIC_LOG(INFO, WIFI_ADAPTER_TAG, "TerminateWifi Success");
+
+ OIC_LOG(DEBUG, WIFI_ADAPTER_TAG, "OUT");
+ return;
+}
--- /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 "cawificlient.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include "caadapterutils.h"
+
+/**
+ * @def WIFI_CLIENT_TAG
+ * @brief Logging tag for module name
+ */
+#define WIFI_CLIENT_TAG "WIFI_CLIENT"
+
+/**
+ * @var gClientSendQueueHandle
+ * @brief Queue Handle for send Data
+ */
+static CAAdapterMessageQueue_t *gClientSendQueueHandle = NULL;
+
+/**
+ * @var gSendDataFlag
+ * @brief Flag to check if Termination is Called
+ */
+static CABool_t gSendDataFlag = CA_FALSE;
+
+/**
+ * @var gClientSendDataCond
+ * @brief Condition for Send Data
+ */
+static u_cond gClientSendDataCond = NULL;
+
+/**
+ * @var gMulticastIP
+ * @brief Multicast IP address
+ */
+static char gMulticastIP[CA_IPADDR_SIZE];
+
+/**
+ * @var gMulticastPort
+ * @brief Multicast Port
+ */
+static uint32_t gMulticastPort;
+
+/**
+ * @var gUnicastServerSocketDescClient
+ * @brief socket descriptor for unicast server
+ */
+static int gUnicastServerSocketDescClient = -1;
+
+void CASetUnicastSocketDescriptor(int unicastSocketDesc)
+{
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "IN");
+ gUnicastServerSocketDescClient = unicastSocketDesc;
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "OUT");
+}
+
+void CASetSendQueueHandle(CAAdapterMessageQueue_t *gSendQueueHandle, CABool_t flag, u_cond cond)
+{
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "IN");
+ gClientSendQueueHandle = gSendQueueHandle;
+ gSendDataFlag = flag;
+ if (cond == NULL)
+ {
+ u_cond_signal(gClientSendDataCond);
+ }
+ gClientSendDataCond = cond;
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "OUT");
+}
+
+void CASetMulticastData(char *mAddr, uint32_t mPort)
+{
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "IN");
+ strncpy(gMulticastIP, mAddr, CA_IPADDR_SIZE - 1);
+ gMulticastPort = mPort;
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "OUT");
+}
+
+CAResult_t CAStartSendDataThread(u_thread_pool_t threadHandle)
+{
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "IN");
+ VERIFY_NON_NULL(threadHandle, WIFI_CLIENT_TAG, "Invalid argument : threadHandle is NULL");
+ if (CA_STATUS_OK != u_thread_pool_add_task(threadHandle, (void *) CAStartThreadForSendData,
+ (void *) NULL))
+ {
+ OIC_LOG(ERROR, WIFI_CLIENT_TAG, "Failed to add task in thread pool");
+ return CA_STATUS_FAILED;
+ }
+ return CA_STATUS_OK;
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "OUT");
+}
+
+uint32_t CAWIFISendData(const char *remoteIpAddress, const uint32_t port, const char *data,
+ uint32_t dataLen, int16_t isMulticast)
+{
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "IN");
+
+ VERIFY_NON_NULL_RET(remoteIpAddress, WIFI_CLIENT_TAG, "Invalid argument : remoteIpAddress is NULL",
+ 0);
+ VERIFY_NON_NULL_RET(data, WIFI_CLIENT_TAG, "Invalid argument : data is NULL", 0);
+
+ OIC_LOG_V(DEBUG, WIFI_CLIENT_TAG, "remoteIPAddress is %s", remoteIpAddress);
+ OIC_LOG_V(DEBUG, WIFI_CLIENT_TAG, "PortNumber is %d", port);
+ OIC_LOG_V(DEBUG, WIFI_CLIENT_TAG, "Data[%d] to send is %s", dataLen, data);
+
+ uint32_t sendDataLength = 0;
+
+ if (dataLen <= 0)
+ {
+ OIC_LOG(ERROR, WIFI_CLIENT_TAG, "Invalid Arguemnet : Datalength is <= 0");
+ return sendDataLength;
+ }
+
+ if (-1 == gUnicastServerSocketDescClient)
+ {
+ OIC_LOG(ERROR, WIFI_CLIENT_TAG, "Unicast Server is not running");
+ return sendDataLength;
+ }
+
+ struct sockaddr_in destAddr;
+ memset((char *)&destAddr, 0, sizeof(destAddr));
+ destAddr.sin_family = AF_INET;
+ destAddr.sin_port = htons(port);
+
+ // Conversion from ASCII format to Network format
+ if (inet_aton(remoteIpAddress, &destAddr.sin_addr) == 0)
+ {
+ OIC_LOG(ERROR, WIFI_CLIENT_TAG, "Failed to convert from ASCII to Network Address");
+ return sendDataLength;
+ }
+
+ sendDataLength = sendto(gUnicastServerSocketDescClient, data, dataLen, 0,
+ (struct sockaddr *)&destAddr, sizeof(destAddr));
+ if (sendDataLength == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_CLIENT_TAG, "Failed to Send Data, Error code: %s", strerror(errno));
+ return 0;
+ }
+
+ OIC_LOG_V(INFO, WIFI_CLIENT_TAG, "Sending data is successful, sent bytes[%d]", sendDataLength);
+
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "OUT");
+ return sendDataLength;
+}
+
+void *CAStartThreadForSendData()
+{
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "IN");
+ if (NULL == gClientSendQueueHandle)
+ {
+ OIC_LOG(ERROR, WIFI_CLIENT_TAG, "Queue Handle is NULL");
+ return NULL;
+ }
+
+ u_mutex sendDataMutex = u_mutex_new();
+ CAAdapterMessage_t *message;
+
+ while (gSendDataFlag)
+ {
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "Inside The while loop");
+ u_mutex_lock(sendDataMutex);
+ u_cond_wait(gClientSendDataCond, sendDataMutex);
+ while (CA_STATUS_OK == CAAdapterDequeueMessage(gClientSendQueueHandle, &message))
+ {
+ if (NULL != message->remoteEndpoint)
+ {
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "Send Unicast Data is called");
+ CAWIFISendData(message->remoteEndpoint->addressInfo.IP.ipAddress,
+ message->remoteEndpoint->addressInfo.IP.port, message->data, message->dataLen, 0);
+ }
+ else
+ {
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "Send Multicast Data is called");
+ CAWIFISendData(gMulticastIP, gMulticastPort, message->data, message->dataLen, 1);
+ }
+ CAAdapterFreeMessage(message);
+ }
+ u_mutex_unlock(sendDataMutex);
+ }
+
+ OIC_LOG(DEBUG, WIFI_CLIENT_TAG, "OUT");
+ return NULL;
+}
--- /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.
+*
+******************************************************************/
+
+/**
+ * @file cawificlient.h
+ * @brief This file contains the APIs for WiFi Client module
+ */
+
+#ifndef _CA_WIFI_CLIENT_
+#define _CA_WIFI_CLIENT_
+
+#include <stdint.h>
+#include "cacommon.h"
+#include "logger.h"
+#include "camessagequeue.h"
+#include "uthreadpool.h"
+
+/**
+ * @brief API to Set the send queue handle
+ * @param gSendQueueHandle [IN] Queue Handle to Send Data
+ * @return - None
+ */
+void CASetSendQueueHandle(CAAdapterMessageQueue_t *gSendQueueHandle, CABool_t flag, u_cond cond);
+
+/**
+ * @brief API to Set the Multicast IP and Port Address
+ * @param mAddr [IN] Multicast IP
+ * @param mPort [IN] Multicast Port
+ * @return - None
+ */
+void CASetMulticastData(char *mAddr, uint32_t mPort);
+
+/**
+ * @brief API to Start the Thread for Send Unicast and Multicast Data
+ * @param threadHandle [IN] ThreadHandle to Add the task in Thread pool
+ * @return - None
+ */
+CAResult_t CAStartSendDataThread(u_thread_pool_t threadHandle);
+
+/**
+ * @brief To send Unicast or Multicast Data
+ * @param remoteIpAddress [IN] RemoteEndpoint IP Address
+ * @param port [IN] RemoteEndpoint Port Number
+ * @param data [IN] Data to be sent to the RemoteEndpoint
+ * @param dataLen [IN] Length of the data to be sent
+ * @param isMulticast [IN] Unicast/Multicast flag, 0 for Unicast and 1 for Multicast
+ * @return Return 0 on failure and length of data on success
+ */
+uint32_t CAWIFISendData(const char *remoteIpAddress, const uint32_t port, const char *data,
+ uint32_t dataLen, int16_t isMulticast);
+
+/**
+ * @brief API to Invoke SendData.
+ * @return - NULL
+ */
+void *CAStartThreadForSendData();
+
+#endif // #ifndef _CA_WIFI_CLIENT_
\ No newline at end of file
--- /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 "cawifimonitor.h"
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <unistd.h>
+#include <wifi.h>
+#include "logger.h"
+#include "caadapterutils.h"
+#include "cawifiadapter.h"
+#include "cawifiserver.h"
+#include "umutex.h"
+
+#define WIFI_MONITOR_TAG "WIFI_MONITOR"
+
+static int gIsStartServerCalled = 0;
+static u_mutex gMutexIsStartServerCalled = NULL;
+CANetworkChangeCallback gNetworkChangeCb = NULL;
+
+CAResult_t CAGetInterfaceAddress(char *address, int32_t addrLen)
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ VERIFY_NON_NULL(address, WIFI_MONITOR_TAG, "Invalid argument : address is NULL");
+ if (addrLen < CA_IPADDR_SIZE)
+ {
+ OIC_LOG_V(ERROR, WIFI_MONITOR_TAG, "addrLen MUST be atleast %d", CA_IPADDR_SIZE);
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ struct ifaddrs *interfaceAddr, *ifAddr;
+ int interfaceFamily, name;
+
+ /* Getting All Interfaces*/
+ if (getifaddrs(&interfaceAddr) == -1)
+ {
+ OIC_LOG(ERROR, WIFI_MONITOR_TAG, "Failed to get interface list");
+ return CA_STATUS_FAILED;
+ }
+
+ for (ifAddr = interfaceAddr; ifAddr != NULL; ifAddr = ifAddr->ifa_next)
+ {
+ if (ifAddr->ifa_addr == NULL)
+ continue;
+
+ /* Currently, check for wifi interface and get the IP Address */
+ OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "interface name = %s", ifAddr->ifa_name);
+ if (0 == strncmp(ifAddr->ifa_name, "wlan0", strlen("wlan0")))
+ {
+ interfaceFamily = ifAddr->ifa_addr->sa_family;
+ OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "interfaceFamily = %d", interfaceFamily);
+
+ if (interfaceFamily == AF_INET || interfaceFamily == AF_INET6)
+ {
+ name = getnameinfo(ifAddr->ifa_addr,
+ (interfaceFamily == AF_INET) ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6),
+ address, CA_IPADDR_SIZE,
+ NULL, 0, NI_NUMERICHOST);
+ if (name != 0)
+ {
+ OIC_LOG_V(ERROR, WIFI_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
+ strerror(errno));
+ return CA_STATUS_FAILED;
+ }
+ OIC_LOG_V(DEBUG, WIFI_MONITOR_TAG, "interface name = %s", address);
+ break;
+ }
+ }
+ }
+ freeifaddrs(interfaceAddr);
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAInitializeWIFIAdapter()
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ wifi_initialize();
+ gMutexIsStartServerCalled = u_mutex_new();
+ wifi_error_e ret = WIFI_ERROR_INVALID_PARAMETER;
+ wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
+ ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
+ if (ret != WIFI_ERROR_NONE)
+ {
+ OIC_LOG(ERROR, WIFI_MONITOR_TAG, "wifi_set_connection_state_changed_cb failed");
+ return CA_STATUS_FAILED;
+ }
+ else
+ {
+ OIC_LOG(INFO, WIFI_MONITOR_TAG, "wifi_set_connection_state_changed_cb sucess");
+ }
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CADeinitializeWIFIAdapter()
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ wifi_error_e ret = WIFI_ERROR_INVALID_PARAMETER;
+ wifi_unset_device_state_changed_cb();
+ ret = wifi_unset_connection_state_changed_cb();
+ if (ret != WIFI_ERROR_NONE)
+ {
+ OIC_LOG(INFO, WIFI_MONITOR_TAG, "wifi_unset_device_state_changed_cb failed");
+ }
+ else
+ {
+ OIC_LOG(INFO, WIFI_MONITOR_TAG, "wifi_unset_device_state_changed_cb success");
+ }
+ wifi_deinitialize();
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CABool_t CAIsWIFIConnected()
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ wifi_connection_state_e connection_state;
+ int retVal = wifi_get_connection_state(&connection_state);
+ if (retVal != WIFI_ERROR_NONE)
+ {
+ OIC_LOG(ERROR, WIFI_MONITOR_TAG, "Failed to get the Connection State");
+ return CA_FALSE;
+ }
+ if (connection_state == WIFI_CONNECTION_STATE_DISCONNECTED)
+ {
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "WIFI is not Connected");
+ return CA_FALSE;
+ }
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "WIFI is Connected");
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+ return CA_TRUE;
+}
+
+void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, void *userData)
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ if (state == WIFI_CONNECTION_STATE_ASSOCIATION
+ || WIFI_CONNECTION_STATE_CONFIGURATION == state)
+ {
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "Connection is in Association State");
+ return;
+ }
+ CANetworkStatus_t nwConnectivityStatus = CA_INTERFACE_DOWN;
+ CALocalConnectivity_t *localEndpoint = NULL;
+ uint32_t size = 0;
+ /* If Wifi is connected, then get the latest IP from the WIFI Interface */
+ if (WIFI_CONNECTION_STATE_CONNECTED == state)
+ {
+ if (gIsStartServerCalled)
+ {
+ CAStartWIFI();
+ }
+ nwConnectivityStatus = CA_INTERFACE_UP;
+ CAGetWIFIInterfaceInformation(&localEndpoint, &size);
+ }
+ else
+ {
+ localEndpoint = CAAdapterCreateLocalEndpoint(CA_WIFI, "", NULL);
+ CAStopUnicastServer();
+ }
+
+ gNetworkChangeCb(localEndpoint, nwConnectivityStatus);
+
+ CAAdapterFreeLocalEndpoint(localEndpoint);
+
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+ return;
+}
+
+void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+
+ if (WIFI_DEVICE_STATE_ACTIVATED == state)
+ {
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "Wifi is in Activated State");
+ }
+ else
+ {
+ CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "Wifi is in Deactivated State");
+ }
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+ return;
+}
+
+void CASetIsStartServerInvoked()
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ u_mutex_lock(gMutexIsStartServerCalled);
+ gIsStartServerCalled = 1;
+ u_mutex_unlock(gMutexIsStartServerCalled);
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+}
+
+void CAUnsetIsStartServerInvoked()
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ u_mutex_lock(gMutexIsStartServerCalled);
+ gIsStartServerCalled = 0;
+ u_mutex_unlock(gMutexIsStartServerCalled);
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+}
+
+void CASetWIFINetworkChangeCallback(CANetworkChangeCallback netCallback)
+{
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "IN");
+ gNetworkChangeCb = netCallback;
+ OIC_LOG(DEBUG, WIFI_MONITOR_TAG, "OUT");
+}
\ No newline at end of file
--- /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.
+*
+******************************************************************/
+
+/**
+ * @file cawifiutils.h
+ * @brief This file contains the APIs for WiFi Specific Calls
+ */
+
+#ifndef _CA_WIFI_MONITOR_
+#define _CA_WIFI_MONITOR_
+
+#include <stdint.h>
+#include <wifi.h>
+#include "caadapterinterface.h"
+#include "cacommon.h"
+
+/**
+ * @brief To send Unicast or Multicast Data
+ * @param remoteIpAddress [OUT] IP Address of the device
+ * @param port [IN] Length of the IP address
+ * @return Return Error Code
+ */
+CAResult_t CAGetInterfaceAddress(char *address, int32_t addrLen);
+
+/**
+ * @brief To Initialize the WIFI Adapter
+ * @return Return Error Code
+ */
+CAResult_t CAInitializeWIFIAdapter();
+
+/**
+ * @brief To Deinitialize WIFI Adapter
+ * @return Return Error Code
+ */
+CAResult_t CADeinitializeWIFIAdapter();
+
+/**
+ * @brief To Check if WIFI is connected
+ * @return Return True or False
+ */
+CABool_t CAIsWIFIConnected();
+
+/**
+ * @brief WIFI connection state Changed Callback
+ * @param state [IN] Connection state of the Device
+ * @param ap [IN] Access Point handler
+ * @param userData [IN] User Data Passed on Setting the Callback
+ * @return Return None
+ */
+void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, void *userData);
+
+/**
+ * @brief WIFI Device state Changed Callback
+ * @param state [IN] Device state
+ * @param userData [IN] User Data Passed on Setting the Callback
+ * @return Return None
+ */
+void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData);
+
+/**
+ * @brief To set the IsStartServerCalled global variable
+ * @return Return None
+ */
+void CASetIsStartServerInvoked();
+
+/**
+ * @brief To unset the IsStartServerCalled global variable
+ * @return Return None
+ */
+void CAUnsetIsStartServerInvoked();
+
+/**
+ * @brief API to set Network Changed callback to upper layer.
+ * @param netCallback - upper layer callback function to notify the change in WIFI connection state.
+ * @return - Error Code
+ */
+void CASetWIFINetworkChangeCallback(CANetworkChangeCallback netCallback);
+#endif
\ No newline at end of file
--- /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 "cawifiserver.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <unistd.h>
+#include "caadapterutils.h"
+#include "umutex.h"
+
+/**
+ * @def WIFI_SERVER_TAG
+ * @brief Logging tag for module name
+ */
+#define WIFI_SERVER_TAG "WIFI_SERVER"
+
+/**
+ * @def CA_BUFFER_LEN
+ * @brief Length of buffer for receiving data
+ */
+#define CA_BUFFER_LEN 512 // Max length of buffer
+
+/**
+ * @def CA_UDP_BIND_RETRY_COUNT
+ * @brief Retry count in case of socket bind failure.
+ */
+#define CA_UDP_BIND_RETRY_COUNT 10
+
+
+/**
+ * @var gUnicastServerSocketDescriptor
+ * @brief socket descriptor for unicast server
+ */
+static int gUnicastServerSocketDescriptor = -1;
+
+/**
+ * @var gMutexUnicastServerSocketDescriptor
+ * @brief Mutex for socket descriptor for unicast server
+ */
+static u_mutex gMutexUnicastServerSocketDescriptor = NULL;
+/**
+ * @var gMulticastServerSocketDescriptor
+ * @brief socket descriptor for multicast server
+ */
+static int gMulticastServerSocketDescriptor = -1;
+
+/**
+ * @var gMutexMulticastServerSocketDescriptor
+ * @brief Mutex for socket descriptor for Multicast server
+ */
+static u_mutex gMutexMulticastServerSocketDescriptor = NULL;
+
+/**
+ * @var gThreadPool
+ * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
+ */
+static u_thread_pool_t gThreadPool = NULL;
+
+/**
+ * @var gMReq
+ * @brief ip_mreq structure passed to join a multicast group
+ */
+static struct ip_mreq gMReq;
+
+/**
+ * @var gStopUnicast
+ * @brief Flag to control the Receive Unicast Data Thread
+ */
+static bool gStopUnicast = false;
+
+/**
+ * @var gMutexStopUnicast
+ * @brief Mutex for gStopUnicast
+ */
+static u_mutex gMutexStopUnicast = NULL;
+
+/**
+ * @var gStopMulticast
+ * @brief Flag to control the Receive Multicast Data Thread
+ */
+static bool gStopMulticast = false;
+
+/**
+ * @var gMutexStopMulticast
+ * @brief Mutex for gStopMulticast
+ */
+static u_mutex gMutexStopMulticast = NULL;
+
+/**
+ * @var gServerRecvQueueHandle
+ * @brief Queue Handle for Receive Data
+ */
+static CAAdapterMessageQueue_t *gServerRecvQueueHandle = NULL;
+
+/* Skip Queue */
+/**
+ * @var gNetworkPacketCallback
+ * @brief receiving request response callback
+ */
+static CANetworkPacketReceivedCallback gNetworkPacketCallback = NULL;
+
+void CAInitializeServerMutex()
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+ gMutexUnicastServerSocketDescriptor = u_mutex_new();
+ gMutexMulticastServerSocketDescriptor = u_mutex_new();
+ gMutexStopUnicast = u_mutex_new();
+ gMutexStopMulticast = u_mutex_new();
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+}
+
+void CASetRecvQueueHandle(CAAdapterMessageQueue_t *recvQueueHandle)
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+ gServerRecvQueueHandle = recvQueueHandle;
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+}
+
+void CASetThreadHandle(u_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+ gThreadPool = handle;
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+}
+
+CAResult_t CAStartUnicastServer(const char *localAddress, int16_t *port)
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+
+ if (gUnicastServerSocketDescriptor != -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server is Started Already! Return Code[%d]",
+ CA_SERVER_STARTED_ALREADY);
+ return CA_SERVER_STARTED_ALREADY;
+ }
+
+ VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "Invalid argument : localAddress is NULL");
+ VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "Invalid argument : port is NULL");
+
+ struct sockaddr_in sockAddr;
+ int16_t isBound = 0;
+ int16_t i = 0;
+ int16_t result = 0;
+ int16_t status = 0;
+ int setOptionOn = 1;
+ u_mutex_lock(gMutexStopUnicast);
+ gStopUnicast = false;
+ u_mutex_unlock(gMutexStopUnicast);
+
+ u_mutex_lock(gMutexUnicastServerSocketDescriptor);
+ // Create a UDP socket
+ if ((gUnicastServerSocketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to Create Socket, Error code: %s", strerror(errno));
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ // Make the socket non-blocking
+ if ((status = fcntl(gUnicastServerSocketDescriptor, F_SETFL, O_NONBLOCK)) < 0)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "fcntl to make the socket non-blocking failed, Error code: %s",
+ strerror(errno));
+ close(gUnicastServerSocketDescriptor);
+ gUnicastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "socket creation success");
+
+ if ((result = setsockopt(gUnicastServerSocketDescriptor, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &setOptionOn,
+ sizeof(setOptionOn))) < 0)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to setsockopt for SO_REUSEADDR! Error code: %s",
+ strerror(errno));
+ close(gUnicastServerSocketDescriptor);
+ gUnicastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ // zero out the structure
+ memset((char *) &sockAddr, 0, sizeof(sockAddr));
+ sockAddr.sin_family = AF_INET;
+ sockAddr.sin_port = htons(*port);
+
+ // TODO: Assign the Particular Address on Multiple Interfaces
+ sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ // Trying for bind in a loop
+ for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
+ {
+ // bind socket to port
+ if (bind(gUnicastServerSocketDescriptor, (struct sockaddr *) &sockAddr, sizeof(sockAddr)) == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]. Trying again... ", strerror(errno));
+ continue;
+ }
+ isBound = 1;
+ break;
+ }
+
+ if (!isBound)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind Socket! Return code[%d]",
+ CA_SOCKET_OPERATION_FAILED);
+ close(gUnicastServerSocketDescriptor);
+ gUnicastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "socket bind success");
+
+ socklen_t len; // = sizeof(sin);
+
+ if (getsockname(gUnicastServerSocketDescriptor, (struct sockaddr *)&sockAddr, &len) == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to getsockname, Error code: %s", strerror(errno));
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "port number %d", ntohs(sockAddr.sin_port));
+ *port = ntohs(sockAddr.sin_port);
+ }
+
+ /**
+ * The task to listen for data from unicast socket is added to the thread pool.
+ * This is a blocking call is made where we try to receive some data.. We will keep waiting until some data is received.
+ * This task will be terminated when thread pool is freed on stopping the adapters.
+ */
+ if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CAReceiveThreadForUnicast,
+ (void *) NULL))
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "[testThreadPool] thread_pool_add_task failed!");
+
+ close(gUnicastServerSocketDescriptor);
+ gUnicastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ return CA_STATUS_FAILED;
+ }
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+
+ // Set Unicast Socket Descriptor in cawificlient
+ CASetUnicastSocketDescriptor(gUnicastServerSocketDescriptor);
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "thread_pool_add_task done");
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "Unicast Server Started Successfully");
+
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartMulticastServer(const char *mcastAddress, const char *localAddress,
+ int16_t *port)
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+
+ if (gMulticastServerSocketDescriptor != -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Multicast Server is Started Already! Return Code[%d]",
+ CA_SERVER_STARTED_ALREADY);
+ return CA_SERVER_STARTED_ALREADY;
+ }
+
+ VERIFY_NON_NULL(mcastAddress, WIFI_SERVER_TAG, "Invalid argument : mcastAddress is NULL");
+ VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "Invalid argument : localAddress is NULL");
+ VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "Invalid argument : port is NULL");
+
+ // Create a datagram socket on which to recv/send.
+ struct sockaddr_in sockAddr;
+ int16_t result = 0;
+ int16_t i = 0;
+ int16_t status = 0;
+
+ int setOptionOn = 1;
+ u_mutex_lock(gMutexStopMulticast);
+ gStopMulticast = false;
+ u_mutex_unlock(gMutexStopMulticast);
+
+ u_mutex_lock(gMutexMulticastServerSocketDescriptor);
+
+ // create a UDP socket
+ if ((gMulticastServerSocketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to Create Socket, Error code: %s", strerror(errno));
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ // Make the socket non-blocking
+ if ((status = fcntl(gMulticastServerSocketDescriptor, F_SETFL, O_NONBLOCK)) < 0)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "fcntl to make the socket non-blocking failed, Error code: %s",
+ strerror(errno));
+ close(gMulticastServerSocketDescriptor);
+ gMulticastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "socket creation success");
+
+ if ((result = setsockopt(gMulticastServerSocketDescriptor, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &setOptionOn,
+ sizeof(setOptionOn))) < 0)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to setsockopt for SO_REUSEADDR, Error code: %s",
+ strerror(errno));
+ close(gMulticastServerSocketDescriptor);
+ gMulticastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ // zero out the structure
+ memset((char *) &sockAddr, 0, sizeof(sockAddr));
+
+ sockAddr.sin_family = AF_INET;
+ sockAddr.sin_port = htons(*port);
+ // TODO: Assign the Particular Address on Multiple Interfaces
+ sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ // Trying for bind in a loop
+ for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
+ {
+ // bind socket to multicast port
+ if (bind(gMulticastServerSocketDescriptor, (struct sockaddr *) &sockAddr, sizeof(sockAddr)) == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]. Trying again...", strerror(errno));
+ continue;
+ }
+ result = 1;
+ break;
+ }
+ if (!result)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to Bind Socket! Return Code[%d]",
+ CA_SOCKET_OPERATION_FAILED);
+ close(gMulticastServerSocketDescriptor);
+ gMulticastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "socket bind success");
+
+ socklen_t len = sizeof(sockAddr);
+
+ if (getsockname(gMulticastServerSocketDescriptor, (struct sockaddr *)&sockAddr, &len) == -1)
+ {
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "getsockname failed, Error code: %s", strerror(errno));
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "port number %d\n", ntohs(sockAddr.sin_port));
+ *port = ntohs(sockAddr.sin_port);
+ }
+
+ // add membership to receiving socket (join group)
+ memset(&gMReq, 0, sizeof(struct ip_mreq));
+ gMReq.imr_interface.s_addr = htonl(INADDR_ANY);
+ inet_aton(mcastAddress, &gMReq.imr_multiaddr);
+
+ if ((result = setsockopt(gMulticastServerSocketDescriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *) &gMReq,
+ sizeof(struct ip_mreq))) < 0)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "setsockopt API for IP_ADD_MEMBERSHIP failed, Error code: %s\n",
+ strerror(errno));
+ close(gMulticastServerSocketDescriptor);
+ gMulticastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ /**
+ * The task to listen to data from multicastcast socket is added to the thread pool.
+ * This is a blocking call is made where we try to receive some data.. We will keep waiting until some data is received.
+ * This task will be terminated when thread pool is freed on stopping the adapters.
+ */
+ if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CAReceiveThreadForMulticast,
+ (void *)NULL))
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "[testThreadPool] thread_pool_add_task failed!");
+
+ close(gMulticastServerSocketDescriptor);
+ gMulticastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ return CA_STATUS_FAILED;
+ }
+
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "thread_pool_add_task done");
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "Multicast Server Started Successfully");
+
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStopUnicastServer()
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+ u_mutex_lock(gMutexUnicastServerSocketDescriptor);
+
+ if (gUnicastServerSocketDescriptor == -1)
+ {
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "Unicast Server is not yet Started");
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ return CA_SERVER_NOT_STARTED;
+ }
+ u_mutex_lock(gMutexStopUnicast);
+ gStopUnicast = true;
+
+ // close the socket
+ int16_t ret = close(gUnicastServerSocketDescriptor);
+
+ if (ret == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server socket close failed, Error code: %s\n",
+ strerror(errno));
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+ u_mutex_unlock(gMutexStopUnicast);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ u_mutex_unlock(gMutexStopUnicast);
+ gUnicastServerSocketDescriptor = -1;
+ // UnSet Unicast Socket Descriptor in cawificlient
+ CASetUnicastSocketDescriptor(gUnicastServerSocketDescriptor);
+ u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "Unicast Server Stopped Successfully");
+
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStopMulticastServer()
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+
+ u_mutex_lock(gMutexMulticastServerSocketDescriptor);
+
+ if (gMulticastServerSocketDescriptor == -1)
+ {
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "Multicast Server is not yet Started");
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ return CA_SERVER_NOT_STARTED;
+ }
+
+ u_mutex_lock(gMutexStopMulticast);
+ gStopMulticast = true;
+
+ // leave the group after you are done
+ int16_t result = setsockopt(gMulticastServerSocketDescriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (char *)&gMReq,
+ sizeof(struct ip_mreq));
+ if (result < 0)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "cannot leave multicast group, Error code: %s\n",
+ strerror(errno));
+ }
+
+ // close the socket
+ result = close(gMulticastServerSocketDescriptor);
+ if (result == -1)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Multicast Server socket close failed, Error code: %s\n",
+ strerror(errno));
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+ u_mutex_unlock(gMutexStopMulticast);
+ return CA_SOCKET_OPERATION_FAILED;
+ }
+
+ u_mutex_unlock(gMutexStopMulticast);
+
+ gMulticastServerSocketDescriptor = -1;
+ u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
+
+ OIC_LOG(INFO, WIFI_SERVER_TAG, "Multicast Server Stopped Successfully");
+
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void *CAReceiveThreadForUnicast(void *data)
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+ if (NULL == gServerRecvQueueHandle)
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "QueueHandle is not Initialized");
+ return NULL;
+ }
+
+ char *buf = (char *) OICMalloc (CA_BUFFER_LEN);
+ if (NULL == buf)
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "Memory Allocation failed");
+ return NULL;
+ }
+ uint32_t recvLen;
+ int32_t ret = 0;
+ struct sockaddr_in siOther;
+ socklen_t sLen = sizeof(siOther);
+ fd_set reads;
+ struct timeval timeout;
+ CARemoteEndpoint_t *endPointUnicast = (CARemoteEndpoint_t *) OICMalloc (sizeof(CARemoteEndpoint_t));
+ if (NULL == endPointUnicast)
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "Memory Allocation failed");
+ return NULL;
+ }
+ memset (endPointUnicast, 0, sizeof(CARemoteEndpoint_t));
+
+
+
+ // keep listening for data
+ while (!gStopUnicast)
+ {
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "Waiting for data..");
+
+ memset(buf, 0, sizeof(char) * CA_BUFFER_LEN);
+
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&reads);
+ // Use select for polling the socket fd
+ FD_SET(gUnicastServerSocketDescriptor, &reads);
+
+ ret = select(gUnicastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
+ if ( ret < 0)
+ {
+ OIC_LOG_V(FATAL, WIFI_SERVER_TAG, "select API failed");
+ continue;
+ }
+ if (!FD_ISSET(gUnicastServerSocketDescriptor, &reads))
+ {
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "No data to read");
+ continue;
+ }
+
+
+ // try to receive some data
+ if ((recvLen = recvfrom(gUnicastServerSocketDescriptor, buf, CA_BUFFER_LEN, 0,
+ (struct sockaddr *) &siOther, &sLen)) == -1)
+ {
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "%s\n", strerror(errno));
+ continue;
+ }
+ else if (0 == recvLen)
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "Unicast socket is shutdown, returning from thread\n");
+ return (void *) NULL;
+ }
+
+ // print details of the client/peer and the data received
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Received packet from %s:%d\n", inet_ntoa(siOther.sin_addr),
+ ntohs(siOther.sin_port));
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Data: %s, DataLength: %d\n", buf, sizeof(buf));
+
+ endPointUnicast->resourceUri = NULL; // will be filled by upper layer
+ strncpy((char *)endPointUnicast->addressInfo.IP.ipAddress, inet_ntoa(siOther.sin_addr),
+ CA_IPADDR_SIZE);
+ endPointUnicast->addressInfo.IP.port = ntohs(siOther.sin_port);
+ endPointUnicast->connectivityType = CA_WIFI;
+
+ // Enqueue the Received Message in the Queue
+#if 0 /* Skip Queue */
+ CAAdapterEnqueueMessage(gServerRecvQueueHandle, &endPointUnicast, buf, recvLen);
+#else
+ if (gNetworkPacketCallback)
+ {
+ gNetworkPacketCallback(endPointUnicast, buf, recvLen);
+ }
+#endif //#if 0
+ }
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "stopUnicastServer is called, Breaking from while loop\n");
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+ return (void *) NULL;
+}
+
+void *CAReceiveThreadForMulticast(void *data)
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+
+ if (NULL == gServerRecvQueueHandle)
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "QueueHandle is not Initialized");
+ return NULL;
+ }
+
+ char *buf = (char *) OICMalloc (CA_BUFFER_LEN);
+ if (NULL == buf)
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "Memory Allocation failed");
+ return NULL;
+ }
+ int recvLen;
+ struct sockaddr_in siOther;
+ int32_t ret = 0;
+ socklen_t sLen = sizeof(siOther);
+ fd_set reads;
+ struct timeval timeout;
+ CARemoteEndpoint_t *endPointMulticast = (CARemoteEndpoint_t *) OICMalloc (sizeof(
+ CARemoteEndpoint_t));
+ if (NULL == endPointMulticast)
+ {
+ OIC_LOG(ERROR, WIFI_SERVER_TAG, "Memory Allocation failed");
+ return NULL;
+ }
+ memset (endPointMulticast, 0, sizeof(CARemoteEndpoint_t));
+
+
+ // keep listening for data
+ while (!gStopMulticast)
+ {
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "Waiting for data...\n");
+
+ memset(buf, 0, sizeof(char) * CA_BUFFER_LEN);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ FD_ZERO(&reads);
+ // Use select for polling the socket fd
+ FD_SET(gMulticastServerSocketDescriptor, &reads);
+
+ ret = select(gMulticastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
+ if ( ret < 0)
+ {
+ OIC_LOG_V(FATAL, WIFI_SERVER_TAG, "select API failed");
+ continue;
+ }
+ if (!FD_ISSET(gMulticastServerSocketDescriptor, &reads))
+ {
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "No data to read");
+ continue;
+ }
+
+ // try to receive some data
+ if ((recvLen = recvfrom(gMulticastServerSocketDescriptor, buf, CA_BUFFER_LEN, 0,
+ (struct sockaddr *) &siOther, &sLen)) == -1)
+ {
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "%s\n", strerror(errno));
+ continue;
+ }
+ else if (0 == recvLen)
+ {
+ OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Multicast socket is shutdown, returning from thread\n");
+ return (void *) NULL;
+ }
+
+ // print details of the client/peer and the data received
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Received packet from %s:%d\n",
+ inet_ntoa(siOther.sin_addr), ntohs(siOther.sin_port));
+ OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Data: %s\t, DataLength: %d\n", buf, recvLen);
+
+ endPointMulticast->resourceUri = NULL; // will be filled by upper layer
+ strncpy((char *)endPointMulticast->addressInfo.IP.ipAddress, inet_ntoa(siOther.sin_addr),
+ strlen(inet_ntoa(siOther.sin_addr)));
+ endPointMulticast->addressInfo.IP.port = ntohs(siOther.sin_port);
+ endPointMulticast->connectivityType = CA_WIFI;
+
+#if 0 /* Skip Queue */
+ // Enqueue the Received Message in the Queue
+ CAAdapterEnqueueMessage(gServerRecvQueueHandle, &endPointMulticast, buf, recvLen);
+#else
+ if (gNetworkPacketCallback)
+ {
+ gNetworkPacketCallback(endPointMulticast, buf, recvLen);
+ }
+#endif //#if 0
+ }
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "stopMulticastServer is called, Breaking from while loop\n");
+
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
+ return (void *) NULL;
+}
+
+/* Skip Queue */
+void CASetWIFINetworkPacketCallback(CANetworkPacketReceivedCallback callback)
+{
+ OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
+ gNetworkPacketCallback = callback;
+ OIC_LOG(DEBUG, WIFI_SERVER_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.
+*
+******************************************************************/
+
+/**
+ * @file cawifiserver.h
+ * @brief This file contains the APIs for WiFi Server module
+ */
+
+#ifndef _CA_WIFI_SERVER_H_
+#define _CA_WIFI_SERVER_H_
+
+#include "caadapterinterface.h"
+#include "logger.h"
+#include "uthreadpool.h"
+#include "camessagequeue.h"
+
+/**
+ * @brief API to Initialize Server Mutex
+ * @return - None
+ */
+void CAInitializeServerMutex();
+
+/**
+ * @brief API to Set the Receive queue handle
+ * @param recvQueueHandle [IN] Queue Handle to Receive Data
+ * @return - None
+ */
+void CASetRecvQueueHandle(CAAdapterMessageQueue_t *recvQueueHandle);
+
+/**
+ * @brief API to Get thread pool handle initialized in interface sample.
+ * @return - None
+ */
+void CASetThreadHandle(u_thread_pool_t gThreadPool);
+
+/**
+ * @brief API to start unicast server.
+ * @param localAddress - Local Unicast IP address to bind the socket.
+ * @param port - Local port number where socket will listen for incoming request.
+ * @return - Error Code
+ */
+CAResult_t CAStartUnicastServer(const char *localAddress, int16_t *port);
+
+/**
+ * @brief API to start multicast server.
+ * @param mcastAddress - IP address to join multicast group.
+ * @param localAddress - Local Unicast IP address to bind the socket.
+ * @param port - multicast port number where socket will listen for incoming request.
+ * @return - Error Code
+ */
+CAResult_t CAStartMulticastServer(const char *mcastAddress, const char *localAddress,
+ int16_t *port);
+
+/**
+ * @brief API to stop unicast server.
+ * @return - Error Code
+ */
+CAResult_t CAStopUnicastServer();
+
+/**
+ * @brief API to stop multicast server.
+ * @return - Error Code
+ */
+CAResult_t CAStopMulticastServer();
+
+/**
+ * @brief API to receive the data in unicast server socket thread.
+ * @param data - data received in server from lower layer.
+ * @return - NULL
+ */
+void *CAReceiveThreadForUnicast(void *data);
+
+/**
+ * @brief API to receive the data in multicast server socket thread.
+ * @param data - data received in server from lower layer.
+ * @return - NULL
+ */
+void *CAReceiveThreadForMulticast(void *data);
+/* Skip Queue */
+/**
+ * @brief API to set request response callback to upper layer.
+ * @param RequestResponseCallback - upper layer callback function to pass the data received in the server.
+ * @return - Error Code
+ */
+void CASetWIFINetworkPacketCallback(CANetworkPacketReceivedCallback callback);
+
+#endif // #ifndef _CA_WIFI_SERVER_H_
using namespace std;
-void request_handler(CARemoteEndpoint* object, CARequestInfo* requestInfo);
-void response_handler(CARemoteEndpoint* object, CAResponseInfo* responseInfo);
+void request_handler(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo);
+void response_handler(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo);
-void request_handler(CARemoteEndpoint* object, CARequestInfo* requestInfo)
+void request_handler(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo)
{
cout << "request_handler, uri : " << (object != NULL) ? object->resourceUri : "";
cout << ", data : " << (requestInfo != NULL) ? requestInfo->info.payload : "";
cout << endl;
}
-void response_handler(CARemoteEndpoint* object, CAResponseInfo* responseInfo)
+void response_handler(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo)
{
cout << "response_handler, uri : " << (object != NULL) ? object->resourceUri : "";
cout << ", data : " << (responseInfo != NULL) ? responseInfo->info.payload : "";
}
char* uri;
-CARemoteEndpoint* tempRep = NULL;
-CARequestInfo requestInfo;
-CAInfo responseData;
-CAResponseInfo responseInfo;
-CAToken tempToken;
+CARemoteEndpoint_t* tempRep = NULL;
+CARequestInfo_t requestInfo;
+CAInfo_t responseData;
+CAResponseInfo_t responseInfo;
+CAToken_t tempToken;
int main(int argc, char **argv)
{
// check return value
TEST(CreateRemoteEndpointTest, TC_06_Positive_01)
{
- uri = (char *) "referenceUri";
+ uri = (char *) "123.123.123.123:1234/b/light";
EXPECT_EQ(CA_STATUS_OK, CACreateRemoteEndpoint(uri, &tempRep));
// check remoteEndpoint and values of remoteEndpoint
TEST(CreateRemoteEndpointTest, TC_07_Positive_02)
{
- uri = (char *) "referenceUri";
+ uri = (char *) "123.123.123.123:1234/b/light";
CACreateRemoteEndpoint(uri, &tempRep);
EXPECT_TRUE(tempRep != NULL);
// check destroyed remoteEndpoint
TEST(DestroyRemoteEndpointTest, TC_10_Positive_01)
{
- uri = (char *) "referenceUri";
+ uri = (char *) "123.123.123.123:1234/b/light";
CACreateRemoteEndpoint(uri, &tempRep);
CADestroyRemoteEndpoint(tempRep);
TEST(FindResourceTest, TC_13_Positive_01)
{
CARegisterHandler(request_handler, response_handler);
- uri = (char *) "referenceUri";
+ uri = (char *) "123.123.123.123:1234/b/light";
EXPECT_EQ(CA_STATUS_OK, CAFindResource(uri));
}
{
CARegisterHandler(request_handler, response_handler);
uri = NULL;
- EXPECT_EQ(CA_SEND_FAILED, CAFindResource(uri));
+ EXPECT_EQ(CA_STATUS_FAILED, CAFindResource(uri));
}
// CASendRequest TC
// check return value
TEST(SendRequestTest, TC_15_Positive_01)
{
- uri = (char *) "referenceUri";
- memset(&requestInfo, 0, sizeof(CARequestInfo));
+ uri = (char *) "123.123.123.123:1234/b/light";
+ memset(&requestInfo, 0, sizeof(CARequestInfo_t));
CACreateRemoteEndpoint(uri, &tempRep);
CAGenerateToken(&tempToken);
requestInfo.method = CA_GET;
TEST(SendRequestTest, TC_16_Nagative_01)
{
uri = NULL;
- memset(&requestInfo, 0, sizeof(CARequestInfo));
+ memset(&requestInfo, 0, sizeof(CARequestInfo_t));
CACreateRemoteEndpoint(uri, &tempRep);
CAGenerateToken(&tempToken);
requestInfo.method = CA_GET;
requestInfo.info.token = tempToken;
requestInfo.info.payload = (char *) "request payload";
- EXPECT_EQ(CA_SEND_FAILED, CASendRequest(tempRep, &requestInfo));
+ EXPECT_EQ(CA_STATUS_FAILED, CASendRequest(tempRep, &requestInfo));
CADestroyToken(tempToken);
CADestroyRemoteEndpoint(tempRep);
// check return value
TEST(SendResponseTest, TC_17_Positive_01)
{
- uri = (char *) "referenceUri";
+ uri = (char *) "123.123.123.123:1234/b/light";
CACreateRemoteEndpoint(uri, &tempRep);
- memset(&responseData, 0, sizeof(CAInfo));
+ memset(&responseData, 0, sizeof(CAInfo_t));
CAGenerateToken(&tempToken);
responseData.token = tempToken;
responseData.payload = (char *) "response payload";
- memset(&responseInfo, 0, sizeof(CAResponseInfo));
- responseInfo.result = CA_SUCCESS;
+ memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
+ responseInfo.result = CA_VALID;
responseInfo.info = responseData;
EXPECT_EQ(CA_STATUS_OK, CASendResponse(tempRep, &responseInfo));
uri = NULL;
CACreateRemoteEndpoint(uri, &tempRep);
- memset(&responseData, 0, sizeof(CAInfo));
+ memset(&responseData, 0, sizeof(CAInfo_t));
CAGenerateToken(&tempToken);
responseData.token = tempToken;
responseData.payload = (char *) "response payload";
- memset(&responseInfo, 0, sizeof(CAResponseInfo));
- responseInfo.result = CA_SUCCESS;
+ memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
+ responseInfo.result = CA_VALID;
responseInfo.info = responseData;
- EXPECT_EQ(CA_SEND_FAILED, CASendResponse(tempRep, &responseInfo));
+ EXPECT_EQ(CA_STATUS_FAILED, CASendResponse(tempRep, &responseInfo));
CADestroyToken(tempToken);
CADestroyRemoteEndpoint(tempRep);
// check return value
TEST(SendNotificationTest, TC_19_Positive_01)
{
- uri = (char *) "referenceUri";
+ uri = (char *) "123.123.123.123:1234/b/light";
CACreateRemoteEndpoint(uri, &tempRep);
- memset(&responseData, 0, sizeof(CAInfo));
- CAGenerateToken(&tempToken);
- responseData.token = tempToken;
- responseData.payload = (char *) "response payload";
+ memset(&responseData, 0, sizeof(CAInfo_t));
+ responseData.token = (char *) "client token";
+ responseData.payload = (char *) "Temp Notification Data";
- memset(&responseInfo, 0, sizeof(CAResponseInfo));
- responseInfo.result = CA_SUCCESS;
+ memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
+ responseInfo.result = CA_CONTENT;
responseInfo.info = responseData;
- EXPECT_EQ(CA_NOT_SUPPORTED, CASendNotification(tempRep, &responseInfo));
+ EXPECT_EQ(CA_STATUS_OK, CASendNotification(tempRep, &responseInfo));
- CADestroyToken(tempToken);
CADestroyRemoteEndpoint(tempRep);
}
uri = NULL;
CACreateRemoteEndpoint(uri, &tempRep);
- memset(&responseData, 0, sizeof(CAInfo));
- CAGenerateToken(&tempToken);
- responseData.token = tempToken;
- responseData.payload = (char *) "response payload";
+ memset(&responseData, 0, sizeof(CAInfo_t));
+ responseData.token = (char *) "client token";
+ responseData.payload = (char *) "Temp Notification Data";
- memset(&responseInfo, 0, sizeof(CAResponseInfo));
- responseInfo.result = CA_SUCCESS;
+ memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
+ responseInfo.result = CA_CONTENT;
responseInfo.info = responseData;
- EXPECT_EQ(CA_NOT_SUPPORTED, CASendNotification(tempRep, &responseInfo));
+ EXPECT_EQ(CA_STATUS_FAILED, CASendNotification(tempRep, &responseInfo));
- CADestroyToken(tempToken);
CADestroyRemoteEndpoint(tempRep);
}
// check return value
TEST(AdvertiseResourceTest, TC_21_Positive_01)
{
- CAURI uri = (char *) "resourceUri";
- CAHeaderOption* options = NULL;
- uint8_t numOptions = 0;
-
- EXPECT_EQ(CA_NOT_SUPPORTED, CAAdvertiseResource(uri, options, numOptions));
+ uri = (char *) "123.123.123.123:1234/b/light";
+ int optionNum = 1;
+ char* optionData;
+ CAHeaderOption_t* headerOpt;
+ headerOpt = (CAHeaderOption_t*) malloc(sizeof(CAHeaderOption_t) * optionNum);
+ memset(headerOpt, 0, sizeof(CAHeaderOption_t) * optionNum);
+
+ int i;
+ for(i = 0 ; i < optionNum ; i++)
+ {
+ int optionID = 2;
+ headerOpt[i].optionID = optionID;
+ optionData = (char *) "aaa";
+ memcpy(headerOpt[i].optionData, optionData, strlen(optionData));
+ headerOpt[i].optionLength = (uint16_t)strlen(optionData);
+ }
+ EXPECT_EQ(CA_STATUS_OK, CAAdvertiseResource(uri, headerOpt, (uint8_t)optionNum));
}
-// check return value if token is NULL
+// check return value if uri is NULL
TEST(AdvertiseResourceTest, TC_22_Nagative_01)
{
- CAURI uri = NULL;
- CAHeaderOption* options = NULL;
- uint8_t numOptions = 0;
-
- EXPECT_EQ(CA_NOT_SUPPORTED, CAAdvertiseResource(uri, options, numOptions));
+ uri = NULL;
+ int optionNum = 1;
+ char* optionData;
+ CAHeaderOption_t* headerOpt;
+ headerOpt = (CAHeaderOption_t*) malloc(sizeof(CAHeaderOption_t) * optionNum);
+ memset(headerOpt, 0, sizeof(CAHeaderOption_t) * optionNum);
+
+ int i;
+ for(i = 0 ; i < optionNum ; i++)
+ {
+ int optionID = 2;
+ headerOpt[i].optionID = optionID;
+ optionData = (char *) "aaa";
+ memcpy(headerOpt[i].optionData, optionData, strlen(optionData));
+ headerOpt[i].optionLength = (uint16_t)strlen(optionData);
+ }
+ EXPECT_EQ(CA_STATUS_FAILED, CAAdvertiseResource(uri, headerOpt, (uint8_t)optionNum));
}
// CASelectNewwork TC
EXPECT_EQ(CA_NOT_SUPPORTED, CAUnSelectNetwork(20));
}
-// CAGetNetworkInfomation TC
-// check return value
-TEST (GetNetworkInfomation, TC_27_Positive_01)
-{
- CALocalConnectivity* info = NULL;
- uint32_t* size = NULL;
-
- EXPECT_EQ(CA_NOT_SUPPORTED, CAGetNetworkInformation(&info, size));
-}
-
// CAHandlerRequestResponse TC
// check return value
-TEST (HandlerRequestResponseTest, TC_28_Positive_01)
+TEST (HandlerRequestResponseTest, TC_27_Positive_01)
{
EXPECT_EQ(CA_STATUS_OK, CAHandleRequestResponse());
}
+
+
--- /dev/null
+TCT Unit tests for Tizen:
+==========================
+1. TCT tool should be setup in linux to execute these test cases. Please refer to "CoreAPI Test Manual.pptx" present in this folder.
+2. OIC-Core and InterfaceAPIs should be built first.
+3. Copy liboic to <TCT Directory>/core-api/src.
+4. Copy packaging/core-liboic-tests.spec to <TCT Directory>/packaging.
+5. Build oic test case project with "tctbuild build liboic".
+6. Install test framework to device with "tctbuild install liboic".
+7. Run tct tool with "tct-mgr".
\ No newline at end of file
--- /dev/null
+SET(PKG_NAME "liboic")
+
+SET(EXEC_NAME "tct-${PKG_NAME}-core")
+SET(RPM_NAME "core-${PKG_NAME}-tests")
+
+SET(CAPI_LIB "liboic")
+SET(TC_SOURCES
+ #utc-liboic.c
+ wifi/utc-wifi-liboic.c
+ #bt/utc-bt-liboic.c
+)
+
+#PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
+# ${CAPI_LIB}
+#)
+PKG_CHECK_MODULES(pkgs REQUIRED
+ capi-network-bluetooth capi-network-wifi com.samsung.oicca dlog
+)
+
+INCLUDE_DIRECTORIES(
+ ${${CAPI_LIB}_INCLUDE_DIRS}
+)
+ADD_DEFINITIONS("-D__TIZEN__")
+ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.c ${TC_SOURCES})
+TARGET_LINK_LIBRARIES(${EXEC_NAME}
+ ${${CAPI_LIB}_LIBRARIES} /usr/lib/liboicinterface.a -lm -lpthread -lrt -ldl -lcapi-network-wifi -lcapi-network-bluetooth -ldlog
+)
+
+INSTALL(PROGRAMS ${EXEC_NAME}
+ DESTINATION ${BIN_DIR}/${EXEC_NAME}
+)
--- /dev/null
+//#include <glib.h>
+#include "assert.h"
+#include "interfaceHeaders/cacommon.h"
+#include "interfaceHeaders/caadapterinterface.h"
+#include "interfaceHeaders/caedradapter.h"
+
+//& set: Liboic
+
+//Bt callbacks
+
+CALocalConnectivity_t* localBtEndpoint = NULL;
+CARemoteEndpoint_t remoteMulticastEndpoint;
+CARemoteEndpoint_t remoteEndpoint[10]; /* 10 RemoteEndpoints are currently kept */
+char remoteIPAddress[CA_IPADDR_SIZE] = "192.168.1.8"; //Change the Corresponding IP address during testing.
+char localIPAddress[CA_IPADDR_SIZE] = {0};
+int localPort = -1;
+int32_t serverId;
+// Global bt Addr. Change this before testing.
+char btAddr[CA_MACADDR_SIZE] = "BC:79:AD:E6:BC:F6";
+char* serviceUUID = "12341234-1C25-481F-9DFB-59193D238280";
+//static GMainLoop *mainloop;
+//int gMainloopStatus = 0;
+
+//Hardcoded values to Test
+
+char coapData[500] = "{\"oc:\[{href\":\"/a/light\",\"ref\":{\"power\":\"20\",\"state\":\"true\"}}\]}";
+
+typedef struct ConnectivityHandlerList {
+ CAConnectivityType_t type;
+ CAConnectivityHandler_t handler;
+ struct ConnectivityHandlerList* nextHandler;
+} ConnectivityHandlerList;
+
+CAConnectivityHandler_t* gConnectivityHandlers = NULL;
+
+void storeInterfaceCallbacks(CAConnectivityHandler_t* newHandler)
+{
+ printf("\nstoreInterfaceCallbacks Entry in Sample");
+ #if 0
+ newHandler->nextHandler = NULL;
+
+ CAConnectivityHandler* tempCAConnectivityHandlers = gCAConnectivityHandlers;
+
+ if (!tempCAConnectivityHandlers) {
+ gCAConnectivityHandlers = newHandler;
+ return;
+ }
+ while (tempCAConnectivityHandlers->nextHandler) {
+ tempCAConnectivityHandlers = tempCAConnectivityHandlers->nextHandler;
+ }
+
+ tempCAConnectivityHandlers->nextHandler = newHandler;
+ #endif
+ printf("\nstoreInterfaceCallbacks Exit in Sample");
+}
+
+void interfaceRegisterCallback(CAConnectivityHandler_t handler,
+ CAConnectivityType_t connType)
+{
+ printf("interfaceRegisterCallback Entry in Sample\n");
+ ConnectivityHandlerList* newConnectivityHandler = (ConnectivityHandlerList*) malloc(sizeof(ConnectivityHandlerList));
+ if (NULL == newConnectivityHandler)
+ {
+ printf("Memory allocation failed!\n");
+ return;
+ }
+
+ newConnectivityHandler->type = connType;
+ newConnectivityHandler->handler = handler;
+ storeInterfaceCallbacks(newConnectivityHandler);
+ printf("interfaceRegisterCallback Exit in Sample\n");
+}
+
+void requestResponseHandler(CARemoteEndpoint_t* object, void* data)
+{
+ printf("\nrequestResponseHandler Entry in Sample");
+ if (object == NULL || data == NULL) {
+ printf("\nNULL Object");
+ return;
+ }
+
+ if (object->addressInfo.BT.btMacAddress)
+ printf("\nData Received from %s\n", object->addressInfo.BT.btMacAddress);
+ if (data)
+ printf("\nReceived Data : %s \n", (char*)data);
+ /*
+ gMainloopStatus = 1;
+ if (mainloop)
+ {
+ g_main_loop_quit(mainloop);
+ mainloop = NULL;
+ }
+ */
+ printf("\nrequestResponseHandler Exit in Sample");
+}
+
+
+void networkInterfaceCallback(CALocalConnectivity_t* localEndPoint, CANetworkStatus_t networkConnectivityState)
+{
+ printf("\nnetworkInterfaceCallback Entry in Sample");
+ if (localEndPoint == NULL) {
+ printf("\nNULL Object");
+ return;
+ }
+
+ if (localEndPoint->addressInfo.BT.btMacAddress)
+ printf("\n Interface Address%s\n", localEndPoint->addressInfo.BT.btMacAddress);
+
+ if (networkConnectivityState == CA_INTERFACE_UP)
+ printf("\n BT Status is UP");
+ else
+ printf("\n BT Status is DOWN");
+ printf("\nnetworkInterfaceCallback Exit in Sample");
+}
+
+void utc_liboic_startup(void)
+{
+
+}
+
+void utc_liboic_cleanup(void)
+{
+
+}
+
+
+int bt_tc_001_intializeBT_p(void)
+{
+ CAResult_t error = CA_STATUS_FAILED;
+ error = CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ assert_eq(error, CA_STATUS_OK);
+ CATerminateEDR();
+ return 0;
+}
+
+int bt_tc_002_intializeBT_n(void)
+{
+ CAResult_t error = CA_STATUS_FAILED;
+ error = CAInitializeEDR(NULL, NULL, NULL);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ return 0;
+}
+
+int bt_tc_003_getBTInterfaceInformation_p(void)
+{
+ CAResult_t error = CA_STATUS_FAILED;
+ //Startup
+ CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+
+ error = CAGetEDRInterfaceInformation(&localBtEndpoint,&size);
+ assert_eq(error, CA_STATUS_OK);
+
+ CATerminateEDR();
+ // Now, check local endpoint information
+ //assert_neq(localBtEndpoint->endpoint_info, NULL);
+ //assert_neq(localBtEndpoint->endpoint_info->address, NULL);
+ return 0;
+}
+
+int bt_tc_004_getBTInterfaceInformation_n(void)
+{
+ CAResult_t error = CA_STATUS_FAILED;
+ error = CAGetEDRInterfaceInformation(NULL,NULL);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ return 0;
+}
+
+int bt_tc_005_startAdapter_p(void)
+{
+ CAResult_t error = CA_STATUS_FAILED;
+ CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ error = CAStartEDR();
+ assert_eq(error, CA_STATUS_OK);
+ CAStopEDR();
+ CATerminateEDR();
+ return 0;
+}
+
+int bt_tc_006_sendBTUnicastData_p(void)
+{
+ int dataSize = 0;
+ int ret = -1;
+ int ref = 0;
+
+ //Startup
+ CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ CAStartEDR();
+ CAStartEDRListeningServer();
+
+ CARemoteEndpoint_t endpoint;
+ endpoint.connectivityType = CA_EDR;
+ strncpy(endpoint.addressInfo.BT.btMacAddress, btAddr, CA_MACADDR_SIZE-1);
+ endpoint.addressInfo.BT.btMacAddress[CA_MACADDR_SIZE-1] = '\0';
+ endpoint.resourceUri = NULL;
+ ret = CASendEDRUnicastData(&endpoint, coapData, strlen(coapData) + 1);
+ sleep(5);
+
+ //Cleanup
+ CAStopEDR();
+ CATerminateEDR();
+
+ assert_eq(ret, strlen(coapData) + 1);
+ return 0;
+}
+
+int bt_tc_007_sendBTUnicastData_n(void)
+{
+ int dataSize = 0;
+ int ret = -1;
+ CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ ret = CASendEDRUnicastData(NULL, NULL, NULL);
+ CATerminateEDR();
+ assert_eq(ret, 0);
+ return 0;
+}
+
+int bt_tc_008_sendBTMulticastDataToAll_p(void)
+{
+ int dataSize = 0;
+ int ret = 0;
+ CAStartEDRListeningServer();
+ ret = CASendEDRMulticastData(coapData, strlen(coapData) + 1);
+ assert_eq(ret, strlen(coapData) + 1);
+ CAStopEDR();
+ CATerminateEDR();
+ return 0;
+}
+
+int bt_tc_009_sendBTMulticastDataToAll_n(void)
+{
+ int dataSize = 0;
+ int ret = -1;
+ CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ ret = CASendEDRMulticastData(NULL, NULL);
+ CATerminateEDR();
+ assert_eq(ret, 0);
+ return 0;
+}
+
+int bt_tc_010_StartListeningServer_p(void)
+{
+ CAResult_t error = CA_STATUS_FAILED;
+ int ref = 0;
+ //Startup
+ CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+
+ error = CAStartEDRListeningServer();
+ assert_eq(error, CA_STATUS_OK);
+ //Cleanup
+ CAStopEDR();
+ CATerminateEDR();
+ return 0;
+}
+
+int bt_tc_011_StopRfCommServer_p(void)
+{
+ CAResult_t error = CA_STATUS_FAILED;
+ int ref = 0;
+ //Startup
+ CAInitializeEDR(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ CAStartEDRListeningServer();
+
+ error = CAStopEDR();
+ assert_eq(error, CA_STATUS_OK);
+ //Cleanup
+ CATerminateEDR();
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "tct-liboic-core.h"
+
+int main(int argc, const char* argv[])
+{
+ int result = -1;
+ int i;
+
+ if (argc != 2) {
+ printf("Usage: %s <testcase name>\n", argv[0]);
+ return 2;
+ }
+
+ for (i = 0; tc_array[i].name; i++) {
+ if (!strcmp(argv[1], tc_array[i].name)) {
+ if (tc_array[i].startup)
+ tc_array[i].startup();
+
+ result = tc_array[i].function();
+
+ if (tc_array[i].cleanup)
+ tc_array[i].cleanup();
+
+ return result;
+ }
+ }
+
+ printf("Unknown testcase name: \"%s\"\n", argv[1]);
+ return 2;
+}
--- /dev/null
+#ifndef __TCT_LIBOIC_CORE_H__
+#define __TCT_LIBOIC_CORE_H__
+
+#include "testcase.h"
+
+extern void utc_liboic_startup(void);
+extern void utc_liboic_cleanup(void);
+
+extern int wifi_tc_001_initializeWifi_p(void);
+extern int wifi_tc_002_initializeWifi_n(void);
+extern int wifi_tc_003_getWIFIInterfaceInformation_p(void);
+extern int wifi_tc_004_getWIFIInterfaceInformation_n(void);
+extern int wifi_tc_005_sendWifiUnicastData_p(void);
+extern int wifi_tc_006_sendWifiUnicastData_n(void);
+extern int wifi_tc_007_sendWifiMulticastData_p(void);
+extern int wifi_tc_008_sendWifiMulticastData_n(void);
+extern int wifi_tc_009_startWifiServers_p(void);
+extern int wifi_tc_010_startWifiServers_n(void);
+extern int wifi_tc_011_stopWifiServers_p(void);
+
+testcase tc_array[] = {
+ {"wifi_tc_001_initializeWifi_p", wifi_tc_001_initializeWifi_p, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_002_initializeWifi_n", wifi_tc_002_initializeWifi_n, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_003_getWIFIInterfaceInformation_p", wifi_tc_003_getWIFIInterfaceInformation_p, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_004_getWIFIInterfaceInformation_n", wifi_tc_004_getWIFIInterfaceInformation_n, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_005_sendWifiUnicastData_p", wifi_tc_005_sendWifiUnicastData_p, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_006_sendWifiUnicastData_n", wifi_tc_006_sendWifiUnicastData_n, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_007_sendWifiMulticastData_p", wifi_tc_007_sendWifiMulticastData_p, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_008_sendWifiMulticastData_n", wifi_tc_008_sendWifiMulticastData_n, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_009_startWifiServers_p", wifi_tc_009_startWifiServers_p, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_010_startWifiServers_n", wifi_tc_010_startWifiServers_n, utc_liboic_startup, utc_liboic_cleanup},
+ {"wifi_tc_011_stopWifiServers_p", wifi_tc_011_stopWifiServers_p, utc_liboic_startup, utc_liboic_cleanup},
+ {NULL, NULL}
+};
+
+#endif // __TCT_LIBOIC_CORE_H__
--- /dev/null
+#include "assert.h"
+#include "oic-core/logger.h"
+#include "oic-core/csdk.h"
+#include "interfaceHeaders/common.h"
+#include "interfaceHeaders/connectivity_interface.h"
+#include "interfaceHeaders/WiFiInterface.h"
+#include "interfaceHeaders/bt_interface.h"
+
+//& set: Liboic
+
+void utc_liboic_startup(void)
+{
+ /*Precondition for each TC*/
+}
+
+void utc_liboic_cleanup(void)
+{
+ /*Postcondition for each TC*/
+}
+
+
+//& purpose: A purpose of a first positive TC.
+int first_tc_p(void)
+{
+ return 0;
+}
+
+//& purpose: A purpose of a first negative TC.
+int first_tc_n(void)
+{
+ return 0;
+}
--- /dev/null
+//#include <glib.h>
+#include "assert.h"
+//#include "oic-core/logger.h"
+//#include "oic-core/ocstack.h"
+#include "interfaceHeaders/cacommon.h"
+#include "interfaceHeaders/caadapterinterface.h"
+#include "interfaceHeaders/cawifiethernetadapter.h"
+
+//& set: Liboic
+
+//Wifi callbacks
+
+CALocalConnectivity* localWifiEndpoint = NULL;
+CARemoteEndpoint remoteMulticastEndpoint;
+CARemoteEndpoint remoteEndpoint[10]; /* 10 RemoteEndpoints are currently kept */
+char remoteIPAddress[CA_IPADDR_SIZE] = "192.168.1.103"; //Change the Corresponding IP address during testing.
+char localIPAddress[CA_IPADDR_SIZE] = {0};
+int localPort = -1;
+int32_t serverId;
+//static GMainLoop *mainloop;
+//int gMainloopStatus = 0;
+
+//Hardcoded values to Test
+typedef struct ConnectivityHandlerList {
+ CAConnectivityType type;
+ CAConnectivityHandler handler;
+ struct ConnectivityHandlerList* nextHandler;
+} ConnectivityHandlerList;
+
+char coapData[500] = "{\"oc:\[{href\":\"/a/light\",\"ref\":{\"power\":\"20\",\"state\":\"true\"}}\]}";
+
+#define CA_PORT 5283
+#define CA_MCAST_PORT 5298
+
+/**
+ * @def CA_MULTICAST_IP
+ * @brief Multicast IP Address
+ */
+#define CA_MULTICAST_IP "224.0.1.187"
+
+
+CAConnectivityHandler* gCAConnectivityHandlers = NULL;
+
+int interfaceInitializeEndpoint(int d)
+{
+ int i = 0;
+ /* As of initializing one endpoint */
+ for (i = 0; i < 1; i++)
+ {
+ remoteEndpoint[i].connectivityType = CA_WIFI;
+ strncpy(remoteEndpoint[i].addressInfo.IP.ipAddress, remoteIPAddress, CA_IPADDR_SIZE);
+ remoteEndpoint[i].addressInfo.IP.port = 5283; /* Send the corresponding port here */
+ }
+
+ remoteMulticastEndpoint.connectivityType = CA_WIFI;
+}
+
+void storeInterfaceCallbacks(CAConnectivityHandler* newHandler)
+{
+ printf("\nstoreInterfaceCallbacks Entry in Sample");
+ #if 0
+ newHandler->nextHandler = NULL;
+
+ CAConnectivityHandler* tempCAConnectivityHandlers = gCAConnectivityHandlers;
+
+ if (!tempCAConnectivityHandlers) {
+ gCAConnectivityHandlers = newHandler;
+ return;
+ }
+ while (tempCAConnectivityHandlers->nextHandler) {
+ tempCAConnectivityHandlers = tempCAConnectivityHandlers->nextHandler;
+ }
+
+ tempCAConnectivityHandlers->nextHandler = newHandler;
+ #endif
+ printf("\nstoreInterfaceCallbacks Exit in Sample");
+}
+
+/*
+void interfaceRegisterCallback(CAConnectivityHandler handler , CAConnectivityType cType)
+{
+ printf("\ninterfaceRegisterCallback Entry in Sample");
+ CAConnectivityHandler newCAConnectivityHandler;
+ newCAConnectivityHandler.start = handler.start;
+ newCAConnectivityHandler.stop = handler.stop;
+ newCAConnectivityHandler.startAdapter = handler.startAdapter;
+ newCAConnectivityHandler.sendData= handler.sendData;
+ newCAConnectivityHandler.sendDataToAll= handler.sendDataToAll;
+ newCAConnectivityHandler.statNotifyServer= handler.statNotifyServer;
+ newCAConnectivityHandler.sendNotification= handler.sendNotification;
+ newCAConnectivityHandler.GetnetInfo= handler.GetnetInfo;
+ //newCAConnectivityHandler.cType= cType;
+ storeInterfaceCallbacks(&newCAConnectivityHandler);
+ printf("\ninterfaceRegisterCallback Exit in Sample");
+}
+*/
+
+void interfaceRegisterCallback(CAConnectivityHandler handler,
+ CAConnectivityType connType)
+{
+ printf("interfaceRegisterCallback Entry in Sample\n");
+ ConnectivityHandlerList* newConnectivityHandler = (ConnectivityHandlerList*) malloc(sizeof(ConnectivityHandlerList));
+ if (NULL == newConnectivityHandler)
+ {
+ printf("Memory allocation failed!\n");
+ return;
+ }
+
+ newConnectivityHandler->type = connType;
+ newConnectivityHandler->handler = handler;
+ storeInterfaceCallbacks(newConnectivityHandler);
+ printf("interfaceRegisterCallback Exit in Sample\n");
+}
+
+
+void requestResponseHandler(CARemoteEndpoint* object, void* data)
+{
+ printf("\nrequestResponseHandler Entry in Sample");
+ if (object == NULL || data == NULL) {
+ printf("\nNULL Object");
+ return;
+ }
+
+ if (object->addressInfo.IP.ipAddress)
+ printf("\nData Received from %s\n", object->addressInfo.IP.ipAddress);
+ if (data)
+ printf("\nReceived Data : %s \n", (char*)data);
+ /*
+ gMainloopStatus = 1;
+ if (mainloop)
+ {
+ g_main_loop_quit(mainloop);
+ mainloop = NULL;
+ }
+ */
+ printf("\nrequestResponseHandler Exit in Sample");
+}
+
+
+void networkInterfaceCallback(CALocalConnectivity* localEndPoint, CANetworkStatus networkConnectivityState)
+{
+ printf("\nnetworkInterfaceCallback Entry in Sample");
+ if (localEndPoint == NULL) {
+ printf("\nNULL Object");
+ return;
+ }
+
+ if (localEndPoint->addressInfo.IP.ipAddress)
+ printf("\n Local Interface Address%s\n", localEndPoint->addressInfo.IP.ipAddress);
+
+ if (networkConnectivityState == CA_INTERFACE_UP)
+ printf("\n WiFi Network Status is UP");
+ else
+ printf("\n WiFi Network Status is DOWN");
+ printf("\nnetworkInterfaceCallback Exit in Sample");
+}
+
+void utc_liboic_startup(void)
+{
+
+}
+
+void utc_liboic_cleanup(void)
+{
+
+}
+
+
+int wifi_tc_001_initializeWifi_p(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ error = CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ assert_eq(error, CA_STATUS_OK);
+ return 0;
+}
+
+int wifi_tc_002_initializeWifi_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ error = CAInitializeWifi(NULL, NULL, NULL);
+ assert_eq(error, CA_STATUS_INVALID_PARAM); //Note: initializeWifi always return OC_STACK_OK
+ return 0;
+}
+
+int wifi_tc_003_getWIFIInterfaceInformation_p(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+ assert_eq(error, CA_STATUS_OK);
+
+ // Now, check local endpoint information
+ //assert_neq(localWifiEndpoint->endpoint_info, NULL);
+ strncpy(localIPAddress, localWifiEndpoint->addressInfo.IP.ipAddress, CA_IPADDR_SIZE);
+ localPort = localWifiEndpoint->addressInfo.IP.port;
+ assert_neq(localPort, -1);
+ return 0;
+}
+
+int wifi_tc_004_getWIFIInterfaceInformation_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(NULL, &size);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ return 0;
+}
+
+int wifi_tc_005_sendWifiUnicastData_p(void)
+{
+ uint32_t dataSize;
+ CAResult error = CA_STATUS_FAILED;
+
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+ assert_eq(error, CA_STATUS_OK);
+
+ localWifiEndpoint->addressInfo.IP.port = 5283;
+ //StartWifiAdapter(localWifiEndpoint);
+
+ interfaceInitializeEndpoint(0);
+ dataSize = CASendWIFIUnicastData(&remoteEndpoint[0], coapData, strlen(coapData));
+ sleep(5);
+
+ assert_eq(dataSize, strlen(coapData));
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_006_sendWifiUnicastData_n(void)
+{
+ int dataSize = 0;
+ interfaceInitializeEndpoint(0);
+ dataSize = CASendWIFIUnicastData(NULL, NULL, NULL);
+ assert_eq(dataSize, 0);
+ return 0;
+}
+
+int wifi_tc_007_sendWifiMulticastData_p(void)
+{
+ uint32_t dataSize = 0;
+ interfaceInitializeEndpoint(0);
+ dataSize = CASendWIFIMulticastData(coapData, strlen(coapData));
+ assert_eq(dataSize, strlen(coapData));
+ return 0;
+}
+
+int wifi_tc_008_sendWifiMulticastData_n(void)
+{
+ int dataSize = 0;
+ interfaceInitializeEndpoint(0);
+ dataSize = CASendWIFIMulticastData(NULL, NULL);
+ assert_eq(dataSize, 0);
+ return 0;
+}
+
+int wifi_tc_009_startUnicastServer_p(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ int16_t unicastPort = CA_PORT;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+
+ error = CAStartUnicastServer("0.0.0.0", &unicastPort);
+ assert_eq(error, CA_STATUS_OK);
+ //Cleanup
+ CAStopUnicastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_010_startUnicastServer_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+ assert_eq(error, CA_STATUS_OK);
+
+ error = CAStartUnicastServer(NULL, localWifiEndpoint->addressInfo.IP.port);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ //Cleanup
+ CAStopUnicastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_011_startUnicastServer_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+ assert_eq(error, CA_STATUS_OK);
+
+ error = CAStartUnicastServer(localWifiEndpoint->addressInfo.IP.ipAddress, NULL);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ //Cleanup
+ CAStopUnicastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_012_startUnicastServer_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+ assert_eq(error, CA_STATUS_OK);
+
+ error = CAStartUnicastServer(NULL, NULL);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ //Cleanup
+ CAStopUnicastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_013_startMulticastServer_p(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ int16_t multicastPort = CA_MCAST_PORT;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+
+ error = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", &multicastPort);
+ assert_eq(error, CA_STATUS_OK);
+ //Cleanup
+ CAStopMulticastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_014_startMulticastServer_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ int16_t multicastPort = CA_MCAST_PORT;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+
+ error = CAStartMulticastServer(NULL, "0.0.0.0", &multicastPort);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ //Cleanup
+ CAStopMulticastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_015_startMulticastServer_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ int16_t multicastPort = CA_MCAST_PORT;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+
+ error = CAStartMulticastServer(CA_MULTICAST_IP, NULL, &multicastPort);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ //Cleanup
+ CAStopMulticastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_016_startMulticastServer_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ int16_t multicastPort = CA_MCAST_PORT;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+
+ error = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", NULL);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ //Cleanup
+ CAStopMulticastServer();
+ CATerminateWifi();
+ return 0;
+}
+
+int wifi_tc_017_startMulticastServer_n(void)
+{
+ CAResult error = CA_STATUS_FAILED;
+ int16_t multicastPort = CA_MCAST_PORT;
+ //Startup
+ CAInitializeWifi(interfaceRegisterCallback, requestResponseHandler, networkInterfaceCallback);
+ uint32_t size = 0;
+ error = CAGetWIFIInterfaceInformation(&localWifiEndpoint, &size);
+
+ error = CAStartMulticastServer(NULL, NULL, NULL);
+ assert_eq(error, CA_STATUS_INVALID_PARAM);
+ //Cleanup
+ CAStopMulticastServer();
+ CATerminateWifi();
+ return 0;
+}
+
--- /dev/null
+%define MODULE_NAME liboic
+%define MODULE_LIBNAME liboic
+Name: core-%{MODULE_NAME}-tests
+Summary: Core API unit TC (%{name})
+Version: 0.1
+Release: 0
+Group: Development/Tools
+License: Apache License, Version 2.0, Samsung Properietary
+Source0: %{name}-%{version}.tar.gz
+#BuildRequires: pkgconfig(%{MODULE_LIBNAME})
+BuildRequires: pkgconfig(capi-network-wifi)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(capi-network-bluetooth)
+BuildRequires: pkgconfig(dlog)
+#BuildRequires: pkgconfig(oic-core)
+BuildRequires: pkgconfig(com.samsung.oicca)
+BuildRequires: cmake
+
+%description
+Core API unit TC (%{name})
+
+%prep
+%setup -q
+
+%build
+
+%define PREFIX "%{_libdir}/%{name}"
+
+export LDFLAGS+="-Wl,--rpath=%{PREFIX} -Wl,--as-needed"
+
+cmake . -DMODULE="%{MODULE_NAME}" -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+mkdir -p %{buildroot}/opt/usr/share/license
+cp LICENSE %{buildroot}/opt/usr/share/license/%{name}
+mkdir -p %{buildroot}/tmp/
+cp scripts/add_all_smack_rule.sh %{buildroot}/tmp/
+cp scripts/all_smack.rule %{buildroot}/tmp/
+#mkdir -p %{buildroot}/opt/usr/bin/tct-liboic-core
+#cp src/liboic/libcapi-network-wifi.so.0 %{buildroot}/opt/usr/bin/tct-liboic-core
+#cp src/liboic/libcapi-network-wifi.so.0.1.20 %{buildroot}/opt/usr/bin/tct-liboic-core
+#cp src/liboic/libcapi-network-wifi.so.1 %{buildroot}/opt/usr/bin/tct-liboic-core
+%post
+
+%postun
+
+
+%files
+/opt/usr/bin/*
+#/usr/$(BIN_DIR)/lib*.so*
+/opt/usr/share/license/%{name}
+/tmp/add_all_smack_rule.sh
+/tmp/all_smack.rule