1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
21 #include "caipinterface.h"
27 #include <EthernetUdp.h>
28 #include <IPAddress.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"
42 // Length of the IP address decimal notation string
43 #define IPNAMESIZE (16)
45 /** Multicast IP address.*/
46 #define IPv4_MULTICAST "224.0.1.187"
49 #define IPv4_MULTICAST_PORT 5683
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);
58 static CAIPPacketReceivedCallback g_packetReceivedCallback = NULL;
59 static int g_unicastSocket = 0;
60 static int g_multicastSocket = 0;
63 * @var g_isMulticastServerStarted
64 * @brief Flag to check if multicast server is started
66 static bool g_isMulticastServerStarted = false;
72 static uint16_t g_unicastPort = 0;
74 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
79 void CAIPTerminateServer(void)
84 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
89 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
92 OIC_LOG(DEBUG, TAG, "IN");
93 VERIFY_NON_NULL(port, TAG, "port");
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);
101 if (CAArduinoInitUdpSocket(port, &serverFD) != CA_STATUS_OK)
103 OIC_LOG(DEBUG, TAG, "failed");
104 return CA_STATUS_FAILED;
107 g_unicastPort = *port;
108 g_unicastSocket = serverFD;
109 CAIPSetUnicastSocket(g_unicastSocket);
110 CAIPSetUnicastPort(g_unicastPort);
111 caglobals.ip.u4.port = *port;
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");
119 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
120 uint16_t multicastPort)
122 OIC_LOG(DEBUG, TAG, "IN");
123 if (g_isMulticastServerStarted == true)
125 OIC_LOG(ERROR, TAG, "Already Started!");
126 return CA_SERVER_STARTED_ALREADY;
129 if (CAArduinoInitMulticastUdpSocket(multicastAddress, multicastPort, multicastPort,
130 &serverFD) != CA_STATUS_OK)
132 OIC_LOG(DEBUG, TAG, "failed");
133 return CA_STATUS_FAILED;
136 g_multicastSocket = serverFD;
137 g_isMulticastServerStarted = true;
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");
145 CAResult_t CAIPStartServer()
147 uint16_t unicastPort = 55555;
149 CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
150 if (CA_STATUS_OK != ret)
152 OIC_LOG_V(ERROR, TAG, "Start unicast server failed[%d]", ret);
155 ret = CAIPStartMulticastServer("0.0.0.0", IPv4_MULTICAST, IPv4_MULTICAST_PORT);
156 if (CA_STATUS_OK != ret)
158 OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
163 CAResult_t CAIPStopUnicastServer()
165 OIC_LOG(DEBUG, TAG, "IN");
166 close(g_unicastSocket);
168 caglobals.ip.u4.port = 0;
169 OIC_LOG(DEBUG, TAG, "OUT");
173 CAResult_t CAIPStopMulticastServer()
175 OIC_LOG(DEBUG, TAG, "IN");
176 close(g_multicastSocket);
177 g_multicastSocket = 0;
178 OIC_LOG(DEBUG, TAG, "OUT");
182 CAResult_t CAIPStartListenServer()
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)
188 OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
190 OIC_LOG(DEBUG, TAG, "OUT");
194 CAResult_t CAIPStopListenServer()
196 OIC_LOG(DEBUG, TAG, "IN");
197 CAResult_t ret = CAIPStopMulticastServer();
198 if (CA_STATUS_OK != ret)
200 OIC_LOG_V(ERROR, TAG, "Stop multicast failed[%d]", ret);
202 OIC_LOG(DEBUG, TAG, "OUT");
206 void CAIPStopServer()
208 OIC_LOG(DEBUG, TAG, "IN");
209 CAResult_t result = CAIPStopUnicastServer();
210 if (CA_STATUS_OK != result)
212 OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
215 CAIPSetUnicastSocket(-1);
216 CAIPSetUnicastPort(0);
218 result = CAIPStopMulticastServer();
219 if (CA_STATUS_OK != result)
221 OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
223 OIC_LOG(DEBUG, TAG, "OUT");
226 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
227 const void *data, const uint32_t dataLength)
229 OIC_LOG(DEBUG, TAG, "IN");
230 if (g_packetReceivedCallback)
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);
237 OIC_LOG(DEBUG, TAG, "OUT");
240 void CAArduinoCheckData()
244 if (CAArduinoRecvData(g_unicastSocket) != CA_STATUS_OK)
246 OIC_LOG(ERROR, TAG, "rcv fail");
247 CAIPStopUnicastServer();
251 if (g_multicastSocket)
253 if (CAArduinoRecvData(g_multicastSocket) != CA_STATUS_OK)
255 OIC_LOG(ERROR, TAG, "rcv fail");
256 CAIPStopMulticastServer();
261 /** Retrieve any available data from UDP socket and call callback.
262 * This is a non-blocking call.
264 CAResult_t CAArduinoRecvData(int32_t sockFd)
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
272 uint8_t senderAddr[4] = { 0 };
273 char addr[IPNAMESIZE] = {0};
274 uint16_t senderPort = 0;
276 uint16_t recvLen = W5100.getRXReceivedSize(sockFd);
279 // No data available on socket
283 OIC_LOG_V(DEBUG, TAG, "rcvd %d", recvLen);
284 recvLen = recvLen > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:recvLen;
286 data = OICCalloc(recvLen + 1, 1);
289 OIC_LOG(DEBUG, TAG, "Out of memory!");
290 return CA_MEMORY_ALLOC_FAILED;
293 // Read available data.
294 int32_t ret = recvfrom(sockFd, (uint8_t *)data, recvLen + 1, senderAddr, &senderPort);
297 OIC_LOG(ERROR, TAG, "rcv fail");
299 return CA_STATUS_FAILED;
303 OIC_LOG(DEBUG, TAG, "data recvd");
304 snprintf(addr, sizeof(addr), "%d.%d.%d.%d", senderAddr[0], senderAddr[1], senderAddr[2],
306 CAPacketReceivedCallback(addr, senderPort, data, ret);
311 OIC_LOG(DEBUG, TAG, "OUT");
315 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
317 OIC_LOG(DEBUG, TAG, "IN");
318 g_packetReceivedCallback = callback;
319 OIC_LOG(DEBUG, TAG, "OUT");
322 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
327 void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
329 OIC_LOG(DEBUG, TAG, "IN");
330 OIC_LOG(DEBUG, TAG, "OUT");
335 CAArduinoCheckData();
338 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
340 OIC_LOG(DEBUG, TAG, "IN");
342 VERIFY_NON_NULL(info, TAG, "info is NULL");
343 VERIFY_NON_NULL(size, TAG, "size is NULL");
345 u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
348 OIC_LOG(ERROR, TAG, "get interface info failed");
349 return CA_STATUS_FAILED;
352 uint32_t len = u_arraylist_length(iflist);
354 CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
357 OIC_LOG(ERROR, TAG, "Malloc Failed");
358 u_arraylist_destroy(iflist);
359 return CA_MEMORY_ALLOC_FAILED;
362 for (uint32_t i = 0, j = 0; i < len; i++)
364 CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
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]);
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;
382 u_arraylist_destroy(iflist);
384 OIC_LOG(DEBUG, TAG, "OUT");