Imported Upstream version 1.1.0
[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 "OIC_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         .stopAdapter = CAStopRA,
378         .startListenServer = CAStartRAListeningServer,
379         .startDiscoveryServer = CAStartRADiscoveryServer,
380         .sendData = CASendRAUnicastData,
381         .sendDataToAll = CASendRAMulticastData,
382         .GetnetInfo = CAGetRAInterfaceInformation,
383         .readData = CAReadRAData,
384         .terminate = CATerminateRA,
385         .cType = CA_ADAPTER_REMOTE_ACCESS};
386
387     registerCallback(raHandler);
388 #ifdef NDEBUG
389     xmpp_log_t *log = xmpp_get_default_logger(XMPP_LEVEL_ERROR);
390 #else
391     xmpp_log_t *log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
392 #endif
393     g_xmppData.xmpp = xmpphelper_new(CARAConnHandler, NULL, log, NULL);
394     xmpphelper_force_tls(g_xmppData.xmpp);
395     g_observerList = ilist_new();
396
397     return CA_STATUS_OK;
398 }
399
400 CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo)
401 {
402     if (!caraInfo)
403     {
404         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
405         return CA_STATUS_INVALID_PARAM;
406     }
407     if (caraInfo->hostName != NULL)
408     {
409         OICStrcpy(g_xmppData.hostName, sizeof(g_xmppData.hostName), caraInfo->hostName);
410     }
411     else
412     {
413         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
414         return CA_STATUS_INVALID_PARAM;
415     }
416     if (caraInfo->userName != NULL && strlen(caraInfo->userName) != 0)
417     {
418         OICStrcpy(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->userName);
419     }
420     else
421     {
422         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
423         return CA_STATUS_INVALID_PARAM;
424     }
425     if (caraInfo->xmppDomain != NULL && strlen(caraInfo->xmppDomain) != 0)
426     {
427         OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), "@");
428         OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->xmppDomain);
429         if (caraInfo->resource != NULL && strlen(caraInfo->resource) != 0)
430         {
431             OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), "/");
432             OICStrcat(g_xmppData.jid, sizeof(g_xmppData.jid), caraInfo->resource);
433         }
434     }
435     if (caraInfo->password != NULL)
436     {
437         OICStrcpy(g_xmppData.password, sizeof(g_xmppData.password), caraInfo->password);
438     }
439     g_xmppData.port = caraInfo->port;
440     g_xmppData.jidBoundCallback = caraInfo->jidBoundCallback;
441
442     return CA_STATUS_OK;
443 }
444
445 void CATerminateRA()
446 {
447     CAStopRA();
448     ilist_destroy(g_observerList);
449     xmpphelper_join(g_xmppData.xmpp);
450     xmpphelper_release(g_xmppData.xmpp);
451     g_xmppData.xmpp = NULL;
452 }
453
454 CAResult_t CAStartRA()
455 {
456     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Starting RA adapter"));
457
458     if (!g_xmppData.xmpp)
459     {
460         OIC_LOG (ERROR, RA_ADAPTER_TAG, "CAStartRA(): g_xmppData.xmpp == NULL");
461         return CA_STATUS_FAILED;
462     }
463
464     g_raadapterMutex = ca_mutex_new ();
465     if (!g_raadapterMutex)
466     {
467         OIC_LOG (ERROR, RA_ADAPTER_TAG, PCF("Memory allocation for mutex failed."));
468         return CA_MEMORY_ALLOC_FAILED;
469     }
470
471     ca_mutex_lock (g_raadapterMutex);
472
473     xmpphelper_connect(g_xmppData.xmpp, g_xmppData.hostName, g_xmppData.port,
474                     g_xmppData.jid, g_xmppData.password);
475     xmpp_ibb_reg_funcs_t regfuncs;
476     regfuncs.open_cb = CARAOpenCB;
477     regfuncs.close_cb = CARACloseCB;
478     regfuncs.recv_cb = CARARecvCB;
479     regfuncs.error_cb = CARAErrorCB;
480     xmpp_ibb_register(xmpphelper_get_conn(g_xmppData.xmpp), &regfuncs);
481
482     xmpphelper_run(g_xmppData.xmpp);
483
484     ca_mutex_unlock (g_raadapterMutex);
485
486     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "RA adapter started succesfully");
487     return CA_STATUS_OK;
488 }
489
490 CAResult_t CAStopRA()
491 {
492     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopping RA adapter"));
493
494     xmpphelper_stop(g_xmppData.xmpp);
495     xmpp_ibb_unregister(xmpphelper_get_conn(g_xmppData.xmpp));
496     if (!g_raadapterMutex)
497     {
498         ca_mutex_free (g_raadapterMutex);
499         g_raadapterMutex = NULL;
500     }
501     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopped RA adapter successfully"));
502     return CA_STATUS_OK;
503 }
504
505 int32_t CASendRAUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data,
506                                   uint32_t dataLength)
507 {
508     if (!remoteEndpoint || !data)
509     {
510         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
511         return -1;
512     }
513
514     if (0 == dataLength)
515     {
516         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Data length is 0!");
517         return 0;
518     }
519     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "Sending unicast data to %s", remoteEndpoint->addr);
520
521     uint32_t code = CA_NOT_FOUND;
522     coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU(data, dataLength, &code, remoteEndpoint);
523     char *sid = CARAGetSIDFromPDU(pdu);
524     int obsopt = CARAGetReqObsOption(pdu, remoteEndpoint);
525     coap_delete_pdu(pdu);
526
527     ca_mutex_lock (g_raadapterMutex);
528     if (CA_INTERFACE_UP != g_xmppData.connectionStatus)
529     {
530         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, RA not connected");
531         ca_mutex_unlock (g_raadapterMutex);
532         return -1;
533     }
534
535     xmpp_ibb_session_t *sess = xmpp_ibb_get_session_by_sid(sid);
536     if (sess == NULL)
537     {
538         sess = xmpp_ibb_open(xmpphelper_get_conn(g_xmppData.xmpp), (char * const) remoteEndpoint->addr, sid);
539         if (sess == NULL)
540         {
541             OIC_LOG(ERROR, RA_ADAPTER_TAG, "IBB session establish failed!");
542             ca_mutex_unlock (g_raadapterMutex);
543             return -1;
544         }
545     }
546     if (CARAPDUIsRequest(code))
547     {
548         if (obsopt == OBSERVE_REGISTER || obsopt == OBSERVE_DEREGISTER)
549         {
550             CARAUpdateObsList(obsopt, sid);
551         }
552     }
553     xmppdata_t xdata = {.data = (char *) data, .size = dataLength};
554     int rc = xmpp_ibb_send_data(sess, &xdata);
555     ca_mutex_unlock (g_raadapterMutex);
556     if (rc < 0)
557     {
558         OIC_LOG(ERROR, RA_ADAPTER_TAG, "IBB send data failed!");
559         return -1;
560     }
561
562     OIC_LOG_V(INFO, RA_ADAPTER_TAG, "Successfully dispatched bytes[%d] to addr[%s]",
563             dataLength, remoteEndpoint->addr);
564
565     return dataLength;
566 }
567
568 CAResult_t CAGetRAInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
569 {
570     VERIFY_NON_NULL(info, RA_ADAPTER_TAG, "info is NULL");
571     VERIFY_NON_NULL(size, RA_ADAPTER_TAG, "size is NULL");
572     return CA_STATUS_OK;
573 }
574
575 int32_t CASendRAMulticastData(const CAEndpoint_t *endpoint,
576                     const void *data, uint32_t dataLength)
577 {
578     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support sending multicast data");
579     SET_BUT_NOT_USED(endpoint);
580     SET_BUT_NOT_USED(data);
581     SET_BUT_NOT_USED(dataLength);
582     return 0;
583 }
584
585 CAResult_t CAStartRAListeningServer()
586 {
587     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
588     return CA_NOT_SUPPORTED;
589 }
590
591 CAResult_t CAStartRADiscoveryServer()
592 {
593     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support discovery of multicast servers");
594     return CA_NOT_SUPPORTED;
595 }
596
597 CAResult_t CAReadRAData()
598 {
599     OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
600     return CA_NOT_SUPPORTED;
601 }
602
603 #else /* #ifdef RA_ADAPTER_IBB */
604
605 /**
606  * Logging tag for module name.
607  */
608 #define RA_ADAPTER_TAG "RA_ADAP"
609
610 /**
611  * Network Packet Received Callback to CA.
612  */
613 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
614
615 /**
616  * Network Changed Callback to CA.
617  */
618 static CANetworkChangeCallback g_networkChangeCallback = NULL;
619
620 /**
621  * Holds XMPP data information.
622  */
623 typedef struct
624 {
625     xmpp_context_t context;
626     xmpp_handle_t handle;
627     xmpp_connection_callback_t connection_callback;
628     xmpp_connection_handle_t connection_handle;
629     xmpp_message_context_t message_context;
630     xmpp_message_callback_t message_callback;
631     CANetworkStatus_t connection_status;
632     xmpp_host_t     g_host;
633     xmpp_identity_t g_identity;
634     char jabberID[CA_RAJABBERID_SIZE];
635 } CARAXmppData_t;
636
637 static ca_mutex g_raadapterMutex = NULL;
638
639 static CARAXmppData_t g_xmppData = {};
640
641 static void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status);
642
643 static void CARAXmppConnectedCB(void * const param, xmpp_error_code_t result,
644         const char *const bound_jid,
645         xmpp_connection_handle_t connection);
646
647 static void CARAXmppDisonnectedCB(void * const param, xmpp_error_code_t result,
648         xmpp_connection_handle_t connection);
649
650 static void CARAXmppMessageSentCB(void * const param, xmpp_error_code_t result,
651         const void *const recipient, const void *const msg, size_t messageOctets);
652
653 static void CARAXmppMessageReceivedCB(void * const param, xmpp_error_code_t result,
654         const void *const sender, const void *const msg, size_t messageOctets);
655
656 void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status)
657 {
658     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange IN");
659
660     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
661                                 CA_ADAPTER_REMOTE_ACCESS,
662                                 address, 0);
663     if (!localEndpoint)
664     {
665         OIC_LOG(ERROR, RA_ADAPTER_TAG, "localEndpoint creation failed!");
666         return;
667     }
668     CANetworkChangeCallback networkChangeCallback = g_networkChangeCallback;
669     if (networkChangeCallback)
670     {
671         networkChangeCallback(localEndpoint, status);
672     }
673     else
674     {
675         OIC_LOG(ERROR, RA_ADAPTER_TAG, "g_networkChangeCallback is NULL");
676     }
677
678     CAFreeEndpoint(localEndpoint);
679
680     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange OUT");
681 }
682
683 void CARAXmppConnectedCB(void * const param, xmpp_error_code_t result,
684         const char *const bound_jid,
685         xmpp_connection_handle_t connection)
686 {
687     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppConnectedCB IN");
688     CANetworkStatus_t connection_status;
689     if (XMPP_ERR_OK == result)
690     {
691         printf("\n\n\t\t===>your jid: %s\n\n", bound_jid);
692
693         ca_mutex_lock (g_raadapterMutex);
694         OICStrcpy (g_xmppData.jabberID, CA_RAJABBERID_SIZE, bound_jid);
695
696         g_xmppData.connection_status = CA_INTERFACE_UP;
697         connection_status = CA_INTERFACE_UP;
698         g_xmppData.connection_handle = connection;
699         g_xmppData.message_callback.on_received = CARAXmppMessageReceivedCB;
700         g_xmppData.message_callback.on_sent = CARAXmppMessageSentCB;
701         g_xmppData.message_context = xmpp_message_context_create(g_xmppData.connection_handle,
702                 g_xmppData.message_callback);
703     }
704     else
705     {
706         g_xmppData.connection_status = CA_INTERFACE_DOWN;
707         connection_status = CA_INTERFACE_DOWN;
708         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "XMPP connected callback status: %d", result);
709     }
710
711     ca_mutex_unlock (g_raadapterMutex);
712     // Notify network change to CA
713     CARANotifyNetworkChange(bound_jid, connection_status);
714
715     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppConnectedCB OUT");
716 }
717
718 void CARAXmppDisonnectedCB(void * const param, xmpp_error_code_t result,
719         xmpp_connection_handle_t connection)
720 {
721     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppDisonnectedCB IN");
722     char jabberID[CA_RAJABBERID_SIZE];
723     ca_mutex_lock (g_raadapterMutex);
724
725     g_xmppData.connection_status = CA_INTERFACE_DOWN;
726     xmpp_message_context_destroy(g_xmppData.message_context);
727     OICStrcpy (jabberID, CA_RAJABBERID_SIZE, g_xmppData.jabberID);
728
729     ca_mutex_unlock (g_raadapterMutex);
730
731     // Notify network change to CA
732     CARANotifyNetworkChange(jabberID, CA_INTERFACE_DOWN);
733
734     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppDisonnectedCB OUT");
735 }
736
737 void CARAXmppMessageSentCB(void * const param, xmpp_error_code_t result,
738         const void *const recipient, const void *const msg, size_t messageOctets)
739 {
740     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "Sending message to %s has result %d",
741         recipient, result);
742 }
743
744 void CARAXmppMessageReceivedCB(void * const param, xmpp_error_code_t result,
745         const void *const sender, const void *const msg, size_t messageOctets)
746 {
747     if (g_networkPacketCallback)
748     {
749         VERIFY_NON_NULL_VOID(sender, RA_ADAPTER_TAG, "sender is NULL");
750         VERIFY_NON_NULL_VOID(msg,    RA_ADAPTER_TAG, "message is NULL");
751
752         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "Message received from %s", sender);
753         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "Message reception result %d", result);
754
755         CAEndpoint_t *endPoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
756                         CA_ADAPTER_REMOTE_ACCESS, sender, 0);
757         if (!endPoint)
758         {
759             OIC_LOG(ERROR, RA_ADAPTER_TAG, "EndPoint creation failed!");
760             return;
761         }
762
763         void *buf = OICMalloc(messageOctets);
764         if (!buf)
765         {
766             OIC_LOG(ERROR, RA_ADAPTER_TAG, "Memory alloc of message failed!");
767             CAFreeEndpoint(endPoint);
768             return;
769         }
770         memcpy(buf, msg, messageOctets);
771         CANetworkPacketReceivedCallback networkPacketCallback = g_networkPacketCallback;
772         if (networkPacketCallback)
773         {
774             g_networkPacketCallback(endPoint, buf, messageOctets);
775         }
776
777         CAFreeEndpoint (endPoint);
778     }
779     else
780     {
781         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "No callback for RA  received message found");
782     }
783 }
784
785 CAResult_t CAInitializeRA(CARegisterConnectivityCallback registerCallback,
786                                 CANetworkPacketReceivedCallback networkPacketCallback,
787                                 CANetworkChangeCallback netCallback, ca_thread_pool_t handle)
788 {
789     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CAInitializeRA IN");
790     if (!registerCallback || !networkPacketCallback || !netCallback || !handle)
791     {
792         return CA_STATUS_INVALID_PARAM;
793     }
794
795     g_networkChangeCallback = netCallback;
796     g_networkPacketCallback = networkPacketCallback;
797
798     CAConnectivityHandler_t raHandler = {
799         .startAdapter = CAStartRA,
800         .stopAdapter = CAStopRA,
801         .startListenServer = CAStartRAListeningServer,
802         .stopListenServer = CAStopRAListeningServer,
803         .startDiscoveryServer = CAStartRADiscoveryServer,
804         .sendData = CASendRAUnicastData,
805         .sendDataToAll = CASendRAMulticastData,
806         .GetnetInfo = CAGetRAInterfaceInformation,
807         .readData = CAReadRAData,
808         .terminate = CATerminateRA,
809         .cType = CA_ADAPTER_REMOTE_ACCESS};
810     registerCallback(raHandler);
811
812     return CA_STATUS_OK;
813 }
814
815 CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo)
816 {
817     if (!caraInfo)
818     {
819         return CA_STATUS_INVALID_PARAM;
820     }
821     xmpp_identity_init(&g_xmppData.g_identity, caraInfo->username, caraInfo->password,
822             caraInfo->user_jid, XMPP_TRY_IN_BAND_REGISTER);
823     xmpp_host_init(&g_xmppData.g_host, caraInfo->hostname, caraInfo->port,
824             caraInfo->xmpp_domain, XMPP_PROTOCOL_XMPP);
825     return CA_STATUS_OK;
826 }
827
828 void CATerminateRA()
829 {
830     CAStopRA();
831 }
832
833 CAResult_t CAStartRA()
834 {
835     if (g_xmppData.handle.abstract_handle)
836     {
837         OIC_LOG(WARNING, RA_ADAPTER_TAG, "RA adapter already started");
838         return CA_STATUS_OK;
839     }
840
841     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Starting RA adapter"));
842
843     g_raadapterMutex = ca_mutex_new ();
844     if (!g_raadapterMutex)
845     {
846         OIC_LOG (ERROR, RA_ADAPTER_TAG, PCF("Memory allocation for mutex failed."));
847         return CA_MEMORY_ALLOC_FAILED;
848     }
849
850     ca_mutex_lock (g_raadapterMutex);
851
852     xmpp_context_init(&g_xmppData.context);
853     g_xmppData.handle = xmpp_startup(&g_xmppData.context);
854
855     // Wire up connection callbacks and call API to connect to XMPP server
856     g_xmppData.connection_callback.on_connected = CARAXmppConnectedCB;
857     g_xmppData.connection_callback.on_disconnected = CARAXmppDisonnectedCB;
858
859     xmpp_error_code_t ret = xmpp_connect(g_xmppData.handle, &g_xmppData.g_host,
860             &g_xmppData.g_identity, g_xmppData.connection_callback);
861
862     // Destroy host and identity structures as they are only
863     // required to establish initial connection
864     xmpp_identity_destroy(&g_xmppData.g_identity);
865     xmpp_host_destroy(&g_xmppData.g_host);
866
867     ca_mutex_unlock (g_raadapterMutex);
868
869     if (XMPP_ERR_OK != ret)
870     {
871         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to init XMPP connection status: %d",
872             ret);
873         return CA_STATUS_FAILED;
874     }
875
876     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "RA adapter started succesfully");
877     return CA_STATUS_OK;
878 }
879
880 CAResult_t CAStopRA()
881 {
882     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopping RA adapter"));
883
884     xmpp_error_code_t ret = xmpp_close(g_xmppData.connection_handle);
885     if (XMPP_ERR_OK != ret)
886     {
887         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to close XMPP connection, status: %d",
888             ret);
889         return CA_STATUS_FAILED;
890     }
891
892     xmpp_shutdown_xmpp(g_xmppData.handle);
893     xmpp_context_destroy(&g_xmppData.context);
894     ca_mutex_free (g_raadapterMutex);
895     g_raadapterMutex = NULL;
896
897     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopped RA adapter successfully"));
898     return CA_STATUS_OK;
899 }
900
901 int32_t CASendRAUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data,
902                                   uint32_t dataLength)
903 {
904     if (!remoteEndpoint || !data)
905     {
906         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
907         return -1;
908     }
909
910     if (0 == dataLength)
911     {
912         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Data length is 0!");
913         return 0;
914     }
915
916     OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Sending unicast data to %s", remoteEndpoint->addr);
917     ca_mutex_lock (g_raadapterMutex);
918
919     if (CA_INTERFACE_UP != g_xmppData.connection_status)
920     {
921         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, RA not connected");
922         ca_mutex_unlock (g_raadapterMutex);
923         return -1;
924     }
925
926     xmpp_error_code_t res = xmpp_send_message(g_xmppData.message_context,
927             remoteEndpoint->addr, data, dataLength,
928             XMPP_MESSAGE_TRANSMIT_DEFAULT);
929     if (XMPP_ERR_OK != res)
930     {
931         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, status: %d", res);
932         ca_mutex_unlock (g_raadapterMutex);
933         return -1;
934     }
935     ca_mutex_unlock (g_raadapterMutex);
936
937     OIC_LOG_V(INFO, RA_ADAPTER_TAG, "Successfully dispatched bytes[%d] to addr[%s]",
938             dataLength, remoteEndpoint->addr);
939
940     return dataLength;
941 }
942
943 CAResult_t CAGetRAInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
944 {
945     VERIFY_NON_NULL(info, RA_ADAPTER_TAG, "info is NULL");
946     VERIFY_NON_NULL(size, RA_ADAPTER_TAG, "size is NULL");
947
948     ca_mutex_lock (g_raadapterMutex);
949
950     if (CA_INTERFACE_UP != g_xmppData.connection_status)
951     {
952         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Failed to get interface info, RA not Connected");
953         ca_mutex_unlock (g_raadapterMutex);
954         return CA_ADAPTER_NOT_ENABLED;
955     }
956
957     ca_mutex_unlock (g_raadapterMutex);
958
959     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
960                                  CA_ADAPTER_REMOTE_ACCESS,
961                                  g_xmppData.jabberID, 0);
962
963     *size = 1;
964     *info = localEndpoint;
965
966     return CA_STATUS_OK;
967 }
968
969 int32_t CASendRAMulticastData(const CAEndpoint_t *endpoint,
970                     const void *data, uint32_t dataLength)
971 {
972     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support sending multicast data");
973     return 0;
974 }
975
976 CAResult_t CAStartRAListeningServer()
977 {
978     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
979     return CA_NOT_SUPPORTED;
980 }
981
982 CAResult_t CAStopRAListeningServer()
983 {
984     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
985     return CA_NOT_SUPPORTED;
986 }
987
988 CAResult_t CAStartRADiscoveryServer()
989 {
990     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support discovery of multicast servers");
991     return CA_NOT_SUPPORTED;
992 }
993
994 CAResult_t CAReadRAData()
995 {
996     OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
997     return CA_NOT_SUPPORTED;
998 }
999 #endif