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