Imported Upstream version 1.0.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 "ra_xmpp.h"
35 #include "caremotehandler.h"
36 #include "cacommon.h"
37
38 /**
39  * Logging tag for module name.
40  */
41 #define RA_ADAPTER_TAG "RA_ADAP"
42
43 /**
44  * Network Packet Received Callback to CA.
45  */
46 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
47
48 /**
49  * Network Changed Callback to CA.
50  */
51 static CANetworkChangeCallback g_networkChangeCallback = NULL;
52
53 /**
54  * Holds XMPP data information.
55  */
56 typedef struct
57 {
58     xmpp_context_t context;
59     xmpp_handle_t handle;
60     xmpp_connection_callback_t connection_callback;
61     xmpp_connection_handle_t connection_handle;
62     xmpp_message_context_t message_context;
63     xmpp_message_callback_t message_callback;
64     CANetworkStatus_t connection_status;
65     xmpp_host_t     g_host;
66     xmpp_identity_t g_identity;
67     char jabberID[CA_RAJABBERID_SIZE];
68 } CARAXmppData_t;
69
70 static ca_mutex g_raadapterMutex = NULL;
71
72 static CARAXmppData_t g_xmppData = {};
73
74 static void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status);
75
76 static void CARAXmppConnectedCB(void * const param, xmpp_error_code_t result,
77         const char *const bound_jid,
78         xmpp_connection_handle_t connection);
79
80 static void CARAXmppDisonnectedCB(void * const param, xmpp_error_code_t result,
81         xmpp_connection_handle_t connection);
82
83 static void CARAXmppMessageSentCB(void * const param, xmpp_error_code_t result,
84         const void *const recipient, const void *const msg, size_t messageOctets);
85
86 static void CARAXmppMessageReceivedCB(void * const param, xmpp_error_code_t result,
87         const void *const sender, const void *const msg, size_t messageOctets);
88
89 void CARANotifyNetworkChange(const char *address, CANetworkStatus_t status)
90 {
91     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange IN");
92
93     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
94                                 CA_ADAPTER_REMOTE_ACCESS,
95                                 address, 0);
96     if (!localEndpoint)
97     {
98         OIC_LOG(ERROR, RA_ADAPTER_TAG, "localEndpoint creation failed!");
99         return;
100     }
101     CANetworkChangeCallback networkChangeCallback = g_networkChangeCallback;
102     if (networkChangeCallback)
103     {
104         networkChangeCallback(localEndpoint, status);
105     }
106     else
107     {
108         OIC_LOG(ERROR, RA_ADAPTER_TAG, "g_networkChangeCallback is NULL");
109     }
110
111     CAFreeEndpoint(localEndpoint);
112
113     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARANotifyNetworkChange OUT");
114 }
115
116 void CARAXmppConnectedCB(void * const param, xmpp_error_code_t result,
117         const char *const bound_jid,
118         xmpp_connection_handle_t connection)
119 {
120     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppConnectedCB IN");
121     CANetworkStatus_t connection_status;
122     if (XMPP_ERR_OK == result)
123     {
124         printf("\n\n\t\t===>your jid: %s\n\n", bound_jid);
125
126         ca_mutex_lock (g_raadapterMutex);
127         OICStrcpy (g_xmppData.jabberID, CA_RAJABBERID_SIZE, bound_jid);
128
129         g_xmppData.connection_status = CA_INTERFACE_UP;
130         connection_status = CA_INTERFACE_UP;
131         g_xmppData.connection_handle = connection;
132         g_xmppData.message_callback.on_received = CARAXmppMessageReceivedCB;
133         g_xmppData.message_callback.on_sent = CARAXmppMessageSentCB;
134         g_xmppData.message_context = xmpp_message_context_create(g_xmppData.connection_handle,
135                 g_xmppData.message_callback);
136     }
137     else
138     {
139         g_xmppData.connection_status = CA_INTERFACE_DOWN;
140         connection_status = CA_INTERFACE_DOWN;
141         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "XMPP connected callback status: %d", result);
142     }
143
144     ca_mutex_unlock (g_raadapterMutex);
145     // Notify network change to CA
146     CARANotifyNetworkChange(bound_jid, connection_status);
147
148     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppConnectedCB OUT");
149 }
150
151 void CARAXmppDisonnectedCB(void * const param, xmpp_error_code_t result,
152         xmpp_connection_handle_t connection)
153 {
154     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppDisonnectedCB IN");
155     char jabberID[CA_RAJABBERID_SIZE];
156     ca_mutex_lock (g_raadapterMutex);
157
158     g_xmppData.connection_status = CA_INTERFACE_DOWN;
159     xmpp_message_context_destroy(g_xmppData.message_context);
160     OICStrcpy (jabberID, CA_RAJABBERID_SIZE, g_xmppData.jabberID);
161
162     ca_mutex_unlock (g_raadapterMutex);
163
164     // Notify network change to CA
165     CARANotifyNetworkChange(jabberID, CA_INTERFACE_DOWN);
166
167     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CARAXmppDisonnectedCB OUT");
168 }
169
170 void CARAXmppMessageSentCB(void * const param, xmpp_error_code_t result,
171         const void *const recipient, const void *const msg, size_t messageOctets)
172 {
173     OIC_LOG_V(DEBUG, RA_ADAPTER_TAG, "Sending message to %s has result %d",
174         recipient, result);
175 }
176
177 void CARAXmppMessageReceivedCB(void * const param, xmpp_error_code_t result,
178         const void *const sender, const void *const msg, size_t messageOctets)
179 {
180     if (g_networkPacketCallback)
181     {
182         VERIFY_NON_NULL_VOID(sender, RA_ADAPTER_TAG, "sender is NULL");
183         VERIFY_NON_NULL_VOID(msg,    RA_ADAPTER_TAG, "message is NULL");
184
185         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "Message received from %s", sender);
186         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "Message reception result %d", result);
187
188         CAEndpoint_t *endPoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
189                         CA_ADAPTER_REMOTE_ACCESS, sender, 0);
190         if (!endPoint)
191         {
192             OIC_LOG(ERROR, RA_ADAPTER_TAG, "EndPoint creation failed!");
193             return;
194         }
195
196         void *buf = OICMalloc(messageOctets);
197         if (!buf)
198         {
199             OIC_LOG(ERROR, RA_ADAPTER_TAG, "Memory alloc of message failed!");
200             CAFreeEndpoint(endPoint);
201             return;
202         }
203         memcpy(buf, msg, messageOctets);
204         CANetworkPacketReceivedCallback networkPacketCallback = g_networkPacketCallback;
205         if (networkPacketCallback)
206         {
207             g_networkPacketCallback(endPoint, buf, messageOctets);
208         }
209
210         CAFreeEndpoint (endPoint);
211     }
212     else
213     {
214         OIC_LOG_V (ERROR, RA_ADAPTER_TAG, "No callback for RA  received message found");
215     }
216 }
217
218 CAResult_t CAInitializeRA(CARegisterConnectivityCallback registerCallback,
219                                 CANetworkPacketReceivedCallback networkPacketCallback,
220                                 CANetworkChangeCallback netCallback, ca_thread_pool_t handle)
221 {
222     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "CAInitializeRA IN");
223     if (!registerCallback || !networkPacketCallback || !netCallback || !handle)
224     {
225         return CA_STATUS_INVALID_PARAM;
226     }
227
228     g_networkChangeCallback = netCallback;
229     g_networkPacketCallback = networkPacketCallback;
230
231     CAConnectivityHandler_t raHandler = {};
232     raHandler.startAdapter = CAStartRA;
233     raHandler.startListenServer = CAStartRAListeningServer;
234     raHandler.stopListenServer = CAStopRAListeningServer;
235     raHandler.startDiscoveryServer = CAStartRADiscoveryServer;
236     raHandler.sendData = CASendRAUnicastData;
237     raHandler.sendDataToAll = CASendRAMulticastData;
238     raHandler.GetnetInfo = CAGetRAInterfaceInformation;
239     raHandler.readData = CAReadRAData;
240     raHandler.stopAdapter = CAStopRA;
241     raHandler.terminate = CATerminateRA;
242     registerCallback(raHandler, CA_ADAPTER_REMOTE_ACCESS);
243
244     return CA_STATUS_OK;
245 }
246
247 CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo)
248 {
249     if (!caraInfo)
250     {
251         return CA_STATUS_INVALID_PARAM;
252     }
253     xmpp_identity_init(&g_xmppData.g_identity, caraInfo->username, caraInfo->password,
254             caraInfo->user_jid, XMPP_TRY_IN_BAND_REGISTER);
255     xmpp_host_init(&g_xmppData.g_host, caraInfo->hostname, caraInfo->port,
256             caraInfo->xmpp_domain, XMPP_PROTOCOL_XMPP);
257     return CA_STATUS_OK;
258 }
259
260 void CATerminateRA()
261 {
262     CAStopRA();
263 }
264
265 CAResult_t CAStartRA()
266 {
267     if (g_xmppData.handle.abstract_handle)
268     {
269         OIC_LOG(WARNING, RA_ADAPTER_TAG, "RA adapter already started");
270         return CA_STATUS_OK;
271     }
272
273     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Starting RA adapter"));
274
275     g_raadapterMutex = ca_mutex_new ();
276     if (!g_raadapterMutex)
277     {
278         OIC_LOG (ERROR, RA_ADAPTER_TAG, PCF("Memory allocation for mutex failed."));
279         return CA_MEMORY_ALLOC_FAILED;
280     }
281
282     ca_mutex_lock (g_raadapterMutex);
283
284     xmpp_context_init(&g_xmppData.context);
285     g_xmppData.handle = xmpp_startup(&g_xmppData.context);
286
287     // Wire up connection callbacks and call API to connect to XMPP server
288     g_xmppData.connection_callback.on_connected = CARAXmppConnectedCB;
289     g_xmppData.connection_callback.on_disconnected = CARAXmppDisonnectedCB;
290
291     xmpp_error_code_t ret = xmpp_connect(g_xmppData.handle, &g_xmppData.g_host,
292             &g_xmppData.g_identity, g_xmppData.connection_callback);
293
294     // Destroy host and identity structures as they are only
295     // required to establish initial connection
296     xmpp_identity_destroy(&g_xmppData.g_identity);
297     xmpp_host_destroy(&g_xmppData.g_host);
298
299     ca_mutex_unlock (g_raadapterMutex);
300
301     if (XMPP_ERR_OK != ret)
302     {
303         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to init XMPP connection status: %d",
304             ret);
305         return CA_STATUS_FAILED;
306     }
307
308     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "RA adapter started succesfully");
309     return CA_STATUS_OK;
310 }
311
312 CAResult_t CAStopRA()
313 {
314     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopping RA adapter"));
315
316     xmpp_error_code_t ret = xmpp_close(g_xmppData.connection_handle);
317     if (XMPP_ERR_OK != ret)
318     {
319         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to close XMPP connection, status: %d",
320             ret);
321         return CA_STATUS_FAILED;
322     }
323
324     xmpp_shutdown_xmpp(g_xmppData.handle);
325     xmpp_context_destroy(&g_xmppData.context);
326     ca_mutex_free (g_raadapterMutex);
327     g_raadapterMutex = NULL;
328
329     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopped RA adapter successfully"));
330     return CA_STATUS_OK;
331 }
332
333 int32_t CASendRAUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data,
334                                   uint32_t dataLength)
335 {
336     if (!remoteEndpoint || !data)
337     {
338         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
339         return -1;
340     }
341
342     if (0 == dataLength)
343     {
344         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Data length is 0!");
345         return 0;
346     }
347
348     OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Sending unicast data to %s", remoteEndpoint->addr);
349     ca_mutex_lock (g_raadapterMutex);
350
351     if (CA_INTERFACE_UP != g_xmppData.connection_status)
352     {
353         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, RA not connected");
354         ca_mutex_unlock (g_raadapterMutex);
355         return -1;
356     }
357
358     xmpp_error_code_t res = xmpp_send_message(g_xmppData.message_context,
359             remoteEndpoint->addr, data, dataLength,
360             XMPP_MESSAGE_TRANSMIT_DEFAULT);
361     if (XMPP_ERR_OK != res)
362     {
363         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, status: %d", res);
364         ca_mutex_unlock (g_raadapterMutex);
365         return -1;
366     }
367     ca_mutex_unlock (g_raadapterMutex);
368
369     OIC_LOG_V(INFO, RA_ADAPTER_TAG, "Successfully dispatched bytes[%d] to addr[%s]",
370             dataLength, remoteEndpoint->addr);
371
372     return dataLength;
373 }
374
375 CAResult_t CAGetRAInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
376 {
377     VERIFY_NON_NULL(info, RA_ADAPTER_TAG, "info is NULL");
378     VERIFY_NON_NULL(size, RA_ADAPTER_TAG, "size is NULL");
379
380     ca_mutex_lock (g_raadapterMutex);
381
382     if (CA_INTERFACE_UP != g_xmppData.connection_status)
383     {
384         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Failed to get interface info, RA not Connected");
385         ca_mutex_unlock (g_raadapterMutex);
386         return CA_ADAPTER_NOT_ENABLED;
387     }
388
389     ca_mutex_unlock (g_raadapterMutex);
390
391     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
392                                  CA_ADAPTER_REMOTE_ACCESS,
393                                  g_xmppData.jabberID, 0);
394
395     *size = 1;
396     *info = localEndpoint;
397
398     return CA_STATUS_OK;
399 }
400
401 int32_t CASendRAMulticastData(const CAEndpoint_t *endpoint,
402                     const void *data, uint32_t dataLength)
403 {
404     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support sending multicast data");
405     return 0;
406 }
407
408 CAResult_t CAStartRAListeningServer()
409 {
410     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
411     return CA_NOT_SUPPORTED;
412 }
413
414 CAResult_t CAStopRAListeningServer()
415 {
416     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
417     return CA_NOT_SUPPORTED;
418 }
419
420 CAResult_t CAStartRADiscoveryServer()
421 {
422     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support discovery of multicast servers");
423     return CA_NOT_SUPPORTED;
424 }
425
426 CAResult_t CAReadRAData()
427 {
428     OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
429     return CA_NOT_SUPPORTED;
430 }