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 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);
52 static CAIPPacketReceivedCallback g_packetReceivedCallback = NULL;
53 static int g_unicastSocket = 0;
54 static int g_multicastSocket = 0;
57 * @var g_isMulticastServerStarted
58 * @brief Flag to check if multicast server is started
60 static bool g_isMulticastServerStarted = false;
66 static uint16_t g_unicastPort = 0;
68 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
73 void CAIPTerminateServer(void)
78 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
83 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
86 OIC_LOG(DEBUG, TAG, "IN");
87 VERIFY_NON_NULL(port, TAG, "port");
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);
95 if (CAArduinoInitUdpSocket(port, &serverFD) != CA_STATUS_OK)
97 OIC_LOG(DEBUG, TAG, "failed");
98 return CA_STATUS_FAILED;
101 g_unicastPort = *port;
102 g_unicastSocket = serverFD;
103 CAIPSetUnicastSocket(g_unicastSocket);
104 CAIPSetUnicastPort(g_unicastPort);
105 caglobals.ip.u4.port = *port;
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");
113 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
114 uint16_t multicastPort)
116 OIC_LOG(DEBUG, TAG, "IN");
117 if (g_isMulticastServerStarted == true)
119 OIC_LOG(ERROR, TAG, "Already Started!");
120 return CA_SERVER_STARTED_ALREADY;
123 if (CAArduinoInitMulticastUdpSocket(multicastAddress, multicastPort, multicastPort,
124 &serverFD) != CA_STATUS_OK)
126 OIC_LOG(DEBUG, TAG, "failed");
127 return CA_STATUS_FAILED;
130 g_multicastSocket = serverFD;
131 g_isMulticastServerStarted = true;
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");
139 CAResult_t CAIPStartServer()
141 uint16_t unicastPort = 55555;
143 CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
144 if (CA_STATUS_OK != ret)
146 OIC_LOG_V(ERROR, TAG, "Start unicast server failed[%d]", ret);
149 ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683);
150 if (CA_STATUS_OK != ret)
152 OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
157 CAResult_t CAIPStopUnicastServer()
159 OIC_LOG(DEBUG, TAG, "IN");
160 close(g_unicastSocket);
162 caglobals.ip.u4.port = 0;
163 OIC_LOG(DEBUG, TAG, "OUT");
167 CAResult_t CAIPStopMulticastServer()
169 OIC_LOG(DEBUG, TAG, "IN");
170 close(g_multicastSocket);
171 g_multicastSocket = 0;
172 OIC_LOG(DEBUG, TAG, "OUT");
176 void CAIPStopServer()
178 OIC_LOG(DEBUG, TAG, "IN");
179 CAResult_t result = CAIPStopUnicastServer();
180 if (CA_STATUS_OK != result)
182 OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
185 CAIPSetUnicastSocket(-1);
186 CAIPSetUnicastPort(0);
188 result = CAIPStopMulticastServer();
189 if (CA_STATUS_OK != result)
191 OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
193 OIC_LOG(DEBUG, TAG, "OUT");
196 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
197 const void *data, const uint32_t dataLength)
199 OIC_LOG(DEBUG, TAG, "IN");
200 if (g_packetReceivedCallback)
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);
207 OIC_LOG(DEBUG, TAG, "OUT");
210 void CAArduinoCheckData()
214 if (CAArduinoRecvData(g_unicastSocket) != CA_STATUS_OK)
216 OIC_LOG(ERROR, TAG, "rcv fail");
217 CAIPStopUnicastServer();
221 if (g_multicastSocket)
223 if (CAArduinoRecvData(g_multicastSocket) != CA_STATUS_OK)
225 OIC_LOG(ERROR, TAG, "rcv fail");
226 CAIPStopMulticastServer();
231 /** Retrieve any available data from UDP socket and call callback.
232 * This is a non-blocking call.
234 CAResult_t CAArduinoRecvData(int32_t sockFd)
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
242 uint8_t senderAddr[4] = { 0 };
243 char addr[IPNAMESIZE] = {0};
244 uint16_t senderPort = 0;
246 uint16_t recvLen = W5100.getRXReceivedSize(sockFd);
249 // No data available on socket
253 OIC_LOG_V(DEBUG, TAG, "rcvd %d", recvLen);
254 recvLen = recvLen > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:recvLen;
256 data = OICCalloc(recvLen + 1, 1);
259 OIC_LOG(DEBUG, TAG, "Out of memory!");
260 return CA_MEMORY_ALLOC_FAILED;
263 // Read available data.
264 int32_t ret = recvfrom(sockFd, (uint8_t *)data, recvLen + 1, senderAddr, &senderPort);
267 OIC_LOG(ERROR, TAG, "rcv fail");
269 return CA_STATUS_FAILED;
273 OIC_LOG(DEBUG, TAG, "data recvd");
274 snprintf(addr, sizeof(addr), "%d.%d.%d.%d", senderAddr[0], senderAddr[1], senderAddr[2],
276 CAPacketReceivedCallback(addr, senderPort, data, ret);
281 OIC_LOG(DEBUG, TAG, "OUT");
285 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
287 OIC_LOG(DEBUG, TAG, "IN");
288 g_packetReceivedCallback = callback;
289 OIC_LOG(DEBUG, TAG, "OUT");
292 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
297 void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
299 OIC_LOG(DEBUG, TAG, "IN");
300 OIC_LOG(DEBUG, TAG, "OUT");
305 CAArduinoCheckData();
308 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
310 OIC_LOG(DEBUG, TAG, "IN");
312 VERIFY_NON_NULL(info, TAG, "info is NULL");
313 VERIFY_NON_NULL(size, TAG, "size is NULL");
315 u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
318 OIC_LOG(ERROR, TAG, "get interface info failed");
319 return CA_STATUS_FAILED;
322 uint32_t len = u_arraylist_length(iflist);
324 CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
327 OIC_LOG(ERROR, TAG, "Malloc Failed");
328 u_arraylist_destroy(iflist);
329 return CA_MEMORY_ALLOC_FAILED;
332 for (uint32_t i = 0, j = 0; i < len; i++)
334 CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
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]);
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;
349 u_arraylist_destroy(iflist);
351 OIC_LOG(DEBUG, TAG, "OUT");