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