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