[Arduino Due] Arduino wifi multicast defalut return value changed to CA_STATUS_OK
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / arduino / caipserver_wifi.cpp
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics 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 "caipinterface.h"
22
23 #include <Arduino.h>
24 #include <WiFi.h>
25 #include <WiFiUdp.h>
26 #include <SPI.h>
27 #include <utility/server_drv.h>
28 #include <utility/wifi_drv.h>
29 #include <IPAddress.h>
30
31 #include "logger.h"
32 #include "cacommon.h"
33 #include "cainterface.h"
34 #include "caadapterinterface.h"
35 #include "caipadapter.h"
36 #include "caadapterutils.h"
37 #include "oic_malloc.h"
38 #include "oic_string.h"
39
40 #define TAG "IPS"
41
42 // Length of the IP address decimal notation string
43 #define IPNAMESIZE (16)
44
45 /** Multicast IP address.*/
46 #define IPv4_MULTICAST      "224.0.1.187"
47
48 /** Multicast Port.*/
49 #define IPv4_MULTICAST_PORT 5683
50
51 // Start offsets based on end of received data buffer
52 #define IP_RECBUF_IPADDR_OFFSET  (6)
53 #define IP_RECBUF_PORT_OFFSET    (2)
54
55 #define IP_RECBUF_IPADDR_SIZE    (IP_RECBUF_IPADDR_OFFSET - IP_RECBUF_PORT_OFFSET)
56 #define IP_RECBUF_PORT_SIZE      (IP_RECBUF_PORT_OFFSET - 0)
57 #define IP_RECBUF_FOOTER_SIZE    (IP_RECBUF_IPADDR_SIZE + IP_RECBUF_PORT_SIZE)
58
59 static void CAArduinoCheckData();
60 static void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
61                                      const void *data, const uint32_t dataLength);
62
63 static CAIPPacketReceivedCallback gPacketReceivedCallback = NULL;
64 static int32_t gUnicastSocket = 0;
65 static bool gServerRunning = false;
66 static WiFiUDP Udp;
67 /**
68  * @var g_unicastPort
69  * @brief Unicast Port
70  */
71 static uint16_t g_unicastPort = 0;
72
73 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
74 {
75     /**
76      * This API is to keep design in sync with other platforms.
77      * The required implementation is done in Start() api's.
78      */
79     return CA_STATUS_OK;
80 }
81
82 void CAIPTerminateServer(void)
83 {
84     /**
85      * This API is to keep design in sync with other platforms.
86      * The required implementation is done in Stop() api's.
87      */
88 }
89
90 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
91 {
92     return g_unicastPort;
93 }
94
95 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
96                                   bool secured)
97 {
98     OIC_LOG(DEBUG, TAG, "IN");
99     VERIFY_NON_NULL(port, TAG, "port");
100
101     if (gServerRunning)
102     {
103         // already running
104         OIC_LOG(DEBUG, TAG, "Error");
105         return CA_STATUS_FAILED;
106     }
107
108     if (WiFi.status() != WL_CONNECTED)
109     {
110         OIC_LOG(ERROR, TAG, "ERROR:No WIFI");
111         return CA_STATUS_FAILED;
112     }
113
114     OIC_LOG_V(DEBUG, TAG, "port: %u", *port);
115
116     Udp.begin((uint16_t ) *port);
117     gServerRunning = true;
118     g_unicastPort = *port;
119     caglobals.ip.u4.port =  *port;
120     OIC_LOG(DEBUG, TAG, "OUT");
121     return CA_STATUS_OK;
122 }
123
124 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
125                                       uint16_t multicastPort)
126 {
127     // wifi shield does not support multicast
128     OIC_LOG(DEBUG, TAG, "IN");
129     OIC_LOG(DEBUG, TAG, "OUT");
130     //Arduino wifi shiled does not support multicast.
131     //OCInit() is failing if an error code is returned here,
132     //hence blocking even uni-cast operations.
133     //So default return value is changed to CA_STATUS_OK.
134     return CA_STATUS_OK;
135 }
136
137 CAResult_t CAIPStartServer()
138 {
139     uint16_t unicastPort = 55555;
140
141     CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
142     if (CA_STATUS_OK != ret)
143     {
144         OIC_LOG_V(ERROR, TAG, "Start unicast server failed[%d]", ret);
145         return ret;
146     }
147     ret = CAIPStartMulticastServer("0.0.0.0", IPv4_MULTICAST, IPv4_MULTICAST_PORT);
148     if (CA_STATUS_OK != ret)
149     {
150         OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
151     }
152     return ret;
153 }
154
155 CAResult_t CAIPStopUnicastServer()
156 {
157     OIC_LOG(DEBUG, TAG, "IN");
158     Udp.stop();
159
160     gServerRunning = false;
161     caglobals.ip.u4.port =  0;
162     OIC_LOG(DEBUG, TAG, "OUT");
163     return CA_STATUS_OK;
164 }
165
166 CAResult_t CAIPStopMulticastServer()
167 {
168     return CAIPStopUnicastServer();
169 }
170
171 CAResult_t CAIPStartListenServer()
172 {
173     CAResult_t ret = CAIPStartMulticastServer("0.0.0.0", IPv4_MULTICAST, IPv4_MULTICAST_PORT);
174     if (CA_STATUS_OK != ret)
175     {
176         OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
177     }
178     return ret;
179 }
180
181 CAResult_t CAIPStopListenServer()
182 {
183     return CAIPStopMulticastServer();
184 }
185
186 void CAIPStopServer()
187 {
188     OIC_LOG(DEBUG, TAG, "IN");
189     CAResult_t result = CAIPStopUnicastServer();
190     if (CA_STATUS_OK != result)
191     {
192         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
193         return;
194     }
195     CAIPSetUnicastSocket(-1);
196     CAIPSetUnicastPort(0);
197
198     result = CAIPStopMulticastServer();
199     if (CA_STATUS_OK != result)
200     {
201         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
202     }
203     OIC_LOG(DEBUG, TAG, "OUT");
204 }
205
206 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
207                               const void *data, const uint32_t dataLength)
208 {
209     OIC_LOG(DEBUG, TAG, "IN");
210     if (gPacketReceivedCallback)
211     {
212         CASecureEndpoint_t sep =
213         {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_IPV4, .port = port}};
214
215         OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), ipAddress);
216         gPacketReceivedCallback(&sep, data, dataLength);
217         OIC_LOG(DEBUG, TAG, "Notified network packet");
218     }
219     OIC_LOG(DEBUG, TAG, "OUT");
220 }
221
222 void CAArduinoCheckData()
223 {
224     OIC_LOG(DEBUG, TAG, "IN");
225     char addr[IPNAMESIZE] = {0};
226     uint16_t senderPort = 0;
227     int16_t packetSize = Udp.parsePacket();
228     OIC_LOG_V(DEBUG, TAG, "Rcv packet of size:%d ", packetSize);
229     if (packetSize)
230     {
231         packetSize = packetSize > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:packetSize;
232         char *data = (char *)OICMalloc(packetSize + 1);
233         if (NULL == data)
234         {
235             return;
236         }
237         IPAddress remoteIp = Udp.remoteIP();
238         senderPort = Udp.remotePort();
239         sprintf(addr, "%d.%d.%d.%d", remoteIp[0], remoteIp[1], remoteIp[2], remoteIp[3]);
240         OIC_LOG_V(DEBUG, TAG, "remoteip: %s, port: %d", addr, senderPort);
241         // read the packet into packetBufffer
242         int32_t dataLen = Udp.read(data, COAP_MAX_PDU_SIZE);
243         if (dataLen > 0)
244         {
245             data[dataLen] = 0;
246         }
247         CAPacketReceivedCallback(addr, senderPort, data, dataLen);
248         OICFree(data);
249     }
250     OIC_LOG(DEBUG, TAG, "OUT");
251 }
252
253 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
254 {
255     OIC_LOG(DEBUG, TAG, "IN");
256     gPacketReceivedCallback = callback;
257     OIC_LOG(DEBUG, TAG, "OUT");
258 }
259
260 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
261 {
262     // TODO
263 }
264
265 void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
266 {
267     OIC_LOG(DEBUG, TAG, "IN");
268     OIC_LOG(DEBUG, TAG, "OUT");
269 }
270
271 void CAIPPullData()
272 {
273     CAArduinoCheckData();
274 }
275
276 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
277 {
278     OIC_LOG(DEBUG, TAG, "IN");
279
280     VERIFY_NON_NULL(info, TAG, "info is NULL");
281     VERIFY_NON_NULL(size, TAG, "size is NULL");
282
283     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
284     if (!iflist)
285     {
286         OIC_LOG(ERROR, TAG, "get interface info failed");
287         return CA_STATUS_FAILED;
288     }
289
290     uint32_t len = u_arraylist_length(iflist);
291
292     CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
293     if (!eps)
294     {
295         OIC_LOG(ERROR, TAG, "Malloc Failed");
296         u_arraylist_destroy(iflist);
297         return CA_MEMORY_ALLOC_FAILED;
298     }
299
300     for (uint32_t i = 0, j = 0; i < len; i++)
301     {
302         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
303         if(!ifitem)
304         {
305             continue;
306         }
307         unsigned char *addr=  (unsigned char *) &(ifitem->ipv4addr);
308         snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
309
310         eps[j].flags = CA_IPV4;
311         eps[j].adapter = CA_ADAPTER_IP;
312         eps[j].interface = 0;
313         eps[j].port = caglobals.ip.u4.port;
314         j++;
315     }
316
317     *info = eps;
318     *size = len;
319
320     u_arraylist_destroy(iflist);
321
322     OIC_LOG(DEBUG, TAG, "OUT");
323     return CA_STATUS_OK;
324 }