Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / arduino / caipserver_eth.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 <Ethernet.h>
25 #include <socket.h>
26 #include <w5100.h>
27 #include <EthernetUdp.h>
28 #include <IPAddress.h>
29
30 #include "logger.h"
31 #include "cacommon.h"
32 #include "cainterface.h"
33 #include "caadapterinterface.h"
34 #include "caipadapter.h"
35 #include "caipadapterutils_eth.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 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
52                                         const bool forceStart, int32_t *serverFD);
53 static CAResult_t CAArduinoRecvData(int32_t sockFd);
54 static void CAArduinoCheckData();
55 static void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
56                               const void *data, const uint32_t dataLength);
57
58 static CAIPPacketReceivedCallback g_packetReceivedCallback = NULL;
59 static int g_unicastSocket = 0;
60 static int g_multicastSocket = 0;
61
62 /**
63  * @var g_isMulticastServerStarted
64  * @brief Flag to check if multicast server is started
65  */
66 static bool g_isMulticastServerStarted = false;
67
68 /**
69  * @var g_unicastPort
70  * @brief Unicast Port
71  */
72 static uint16_t g_unicastPort = 0;
73
74 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
75 {
76     return CA_STATUS_OK;
77 }
78
79 void CAIPTerminateServer(void)
80 {
81     return;
82 }
83
84 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
85 {
86     return g_unicastPort;
87 }
88
89 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
90                                   bool secured)
91 {
92     OIC_LOG(DEBUG, TAG, "IN");
93     VERIFY_NON_NULL(port, TAG, "port");
94
95     uint8_t rawIPAddr[4];
96     char address[16];
97     W5100.getIPAddress(rawIPAddr);
98     sprintf(address, "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2], rawIPAddr[3]);
99     OIC_LOG_V(DEBUG, TAG, "address:%s", address);
100     int serverFD = 1;
101     if (CAArduinoInitUdpSocket(port, &serverFD) != CA_STATUS_OK)
102     {
103         OIC_LOG(DEBUG, TAG, "failed");
104         return CA_STATUS_FAILED;
105     }
106
107     g_unicastPort = *port;
108     g_unicastSocket = serverFD;
109     CAIPSetUnicastSocket(g_unicastSocket);
110     CAIPSetUnicastPort(g_unicastPort);
111     caglobals.ip.u4.port =  *port;
112
113     OIC_LOG_V(DEBUG, TAG, "g_unicastPort: %u", g_unicastPort);
114     OIC_LOG_V(DEBUG, TAG, "g_unicastSocket: %d", g_unicastSocket);
115     OIC_LOG(DEBUG, TAG, "OUT");
116     return CA_STATUS_OK;
117 }
118
119 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
120                                     uint16_t multicastPort)
121 {
122     OIC_LOG(DEBUG, TAG, "IN");
123     if (g_isMulticastServerStarted == true)
124     {
125         OIC_LOG(ERROR, TAG, "Already Started!");
126         return CA_SERVER_STARTED_ALREADY;
127     }
128     int serverFD = 1;
129     if (CAArduinoInitMulticastUdpSocket(multicastAddress, multicastPort, multicastPort,
130                                         &serverFD) != CA_STATUS_OK)
131     {
132         OIC_LOG(DEBUG, TAG, "failed");
133         return CA_STATUS_FAILED;
134     }
135
136     g_multicastSocket = serverFD;
137     g_isMulticastServerStarted = true;
138
139     OIC_LOG_V(DEBUG, TAG, "gMulticastPort: %d", multicastPort);
140     OIC_LOG_V(DEBUG, TAG, "g_multicastSocket: %d", g_multicastSocket);
141     OIC_LOG(DEBUG, TAG, "OUT");
142     return CA_STATUS_OK;
143 }
144
145 CAResult_t CAIPStartServer()
146 {
147     uint16_t unicastPort = 55555;
148
149     CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
150     if (CA_STATUS_OK != ret)
151     {
152         OIC_LOG_V(ERROR, TAG, "Start unicast server failed[%d]", ret);
153         return ret;
154     }
155     ret = CAIPStartMulticastServer("0.0.0.0", IPv4_MULTICAST, IPv4_MULTICAST_PORT);
156     if (CA_STATUS_OK != ret)
157     {
158         OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
159     }
160     return ret;
161 }
162
163 CAResult_t CAIPStopUnicastServer()
164 {
165     OIC_LOG(DEBUG, TAG, "IN");
166     close(g_unicastSocket);
167     g_unicastSocket = 0;
168     caglobals.ip.u4.port =  0;
169     OIC_LOG(DEBUG, TAG, "OUT");
170     return CA_STATUS_OK;
171 }
172
173 CAResult_t CAIPStopMulticastServer()
174 {
175     OIC_LOG(DEBUG, TAG, "IN");
176     close(g_multicastSocket);
177     g_multicastSocket = 0;
178     OIC_LOG(DEBUG, TAG, "OUT");
179     return CA_STATUS_OK;
180 }
181
182 CAResult_t CAIPStartListenServer()
183 {
184     OIC_LOG(DEBUG, TAG, "IN");
185     CAResult_t ret = CAIPStartMulticastServer("0.0.0.0", IPv4_MULTICAST, IPv4_MULTICAST_PORT);
186     if (CA_STATUS_OK != ret)
187     {
188         OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
189     }
190     OIC_LOG(DEBUG, TAG, "OUT");
191     return CA_STATUS_OK;
192 }
193
194 CAResult_t CAIPStopListenServer()
195 {
196     OIC_LOG(DEBUG, TAG, "IN");
197     CAResult_t ret = CAIPStopMulticastServer();
198     if (CA_STATUS_OK != ret)
199     {
200         OIC_LOG_V(ERROR, TAG, "Stop multicast failed[%d]", ret);
201     }
202     OIC_LOG(DEBUG, TAG, "OUT");
203     return CA_STATUS_OK;
204 }
205
206 void CAIPStopServer()
207 {
208     OIC_LOG(DEBUG, TAG, "IN");
209     CAResult_t result = CAIPStopUnicastServer();
210     if (CA_STATUS_OK != result)
211     {
212         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
213         return;
214     }
215     CAIPSetUnicastSocket(-1);
216     CAIPSetUnicastPort(0);
217
218     result = CAIPStopMulticastServer();
219     if (CA_STATUS_OK != result)
220     {
221         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
222     }
223     OIC_LOG(DEBUG, TAG, "OUT");
224 }
225
226 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
227                               const void *data, const uint32_t dataLength)
228 {
229     OIC_LOG(DEBUG, TAG, "IN");
230     if (g_packetReceivedCallback)
231     {
232         CASecureEndpoint_t sep =
233         {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_IPV4, .port = port}};
234         OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), ipAddress);
235         g_packetReceivedCallback(&sep, data, dataLength);
236     }
237     OIC_LOG(DEBUG, TAG, "OUT");
238 }
239
240 void CAArduinoCheckData()
241 {
242     if (g_unicastSocket)
243     {
244         if (CAArduinoRecvData(g_unicastSocket) != CA_STATUS_OK)
245         {
246             OIC_LOG(ERROR, TAG, "rcv fail");
247             CAIPStopUnicastServer();
248         }
249     }
250
251     if (g_multicastSocket)
252     {
253         if (CAArduinoRecvData(g_multicastSocket) != CA_STATUS_OK)
254         {
255             OIC_LOG(ERROR, TAG, "rcv fail");
256             CAIPStopMulticastServer();
257         }
258     }
259 }
260
261 /** Retrieve any available data from UDP socket and call callback.
262  *  This is a non-blocking call.
263  */
264 CAResult_t CAArduinoRecvData(int32_t sockFd)
265 {
266     /**Bug : When there are multiple UDP packets in Wiznet buffer, W5100.getRXReceivedSize
267      * will not return correct length of the first packet.
268      * Fix : Use the patch provided for arduino/libraries/Ethernet/utility/socket.cpp
269      */
270
271     void *data = NULL;
272     uint8_t senderAddr[4] = { 0 };
273     char addr[IPNAMESIZE] = {0};
274     uint16_t senderPort = 0;
275
276     uint16_t recvLen = W5100.getRXReceivedSize(sockFd);
277     if (recvLen == 0)
278     {
279         // No data available on socket
280         return CA_STATUS_OK;
281     }
282
283     OIC_LOG_V(DEBUG, TAG, "rcvd %d", recvLen);
284     recvLen = recvLen > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:recvLen;
285
286     data = OICCalloc(recvLen + 1, 1);
287     if (NULL == data)
288     {
289         OIC_LOG(DEBUG, TAG, "Out of memory!");
290         return CA_MEMORY_ALLOC_FAILED;
291     }
292
293     // Read available data.
294     int32_t ret = recvfrom(sockFd, (uint8_t *)data, recvLen + 1, senderAddr, &senderPort);
295     if (ret < 0)
296     {
297         OIC_LOG(ERROR, TAG, "rcv fail");
298         OICFree(data);
299         return CA_STATUS_FAILED;
300     }
301     else if (ret > 0)
302     {
303         OIC_LOG(DEBUG, TAG, "data recvd");
304         snprintf(addr, sizeof(addr), "%d.%d.%d.%d", senderAddr[0], senderAddr[1], senderAddr[2],
305                  senderAddr[3]);
306         CAPacketReceivedCallback(addr, senderPort, data, ret);
307     }
308
309     OICFree(data);
310
311     OIC_LOG(DEBUG, TAG, "OUT");
312     return CA_STATUS_OK;
313 }
314
315 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
316 {
317     OIC_LOG(DEBUG, TAG, "IN");
318     g_packetReceivedCallback = callback;
319     OIC_LOG(DEBUG, TAG, "OUT");
320 }
321
322 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
323 {
324     // TODO
325 }
326
327 void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
328 {
329     OIC_LOG(DEBUG, TAG, "IN");
330     OIC_LOG(DEBUG, TAG, "OUT");
331 }
332
333 void CAIPPullData()
334 {
335     CAArduinoCheckData();
336 }
337
338 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
339 {
340     OIC_LOG(DEBUG, TAG, "IN");
341
342     VERIFY_NON_NULL(info, TAG, "info is NULL");
343     VERIFY_NON_NULL(size, TAG, "size is NULL");
344
345     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
346     if (!iflist)
347     {
348         OIC_LOG(ERROR, TAG, "get interface info failed");
349         return CA_STATUS_FAILED;
350     }
351
352     uint32_t len = u_arraylist_length(iflist);
353
354     CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
355     if (!eps)
356     {
357         OIC_LOG(ERROR, TAG, "Malloc Failed");
358         u_arraylist_destroy(iflist);
359         return CA_MEMORY_ALLOC_FAILED;
360     }
361
362     for (uint32_t i = 0, j = 0; i < len; i++)
363     {
364         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
365         if(!ifitem)
366         {
367             continue;
368         }
369         unsigned char *addr=  (unsigned char *) &(ifitem->ipv4addr);
370         snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
371
372         eps[j].flags = CA_IPV4;
373         eps[j].adapter = CA_ADAPTER_IP;
374         eps[j].interface = 0;
375         eps[j].port = caglobals.ip.u4.port;
376         j++;
377     }
378
379     *info = eps;
380     *size = len;
381
382     u_arraylist_destroy(iflist);
383
384     OIC_LOG(DEBUG, TAG, "OUT");
385     return CA_STATUS_OK;
386 }
387