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_singlethread.h"
27 #include <EthernetUdp.h>
28 #include <IPAddress.h>
32 #include "cainterface.h"
33 #include "caadapterinterface.h"
34 #include "caipadapter_singlethread.h"
35 #include "caipadapterutils_eth.h"
36 #include "caadapterutils.h"
37 #include "oic_malloc.h"
41 // Length of the IP address decimal notation string
42 #define IPNAMESIZE (16)
44 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
45 const bool forceStart, int32_t *serverFD);
46 static CAResult_t CAArduinoRecvData(int32_t sockFd);
47 static CAResult_t CAArduinoGetInterfaceAddress(char *address, int32_t addrLen);
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;
60 static uint16_t g_unicastPort = 0;
62 CAResult_t CAIPInitializeServer(void)
67 void CAIPTerminateServer(void)
72 CAResult_t CAIPGetUnicastServerInfo(char **ipAddress, uint16_t *port,
78 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
79 const bool forceStart, int *serverFD)
81 OIC_LOG(DEBUG, TAG, "IN");
82 VERIFY_NON_NULL(port, TAG, "port");
86 W5100.getIPAddress(rawIPAddr);
87 sprintf(address, "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2], rawIPAddr[3]);
88 OIC_LOG_V(DEBUG, TAG, "address:%s", address);
90 if (CAArduinoInitUdpSocket(port, serverFD) != CA_STATUS_OK)
92 OIC_LOG(DEBUG, TAG, "failed");
93 return CA_STATUS_FAILED;
96 g_unicastPort = *port;
97 g_unicastSocket = *serverFD;
98 OIC_LOG_V(DEBUG, TAG, "g_unicastPort: %d", g_unicastPort);
99 OIC_LOG_V(DEBUG, TAG, "g_unicastSocket: %d", g_unicastSocket);
100 OIC_LOG(DEBUG, TAG, "OUT");
104 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
105 uint16_t multicastPort, int *serverFD)
107 OIC_LOG(DEBUG, TAG, "IN");
108 if (CAArduinoInitMulticastUdpSocket(multicastAddress, multicastPort, multicastPort,
109 serverFD) != CA_STATUS_OK)
111 OIC_LOG(DEBUG, TAG, "failed");
112 return CA_STATUS_FAILED;
115 g_multicastSocket = *serverFD;
116 OIC_LOG_V(DEBUG, TAG, "gMulticastPort: %d", multicastPort);
117 OIC_LOG_V(DEBUG, TAG, "g_multicastSocket: %d", g_multicastSocket);
118 OIC_LOG(DEBUG, TAG, "OUT");
122 CAResult_t CAIPStopUnicastServer()
124 OIC_LOG(DEBUG, TAG, "IN");
125 close(g_unicastSocket);
127 OIC_LOG(DEBUG, TAG, "OUT");
131 CAResult_t CAIPStopMulticastServer()
133 OIC_LOG(DEBUG, TAG, "IN");
134 close(g_multicastSocket);
135 g_multicastSocket = 0;
136 OIC_LOG(DEBUG, TAG, "OUT");
140 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
141 const void *data, const uint32_t dataLength)
143 OIC_LOG(DEBUG, TAG, "IN");
144 if (g_packetReceivedCallback)
146 g_packetReceivedCallback(ipAddress, port, data, dataLength);
148 OIC_LOG(DEBUG, TAG, "OUT");
151 void CAArduinoCheckData()
155 if (CAArduinoRecvData(g_unicastSocket) != CA_STATUS_OK)
157 OIC_LOG(ERROR, TAG, "rcv fail");
158 CAIPStopUnicastServer();
162 if (g_multicastSocket)
164 if (CAArduinoRecvData(g_multicastSocket) != CA_STATUS_OK)
166 OIC_LOG(ERROR, TAG, "rcv fail");
167 CAIPStopMulticastServer();
172 /** Retrieve any available data from UDP socket and call callback.
173 * This is a non-blocking call.
175 CAResult_t CAArduinoRecvData(int32_t sockFd)
177 /**Bug : When there are multiple UDP packets in Wiznet buffer, W5100.getRXReceivedSize
178 * will not return correct length of the first packet.
179 * Fix : Use the patch provided for arduino/libraries/Ethernet/utility/socket.cpp
183 uint8_t senderAddr[4] = { 0 };
184 char addr[IPNAMESIZE] = {0};
185 uint16_t senderPort = 0;
187 uint16_t recvLen = W5100.getRXReceivedSize(sockFd);
190 // No data available on socket
194 OIC_LOG_V(DEBUG, TAG, "rcvd %d", recvLen);
195 recvLen = recvLen > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:recvLen;
197 data = OICCalloc(recvLen + 1, 1);
200 OIC_LOG(DEBUG, TAG, "Out of memory!");
201 return CA_MEMORY_ALLOC_FAILED;
204 // Read available data.
205 int32_t ret = recvfrom(sockFd, (uint8_t *)data, recvLen + 1, senderAddr, &senderPort);
208 OIC_LOG(ERROR, TAG, "rcv fail");
210 return CA_STATUS_FAILED;
214 OIC_LOG(DEBUG, TAG, "data recvd");
215 snprintf(addr, sizeof(addr), "%d.%d.%d.%d", senderAddr[0], senderAddr[1], senderAddr[2],
217 CAPacketReceivedCallback(addr, senderPort, data, ret);
222 OIC_LOG(DEBUG, TAG, "OUT");
226 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
228 OIC_LOG(DEBUG, TAG, "IN");
229 g_packetReceivedCallback = callback;
230 OIC_LOG(DEBUG, TAG, "OUT");
233 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
240 CAArduinoCheckData();
243 /// Retrieves the IP address assigned to Arduino Ethernet shield
244 CAResult_t CAArduinoGetInterfaceAddress(char *address, int32_t addrLen)
246 OIC_LOG(DEBUG, TAG, "IN");
247 VERIFY_NON_NULL(address, TAG, "address");
249 //TODO : Fix this for scenarios when this API is invoked when device is not connected
250 uint8_t rawIPAddr[4];
251 if (addrLen < IPNAMESIZE)
253 OIC_LOG(ERROR, TAG, "Invalid addrLen");
254 return CA_STATUS_FAILED;
257 W5100.getIPAddress(rawIPAddr);
258 snprintf(address, sizeof(address), "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2],
261 OIC_LOG_V(DEBUG, TAG, "address:%s", address);
262 OIC_LOG(DEBUG, TAG, "OUT");