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 "cawifiinterface.h"
27 #include <utility/server_drv.h>
28 #include <utility/wifi_drv.h>
29 #include <IPAddress.h>
30 #include <TimedAction.h>
34 #include "cainterface.h"
35 #include "caadapterinterface.h"
36 #include "cawifiadapter.h"
37 #include "caadapterutils.h"
38 #include "oic_malloc.h"
40 #define COAP_MAX_PDU_SIZE 320
41 #define MOD_NAME "WiFiServer"
43 char ssid[] = "NETGEAR99"; // your network SSID (name)
44 char pass[] = "jollysky325"; // your network password
45 int16_t status = WL_IDLE_STATUS; // the Wifi radio's status
47 // Length of the IP address decimal notation string
48 #define IPNAMESIZE (16)
50 // Start offsets based on end of received data buffer
51 #define WIFI_RECBUF_IPADDR_OFFSET (6)
52 #define WIFI_RECBUF_PORT_OFFSET (2)
54 #define WIFI_RECBUF_IPADDR_SIZE (WIFI_RECBUF_IPADDR_OFFSET - WIFI_RECBUF_PORT_OFFSET)
55 #define WIFI_RECBUF_PORT_SIZE (WIFI_RECBUF_PORT_OFFSET - 0)
56 #define WIFI_RECBUF_FOOTER_SIZE (WIFI_RECBUF_IPADDR_SIZE + WIFI_RECBUF_PORT_SIZE)
58 static CAResult_t CAArduinoInitUdpSocket(int16_t *port, int32_t *socketID);
59 static int32_t CAArduinoRecvData(int32_t sockFd, uint8_t *buf, uint32_t bufLen,
60 uint8_t *senderAddr, uint16_t *senderPort);
61 static CAResult_t CAArduinoGetInterfaceAddress(char *address, int32_t addrLen);
62 static void CAArduinoCheckData();
63 void CAPacketReceivedCallback(const char *ipAddress, const uint32_t port,
64 const void *data, const uint32_t dataLength);
66 static CAWiFiPacketReceivedCallback gPacketReceivedCallback = NULL;
67 static int32_t gUnicastSocket = 0;
68 static bool gServerRunning = false;
69 static TimedAction gRcvAction = TimedAction(3000, CAArduinoCheckData);
72 CAResult_t CAWiFiInitializeServer(void)
77 void CAWiFiTerminateServer(void)
82 CAResult_t CAWiFiGetUnicastServerInfo(char **ipAddress, int *port, int32_t *serverID)
87 CAResult_t CAArduinoInitUdpSocket(int16_t *port, int32_t *socketID)
89 OIC_LOG(DEBUG, MOD_NAME, "IN");
90 VERIFY_NON_NULL(port, MOD_NAME, "port");
91 VERIFY_NON_NULL(socketID, MOD_NAME, "socketID");
94 //Is any socket available to work with ?
97 sock = WiFiClass::getSocket();
98 if (sock != NO_SOCKET_AVAIL)
100 *socketID = (int32_t)sock;
101 OIC_LOG_V(ERROR, MOD_NAME, "socket: %d", *socketID);
105 OIC_LOG(DEBUG, MOD_NAME, "Error");
106 return CA_STATUS_FAILED;
109 OIC_LOG(DEBUG, MOD_NAME, "OUT");
113 CAResult_t CAWiFiStartUnicastServer(const char *localAddress, int16_t *port,
114 const bool forceStart, int32_t *serverFD)
116 OIC_LOG(DEBUG, MOD_NAME, "IN");
117 VERIFY_NON_NULL(port, MOD_NAME, "port");
120 if (WiFi.status() == WL_NO_SHIELD)
122 OIC_LOG(DEBUG, MOD_NAME, "Error");
123 return CA_STATUS_FAILED;
126 while (status != WL_CONNECTED)
128 OIC_LOG_V(ERROR, MOD_NAME, "connecting: %s", ssid);
129 status = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network:
131 // wait 10 seconds for connection:
135 char localIpAddress[CA_IPADDR_SIZE];
136 int32_t localIpAddressLen = sizeof(localIpAddress);
137 CAArduinoGetInterfaceAddress(localIpAddress, localIpAddressLen);
138 OIC_LOG_V(DEBUG, MOD_NAME, "address: %s", localIpAddress);
143 OIC_LOG(DEBUG, MOD_NAME, "Error");
144 return CA_STATUS_FAILED;
147 OIC_LOG_V(DEBUG, MOD_NAME, "port: %d", *port);
148 Udp.begin((uint16_t ) *port);
150 // start thread to monitor socket here
154 gServerRunning = true;
156 OIC_LOG(DEBUG, MOD_NAME, "OUT");
160 CAResult_t CAWiFiStartMulticastServer(const char *localAddress, const char *multicastAddress,
161 const int16_t multicastPort, int32_t *serverFD)
163 // wifi shield do not support multicast
164 OIC_LOG(DEBUG, MOD_NAME, "IN");
165 OIC_LOG(DEBUG, MOD_NAME, "IN");
166 return CA_NOT_SUPPORTED;
169 CAResult_t CAWiFiStopUnicastServer()
171 OIC_LOG(DEBUG, MOD_NAME, "IN");
172 if (gUnicastSocket >= MAX_SOCK_NUM)
174 OIC_LOG(DEBUG, MOD_NAME, "Invalid sockfd");
175 return CA_STATUS_FAILED;
178 ServerDrv::stopClient(gUnicastSocket);
179 WiFiClass::_server_port[gUnicastSocket] = 0;
180 WiFiClass::_state[gUnicastSocket] = NA_STATE;
183 // Terminate server thread
184 gRcvAction.disable();
185 gServerRunning = false;
186 OIC_LOG(DEBUG, MOD_NAME, "OUT");
190 CAResult_t CAWiFiStopMulticastServer()
192 return CAWiFiStopUnicastServer();
195 void CAPacketReceivedCallback(const char *ipAddress, const uint32_t port,
196 const void *data, const uint32_t dataLength)
198 OIC_LOG(DEBUG, MOD_NAME, "notifyCallback Entry");
199 if (gPacketReceivedCallback)
201 gPacketReceivedCallback(ipAddress, port, data, dataLength);
202 OIC_LOG(DEBUG, MOD_NAME, "Notified network packet");
204 OIC_LOG(DEBUG, MOD_NAME, "notifyCallback Exit");
207 void CAArduinoCheckData()
209 OIC_LOG(DEBUG, MOD_NAME, "CAACD Being called");
210 char *data = (char *)OICMalloc(COAP_MAX_PDU_SIZE);
212 char addr[IPNAMESIZE] = {0};
213 uint16_t senderPort = 0;
214 int16_t packetSize = Udp.parsePacket();
215 OIC_LOG_V(DEBUG, MOD_NAME, "Rcv packet of size:%d ", packetSize);
216 senderPort = Udp.remotePort();
217 OIC_LOG_V(DEBUG, MOD_NAME, "senderport: %d", senderPort);
220 IPAddress remoteIp = Udp.remoteIP();
221 senderPort = Udp.remotePort();
222 OIC_LOG_V(DEBUG, MOD_NAME, "senderport: %d", senderPort);
223 sprintf(addr, "%d.%d.%d.%d", remoteIp[0], remoteIp[1], remoteIp[2], remoteIp[3]);
224 OIC_LOG_V(DEBUG, MOD_NAME, "remoteip: %s, port: %d", addr, senderPort);
225 // read the packet into packetBufffer
226 int16_t len = Udp.read(data, COAP_MAX_PDU_SIZE);
231 CAPacketReceivedCallback(addr, senderPort, data, dataLen);
236 /// Retrieve any available data from UDP socket. This is a non-blocking call.
237 int32_t CAArduinoRecvData(int32_t sockFd, uint8_t *buf, uint32_t bufLen, uint8_t *senderAddr,
238 uint16_t *senderPort)
240 OIC_LOG(DEBUG, MOD_NAME, "arduinoRecvData Entry");
241 /**Bug : When there are multiple UDP packets in Wiznet buffer, W5100.getRXReceivedSize
242 * will not return correct length of the first packet.
243 * Fix : Use the patch provided for arduino/libraries/Ethernet/utility/socket.cpp
246 uint16_t recvLen = 0;
248 VERIFY_NON_NULL(buf, MOD_NAME, "Invalid buf");
249 VERIFY_NON_NULL(senderAddr, MOD_NAME, "Invalid senderAddr");
250 VERIFY_NON_NULL(senderPort, MOD_NAME, "Invalid senderPort");
252 OIC_LOG(DEBUG, MOD_NAME, "arduinoRecvData Begin");
253 if (sockFd >= MAX_SOCK_NUM)
255 OIC_LOG(ERROR, MOD_NAME, "Invalid sockfd");
259 recvLen = (int32_t)ServerDrv::availData((uint8_t)sockFd);
265 // Make sure buf is large enough for received data
266 if ((uint32_t)recvLen > bufLen)
268 OIC_LOG(ERROR, MOD_NAME, "Receive buffer too small");
272 if (!ServerDrv::getDataBuf((uint8_t)sockFd, (uint8_t *)buf, &recvLen))
274 OIC_LOG(ERROR, MOD_NAME, "getDataBuf error");
278 // Read IP Address and Port from end of receive buffer
279 memcpy(senderAddr, &buf[recvLen - WIFI_RECBUF_IPADDR_OFFSET], WIFI_RECBUF_IPADDR_SIZE);
280 // Change the endianness of the port number
281 *((uint8_t *)senderPort) = buf[recvLen - (WIFI_RECBUF_PORT_OFFSET - 1)];
282 *((uint8_t *)senderPort + 1) = buf[recvLen - (WIFI_RECBUF_PORT_OFFSET)];
284 recvLen -= WIFI_RECBUF_FOOTER_SIZE;
285 OIC_LOG(DEBUG, MOD_NAME, "arduinoRecvData End");
286 return (int32_t)recvLen;
289 void CAWiFiSetPacketReceiveCallback(CAWiFiPacketReceivedCallback callback)
291 OIC_LOG(DEBUG, MOD_NAME, "CAWSPRC Entry");
292 gPacketReceivedCallback = callback;
293 OIC_LOG(DEBUG, MOD_NAME, "CAWSPRC Exit");
296 void CAWiFiSetExceptionCallback(CAWiFiExceptionCallback callback)
301 void CAWiFiPullData()
306 /// Retrieves the IP address assigned to Arduino Ethernet shield
307 CAResult_t CAArduinoGetInterfaceAddress(char *address, int32_t addrLen)
309 OIC_LOG(DEBUG, MOD_NAME, "IN");
311 if (WiFi.status() == WL_NO_SHIELD)
313 OIC_LOG(DEBUG, MOD_NAME, "WIFI SHIELD NOT PRESENT");
314 return CA_STATUS_FAILED;
317 while ( status != WL_CONNECTED)
319 OIC_LOG_V(ERROR, MOD_NAME, "Attempting to connect to WPA SSID: %s", ssid);
320 status = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network:
322 // wait 10 seconds for connection:
324 OIC_LOG(DEBUG, MOD_NAME, "Attempting connection again");
327 VERIFY_NON_NULL(address, MOD_NAME, "Invalid address");
328 if (addrLen < IPNAMESIZE)
330 OIC_LOG_V(ERROR, MOD_NAME, "arduinoGetInterfaceAddress: addrLen MUST be atleast %d", IPNAMESIZE);
331 return CA_STATUS_FAILED;
334 IPAddress ip = WiFi.localIP();
335 sprintf((char *)address, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
337 OIC_LOG_V(DEBUG, MOD_NAME, "Wifi shield address is: %s", address);
338 OIC_LOG(DEBUG, MOD_NAME, "arduinoGetInterfaceAddress::Exit");