5c31cf9f57a45fdfda21813bff398faf9f8ddb1e
[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
39 #define TAG "IPS"
40
41 // Length of the IP address decimal notation string
42 #define IPNAMESIZE (16)
43
44 // Start offsets based on end of received data buffer
45 #define IP_RECBUF_IPADDR_OFFSET  (6)
46 #define IP_RECBUF_PORT_OFFSET    (2)
47
48 #define IP_RECBUF_IPADDR_SIZE    (IP_RECBUF_IPADDR_OFFSET - IP_RECBUF_PORT_OFFSET)
49 #define IP_RECBUF_PORT_SIZE      (IP_RECBUF_PORT_OFFSET - 0)
50 #define IP_RECBUF_FOOTER_SIZE    (IP_RECBUF_IPADDR_SIZE + IP_RECBUF_PORT_SIZE)
51
52 static void CAArduinoCheckData();
53 static void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
54                                      const void *data, const uint32_t dataLength);
55
56 static CAIPPacketReceivedCallback gPacketReceivedCallback = NULL;
57 static int32_t gUnicastSocket = 0;
58 static bool gServerRunning = false;
59 static WiFiUDP Udp;
60 /**
61  * @var g_unicastPort
62  * @brief Unicast Port
63  */
64 static uint16_t g_unicastPort = 0;
65
66 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
67 {
68     /**
69      * This API is to keep design in sync with other platforms.
70      * The required implementation is done in Start() api's.
71      */
72     return CA_STATUS_OK;
73 }
74
75 void CAIPTerminateServer(void)
76 {
77     /**
78      * This API is to keep design in sync with other platforms.
79      * The required implementation is done in Stop() api's.
80      */
81 }
82
83 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
84 {
85     return g_unicastPort;
86 }
87
88 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
89                                   bool secured)
90 {
91     OIC_LOG(DEBUG, TAG, "IN");
92     VERIFY_NON_NULL(port, TAG, "port");
93
94     if (gServerRunning)
95     {
96         // already running
97         OIC_LOG(DEBUG, TAG, "Error");
98         return CA_STATUS_FAILED;
99     }
100
101     if (WiFi.status() != WL_CONNECTED)
102     {
103         OIC_LOG(ERROR, TAG, "ERROR:No WIFI");
104         return CA_STATUS_FAILED;
105     }
106
107     OIC_LOG_V(DEBUG, TAG, "port: %d", *port);
108
109     Udp.begin((uint16_t ) *port);
110     gServerRunning = true;
111     g_unicastPort = *port;
112     OIC_LOG(DEBUG, TAG, "OUT");
113     return CA_STATUS_OK;
114 }
115
116 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
117                                       uint16_t multicastPort)
118 {
119     // wifi shield does not support multicast
120     OIC_LOG(DEBUG, TAG, "IN");
121     OIC_LOG(DEBUG, TAG, "OUT");
122     return CA_NOT_SUPPORTED;
123 }
124
125 CAResult_t CAIPStopUnicastServer()
126 {
127     OIC_LOG(DEBUG, TAG, "IN");
128     Udp.stop();
129
130     gServerRunning = false;
131     OIC_LOG(DEBUG, TAG, "OUT");
132     return CA_STATUS_OK;
133 }
134
135 CAResult_t CAIPStopMulticastServer()
136 {
137     return CAIPStopUnicastServer();
138 }
139
140 CAResult_t CAIPStopServer(const char *interfaceAddress)
141 {
142     /* For arduino, Server will be running in only one interface */
143     return CAIPStopAllServers();
144 }
145
146 CAResult_t CAIPStopAllServers()
147 {
148     OIC_LOG(DEBUG, TAG, "IN");
149     CAResult_t result = CAIPStopUnicastServer();
150     if (CA_STATUS_OK != result)
151     {
152         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
153         return result;
154     }
155     CAIPSetUnicastSocket(-1);
156     CAIPSetUnicastPort(0);
157
158     result = CAIPStopMulticastServer();
159     if (CA_STATUS_OK != result)
160     {
161         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
162     }
163     OIC_LOG(DEBUG, TAG, "OUT");
164     return result;
165 }
166
167 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
168                               const void *data, const uint32_t dataLength)
169 {
170     OIC_LOG(DEBUG, TAG, "IN");
171     if (gPacketReceivedCallback)
172     {
173         CAEndpoint_t ep;
174         strncpy(ep.addr, ipAddress, MAX_ADDR_STR_SIZE_CA);
175         ep.port = port;
176         ep.flags = CA_IPV4;
177         ep.adapter = CA_ADAPTER_IP;
178         gPacketReceivedCallback(&ep, data, dataLength);
179         OIC_LOG(DEBUG, TAG, "Notified network packet");
180     }
181     OIC_LOG(DEBUG, TAG, "OUT");
182 }
183
184 void CAArduinoCheckData()
185 {
186     OIC_LOG(DEBUG, TAG, "IN");
187     char addr[IPNAMESIZE] = {0};
188     uint16_t senderPort = 0;
189     int16_t packetSize = Udp.parsePacket();
190     OIC_LOG_V(DEBUG, TAG, "Rcv packet of size:%d ", packetSize);
191     if (packetSize)
192     {
193         packetSize = packetSize > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:packetSize;
194         char *data = (char *)OICMalloc(packetSize + 1);
195         if (NULL == data)
196         {
197             return;
198         }
199         IPAddress remoteIp = Udp.remoteIP();
200         senderPort = Udp.remotePort();
201         sprintf(addr, "%d.%d.%d.%d", remoteIp[0], remoteIp[1], remoteIp[2], remoteIp[3]);
202         OIC_LOG_V(DEBUG, TAG, "remoteip: %s, port: %d", addr, senderPort);
203         // read the packet into packetBufffer
204         int32_t dataLen = Udp.read(data, COAP_MAX_PDU_SIZE);
205         if (dataLen > 0)
206         {
207             data[dataLen] = 0;
208         }
209         CAPacketReceivedCallback(addr, senderPort, data, dataLen);
210         OICFree(data);
211     }
212     OIC_LOG(DEBUG, TAG, "OUT");
213 }
214
215 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
216 {
217     OIC_LOG(DEBUG, TAG, "IN");
218     gPacketReceivedCallback = callback;
219     OIC_LOG(DEBUG, TAG, "OUT");
220 }
221
222 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
223 {
224     // TODO
225 }
226
227 void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
228 {
229     OIC_LOG(DEBUG, TAG, "IN");
230     OIC_LOG(DEBUG, TAG, "OUT");
231 }
232
233 void CAIPPullData()
234 {
235     CAArduinoCheckData();
236 }