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 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");
111 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
112 uint16_t multicastPort)
114 OIC_LOG(DEBUG, TAG, "IN");
115 if (g_isMulticastServerStarted == true)
117 OIC_LOG(ERROR, TAG, "Already Started!");
118 return CA_SERVER_STARTED_ALREADY;
121 if (CAArduinoInitMulticastUdpSocket(multicastAddress, multicastPort, multicastPort,
122 &serverFD) != CA_STATUS_OK)
124 OIC_LOG(DEBUG, TAG, "failed");
125 return CA_STATUS_FAILED;
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");
136 CAResult_t CAIPStartServer()
138 uint16_t unicastPort = 55555;
140 CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
141 if (CA_STATUS_OK != ret)
143 OIC_LOG_V(DEBUG, TAG, "Start unicast serv failed[%d]", ret);
145 ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683);
146 if (CA_STATUS_OK != ret)
148 OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret);
153 CAResult_t CAIPStopUnicastServer()
155 OIC_LOG(DEBUG, TAG, "IN");
156 close(g_unicastSocket);
158 OIC_LOG(DEBUG, TAG, "OUT");
162 CAResult_t CAIPStopMulticastServer()
164 OIC_LOG(DEBUG, TAG, "IN");
165 close(g_multicastSocket);
166 g_multicastSocket = 0;
167 OIC_LOG(DEBUG, TAG, "OUT");
171 void CAIPStopServer()
173 OIC_LOG(DEBUG, TAG, "IN");
174 CAResult_t result = CAIPStopUnicastServer();
175 if (CA_STATUS_OK != result)
177 OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
180 CAIPSetUnicastSocket(-1);
181 CAIPSetUnicastPort(0);
183 result = CAIPStopMulticastServer();
184 if (CA_STATUS_OK != result)
186 OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
188 OIC_LOG(DEBUG, TAG, "OUT");
191 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
192 const void *data, const uint32_t dataLength)
194 OIC_LOG(DEBUG, TAG, "IN");
195 if (g_packetReceivedCallback)
198 strncpy(ep.addr, ipAddress, MAX_ADDR_STR_SIZE_CA);
201 ep.adapter = CA_ADAPTER_IP;
202 g_packetReceivedCallback(&ep, data, dataLength);
204 OIC_LOG(DEBUG, TAG, "OUT");
207 void CAArduinoCheckData()
211 if (CAArduinoRecvData(g_unicastSocket) != CA_STATUS_OK)
213 OIC_LOG(ERROR, TAG, "rcv fail");
214 CAIPStopUnicastServer();
218 if (g_multicastSocket)
220 if (CAArduinoRecvData(g_multicastSocket) != CA_STATUS_OK)
222 OIC_LOG(ERROR, TAG, "rcv fail");
223 CAIPStopMulticastServer();
228 /** Retrieve any available data from UDP socket and call callback.
229 * This is a non-blocking call.
231 CAResult_t CAArduinoRecvData(int32_t sockFd)
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
239 uint8_t senderAddr[4] = { 0 };
240 char addr[IPNAMESIZE] = {0};
241 uint16_t senderPort = 0;
243 uint16_t recvLen = W5100.getRXReceivedSize(sockFd);
246 // No data available on socket
250 OIC_LOG_V(DEBUG, TAG, "rcvd %d", recvLen);
251 recvLen = recvLen > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:recvLen;
253 data = OICCalloc(recvLen + 1, 1);
256 OIC_LOG(DEBUG, TAG, "Out of memory!");
257 return CA_MEMORY_ALLOC_FAILED;
260 // Read available data.
261 int32_t ret = recvfrom(sockFd, (uint8_t *)data, recvLen + 1, senderAddr, &senderPort);
264 OIC_LOG(ERROR, TAG, "rcv fail");
266 return CA_STATUS_FAILED;
270 OIC_LOG(DEBUG, TAG, "data recvd");
271 snprintf(addr, sizeof(addr), "%d.%d.%d.%d", senderAddr[0], senderAddr[1], senderAddr[2],
273 CAPacketReceivedCallback(addr, senderPort, data, ret);
278 OIC_LOG(DEBUG, TAG, "OUT");
282 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
284 OIC_LOG(DEBUG, TAG, "IN");
285 g_packetReceivedCallback = callback;
286 OIC_LOG(DEBUG, TAG, "OUT");
289 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
294 void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
296 OIC_LOG(DEBUG, TAG, "IN");
297 OIC_LOG(DEBUG, TAG, "OUT");
302 CAArduinoCheckData();
305 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
307 OIC_LOG(DEBUG, TAG, "IN");
309 VERIFY_NON_NULL(info, TAG, "info is NULL");
310 VERIFY_NON_NULL(size, TAG, "size is NULL");
312 u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
315 OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
316 return CA_STATUS_FAILED;
319 uint32_t len = u_arraylist_length(iflist);
321 CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
324 OIC_LOG(ERROR, TAG, "Malloc Failed");
325 u_arraylist_destroy(iflist);
326 return CA_MEMORY_ALLOC_FAILED;
329 for (uint32_t i = 0, j = 0; i < len; i++)
331 CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
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;
344 u_arraylist_destroy(iflist);
346 OIC_LOG(DEBUG, TAG, "OUT");