Imported Upstream version 0.9.1
[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_singlethread.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_singlethread.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 CAResult_t CAArduinoGetInterfaceAddress(char *address, int32_t addrLen);
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 CAResult_t CAIPInitializeServer(void)
63 {
64     /**
65      * This API is to keep design in sync with other platforms.
66      * The required implementation is done in Start() api's.
67      */
68     return CA_STATUS_OK;
69 }
70
71 void CAIPTerminateServer(void)
72 {
73     /**
74      * This API is to keep design in sync with other platforms.
75      * The required implementation is done in Stop() api's.
76      */
77 }
78
79 CAResult_t CAIPGetUnicastServerInfo(char **ipAddress, uint16_t *port, int *serverID)
80 {
81     /*
82      * This API is to keep design in sync with other platforms.
83      * Will be implemented as and when CA layer wants this info.
84      */
85     return CA_STATUS_OK;
86 }
87
88 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
89                                   bool forceStart, int *serverFD)
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     char localIpAddress[CA_IPADDR_SIZE];
108     int32_t localIpAddressLen = sizeof(localIpAddress);
109     CAArduinoGetInterfaceAddress(localIpAddress, localIpAddressLen);
110     OIC_LOG_V(DEBUG, TAG, "address: %s", localIpAddress);
111     OIC_LOG_V(DEBUG, TAG, "port: %d", *port);
112
113     Udp.begin((uint16_t ) *port);
114     gServerRunning = true;
115
116     OIC_LOG(DEBUG, TAG, "OUT");
117     return CA_STATUS_OK;
118 }
119
120 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
121                                       uint16_t multicastPort, int *serverFD)
122 {
123     // wifi shield does not support multicast
124     OIC_LOG(DEBUG, TAG, "IN");
125     OIC_LOG(DEBUG, TAG, "OUT");
126     return CA_NOT_SUPPORTED;
127 }
128
129 CAResult_t CAIPStopUnicastServer()
130 {
131     OIC_LOG(DEBUG, TAG, "IN");
132     Udp.stop();
133
134     gServerRunning = false;
135     OIC_LOG(DEBUG, TAG, "OUT");
136     return CA_STATUS_OK;
137 }
138
139 CAResult_t CAIPStopMulticastServer()
140 {
141     return CAIPStopUnicastServer();
142 }
143
144 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
145                               const void *data, const uint32_t dataLength)
146 {
147     OIC_LOG(DEBUG, TAG, "IN");
148     if (gPacketReceivedCallback)
149     {
150         gPacketReceivedCallback(ipAddress, port, data, dataLength);
151         OIC_LOG(DEBUG, TAG, "Notified network packet");
152     }
153     OIC_LOG(DEBUG, TAG, "OUT");
154 }
155
156 void CAArduinoCheckData()
157 {
158     OIC_LOG(DEBUG, TAG, "IN");
159     char addr[IPNAMESIZE] = {0};
160     uint16_t senderPort = 0;
161     int16_t packetSize = Udp.parsePacket();
162     OIC_LOG_V(DEBUG, TAG, "Rcv packet of size:%d ", packetSize);
163     if (packetSize)
164     {
165         packetSize = packetSize > COAP_MAX_PDU_SIZE ? COAP_MAX_PDU_SIZE:packetSize;
166         char *data = (char *)OICMalloc(packetSize + 1);
167         if (NULL == data)
168         {
169             return;
170         }
171         IPAddress remoteIp = Udp.remoteIP();
172         senderPort = Udp.remotePort();
173         sprintf(addr, "%d.%d.%d.%d", remoteIp[0], remoteIp[1], remoteIp[2], remoteIp[3]);
174         OIC_LOG_V(DEBUG, TAG, "remoteip: %s, port: %d", addr, senderPort);
175         // read the packet into packetBufffer
176         int32_t dataLen = Udp.read(data, COAP_MAX_PDU_SIZE);
177         if (dataLen > 0)
178         {
179             data[dataLen] = 0;
180         }
181         CAPacketReceivedCallback(addr, senderPort, data, dataLen);
182         OICFree(data);
183     }
184     OIC_LOG(DEBUG, TAG, "OUT");
185 }
186
187 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
188 {
189     OIC_LOG(DEBUG, TAG, "IN");
190     gPacketReceivedCallback = callback;
191     OIC_LOG(DEBUG, TAG, "OUT");
192 }
193
194 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
195 {
196     // TODO
197 }
198
199 void CAIPPullData()
200 {
201     CAArduinoCheckData();
202 }
203
204 /// Retrieves the IP address assigned to Arduino WiFi shield
205 CAResult_t CAArduinoGetInterfaceAddress(char *address, int32_t addrLen)
206 {
207     OIC_LOG(DEBUG, TAG, "IN");
208     if (WiFi.status() != WL_CONNECTED)
209     {
210         OIC_LOG(DEBUG, TAG, "No WIFI");
211         return CA_STATUS_FAILED;
212     }
213
214     VERIFY_NON_NULL(address, TAG, "Invalid address");
215     if (addrLen < IPNAMESIZE)
216     {
217         OIC_LOG_V(ERROR, TAG, "AddrLen MUST be atleast %d", IPNAMESIZE);
218         return CA_STATUS_FAILED;
219     }
220
221     IPAddress ip = WiFi.localIP();
222     sprintf((char *)address, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
223
224     OIC_LOG_V(DEBUG, TAG, "Wifi shield address is: %s", address);
225     OIC_LOG(DEBUG, TAG, "OUT");
226     return CA_STATUS_OK;
227 }
228
229
230