Merge branch 'security-summit' into 'master'
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / arduino / caipserver_wifi.cpp
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
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
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 ******************************************************************/
20
21 #include "caipinterface.h"
22
23 #include <Arduino.h>
24 #include <WiFi.h>
25 #include <WiFiUdp.h>
26 #include <SPI.h>
27 #include <utility/server_drv.h>
28 #include <utility/wifi_drv.h>
29 #include <IPAddress.h>
30
31 #include "logger.h"
32 #include "cacommon.h"
33 #include "cainterface.h"
34 #include "caadapterinterface.h"
35 #include "caipadapter.h"
36 #include "caadapterutils.h"
37 #include "oic_malloc.h"
38 #include "oic_string.h"
39
40 #define TAG "IPS"
41
42 // Length of the IP address decimal notation string
43 #define IPNAMESIZE (16)
44
45 // Start offsets based on end of received data buffer
46 #define IP_RECBUF_IPADDR_OFFSET  (6)
47 #define IP_RECBUF_PORT_OFFSET    (2)
48
49 #define IP_RECBUF_IPADDR_SIZE    (IP_RECBUF_IPADDR_OFFSET - IP_RECBUF_PORT_OFFSET)
50 #define IP_RECBUF_PORT_SIZE      (IP_RECBUF_PORT_OFFSET - 0)
51 #define IP_RECBUF_FOOTER_SIZE    (IP_RECBUF_IPADDR_SIZE + IP_RECBUF_PORT_SIZE)
52
53 static void CAArduinoCheckData();
54 static void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
55                                      const void *data, const uint32_t dataLength);
56
57 static CAIPPacketReceivedCallback gPacketReceivedCallback = NULL;
58 static int32_t gUnicastSocket = 0;
59 static bool gServerRunning = false;
60 static WiFiUDP Udp;
61 /**
62  * @var g_unicastPort
63  * @brief Unicast Port
64  */
65 static uint16_t g_unicastPort = 0;
66
67 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
68 {
69     /**
70      * This API is to keep design in sync with other platforms.
71      * The required implementation is done in Start() api's.
72      */
73     return CA_STATUS_OK;
74 }
75
76 void CAIPTerminateServer(void)
77 {
78     /**
79      * This API is to keep design in sync with other platforms.
80      * The required implementation is done in Stop() api's.
81      */
82 }
83
84 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
85 {
86     return g_unicastPort;
87 }
88
89 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
90                                   bool secured)
91 {
92     OIC_LOG(DEBUG, TAG, "IN");
93     VERIFY_NON_NULL(port, TAG, "port");
94
95     if (gServerRunning)
96     {
97         // already running
98         OIC_LOG(DEBUG, TAG, "Error");
99         return CA_STATUS_FAILED;
100     }
101
102     if (WiFi.status() != WL_CONNECTED)
103     {
104         OIC_LOG(ERROR, TAG, "ERROR:No WIFI");
105         return CA_STATUS_FAILED;
106     }
107
108     OIC_LOG_V(DEBUG, TAG, "port: %u", *port);
109
110     Udp.begin((uint16_t ) *port);
111     gServerRunning = true;
112     g_unicastPort = *port;
113     caglobals.ip.u4.port =  *port;
114     OIC_LOG(DEBUG, TAG, "OUT");
115     return CA_STATUS_OK;
116 }
117
118 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
119                                       uint16_t multicastPort)
120 {
121     // wifi shield does not support multicast
122     OIC_LOG(DEBUG, TAG, "IN");
123     OIC_LOG(DEBUG, TAG, "OUT");
124     return CA_NOT_SUPPORTED;
125 }
126
127 CAResult_t CAIPStartServer()
128 {
129     uint16_t unicastPort = 55555;
130
131     CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
132     if (CA_STATUS_OK != ret)
133     {
134         OIC_LOG_V(ERROR, TAG, "Start unicast server failed[%d]", ret);
135         return ret;
136     }
137     ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683);
138     if (CA_STATUS_OK != ret)
139     {
140         OIC_LOG_V(ERROR, TAG, "Start multicast failed[%d]", ret);
141     }
142     return ret;
143 }
144
145 CAResult_t CAIPStopUnicastServer()
146 {
147     OIC_LOG(DEBUG, TAG, "IN");
148     Udp.stop();
149
150     gServerRunning = false;
151     caglobals.ip.u4.port =  0;
152     OIC_LOG(DEBUG, TAG, "OUT");
153     return CA_STATUS_OK;
154 }
155
156 CAResult_t CAIPStopMulticastServer()
157 {
158     return CAIPStopUnicastServer();
159 }
160
161 void CAIPStopServer()
162 {
163     OIC_LOG(DEBUG, TAG, "IN");
164     CAResult_t result = CAIPStopUnicastServer();
165     if (CA_STATUS_OK != result)
166     {
167         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
168         return;
169     }
170     CAIPSetUnicastSocket(-1);
171     CAIPSetUnicastPort(0);
172
173     result = CAIPStopMulticastServer();
174     if (CA_STATUS_OK != result)
175     {
176         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
177     }
178     OIC_LOG(DEBUG, TAG, "OUT");
179 }
180
181 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
182                               const void *data, const uint32_t dataLength)
183 {
184     OIC_LOG(DEBUG, TAG, "IN");
185     if (gPacketReceivedCallback)
186     {
187         CASecureEndpoint_t sep =
188         {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_IPV4, .port = port}};
189
190         OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), ipAddress);
191         gPacketReceivedCallback(&sep, data, dataLength);
192         OIC_LOG(DEBUG, TAG, "Notified network packet");
193     }
194     OIC_LOG(DEBUG, TAG, "OUT");
195 }
196
197 void CAArduinoCheckData()
198 {
199     OIC_LOG(DEBUG, TAG, "IN");
200     char addr[IPNAMESIZE] = {0};
201     uint16_t senderPort = 0;
202     int16_t packetSize = Udp.parsePacket();
203     OIC_LOG_V(DEBUG, TAG, "Rcv packet of size:%d ", packetSize);
204     if (packetSize)
205     {
206         packetSize = packetSize > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:packetSize;
207         char *data = (char *)OICMalloc(packetSize + 1);
208         if (NULL == data)
209         {
210             return;
211         }
212         IPAddress remoteIp = Udp.remoteIP();
213         senderPort = Udp.remotePort();
214         sprintf(addr, "%d.%d.%d.%d", remoteIp[0], remoteIp[1], remoteIp[2], remoteIp[3]);
215         OIC_LOG_V(DEBUG, TAG, "remoteip: %s, port: %d", addr, senderPort);
216         // read the packet into packetBufffer
217         int32_t dataLen = Udp.read(data, COAP_MAX_PDU_SIZE);
218         if (dataLen > 0)
219         {
220             data[dataLen] = 0;
221         }
222         CAPacketReceivedCallback(addr, senderPort, data, dataLen);
223         OICFree(data);
224     }
225     OIC_LOG(DEBUG, TAG, "OUT");
226 }
227
228 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
229 {
230     OIC_LOG(DEBUG, TAG, "IN");
231     gPacketReceivedCallback = callback;
232     OIC_LOG(DEBUG, TAG, "OUT");
233 }
234
235 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
236 {
237     // TODO
238 }
239
240 void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
241 {
242     OIC_LOG(DEBUG, TAG, "IN");
243     OIC_LOG(DEBUG, TAG, "OUT");
244 }
245
246 void CAIPPullData()
247 {
248     CAArduinoCheckData();
249 }
250
251 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
252 {
253     OIC_LOG(DEBUG, TAG, "IN");
254
255     VERIFY_NON_NULL(info, TAG, "info is NULL");
256     VERIFY_NON_NULL(size, TAG, "size is NULL");
257
258     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
259     if (!iflist)
260     {
261         OIC_LOG(ERROR, TAG, "get interface info failed");
262         return CA_STATUS_FAILED;
263     }
264
265     uint32_t len = u_arraylist_length(iflist);
266
267     CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
268     if (!eps)
269     {
270         OIC_LOG(ERROR, TAG, "Malloc Failed");
271         u_arraylist_destroy(iflist);
272         return CA_MEMORY_ALLOC_FAILED;
273     }
274
275     for (uint32_t i = 0, j = 0; i < len; i++)
276     {
277         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
278
279         unsigned char *addr=  (unsigned char *) &(ifitem->ipv4addr);
280         snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
281
282         eps[j].flags = CA_IPV4;
283         eps[j].adapter = CA_ADAPTER_IP;
284         eps[j].interface = 0;
285         eps[j].port = caglobals.ip.u4.port;
286         j++;
287     }
288
289     *info = eps;
290     *size = len;
291
292     u_arraylist_destroy(iflist);
293
294     OIC_LOG(DEBUG, TAG, "OUT");
295     return CA_STATUS_OK;
296 }
297