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