Merge branch 'master' into 'security-CKM' branch.
[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.startDiscoveryServer = CAStartRADiscoveryServer;
235     raHandler.sendData = CASendRAUnicastData;
236     raHandler.sendDataToAll = CASendRAMulticastData;
237     raHandler.GetnetInfo = CAGetRAInterfaceInformation;
238     raHandler.readData = CAReadRAData;
239     raHandler.stopAdapter = CAStopRA;
240     raHandler.terminate = CATerminateRA;
241     registerCallback(raHandler, CA_ADAPTER_REMOTE_ACCESS);
242
243     return CA_STATUS_OK;
244 }
245
246 CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo)
247 {
248     if (!caraInfo)
249     {
250         return CA_STATUS_INVALID_PARAM;
251     }
252     xmpp_identity_init(&g_xmppData.g_identity, caraInfo->username, caraInfo->password,
253             caraInfo->user_jid, XMPP_TRY_IN_BAND_REGISTER);
254     xmpp_host_init(&g_xmppData.g_host, caraInfo->hostname, caraInfo->port,
255             caraInfo->xmpp_domain, XMPP_PROTOCOL_XMPP);
256     return CA_STATUS_OK;
257 }
258
259 void CATerminateRA()
260 {
261     CAStopRA();
262 }
263
264 CAResult_t CAStartRA()
265 {
266     if (g_xmppData.handle.abstract_handle)
267     {
268         OIC_LOG(WARNING, RA_ADAPTER_TAG, "RA adapter already started");
269         return CA_STATUS_OK;
270     }
271
272     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Starting RA adapter"));
273
274     g_raadapterMutex = ca_mutex_new ();
275     if (!g_raadapterMutex)
276     {
277         OIC_LOG (ERROR, RA_ADAPTER_TAG, PCF("Memory allocation for mutex failed."));
278         return CA_MEMORY_ALLOC_FAILED;
279     }
280
281     ca_mutex_lock (g_raadapterMutex);
282
283     xmpp_context_init(&g_xmppData.context);
284     g_xmppData.handle = xmpp_startup(&g_xmppData.context);
285
286     // Wire up connection callbacks and call API to connect to XMPP server
287     g_xmppData.connection_callback.on_connected = CARAXmppConnectedCB;
288     g_xmppData.connection_callback.on_disconnected = CARAXmppDisonnectedCB;
289
290     xmpp_error_code_t ret = xmpp_connect(g_xmppData.handle, &g_xmppData.g_host,
291             &g_xmppData.g_identity, g_xmppData.connection_callback);
292
293     // Destroy host and identity structures as they are only
294     // required to establish initial connection
295     xmpp_identity_destroy(&g_xmppData.g_identity);
296     xmpp_host_destroy(&g_xmppData.g_host);
297
298     ca_mutex_unlock (g_raadapterMutex);
299
300     if (XMPP_ERR_OK != ret)
301     {
302         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to init XMPP connection status: %d",
303             ret);
304         return CA_STATUS_FAILED;
305     }
306
307     OIC_LOG(DEBUG, RA_ADAPTER_TAG, "RA adapter started succesfully");
308     return CA_STATUS_OK;
309 }
310
311 CAResult_t CAStopRA()
312 {
313     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopping RA adapter"));
314
315     xmpp_error_code_t ret = xmpp_close(g_xmppData.connection_handle);
316     if (XMPP_ERR_OK != ret)
317     {
318         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Failed to close XMPP connection, status: %d",
319             ret);
320         return CA_STATUS_FAILED;
321     }
322
323     xmpp_shutdown_xmpp(g_xmppData.handle);
324     xmpp_context_destroy(&g_xmppData.context);
325     ca_mutex_free (g_raadapterMutex);
326     g_raadapterMutex = NULL;
327
328     OIC_LOG(DEBUG, RA_ADAPTER_TAG, PCF("Stopped RA adapter successfully"));
329     return CA_STATUS_OK;
330 }
331
332 int32_t CASendRAUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data,
333                                   uint32_t dataLength)
334 {
335     if (!remoteEndpoint || !data)
336     {
337         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Invalid parameter!");
338         return -1;
339     }
340
341     if (0 == dataLength)
342     {
343         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Data length is 0!");
344         return 0;
345     }
346
347     OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Sending unicast data to %s", remoteEndpoint->addr);
348     ca_mutex_lock (g_raadapterMutex);
349
350     if (CA_INTERFACE_UP != g_xmppData.connection_status)
351     {
352         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, RA not connected");
353         ca_mutex_unlock (g_raadapterMutex);
354         return -1;
355     }
356
357     xmpp_error_code_t res = xmpp_send_message(g_xmppData.message_context,
358             remoteEndpoint->addr, data, dataLength,
359             XMPP_MESSAGE_TRANSMIT_DEFAULT);
360     if (XMPP_ERR_OK != res)
361     {
362         OIC_LOG_V(ERROR, RA_ADAPTER_TAG, "Unable to send XMPP message, status: %d", res);
363         ca_mutex_unlock (g_raadapterMutex);
364         return -1;
365     }
366     ca_mutex_unlock (g_raadapterMutex);
367
368     OIC_LOG_V(INFO, RA_ADAPTER_TAG, "Successfully dispatched bytes[%d] to addr[%s]",
369             dataLength, remoteEndpoint->addr);
370
371     return dataLength;
372 }
373
374 CAResult_t CAGetRAInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
375 {
376     VERIFY_NON_NULL(info, RA_ADAPTER_TAG, "info is NULL");
377     VERIFY_NON_NULL(size, RA_ADAPTER_TAG, "size is NULL");
378
379     ca_mutex_lock (g_raadapterMutex);
380
381     if (CA_INTERFACE_UP != g_xmppData.connection_status)
382     {
383         OIC_LOG(ERROR, RA_ADAPTER_TAG, "Failed to get interface info, RA not Connected");
384         ca_mutex_unlock (g_raadapterMutex);
385         return CA_ADAPTER_NOT_ENABLED;
386     }
387
388     ca_mutex_unlock (g_raadapterMutex);
389
390     CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
391                                  CA_ADAPTER_REMOTE_ACCESS,
392                                  g_xmppData.jabberID, 0);
393
394     *size = 1;
395     *info = localEndpoint;
396
397     return CA_STATUS_OK;
398 }
399
400 int32_t CASendRAMulticastData(const CAEndpoint_t *endpoint,
401                     const void *data, uint32_t dataLength)
402 {
403     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support sending multicast data");
404     return 0;
405 }
406
407 CAResult_t CAStartRAListeningServer()
408 {
409     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support listening for multicast data");
410     return CA_NOT_SUPPORTED;
411 }
412
413 CAResult_t CAStartRADiscoveryServer()
414 {
415     OIC_LOG(INFO, RA_ADAPTER_TAG, "RA adapter does not support discovery of multicast servers");
416     return CA_NOT_SUPPORTED;
417 }
418
419 CAResult_t CAReadRAData()
420 {
421     OIC_LOG(INFO, RA_ADAPTER_TAG, "Read data is not implemented for the RA adapter");
422     return CA_NOT_SUPPORTED;
423 }