Remote Access base on libstrophe 56/2156/17
authorK.J. Kao <jeremyk@workssys.com>
Wed, 29 Jul 2015 08:53:00 +0000 (16:53 +0800)
committerJon A. Cruz <jonc@osg.samsung.com>
Fri, 4 Sep 2015 18:46:59 +0000 (18:46 +0000)
merge from 'Change 1971'

add a option(WITH_RA_IBB) and two folders(libstrophe,wksxmppxep)

add test code with wksxmpp_chat

try to checkout specific version

Conflicts:
resource/csdk/SConscript

disable ra_xmpp library link when using libstrophe.
remove wks prefix file name and function name.

use IBB instread of chat message.

multi session support
  use pdu token(CoAP data) as session id

add error_cb function

add connection_status

Patch Set 7:
observe in persistent ibb session

Patch Set 8:
remove xmpp chat code
code format review

Patch Set 9:
patch libstrophe, add function xmpp_conn_is_secured()

Patch Set 10:
update README, apt-get install libtool for libstrophe
update code follow comments
call force tls function

Patch Set 11:
add README-building-and-running-remote-access-sample.txt

Patch Set 12:
update README

Patch Set 13:
update for comments, code format review.

Patch Set 14:
update example code for comments

Patch Set 15:
update for xep0047.
fix xep0047 git version.

Patch Set 16:
update for comments.

Change-Id: Ia48642bd3a347248a1d2cf810c575333d010368a
Signed-off-by: K.J. Kao <jeremyk@workssys.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2156
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
Tested-by: Jon A. Cruz <jonc@osg.samsung.com>
13 files changed:
README-building-and-running-remote-access-sample.txt [new file with mode: 0644]
Readme.scons.txt
build_common/SConscript
build_common/external_libs.scons
extlibs/libstrophe/SConscript [new file with mode: 0644]
extlibs/libstrophe/strophe-xmpp_conn_is_secured.patch [new file with mode: 0644]
extlibs/wksxmppxep/SConscript [new file with mode: 0644]
resource/csdk/SConscript
resource/csdk/connectivity/samples/linux/SConscript
resource/csdk/connectivity/src/ra_adapter/SConscript
resource/csdk/connectivity/src/ra_adapter/caraadapter.c
resource/csdk/stack/samples/linux/SimpleClientServer/ocremoteaccessclient.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp

diff --git a/README-building-and-running-remote-access-sample.txt b/README-building-and-running-remote-access-sample.txt
new file mode 100644 (file)
index 0000000..79d7fbd
--- /dev/null
@@ -0,0 +1,42 @@
+== Quick guide: build and run IoTivity(remote access) projects on Ubuntu ==
+
+1. Build
+       Go to the top directory of 'iotivity' project
+    (Note: should always run 'scons' command in this directory)
+
+    Install external libraries:
+      $ sudo apt-get install libboost-dev libboost-program-options-dev libexpat1-dev libboost-thread-dev uuid-dev libssl-dev
+      $ sudo apt-get install libglib2.0-dev autoconf libtool
+
+    Build release binaries:
+      $ scons WITH_RA=1 WITH_RA_IBB=1
+(Note: C sdk requires tiny-cbor. Please follow the instruction in the build
+message to install tiny-cbor)
+
+    Build debug binaries:
+      $ scons WITH_RA=1 WITH_RA_IBB=1 RELEASE=false
+
+    Help:
+      $ scons -h
+
+    Clear:
+      $ scons -c
+
+2. Run the remote access testing
+    remote access samples in <iotivity>/out/linux/x86_64/release/resource/csdk/stack/samples/linux/SimpleClientServer
+
+    before testing,
+      setup a XMPP server and create an account in XMPP server
+      ex: account: user1@localhost / password: 1234
+
+    oic server:
+      $ ocserver -o 1 -u user1 -d localhost -w 1234 -s localhost
+
+    oic client:
+      $ ocremoteaccessclient -t 1 -u user1 -d localhost -w 1234 -s localhost
+
+    test steps:
+      1. run ocserver, and copy the bound jid
+      2. run ocremoteaccessclient on the another term, and paste the bound jid of ocserver and press 'Enter'
+        use '-t' to change testcase.
+
index fd0b3a0..fb86cd6 100644 (file)
@@ -5,7 +5,7 @@
 command in this directory)
 
     Install external libraries:
-      $ sudo apt-get install libboost-dev libboost-program-options-dev libexpat1-dev libboost-thread-dev uuid-dev libssl-dev
+      $ sudo apt-get install libboost-dev libboost-program-options-dev libexpat1-dev libboost-thread-dev uuid-dev libssl-dev libtool
 
     Build release binaries:
       $ scons
@@ -137,7 +137,7 @@ to skip it.
 
 1. Build IoTivity project for Linux
       $ cd <top directory of the project>
-      $ sudo apt-get install libboost-dev libexpat1-dev libboost-thread-dev libssl-dev
+      $ sudo apt-get install libboost-dev libexpat1-dev libboost-thread-dev libssl-dev libtool
       $ scons
 
 2. Build IoTivity project for Android
index 7f4c650..db0d14d 100644 (file)
@@ -79,6 +79,7 @@ help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map
 
 
 help_vars.Add(BoolVariable('WITH_RA', 'Build with Remote Access module', False))
+help_vars.Add(BoolVariable('WITH_RA_IBB', 'Build with Remote Access module(workssys)', False))
 
 if target_os in targets_disallow_multitransport:
        help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'IP', ['BT', 'BLE', 'IP']))
index 52f0546..65c25ec 100644 (file)
@@ -128,6 +128,10 @@ with_ra = env.get('WITH_RA')
 if with_ra:
        SConscript(os.path.join(env.get('SRC_DIR'), 'extlibs', 'raxmpp', 'SConscript'))
 
+with_ra_ibb = env.get('WITH_RA_IBB')
+if with_ra_ibb:
+       SConscript(os.path.join(env.get('SRC_DIR'), 'extlibs', 'wksxmppxep', 'SConscript'))
+
 
 env.AddMethod(__prepare_lib, "PrepareLib")
 env.AddMethod(__configure, "Configure")
diff --git a/extlibs/libstrophe/SConscript b/extlibs/libstrophe/SConscript
new file mode 100644 (file)
index 0000000..55871d6
--- /dev/null
@@ -0,0 +1,75 @@
+######################################################################
+# ref. raxmpp library build script
+#
+######################################################################
+import os
+import commands
+
+Import('env')
+
+base_dir = env.get('SRC_DIR')
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+build_path = Dir('.').abspath
+
+with_ra_ibb = env.get('WITH_RA_IBB')
+PKG_NAME = 'strophe'
+SRC_NAME = 'libstrophe'
+EXT_NAME = 'libstrophe'
+EXT_BASE = 'extlibs/' + EXT_NAME
+EXT_PATH = EXT_BASE + '/' + SRC_NAME
+SRC_PATH = base_dir + '/' + EXT_PATH
+INC_PATH = SRC_PATH
+LIB_PATH = SRC_PATH + '/' + '.libs'
+
+if with_ra_ibb:
+       # check 'libstrophe' library, if it doesn't exits, ask user to download it
+       if not os.path.exists(SRC_NAME):
+               raxmpp_env = Environment(ENV = os.environ)
+               c = raxmpp_env.Action(['git clone https://github.com/strophe/libstrophe.git ' + SRC_NAME,
+                       'cd ' + SRC_NAME + ' && git checkout 527bc0573a52f2af3ecad5b9ef39aeec7b669f77'
+                       ])
+
+               print 'Downloading xmpp library ...'
+               if raxmpp_env.Execute(c):
+                       print '''
+       *********************************** Error: ***********************************************
+       * Please download ra_xmpp as following:
+       *     $ git clone https://github.com/strophe/libstrophe.git extlibs/libstrophe/libstrophe
+       *     $ cd  extlibs/libstrophe/libstrophe
+       *     $ git checkout 527bc0573a52f2af3ecad5b9ef39aeec7b669f77
+       ******************************************************************************************
+       '''
+                       Exit(1)
+               else:
+                       print 'Download xmpp library complete'
+
+       print 'Building with ' + SRC_NAME
+       #print 'base_dir', base_dir
+       #print 'target_os', target_os
+       #print 'target_arch', target_arch
+
+       foo=commands.getoutput('patch -N -p1 -d libstrophe < strophe-xmpp_conn_is_secured.patch')
+       print foo
+
+       os.chdir(SRC_NAME)
+       #sconsflags = ' RELEASE=true' if  env['RELEASE'] else ' RELEASE=false'
+       if not os.path.exists('configure') :
+               foo=commands.getoutput('./bootstrap.sh')
+               #print foo
+       if not os.path.exists('config.status') :
+               foo=commands.getoutput('./configure')
+               #print foo
+       if not os.path.exists('.libs/libstrophe.a') :
+               foo=commands.getoutput('make libstrophe.la')
+               #print foo
+       if not os.path.exists('.libs/libstrophe.a') :
+               print 'Building with ' + SRC_NAME + ' failed.'
+               Exit(2)
+
+       print 'Building with ' + SRC_NAME + ' Completely.'
+       env.AppendUnique(CPPPATH = [INC_PATH], RALIBS = ['strophe', 'ssl', 'crypto', 'resolv', 'expat'], RALIBPATH = [LIB_PATH], RARPATH = [LIB_PATH])
+
+if env.GetOption('clean') :
+       act = env.Action(['cd ' + SRC_PATH, 'make clean'])
+       env.Execute(act)
diff --git a/extlibs/libstrophe/strophe-xmpp_conn_is_secured.patch b/extlibs/libstrophe/strophe-xmpp_conn_is_secured.patch
new file mode 100644 (file)
index 0000000..958783b
--- /dev/null
@@ -0,0 +1,28 @@
+diff --git a/src/conn.c b/src/conn.c
+index d72386f..e4f0a39 100644
+--- a/src/conn.c
++++ b/src/conn.c
+@@ -742,6 +742,11 @@ void xmpp_conn_disable_tls(xmpp_conn_t * const conn)
+     conn->tls_disabled = 1;
+ }
++int xmpp_conn_is_secured(xmpp_conn_t * const conn)
++{
++    return conn->secured == 1 && conn->tls_failed == 0 ? 1 : 0;
++}
++
+ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
+ {
+     char buf[4096];
+diff --git a/strophe.h b/strophe.h
+index 80a5390..64b2352 100644
+--- a/strophe.h
++++ b/strophe.h
+@@ -215,6 +215,7 @@ const char *xmpp_conn_get_pass(const xmpp_conn_t * const conn);
+ void xmpp_conn_set_pass(xmpp_conn_t * const conn, const char * const pass);
+ xmpp_ctx_t* xmpp_conn_get_context(xmpp_conn_t * const conn);
+ void xmpp_conn_disable_tls(xmpp_conn_t * const conn);
++int xmpp_conn_is_secured(xmpp_conn_t * const conn);
+ int xmpp_connect_client(xmpp_conn_t * const conn, 
+                         const char * const altdomain,
diff --git a/extlibs/wksxmppxep/SConscript b/extlibs/wksxmppxep/SConscript
new file mode 100644 (file)
index 0000000..9dc9833
--- /dev/null
@@ -0,0 +1,55 @@
+######################################################################
+# Ref. libstrophe library build script
+#
+######################################################################
+import os
+import commands
+
+Import('env')
+
+base_dir = env.get('SRC_DIR')
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+
+with_ra_ibb = env.get('WITH_RA_IBB')
+
+SRC_NAME = 'wks_xep0047'
+EXT_NAME = 'wksxmppxep'
+EXT_BASE = 'extlibs/' + EXT_NAME
+EXT_PATH = EXT_BASE + '/' + SRC_NAME
+SRC_PATH = base_dir + '/' + EXT_PATH
+INC_PATH = SRC_PATH + '/include'
+LIB_PATH = SRC_PATH
+
+if with_ra_ibb:
+       env.SConscript(base_dir + '/extlibs/libstrophe/SConscript')
+       if not os.path.exists(SRC_NAME):
+               raxmpp_env = Environment(ENV = os.environ)
+               c = raxmpp_env.Action(['git clone https://github.com/WorksSystems/wks_xep0047.git ' + SRC_NAME,
+                       'cd ' + SRC_NAME + ' && git checkout b95f22064241d1319c4dc967878706b4a446d186'
+        ])
+
+               print 'Downloading', SRC_NAME ,'library ...'
+               if raxmpp_env.Execute(c):
+                       print '''
+       *********************************** Error: ***********************************************
+       * Please download ra_xmpp as following:
+       *     $ git clone https://github.com/WorksSystems/wksxmpp_chat.git extlibs/wksxmppxep/wksxmpp_chat
+       *     $ cd extlibs/wksxmppxep/wksxmpp_chat
+       *     $ git checkout 9f5d726df9779bec5d3036acfbca70c97958921d
+       ******************************************************************************************
+       '''
+                       Exit(1)
+               else:
+                       print 'Download', SRC_NAME, 'library complete'
+
+       os.chdir(SRC_NAME)
+       if not os.path.exists(SRC_NAME + '/libwksxmppxep.so') :
+               LIBSTROPHE_BASE=base_dir + '/extlibs/libstrophe/libstrophe'
+               foo=commands.getoutput('make LIBSTROPHE_BASE=' + LIBSTROPHE_BASE + ' libraries')
+               #print foo
+       env.PrependUnique(CPPPATH = [INC_PATH], RALIBS = ['wksxmppxep', 'm', 'crypto'], RALIBPATH = [LIB_PATH], RARPATH = [LIB_PATH])
+
+if env.GetOption('clean') :
+       act = env.Action(['cd ' + SRC_PATH, 'make clean'])
+       env.Execute(act)
index a9e30c8..01e67d3 100644 (file)
@@ -30,6 +30,7 @@ liboctbstack_env = lib_env.Clone()
 
 target_os = env.get('TARGET_OS')
 with_ra = env.get('WITH_RA')
+with_ra_ibb = env.get('WITH_RA_IBB')
 # As in the source code, it includes arduino Time library (C++)
 # It requires compile the .c with g++
 if target_os == 'arduino':
@@ -68,9 +69,11 @@ liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 
 if target_os in ['android', 'linux', 'tizen']:
        liboctbstack_env.PrependUnique(LIBS = ['connectivity_abstraction'])
-       if with_ra:
-               liboctbstack_env.AppendUnique(LIBS = ['ra_xmpp'])
-
+       if with_ra_ibb:
+               liboctbstack_env.AppendUnique(LIBS = liboctbstack_env['RALIBS'], LIBPATH = liboctbstack_env['RALIBPATH'], RPATH = liboctbstack_env['RARPATH'])
+       else :
+               if with_ra:
+                       liboctbstack_env.AppendUnique(LIBS = ['ra_xmpp'])
 liboctbstack_env.AppendUnique(LIBS = ['coap', 'm'])
 
 if target_os == 'tizen':
index 9bcc7e2..71c7388 100644 (file)
@@ -10,6 +10,7 @@ ca_os = sample_env.get('TARGET_OS')
 ca_transport = sample_env.get('TARGET_TRANSPORT')
 secured = sample_env.get('SECURED')
 with_ra = sample_env.get('WITH_RA')
+with_ra_ibb = sample_env.get('WITH_RA_IBB')
 root_dir = './../../'
 
 #####################################################################
@@ -39,8 +40,11 @@ print " sample src %s" % sample_src
 sample_env.PrependUnique(LIBPATH = [sample_env.get('BUILD_DIR'), '.'])
 sample_env.PrependUnique(RPATH = [sample_env.get('BUILD_DIR'), '.',])
 sample_env.PrependUnique(LIBS = ['connectivity_abstraction'])
-if with_ra:
-       sample_env.AppendUnique(LIBS = ['ra_xmpp'])
+if with_ra_ibb:
+       sample_env.AppendUnique(LIBPATH = sample_env['RALIBPATH'], RPATH = sample_env['RARPATH'], LIBS = sample_env['RALIBS'])
+else :
+       if with_ra:
+               sample_env.AppendUnique(LIBS = ['ra_xmpp'])
 sample_env.AppendUnique(LIBS = ['coap', 'pthread'])
 
 if ca_os not in ['darwin']:
index 2b077bb..3cce282 100644 (file)
@@ -25,7 +25,11 @@ print "Reading RA adapter script"
 
 target_os = env.get('TARGET_OS')
 inc_files = env.get('CPPPATH')
+with_ra_ibb = env.get('WITH_RA_IBB')
 src_dir = './ra_adapter'
 
 #Source files to build in Linux platform
 env.AppendUnique(CA_SRC=[os.path.join(src_dir, 'caraadapter.c')])
+
+if with_ra_ibb:
+       env.AppendUnique(CPPDEFINES = ['RA_ADAPTER_IBB'])
index 4ae741f..4ace491 100644 (file)
 #include "logger.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
-#include "ra_xmpp.h"
 #include "caremotehandler.h"
 #include "cacommon.h"
 
+#ifdef RA_ADAPTER_IBB
+#include "caprotocolmessage.h"
+#include "xmpp_helper.h"
+#include "xmpp_utils.h"
+#include "xmpp_ibb.h"
+#include "xmpp_utils.h"
+#else
+#include "ra_xmpp.h"
+#endif
+
+#ifdef RA_ADAPTER_IBB
+/**
+ * Logging tag for module name.
+ */
+#define RA_ADAPTER_TAG "RA_ADAP_IBB"
+
+/**
+ * Network Packet Received Callback to CA.
+ */
+static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
+
+/**
+ * Network Changed Callback to CA.
+ */
+static CANetworkChangeCallback g_networkChangeCallback = NULL;
+
+/**
+ * Holds XMPP data information.
+ */
+#define RA_MAX_HOSTNAME_LENGTH 256
+#define RA_MAX_PASSWORD_LENGTH 64
+typedef struct
+{
+    xmpp_t     *xmpp;
+    int         port;
+    char        hostname[RA_MAX_HOSTNAME_LENGTH];
+    char        password[RA_MAX_PASSWORD_LENGTH];
+    char        jid[CA_RAJABBERID_SIZE];
+    CANetworkStatus_t connection_status;
+} CARAXmppData_t;
+
+static ca_mutex g_raadapterMutex = NULL;
+
+static CARAXmppData_t g_xmppData = {.xmpp = NULL, .port = 5222, .hostname = {0},
+    .password = {0}, .jid = {0}, .connection_status = CA_INTERFACE_DOWN};
+
+static void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status);
+
+void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status)
+{
+    OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange IN");
+
+    g_xmppData.connection_status = status;
+
+    CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
+                                CA_ADAPTER_REMOTE_ACCESS,
+                                address, 0);
+    if (!localEndpoint)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "localEndpoint creation failed!");
+        return;
+    }
+    CANetworkChangeCallback networkChangeCallback = g_networkChangeCallback;
+    if (networkChangeCallback)
+    {
+        networkChangeCallback(localEndpoint, status);
+    }
+    else
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "g_networkChangeCallback is NULL");
+    }
+
+    CAFreeEndpoint(localEndpoint);
+
+    OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange OUT");
+}
+
+#define MAX_IBB_SESSION_ID_LENGTH 32
+/* Ref. octypes.h */
+#define OBSERVE_REGISTER    0
+#define OBSERVE_DEREGISTER  1
+/* Ref. octypes.h */
+
+static ilist_t * g_observerList = NULL;
+
+typedef struct _obs_item_t
+{
+    char sessid[MAX_IBB_SESSION_ID_LENGTH + 1];
+    int  option;
+} obs_item_t;
+
+static bool CARAFindSessID(obs_item_t *item, char *key)
+{
+    if (item == NULL || key == NULL)
+    {
+        return false;
+    }
+    if (strcmp(item->sessid, key) == 0)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+static bool CARAPDUIsRequest(uint32_t x)
+{
+    return (x == CA_GET || x == CA_POST || x == CA_PUT || x == CA_DELETE);
+}
+
+static void CARAUpdateObsList(int option, char *sid)
+{
+    if (option == OBSERVE_REGISTER)
+    {
+        obs_item_t *item = (obs_item_t *) OICMalloc(sizeof(*item));
+        OICStrcpy(item->sessid, sizeof(item->sessid), sid);
+        item->option = OBSERVE_REGISTER;
+        ilist_add(g_observerList, item);
+    }
+    else if (option == OBSERVE_DEREGISTER)
+    {
+        obs_item_t *item = ilist_finditem_func(g_observerList, CARAFindSessID, sid);
+        if (item != NULL)
+        {
+            item->option = OBSERVE_DEREGISTER;
+        }
+    }
+}
+
+static int CARAGetReqObsOption(coap_pdu_t *pdu)
+{
+    uint32_t obsopt = -1;
+
+    CARequestInfo_t *reqInfo = (CARequestInfo_t *) OICMalloc(sizeof(*reqInfo));
+    VERIFY_NON_NULL_RET(reqInfo, RA_ADAPTER_TAG, "Memory alloc of CARequestInfo_t failed!", -1);
+
+    CAResult_t result = CAGetRequestInfoFromPDU(pdu, reqInfo);
+    if (CA_STATUS_OK != result)
+    {
+        OICFree(reqInfo);
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Get Request Info failed!");
+        return -1;
+    }
+    if (!CARAPDUIsRequest(reqInfo->method))
+    {
+        OICFree(reqInfo);
+        OIC_LOG(DEBUG, RA_ADAPTER_TAG, "It is not a request data.");
+        return -1;
+    }
+
+    uint8_t numOpt = reqInfo->info.numOptions;
+    CAHeaderOption_t *options = reqInfo->info.options;
+    for (uint8_t i = 0; i < numOpt; i++)
+    {
+        if(options[i].protocolID == CA_COAP_ID &&
+                options[i].optionID == COAP_OPTION_OBSERVE)
+        {
+            obsopt = options[i].optionData[0];
+            break;
+        }
+    }
+    OICFree(reqInfo);
+    return obsopt;
+}
+
+static int CARAErrorCB(xmpp_ibb_session_t *sess, xmpperror_t *xerr)
+{
+    OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "%s(): code(%d) tyep'%s' mesg'%s'",
+            __FUNCTION__, xerr->code, xerr->type, xerr->mesg);
+    return 0;
+}
+
+static int CARAOpenCB(xmpp_ibb_session_t *sess, char *type)
+{
+    OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "%s(): set type '%s'", __FUNCTION__, type);
+    return 0;
+}
+
+static int CARACloseCB(xmpp_ibb_session_t *sess, char *type)
+{
+    OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "%s(): set type '%s'", __FUNCTION__, type);
+    char *sid = xmpp_ibb_get_sid(sess);
+    obs_item_t *item = ilist_finditem_func(g_observerList, CARAFindSessID, sid);
+    if (item != NULL)
+    {
+        ilist_remove(g_observerList, item);
+        OICFree(item);
+    }
+    return 0;
+}
+
+static char *CARAGetSIDFromPDU(coap_pdu_t *pdu)
+{
+    static char s_sid[MAX_IBB_SESSION_ID_LENGTH + 1] = {0};
+
+    VERIFY_NON_NULL_RET(pdu, RA_ADAPTER_TAG, "Invalid parameter!", NULL);
+
+    if (pdu->hdr->token_length * 2 > MAX_IBB_SESSION_ID_LENGTH)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Token length more than expected!");
+        return NULL;
+    }
+
+    char hex[3] = {0};
+    for (int i = 0; i < pdu->hdr->token_length; i++)
+    {
+        snprintf(hex, 3, "%02x", pdu->hdr->token[i]);
+        OICStrcat(s_sid, sizeof(s_sid), hex);
+    }
+
+    return s_sid;
+}
+
+static int CARARecvCB(xmpp_ibb_session_t *sess, xmppdata_t *xdata)
+{
+    if (xdata == NULL)
+    {
+        /* xdata == NULL, send ack result */
+        return 0;
+    }
+
+    char *msg = xdata->data;
+    char *from = xmpp_ibb_get_remote_jid(sess);
+    if (g_networkPacketCallback)
+    {
+        VERIFY_NON_NULL_RET(from, RA_ADAPTER_TAG, "from sender is NULL", -1);
+        VERIFY_NON_NULL_RET(msg, RA_ADAPTER_TAG, "message is NULL", -1);
+
+        OIC_LOG_V (DEBUG, RA_ADAPTER_TAG, "Message received from %s", from);
+
+        CAEndpoint_t *endPoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
+                        CA_ADAPTER_REMOTE_ACCESS, from, 0);
+        if (!endPoint)
+        {
+            OIC_LOG(ERROR, RA_ADAPTER_TAG, "EndPoint creation failed!");
+            return -1;
+        }
+        uint32_t code = CA_NOT_FOUND;
+        coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU(xdata->data, xdata->size, &code);
+        char *sid = CARAGetSIDFromPDU(pdu);
+        int obsopt = CARAGetReqObsOption(pdu);
+        coap_delete_pdu(pdu);
+
+        if (CARAPDUIsRequest(code))
+        {
+            OIC_LOG(DEBUG, RA_ADAPTER_TAG, "this is a request data");
+            if (obsopt == OBSERVE_DEREGISTER || obsopt == OBSERVE_REGISTER)
+            {
+                CARAUpdateObsList(obsopt, sid);
+            }
+        }
+        else
+        {
+            OIC_LOG(DEBUG, RA_ADAPTER_TAG, "this is a response data");
+            obs_item_t *item = ilist_finditem_func(g_observerList, CARAFindSessID, sid);
+            if (item != NULL)
+            {
+                if (item->option == OBSERVE_DEREGISTER)
+                {
+                    xmpp_ibb_close(sess);
+                    ilist_remove(g_observerList, item);
+                    OICFree(item);
+                }
+            }
+            else
+            {
+                xmpp_ibb_close(sess);
+            }
+        }
+
+        void *buf = NULL;
+        xmpp_ibb_userdata_alloc(sess, &buf, xdata->size);
+        if (!buf)
+        {
+            OIC_LOG(ERROR, RA_ADAPTER_TAG, "Memory alloc of message failed!");
+            CAFreeEndpoint(endPoint);
+            return -1;
+        }
+        memcpy(buf, xdata->data, xdata->size);
+        g_networkPacketCallback(endPoint, buf, xdata->size);
+
+        CAFreeEndpoint (endPoint);
+    }
+    else
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "No callback for RA received message found");
+    }
+    return 0;
+}
+
+static int CARAConnHandler(xmpp_t *xmpp, xmppconn_info_t *conninfo, void *udata)
+{
+    if (conninfo->connevent != 0)
+    {
+        OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, " status(%d) error(%d) errorType(%d) errorText '%s'\n",
+                conninfo->connevent, conninfo->error, conninfo->errortype,
+                conninfo->errortext);
+        CARANotifyNetworkChange(g_xmppData.jid, CA_INTERFACE_DOWN);
+        return -1;
+    }
+    OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "\n\n  Bound JID: '%s'\n\n\n", xmpphelper_get_bound_jid(xmpp));
+    CARANotifyNetworkChange(xmpphelper_get_bound_jid(xmpp), CA_INTERFACE_UP);
+    return 0;
+}
+
+CAResult_t CAInitializeRA(CARegisterConnectivityCallback registerCallback,
+                                CANetworkPacketReceivedCallback networkPacketCallback,
+                                CANetworkChangeCallback netCallback, ca_thread_pool_t handle)
+{
+    OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CAInitializeRA IN");
+    if (!registerCallback || !networkPacketCallback || !netCallback || !handle)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    g_networkChangeCallback = netCallback;
+    g_networkPacketCallback = networkPacketCallback;
+
+    CAConnectivityHandler_t raHandler = {
+        .startAdapter = CAStartRA,
+        .startListenServer = CAStartRAListeningServer,
+        .startDiscoveryServer = CAStartRADiscoveryServer,
+        .sendData = CASendRAUnicastData,
+        .sendDataToAll = CASendRAMulticastData,
+        .GetnetInfo = CAGetRAInterfaceInformation,
+        .readData = CAReadRAData,
+        .stopAdapter = CAStopRA,
+        .terminate = CATerminateRA};
+    registerCallback(raHandler, CA_ADAPTER_REMOTE_ACCESS);
+
+    g_xmppData.xmpp = xmpphelper_new(CARAConnHandler, NULL);
+    xmpphelper_force_tls(g_xmppData.xmpp);
+    g_observerList = ilist_new();
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo)
+{
+    if (!caraInfo)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
+        return CA_STATUS_INVALID_PARAM;
+    }
+    if (caraInfo->hostname != NULL)
+    {
+        OICStrcpy(g_xmppData.hostname, sizeof(g_xmppData.hostname), caraInfo->hostname);
+    }
+    else
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
+        return CA_STATUS_INVALID_PARAM;
+    }
+    if (caraInfo->username != NULL && strlen(caraInfo->username) != 0)
+    {
+        OICStrcpy(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->username);
+    }
+    else
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
+        return CA_STATUS_INVALID_PARAM;
+    }
+    if (caraInfo->xmpp_domain != NULL && strlen(caraInfo->xmpp_domain) != 0)
+    {
+        OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), "@");
+        OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->xmpp_domain);
+        if (caraInfo->resource != NULL && strlen(caraInfo->resource) != 0)
+        {
+            OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), "/");
+            OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->resource);
+        }
+    }
+    if (caraInfo->password != NULL)
+    {
+        OICStrcpy(g_xmppData.password, sizeof(g_xmppData.password), caraInfo->password);
+    }
+    g_xmppData.port = caraInfo->port;
+
+    return CA_STATUS_OK;
+}
+
+void CATerminateRA()
+{
+    CAStopRA();
+    ilist_destroy(g_observerList);
+    xmpphelper_join(g_xmppData.xmpp);
+    xmpphelper_release(g_xmppData.xmpp);
+    g_xmppData.xmpp = NULL;
+}
+
+CAResult_t CAStartRA()
+{
+    OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Starting RA adapter"));
+
+    if (!g_xmppData.xmpp)
+    {
+        OIC_LOG (ERROR, RA_ADAPTER_TAG, "CAStartRA(): g_xmppData.xmpp == NULL");
+        return CA_STATUS_FAILED;
+    }
+
+    g_raadapterMutex = ca_mutex_new ();
+    if (!g_raadapterMutex)
+    {
+        OIC_LOG (ERROR, RA_ADAPTER_TAG, PCF("Memory allocation for mutex failed."));
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    ca_mutex_lock (g_raadapterMutex);
+
+    xmpphelper_connect(g_xmppData.xmpp, g_xmppData.hostname, g_xmppData.port,
+                    g_xmppData.jid, g_xmppData.password);
+    xmpp_ibb_reg_funcs_t regfuncs;
+    regfuncs.open_cb = CARAOpenCB;
+    regfuncs.close_cb = CARACloseCB;
+    regfuncs.recv_cb = CARARecvCB;
+    regfuncs.error_cb = CARAErrorCB;
+    xmpp_ibb_register(xmpphelper_get_conn(g_xmppData.xmpp), &regfuncs);
+
+    xmpphelper_run(g_xmppData.xmpp);
+
+    ca_mutex_unlock (g_raadapterMutex);
+
+    OIC_LOG(DEBUG, RA_ADAPTER_TAG, "RA adapter started succesfully");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStopRA()
+{
+    OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopping RA adapter"));
+
+    xmpphelper_stop(g_xmppData.xmpp);
+    xmpp_ibb_unregister(xmpphelper_get_conn(g_xmppData.xmpp));
+    if (!g_raadapterMutex)
+    {
+        ca_mutex_free (g_raadapterMutex);
+        g_raadapterMutex = NULL;
+    }
+    OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopped RA adapter successfully"));
+    return CA_STATUS_OK;
+}
+
+int32_t CASendRAUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data,
+                                  uint32_t dataLength)
+{
+    if (!remoteEndpoint || !data)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
+        return -1;
+    }
+
+    if (0 == dataLength)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Data length is 0!");
+        return 0;
+    }
+    OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "Sending unicast data to %s", remoteEndpoint->addr);
+
+    uint32_t code = CA_NOT_FOUND;
+    coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU(data, dataLength, &code);
+    char *sid = CARAGetSIDFromPDU(pdu);
+    int obsopt = CARAGetReqObsOption(pdu);
+    coap_delete_pdu(pdu);
+
+    ca_mutex_lock (g_raadapterMutex);
+    if (CA_INTERFACE_UP != g_xmppData.connection_status)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, RA not connected");
+        ca_mutex_unlock (g_raadapterMutex);
+        return -1;
+    }
+
+    xmpp_ibb_session_t *sess = xmpp_ibb_get_session_by_sid(sid);
+    if (sess == NULL)
+    {
+        sess = xmpp_ibb_open(xmpphelper_get_conn(g_xmppData.xmpp), remoteEndpoint->addr, sid);
+        if (sess == NULL)
+        {
+            OIC_LOG(ERROR, RA_ADAPTER_TAG, "IBB session establish failed!");
+            ca_mutex_unlock (g_raadapterMutex);
+            return -1;
+        }
+    }
+    if (CARAPDUIsRequest(code))
+    {
+        if (obsopt == OBSERVE_REGISTER || obsopt == OBSERVE_DEREGISTER)
+        {
+            CARAUpdateObsList(obsopt, sid);
+        }
+    }
+    xmppdata_t xdata = {.data = data, .size = dataLength};
+    int rc = xmpp_ibb_send_data(sess, &xdata);
+    ca_mutex_unlock (g_raadapterMutex);
+    if (rc < 0)
+    {
+        OIC_LOG(ERROR, RA_ADAPTER_TAG, "IBB send data failed!");
+        return -1;
+    }
+
+    OIC_LOG_V(INFO, RA_ADAPTER_TAG, "Successfully dispatched bytes[%d] to addr[%s]",
+            dataLength, remoteEndpoint->addr);
+
+    return dataLength;
+}
+
+CAResult_t CAGetRAInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+{
+    VERIFY_NON_NULL(info, RA_ADAPTER_TAG, "info is NULL");
+    VERIFY_NON_NULL(size, RA_ADAPTER_TAG, "size is NULL");
+    return CA_STATUS_OK;
+}
+
+int32_t CASendRAMulticastData(const CAEndpoint_t *endpoint,
+                    const void *data, uint32_t dataLength)
+{
+    OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support sending multicast data");
+    return 0;
+}
+
+CAResult_t CAStartRAListeningServer()
+{
+    OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
+    return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAStartRADiscoveryServer()
+{
+    OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support discovery of multicast servers");
+    return CA_NOT_SUPPORTED;
+}
+
+CAResult_t CAReadRAData()
+{
+    OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
+    return CA_NOT_SUPPORTED;
+}
+
+#else /* #ifdef RA_ADAPTER_IBB */
+
 /**
  * Logging tag for module name.
  */
@@ -421,3 +961,4 @@ CAResult_t CAReadRAData()
     OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
     return CA_NOT_SUPPORTED;
 }
+#endif
index 89da3ff..72bc44a 100644 (file)
@@ -437,38 +437,48 @@ int InitDiscovery(OCQualityOfService qos)
     return ret;
 }
 
-OCStackResult initRemoteAccessAdapter ()
-{
-    OCRAInfo_t rainfo;
-    rainfo.hostname = "localhost";
-    rainfo.port = 5222;
-    rainfo.xmpp_domain = "localhost";
-    rainfo.username = "test1";
-    rainfo.password = "intel123";
-    rainfo.resource = "";
-    rainfo.user_jid = "";
-
-    return OCSetRAInfo(&rainfo);
-}
-
 int main(int argc, char* argv[])
 {
-    int opt;
+    OCRAInfo_t rainfo = {.hostname = "localhost", .port = 5222,
+        .xmpp_domain = "localhost", .username = "test1", .password = "intel123",
+        .resource = "", .user_jid = ""};
 
-    while ((opt = getopt(argc, argv, "t:")) != -1)
+    int opt = 0;
+    while ((opt = getopt(argc, argv, "t:s:p:d:u:w:r:j:")) != -1)
     {
         switch(opt)
         {
             case 't':
                 TEST_CASE = atoi(optarg);
                 break;
+            case 's':
+                rainfo.hostname = optarg;
+                break;
+            case 'p':
+                rainfo.port = atoi(optarg);
+                break;
+            case 'd':
+                rainfo.xmpp_domain = optarg;
+                break;
+            case 'u':
+                rainfo.username = optarg;
+                break;
+            case 'w':
+                rainfo.password = optarg;
+                break;
+            case 'j':
+                rainfo.user_jid = optarg;
+                break;
+            case 'r':
+                rainfo.resource = optarg;
+                break;
             default:
                 PrintUsage();
                 return -1;
         }
     }
 
-    if (initRemoteAccessAdapter() != OC_STACK_OK)
+    if (OCSetRAInfo(&rainfo) != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "Error initiating remote access adapter");
         return 0;
index e40f06a..35bb562 100644 (file)
@@ -929,15 +929,44 @@ int main(int argc, char* argv[])
 {
     pthread_t threadId;
     pthread_t threadId_presence;
-    int opt;
 
-    while ((opt = getopt(argc, argv, "o:")) != -1)
+#ifdef RA_ADAPTER
+    OCRAInfo_t rainfo = {.hostname = "localhost", .port = 5222,
+        .xmpp_domain = "localhost", .username = "test1", .password = "intel123",
+        .resource = "", .user_jid = ""};
+#endif
+
+    int opt = 0;
+    while ((opt = getopt(argc, argv, "o:s:p:d:u:w:r:j:")) != -1)
     {
         switch(opt)
         {
             case 'o':
                 gObserveNotifyType = atoi(optarg);
                 break;
+#ifdef RA_ADAPTER
+            case 's':
+                rainfo.hostname = optarg;
+                break;
+            case 'p':
+                rainfo.port = atoi(optarg);
+                break;
+            case 'd':
+                rainfo.xmpp_domain = optarg;
+                break;
+            case 'u':
+                rainfo.username = optarg;
+                break;
+            case 'w':
+                rainfo.password = optarg;
+                break;
+            case 'j':
+                rainfo.user_jid = optarg;
+                break;
+            case 'r':
+                rainfo.resource = optarg;
+                break;
+#endif
             default:
                 PrintUsage();
                 return -1;
@@ -949,18 +978,10 @@ int main(int argc, char* argv[])
         PrintUsage();
         return -1;
     }
-    #ifdef RA_ADAPTER
-    OCRAInfo_t rainfo;
-    rainfo.hostname = "localhost";
-    rainfo.port = 5222;
-    rainfo.xmpp_domain = "localhost";
-    rainfo.username = "test1";
-    rainfo.password = "intel123";
-    rainfo.resource = "";
-    rainfo.user_jid = "";
 
+#ifdef RA_ADAPTER
     OCSetRAInfo(&rainfo);
-    #endif
+#endif
 
     OC_LOG(DEBUG, TAG, "OCServer is starting...");