Merge branch 'plugin-interface' into master
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ra_adapter / caraadapter.c
1 //*****************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //****************************************************************
20
21 #include "caraadapter.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdint.h>
27
28 #include "caadapterutils.h"
29 #include "camutex.h"
30 #include "uarraylist.h"
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "oic_string.h"
34 #include "caremotehandler.h"
35 #include "cacommon.h"
36
37 #ifdef RA_ADAPTER_IBB
38 #include "caprotocolmessage.h"
39 #include "xmpp_helper.h"
40 #include "xmpp_utils.h"
41 #include "xmpp_ibb.h"
42 #include "xmpp_utils.h"
43 #else
44 #include "ra_xmpp.h"
45 #endif
46
47 #ifdef RA_ADAPTER_IBB
48 #define SET_BUT_NOT_USED(x) (void) x
49 /**
50  * Logging tag for module name.
51  */
52 #define RA_ADAPTER_TAG "RA_ADAP_IBB"
53
54 /**
55  * Network Packet Received Callback to CA.
56  */
57 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
58
59 /**
60  * Network Changed Callback to CA.
61  */
62 static CANetworkChangeCallback g_networkChangeCallback = NULL;
63
64 /**
65  * Holds XMPP data information.
66  */
67 #define RA_MAX_HOSTNAME_LENGTH 256
68 #define RA_MAX_PASSWORD_LENGTH 64
69 typedef struct
70 {
71     xmpp_t     *xmpp;
72     int         port;
73     char        hostName[RA_MAX_HOSTNAME_LENGTH];
74     char        password[RA_MAX_PASSWORD_LENGTH];
75     char        jid[CA_RAJABBERID_SIZE];
76     CANetworkStatus_t connectionStatus;
77     CAJidBoundCallback jidBoundCallback;
78 } CARAXmppData_t;
79
80 static ca_mutex g_raadapterMutex = NULL;
81
82 static CARAXmppData_t g_xmppData = {.xmpp = NULL, .port = 5222, .hostName = {0},
83     .password = {0}, .jid = {0}, .connectionStatus = CA_INTERFACE_DOWN,
84     .jidBoundCallback = NULL};
85
86 static void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status);
87
88 void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status)
89 {
90     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange IN");
91
92     g_xmppData.connectionStatus = status;
93
94     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
95                                 CA_ADAPTER_REMOTE_ACCESS,
96                                 address, 0);
97     if (!localEndpoint)
98     {
99         OIC_LOG(ERROR, RA_ADAPTER_TAG, "localEndpoint creation failed!");
100         return;
101     }
102     CANetworkChangeCallback networkChangeCallback = g_networkChangeCallback;
103     if (networkChangeCallback)
104     {
105         networkChangeCallback(localEndpoint, status);
106     }
107     else
108     {
109         OIC_LOG(ERROR, RA_ADAPTER_TAG, "g_networkChangeCallback is NULL");
110     }
111
112     CAFreeEndpoint(localEndpoint);
113
114     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange OUT");
115 }
116
117 #define MAX_IBB_SESSION_ID_LENGTH 32
118 /* Ref. octypes.h */
119 #define OBSERVE_REGISTER    0
120 #define OBSERVE_DEREGISTER  1
121 /* Ref. octypes.h */
122
123 static ilist_t * g_observerList = NULL;
124
125 typedef struct _obs_item_t
126 {
127     char sessid[MAX_IBB_SESSION_ID_LENGTH + 1];
128     int  option;
129 } obs_item_t;
130
131 static bool CARAFindSessID(obs_item_t *item, char *key)
132 {
133     if (item == NULL || key == NULL)
134     {
135         return false;
136     }
137     if (strcmp(item->sessid, key) == 0)
138     {
139         return true;
140     }
141     else
142     {
143         return false;
144     }
145 }
146
147 static bool CARAPDUIsRequest(uint32_t x)
148 {
149     return (x == CA_GET || x == CA_POST || x == CA_PUT || x == CA_DELETE);
150 }
151
152 static void CARAUpdateObsList(int option, char *sid)
153 {
154     if (option == OBSERVE_REGISTER)
155     {
156         obs_item_t *item = (obs_item_t *) OICMalloc(sizeof(*item));
157         OICStrcpy(item->sessid, sizeof(item->sessid), sid);
158         item->option = OBSERVE_REGISTER;
159         ilist_add(g_observerList, item);
160     }
161     else if (option == OBSERVE_DEREGISTER)
162     {
163         obs_item_t *item = ilist_finditem_func(g_observerList, (find_fp) CARAFindSessID, sid);
164         if (item != NULL)
165         {
166             item->option = OBSERVE_DEREGISTER;
167         }
168     }
169 }
170
171 static int CARAGetReqObsOption(coap_pdu_t *pdu, const CAEndpoint_t *endPoint)
172 {
173     uint32_t obsopt = -1;
174
175     CARequestInfo_t *reqInfo = (CARequestInfo_t *) OICMalloc(sizeof(*reqInfo));
176     VERIFY_NON_NULL_RET(reqInfo, RA_ADAPTER_TAG, "Memory alloc of CARequestInfo_t failed!", -1);
177
178     CAResult_t result = CAGetRequestInfoFromPDU(pdu, endPoint, reqInfo);
179     if (CA_STATUS_OK != result)
180     {
181         OICFree(reqInfo);
182         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Get Request Info failed!");
183         return -1;
184     }
185     if (!CARAPDUIsRequest(reqInfo->method))
186     {
187         OICFree(reqInfo);
188         OIC_LOG(DEBUG, RA_ADAPTER_TAG, "It is not a request data.");
189         return -1;
190     }
191
192     uint8_t numOpt = reqInfo->info.numOptions;
193     CAHeaderOption_t *options = reqInfo->info.options;
194     for (uint8_t i = 0; i < numOpt; i++)
195     {
196         if(options[i].protocolID == CA_COAP_ID &&
197                 options[i].optionID == COAP_OPTION_OBSERVE)
198         {
199             obsopt = options[i].optionData[0];
200             break;
201         }
202     }
203     OICFree(reqInfo);
204     return obsopt;
205 }
206
207 static int CARAErrorCB(xmpp_ibb_session_t *sess, xmpperror_t *xerr)
208 {
209     OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "%s(): code(%d) tyep'%s' mesg'%s'",
210             __FUNCTION__, xerr->code, xerr->type, xerr->mesg);
211     SET_BUT_NOT_USED(sess);
212     SET_BUT_NOT_USED(xerr);
213     return 0;
214 }
215
216 static int CARAOpenCB(xmpp_ibb_session_t *sess, char *type)
217 {
218     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "%s(): set type '%s'", __FUNCTION__, type);
219     SET_BUT_NOT_USED(sess);
220     SET_BUT_NOT_USED(type);
221     return 0;
222 }
223
224 static int CARACloseCB(xmpp_ibb_session_t *sess, char *type)
225 {
226     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "%s(): set type '%s'", __FUNCTION__, type);
227     char *sid = xmpp_ibb_get_sid(sess);
228     obs_item_t *item = ilist_finditem_func(g_observerList, (find_fp) CARAFindSessID, sid);
229     if (item != NULL)
230     {
231         ilist_remove(g_observerList, item);
232         OICFree(item);
233     }
234     SET_BUT_NOT_USED(type);
235     return 0;
236 }
237
238 static char *CARAGetSIDFromPDU(coap_pdu_t *pdu)
239 {
240     static char s_sid[MAX_IBB_SESSION_ID_LENGTH + 1] = {0};
241
242     VERIFY_NON_NULL_RET(pdu, RA_ADAPTER_TAG, "Invalid parameter!", NULL);
243
244     if (pdu->hdr->coap_hdr_udp_t.token_length * 2 > MAX_IBB_SESSION_ID_LENGTH)
245     {
246         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Token length more than expected!");
247         return NULL;
248     }
249
250     char hex[3] = {0};
251     for (int i = 0; i < pdu->hdr->coap_hdr_udp_t.token_length; i++)
252     {
253         snprintf(hex, 3, "%02x", pdu->hdr->coap_hdr_udp_t.token[i]);
254         OICStrcat(s_sid, sizeof(s_sid), hex);
255     }
256
257     return s_sid;
258 }
259
260 static int CARARecvCB(xmpp_ibb_session_t *sess, xmppdata_t *xdata)
261 {
262     if (xdata == NULL)
263     {
264         /* xdata == NULL, send ack result */
265         return 0;
266     }
267
268     char *msg = xdata->data;
269     char *from = xmpp_ibb_get_remote_jid(sess);
270     if (g_networkPacketCallback)
271     {
272         VERIFY_NON_NULL_RET(from, RA_ADAPTER_TAG, "from sender is NULL", -1);
273         VERIFY_NON_NULL_RET(msg, RA_ADAPTER_TAG, "message is NULL", -1);
274
275         OIC_LOG_V (DEBUG, RA_ADAPTER_TAG, "Message received from %s", from);
276
277         CAEndpoint_t *endPoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
278                         CA_ADAPTER_REMOTE_ACCESS, from, 0);
279         if (!endPoint)
280         {
281             OIC_LOG(ERROR, RA_ADAPTER_TAG, "EndPoint creation failed!");
282             return -1;
283         }
284         uint32_t code = CA_NOT_FOUND;
285         coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU(xdata->data, xdata->size, &code,
286             endPoint);
287         char *sid = CARAGetSIDFromPDU(pdu);
288         int obsopt = CARAGetReqObsOption(pdu, endPoint);
289         coap_delete_pdu(pdu);
290
291         if (CARAPDUIsRequest(code))
292         {
293             OIC_LOG(DEBUG, RA_ADAPTER_TAG, "this is a request data");
294             if (obsopt == OBSERVE_DEREGISTER || obsopt == OBSERVE_REGISTER)
295             {
296                 CARAUpdateObsList(obsopt, sid);
297             }
298         }
299         else
300         {
301             OIC_LOG(DEBUG, RA_ADAPTER_TAG, "this is a response data");
302             obs_item_t *item = ilist_finditem_func(g_observerList, (find_fp) CARAFindSessID, sid);
303             if (item != NULL)
304             {
305                 if (item->option == OBSERVE_DEREGISTER)
306                 {
307                     xmpp_ibb_close(sess);
308                     ilist_remove(g_observerList, item);
309                     OICFree(item);
310                 }
311             }
312             else
313             {
314                 xmpp_ibb_close(sess);
315             }
316         }
317
318         void *buf = NULL;
319         xmpp_ibb_userdata_alloc(sess, &buf, xdata->size);
320         if (!buf)
321         {
322             OIC_LOG(ERROR, RA_ADAPTER_TAG, "Memory alloc of message failed!");
323             CAFreeEndpoint(endPoint);
324             return -1;
325         }
326         memcpy(buf, xdata->data, xdata->size);
327         CASecureEndpoint_t sep =
328         {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_DEFAULT_FLAGS}};
329         memcpy(&sep.endpoint, endPoint, sizeof(sep.endpoint));
330         g_networkPacketCallback(&sep, buf, xdata->size);
331
332         CAFreeEndpoint (endPoint);
333     }
334     else
335     {
336         OIC_LOG(ERROR, RA_ADAPTER_TAG, "No callback for RA received message found");
337     }
338     return 0;
339 }
340
341 static int CARAConnHandler(xmpp_t *xmpp, xmppconn_info_t *conninfo, void *udata)
342 {
343     if (conninfo->connevent != 0)
344     {
345         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, " status(%d) error(%d) errorType(%d) errorText '%s'\n",
346                 conninfo->connevent, conninfo->error, conninfo->errortype,
347                 conninfo->errortext);
348         CARANotifyNetworkChange(g_xmppData.jid, CA_INTERFACE_DOWN);
349         return -1;
350     }
351     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "Bound JID: '%s'", xmpphelper_get_bound_jid(xmpp));
352     if (g_xmppData.jidBoundCallback != NULL)
353     {
354         g_xmppData.jidBoundCallback((char *) xmpphelper_get_bound_jid(xmpp));
355     }
356     CARANotifyNetworkChange(xmpphelper_get_bound_jid(xmpp), CA_INTERFACE_UP);
357     VERIFY_NON_NULL_RET(udata, RA_ADAPTER_TAG, "Invalid parameter!", 0);
358     return 0;
359 }
360
361 CAResult_t CAInitializeRA(CARegisterConnectivityCallback registerCallback,
362                                 CANetworkPacketReceivedCallback networkPacketCallback,
363                                 CANetworkChangeCallback netCallback, ca_thread_pool_t handle)
364 {
365     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CAInitializeRA IN");
366     if (!registerCallback || !networkPacketCallback || !netCallback || !handle)
367     {
368         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
369         return CA_STATUS_INVALID_PARAM;
370     }
371
372     g_networkChangeCallback = netCallback;
373     g_networkPacketCallback = networkPacketCallback;
374
375     CAConnectivityHandler_t raHandler = {
376         .startAdapter = CAStartRA,
377         .startListenServer = CAStartRAListeningServer,
378         .startDiscoveryServer = CAStartRADiscoveryServer,
379         .sendData = CASendRAUnicastData,
380         .sendDataToAll = CASendRAMulticastData,
381         .GetnetInfo = CAGetRAInterfaceInformation,
382         .readData = CAReadRAData,
383         .stopAdapter = CAStopRA,
384         .terminate = CATerminateRA};
385     registerCallback(raHandler, CA_ADAPTER_REMOTE_ACCESS);
386 #ifdef NDEBUG
387     xmpp_log_t *log = xmpp_get_default_logger(XMPP_LEVEL_ERROR);
388 #else
389     xmpp_log_t *log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
390 #endif
391     g_xmppData.xmpp = xmpphelper_new(CARAConnHandler, NULL, log, NULL);
392     xmpphelper_force_tls(g_xmppData.xmpp);
393     g_observerList = ilist_new();
394
395     return CA_STATUS_OK;
396 }
397
398 CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo)
399 {
400     if (!caraInfo)
401     {
402         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
403         return CA_STATUS_INVALID_PARAM;
404     }
405     if (caraInfo->hostName != NULL)
406     {
407         OICStrcpy(g_xmppData.hostName, sizeof(g_xmppData.hostName), caraInfo->hostName);
408     }
409     else
410     {
411         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
412         return CA_STATUS_INVALID_PARAM;
413     }
414     if (caraInfo->userName != NULL && strlen(caraInfo->userName) != 0)
415     {
416         OICStrcpy(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->userName);
417     }
418     else
419     {
420         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
421         return CA_STATUS_INVALID_PARAM;
422     }
423     if (caraInfo->xmppDomain != NULL && strlen(caraInfo->xmppDomain) != 0)
424     {
425         OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), "@");
426         OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->xmppDomain);
427         if (caraInfo->resource != NULL && strlen(caraInfo->resource) != 0)
428         {
429             OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), "/");
430             OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->resource);
431         }
432     }
433     if (caraInfo->password != NULL)
434     {
435         OICStrcpy(g_xmppData.password, sizeof(g_xmppData.password), caraInfo->password);
436     }
437     g_xmppData.port = caraInfo->port;
438     g_xmppData.jidBoundCallback = caraInfo->jidBoundCallback;
439
440     return CA_STATUS_OK;
441 }
442
443 void CATerminateRA()
444 {
445     CAStopRA();
446     ilist_destroy(g_observerList);
447     xmpphelper_join(g_xmppData.xmpp);
448     xmpphelper_release(g_xmppData.xmpp);
449     g_xmppData.xmpp = NULL;
450 }
451
452 CAResult_t CAStartRA()
453 {
454     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Starting RA adapter"));
455
456     if (!g_xmppData.xmpp)
457     {
458         OIC_LOG (ERROR, RA_ADAPTER_TAG, "CAStartRA(): g_xmppData.xmpp == NULL");
459         return CA_STATUS_FAILED;
460     }
461
462     g_raadapterMutex = ca_mutex_new ();
463     if (!g_raadapterMutex)
464     {
465         OIC_LOG (ERROR, RA_ADAPTER_TAG, PCF("Memory allocation for mutex failed."));
466         return CA_MEMORY_ALLOC_FAILED;
467     }
468
469     ca_mutex_lock (g_raadapterMutex);
470
471     xmpphelper_connect(g_xmppData.xmpp, g_xmppData.hostName, g_xmppData.port,
472                     g_xmppData.jid, g_xmppData.password);
473     xmpp_ibb_reg_funcs_t regfuncs;
474     regfuncs.open_cb = CARAOpenCB;
475     regfuncs.close_cb = CARACloseCB;
476     regfuncs.recv_cb = CARARecvCB;
477     regfuncs.error_cb = CARAErrorCB;
478     xmpp_ibb_register(xmpphelper_get_conn(g_xmppData.xmpp), &regfuncs);
479
480     xmpphelper_run(g_xmppData.xmpp);
481
482     ca_mutex_unlock (g_raadapterMutex);
483
484     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "RA adapter started succesfully");
485     return CA_STATUS_OK;
486 }
487
488 CAResult_t CAStopRA()
489 {
490     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopping RA adapter"));
491
492     xmpphelper_stop(g_xmppData.xmpp);
493     xmpp_ibb_unregister(xmpphelper_get_conn(g_xmppData.xmpp));
494     if (!g_raadapterMutex)
495     {
496         ca_mutex_free (g_raadapterMutex);
497         g_raadapterMutex = NULL;
498     }
499     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopped RA adapter successfully"));
500     return CA_STATUS_OK;
501 }
502
503 int32_t CASendRAUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data,
504                                   uint32_t dataLength)
505 {
506     if (!remoteEndpoint || !data)
507     {
508         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
509         return -1;
510     }
511
512     if (0 == dataLength)
513     {
514         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Data length is 0!");
515         return 0;
516     }
517     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "Sending unicast data to %s", remoteEndpoint->addr);
518
519     uint32_t code = CA_NOT_FOUND;
520     coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU(data, dataLength, &code, remoteEndpoint);
521     char *sid = CARAGetSIDFromPDU(pdu);
522     int obsopt = CARAGetReqObsOption(pdu, remoteEndpoint);
523     coap_delete_pdu(pdu);
524
525     ca_mutex_lock (g_raadapterMutex);
526     if (CA_INTERFACE_UP != g_xmppData.connectionStatus)
527     {
528         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, RA not connected");
529         ca_mutex_unlock (g_raadapterMutex);
530         return -1;
531     }
532
533     xmpp_ibb_session_t *sess = xmpp_ibb_get_session_by_sid(sid);
534     if (sess == NULL)
535     {
536         sess = xmpp_ibb_open(xmpphelper_get_conn(g_xmppData.xmpp), (char * const) remoteEndpoint->addr, sid);
537         if (sess == NULL)
538         {
539             OIC_LOG(ERROR, RA_ADAPTER_TAG, "IBB session establish failed!");
540             ca_mutex_unlock (g_raadapterMutex);
541             return -1;
542         }
543     }
544     if (CARAPDUIsRequest(code))
545     {
546         if (obsopt == OBSERVE_REGISTER || obsopt == OBSERVE_DEREGISTER)
547         {
548             CARAUpdateObsList(obsopt, sid);
549         }
550     }
551     xmppdata_t xdata = {.data = (char *) data, .size = dataLength};
552     int rc = xmpp_ibb_send_data(sess, &xdata);
553     ca_mutex_unlock (g_raadapterMutex);
554     if (rc < 0)
555     {
556         OIC_LOG(ERROR, RA_ADAPTER_TAG, "IBB send data failed!");
557         return -1;
558     }
559
560     OIC_LOG_V(INFO, RA_ADAPTER_TAG, "Successfully dispatched bytes[%d] to addr[%s]",
561             dataLength, remoteEndpoint->addr);
562
563     return dataLength;
564 }
565
566 CAResult_t CAGetRAInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
567 {
568     VERIFY_NON_NULL(info, RA_ADAPTER_TAG, "info is NULL");
569     VERIFY_NON_NULL(size, RA_ADAPTER_TAG, "size is NULL");
570     return CA_STATUS_OK;
571 }
572
573 int32_t CASendRAMulticastData(const CAEndpoint_t *endpoint,
574                     const void *data, uint32_t dataLength)
575 {
576     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support sending multicast data");
577     SET_BUT_NOT_USED(endpoint);
578     SET_BUT_NOT_USED(data);
579     SET_BUT_NOT_USED(dataLength);
580     return 0;
581 }
582
583 CAResult_t CAStartRAListeningServer()
584 {
585     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
586     return CA_NOT_SUPPORTED;
587 }
588
589 CAResult_t CAStartRADiscoveryServer()
590 {
591     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support discovery of multicast servers");
592     return CA_NOT_SUPPORTED;
593 }
594
595 CAResult_t CAReadRAData()
596 {
597     OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
598     return CA_NOT_SUPPORTED;
599 }
600
601 #else /* #ifdef RA_ADAPTER_IBB */
602
603 /**
604  * Logging tag for module name.
605  */
606 #define RA_ADAPTER_TAG "RA_ADAP"
607
608 /**
609  * Network Packet Received Callback to CA.
610  */
611 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
612
613 /**
614  * Network Changed Callback to CA.
615  */
616 static CANetworkChangeCallback g_networkChangeCallback = NULL;
617
618 /**
619  * Holds XMPP data information.
620  */
621 typedef struct
622 {
623     xmpp_context_t context;
624     xmpp_handle_t handle;
625     xmpp_connection_callback_t connection_callback;
626     xmpp_connection_handle_t connection_handle;
627     xmpp_message_context_t message_context;
628     xmpp_message_callback_t message_callback;
629     CANetworkStatus_t connection_status;
630     xmpp_host_t     g_host;
631     xmpp_identity_t g_identity;
632     char jabberID[CA_RAJABBERID_SIZE];
633 } CARAXmppData_t;
634
635 static ca_mutex g_raadapterMutex = NULL;
636
637 static CARAXmppData_t g_xmppData = {};
638
639 static void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status);
640
641 static void CARAXmppConnectedCB(void * const param, xmpp_error_code_t result,
642         const char *const bound_jid,
643         xmpp_connection_handle_t connection);
644
645 static void CARAXmppDisonnectedCB(void * const param, xmpp_error_code_t result,
646         xmpp_connection_handle_t connection);
647
648 static void CARAXmppMessageSentCB(void * const param, xmpp_error_code_t result,
649         const void *const recipient, const void *const msg, size_t messageOctets);
650
651 static void CARAXmppMessageReceivedCB(void * const param, xmpp_error_code_t result,
652         const void *const sender, const void *const msg, size_t messageOctets);
653
654 void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status)
655 {
656     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange IN");
657
658     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
659                                 CA_ADAPTER_REMOTE_ACCESS,
660                                 address, 0);
661     if (!localEndpoint)
662     {
663         OIC_LOG(ERROR, RA_ADAPTER_TAG, "localEndpoint creation failed!");
664         return;
665     }
666     CANetworkChangeCallback networkChangeCallback = g_networkChangeCallback;
667     if (networkChangeCallback)
668     {
669         networkChangeCallback(localEndpoint, status);
670     }
671     else
672     {
673         OIC_LOG(ERROR, RA_ADAPTER_TAG, "g_networkChangeCallback is NULL");
674     }
675
676     CAFreeEndpoint(localEndpoint);
677
678     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange OUT");
679 }
680
681 void CARAXmppConnectedCB(void * const param, xmpp_error_code_t result,
682         const char *const bound_jid,
683         xmpp_connection_handle_t connection)
684 {
685     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppConnectedCB IN");
686     CANetworkStatus_t connection_status;
687     if (XMPP_ERR_OK == result)
688     {
689         printf("\n\n\t\t===>your jid: %s\n\n", bound_jid);
690
691         ca_mutex_lock (g_raadapterMutex);
692         OICStrcpy (g_xmppData.jabberID, CA_RAJABBERID_SIZE, bound_jid);
693
694         g_xmppData.connection_status = CA_INTERFACE_UP;
695         connection_status = CA_INTERFACE_UP;
696         g_xmppData.connection_handle = connection;
697         g_xmppData.message_callback.on_received = CARAXmppMessageReceivedCB;
698         g_xmppData.message_callback.on_sent = CARAXmppMessageSentCB;
699         g_xmppData.message_context = xmpp_message_context_create(g_xmppData.connection_handle,
700                 g_xmppData.message_callback);
701     }
702     else
703     {
704         g_xmppData.connection_status = CA_INTERFACE_DOWN;
705         connection_status = CA_INTERFACE_DOWN;
706         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "XMPP connected callback status: %d", result);
707     }
708
709     ca_mutex_unlock (g_raadapterMutex);
710     // Notify network change to CA
711     CARANotifyNetworkChange(bound_jid, connection_status);
712
713     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppConnectedCB OUT");
714 }
715
716 void CARAXmppDisonnectedCB(void * const param, xmpp_error_code_t result,
717         xmpp_connection_handle_t connection)
718 {
719     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppDisonnectedCB IN");
720     char jabberID[CA_RAJABBERID_SIZE];
721     ca_mutex_lock (g_raadapterMutex);
722
723     g_xmppData.connection_status = CA_INTERFACE_DOWN;
724     xmpp_message_context_destroy(g_xmppData.message_context);
725     OICStrcpy (jabberID, CA_RAJABBERID_SIZE, g_xmppData.jabberID);
726
727     ca_mutex_unlock (g_raadapterMutex);
728
729     // Notify network change to CA
730     CARANotifyNetworkChange(jabberID, CA_INTERFACE_DOWN);
731
732     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppDisonnectedCB OUT");
733 }
734
735 void CARAXmppMessageSentCB(void * const param, xmpp_error_code_t result,
736         const void *const recipient, const void *const msg, size_t messageOctets)
737 {
738     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "Sending message to %s has result %d",
739         recipient, result);
740 }
741
742 void CARAXmppMessageReceivedCB(void * const param, xmpp_error_code_t result,
743         const void *const sender, const void *const msg, size_t messageOctets)
744 {
745     if (g_networkPacketCallback)
746     {
747         VERIFY_NON_NULL_VOID(sender, RA_ADAPTER_TAG, "sender is NULL");
748         VERIFY_NON_NULL_VOID(msg,    RA_ADAPTER_TAG, "message is NULL");
749
750         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "Message received from %s", sender);
751         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "Message reception result %d", result);
752
753         CAEndpoint_t *endPoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
754                         CA_ADAPTER_REMOTE_ACCESS, sender, 0);
755         if (!endPoint)
756         {
757             OIC_LOG(ERROR, RA_ADAPTER_TAG, "EndPoint creation failed!");
758             return;
759         }
760
761         void *buf = OICMalloc(messageOctets);
762         if (!buf)
763         {
764             OIC_LOG(ERROR, RA_ADAPTER_TAG, "Memory alloc of message failed!");
765             CAFreeEndpoint(endPoint);
766             return;
767         }
768         memcpy(buf, msg, messageOctets);
769         CANetworkPacketReceivedCallback networkPacketCallback = g_networkPacketCallback;
770         if (networkPacketCallback)
771         {
772             g_networkPacketCallback(endPoint, buf, messageOctets);
773         }
774
775         CAFreeEndpoint (endPoint);
776     }
777     else
778     {
779         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "No callback for RA  received message found");
780     }
781 }
782
783 CAResult_t CAInitializeRA(CARegisterConnectivityCallback registerCallback,
784                                 CANetworkPacketReceivedCallback networkPacketCallback,
785                                 CANetworkChangeCallback netCallback, ca_thread_pool_t handle)
786 {
787     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CAInitializeRA IN");
788     if (!registerCallback || !networkPacketCallback || !netCallback || !handle)
789     {
790         return CA_STATUS_INVALID_PARAM;
791     }
792
793     g_networkChangeCallback = netCallback;
794     g_networkPacketCallback = networkPacketCallback;
795
796     CAConnectivityHandler_t raHandler = {};
797     raHandler.startAdapter = CAStartRA;
798     raHandler.startListenServer = CAStartRAListeningServer;
799     raHandler.stopListenServer = CAStopRAListeningServer;
800     raHandler.startDiscoveryServer = CAStartRADiscoveryServer;
801     raHandler.sendData = CASendRAUnicastData;
802     raHandler.sendDataToAll = CASendRAMulticastData;
803     raHandler.GetnetInfo = CAGetRAInterfaceInformation;
804     raHandler.readData = CAReadRAData;
805     raHandler.stopAdapter = CAStopRA;
806     raHandler.terminate = CATerminateRA;
807     registerCallback(raHandler, CA_ADAPTER_REMOTE_ACCESS);
808
809     return CA_STATUS_OK;
810 }
811
812 CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo)
813 {
814     if (!caraInfo)
815     {
816         return CA_STATUS_INVALID_PARAM;
817     }
818     xmpp_identity_init(&g_xmppData.g_identity, caraInfo->username, caraInfo->password,
819             caraInfo->user_jid, XMPP_TRY_IN_BAND_REGISTER);
820     xmpp_host_init(&g_xmppData.g_host, caraInfo->hostname, caraInfo->port,
821             caraInfo->xmpp_domain, XMPP_PROTOCOL_XMPP);
822     return CA_STATUS_OK;
823 }
824
825 void CATerminateRA()
826 {
827     CAStopRA();
828 }
829
830 CAResult_t CAStartRA()
831 {
832     if (g_xmppData.handle.abstract_handle)
833     {
834         OIC_LOG(WARNING, RA_ADAPTER_TAG, "RA adapter already started");
835         return CA_STATUS_OK;
836     }
837
838     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Starting RA adapter"));
839
840     g_raadapterMutex = ca_mutex_new ();
841     if (!g_raadapterMutex)
842     {
843         OIC_LOG (ERROR, RA_ADAPTER_TAG, PCF("Memory allocation for mutex failed."));
844         return CA_MEMORY_ALLOC_FAILED;
845     }
846
847     ca_mutex_lock (g_raadapterMutex);
848
849     xmpp_context_init(&g_xmppData.context);
850     g_xmppData.handle = xmpp_startup(&g_xmppData.context);
851
852     // Wire up connection callbacks and call API to connect to XMPP server
853     g_xmppData.connection_callback.on_connected = CARAXmppConnectedCB;
854     g_xmppData.connection_callback.on_disconnected = CARAXmppDisonnectedCB;
855
856     xmpp_error_code_t ret = xmpp_connect(g_xmppData.handle, &g_xmppData.g_host,
857             &g_xmppData.g_identity, g_xmppData.connection_callback);
858
859     // Destroy host and identity structures as they are only
860     // required to establish initial connection
861     xmpp_identity_destroy(&g_xmppData.g_identity);
862     xmpp_host_destroy(&g_xmppData.g_host);
863
864     ca_mutex_unlock (g_raadapterMutex);
865
866     if (XMPP_ERR_OK != ret)
867     {
868         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to init XMPP connection status: %d",
869             ret);
870         return CA_STATUS_FAILED;
871     }
872
873     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "RA adapter started succesfully");
874     return CA_STATUS_OK;
875 }
876
877 CAResult_t CAStopRA()
878 {
879     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopping RA adapter"));
880
881     xmpp_error_code_t ret = xmpp_close(g_xmppData.connection_handle);
882     if (XMPP_ERR_OK != ret)
883     {
884         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to close XMPP connection, status: %d",
885             ret);
886         return CA_STATUS_FAILED;
887     }
888
889     xmpp_shutdown_xmpp(g_xmppData.handle);
890     xmpp_context_destroy(&g_xmppData.context);
891     ca_mutex_free (g_raadapterMutex);
892     g_raadapterMutex = NULL;
893
894     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopped RA adapter successfully"));
895     return CA_STATUS_OK;
896 }
897
898 int32_t CASendRAUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data,
899                                   uint32_t dataLength)
900 {
901     if (!remoteEndpoint || !data)
902     {
903         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
904         return -1;
905     }
906
907     if (0 == dataLength)
908     {
909         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Data length is 0!");
910         return 0;
911     }
912
913     OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Sending unicast data to %s", remoteEndpoint->addr);
914     ca_mutex_lock (g_raadapterMutex);
915
916     if (CA_INTERFACE_UP != g_xmppData.connection_status)
917     {
918         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, RA not connected");
919         ca_mutex_unlock (g_raadapterMutex);
920         return -1;
921     }
922
923     xmpp_error_code_t res = xmpp_send_message(g_xmppData.message_context,
924             remoteEndpoint->addr, data, dataLength,
925             XMPP_MESSAGE_TRANSMIT_DEFAULT);
926     if (XMPP_ERR_OK != res)
927     {
928         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, status: %d", res);
929         ca_mutex_unlock (g_raadapterMutex);
930         return -1;
931     }
932     ca_mutex_unlock (g_raadapterMutex);
933
934     OIC_LOG_V(INFO, RA_ADAPTER_TAG, "Successfully dispatched bytes[%d] to addr[%s]",
935             dataLength, remoteEndpoint->addr);
936
937     return dataLength;
938 }
939
940 CAResult_t CAGetRAInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
941 {
942     VERIFY_NON_NULL(info, RA_ADAPTER_TAG, "info is NULL");
943     VERIFY_NON_NULL(size, RA_ADAPTER_TAG, "size is NULL");
944
945     ca_mutex_lock (g_raadapterMutex);
946
947     if (CA_INTERFACE_UP != g_xmppData.connection_status)
948     {
949         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Failed to get interface info, RA not Connected");
950         ca_mutex_unlock (g_raadapterMutex);
951         return CA_ADAPTER_NOT_ENABLED;
952     }
953
954     ca_mutex_unlock (g_raadapterMutex);
955
956     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
957                                  CA_ADAPTER_REMOTE_ACCESS,
958                                  g_xmppData.jabberID, 0);
959
960     *size = 1;
961     *info = localEndpoint;
962
963     return CA_STATUS_OK;
964 }
965
966 int32_t CASendRAMulticastData(const CAEndpoint_t *endpoint,
967                     const void *data, uint32_t dataLength)
968 {
969     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support sending multicast data");
970     return 0;
971 }
972
973 CAResult_t CAStartRAListeningServer()
974 {
975     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
976     return CA_NOT_SUPPORTED;
977 }
978
979 CAResult_t CAStopRAListeningServer()
980 {
981     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
982     return CA_NOT_SUPPORTED;
983 }
984
985 CAResult_t CAStartRADiscoveryServer()
986 {
987     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support discovery of multicast servers");
988     return CA_NOT_SUPPORTED;
989 }
990
991 CAResult_t CAReadRAData()
992 {
993     OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
994     return CA_NOT_SUPPORTED;
995 }
996 #endif