Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / service / easy-setup / mediator / csdk / src / wifiprovisioning.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 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 // NOTE : Keeping Wifi provisioning in this file to have adaptability while doing OOPs refactoring
22
23 #include "provisioning.h"
24
25 //Standard includes
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <signal.h>
30 #include <unistd.h>
31 #include <pthread.h>
32
33 //EasySetup include files
34 #include "ocpayload.h"
35 #include "escommon.h"
36
37 // External includes
38 #include "logger.h"
39 #include "oic_string.h"
40
41 #define ES_WIFI_PROV_TAG "ES_WIFI_PROVISIONING"
42
43 static const char * UNICAST_PROV_STATUS_QUERY = "coap://%s:%d%s";
44
45 OCStackApplicationResult ProvisionEnrolleeResponse(void* /*ctx*/, OCDoHandle /*handle*/,
46         OCClientResponse *clientResponse)
47 {
48     OIC_LOG_V(DEBUG, ES_WIFI_PROV_TAG, "Inside ProvisionEnrolleeResponse");
49
50     // If user stopped the process then return from this function;
51     if (IsSetupStopped())
52     {
53         ErrorCallback(DEVICE_NOT_PROVISIONED);
54         ClearMemory();
55         return OC_STACK_DELETE_TRANSACTION;
56     }
57
58     if (!ValidateEnrolleeResponse(clientResponse))
59     {
60         ErrorCallback(DEVICE_NOT_PROVISIONED);
61         return OC_STACK_DELETE_TRANSACTION;
62     }
63
64     char query[OIC_STRING_MAX_VALUE] =
65     { '\0' };
66     char resUri[MAX_URI_LENGTH] =
67     { '\0' };
68
69     OIC_LOG_V(DEBUG, ES_WIFI_PROV_TAG, "Resource URI = %s", clientResponse->resourceUri);
70
71     OICStrcpy(resUri, sizeof(resUri), clientResponse->resourceUri);
72
73 #ifdef REMOTE_ARDUINO_ENROLEE
74     //Arduino Enrollee needs mediator application provide IP and port55555 which is specific
75     // to Arduino WiFi enrollee
76     // REMOTE_ARDUINO_ENROLEE has to be defined if Mediator is being tested with Arduino
77     snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY, clientResponse->addr->addr, IP_PORT,
78             resUri);
79 #else
80     snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY, clientResponse->addr->addr,
81             clientResponse->addr->port, resUri);
82 #endif
83
84     if (TriggerNetworkConnection(OC_HIGH_QOS, query, OC_RSRVD_ES_URI_PROV, clientResponse->addr, 0)
85             != OC_STACK_OK)
86     {
87         OIC_LOG(INFO, ES_WIFI_PROV_TAG, "GetProvisioningStatusResponse received NULL clientResponse");
88
89         ErrorCallback(DEVICE_NOT_PROVISIONED);
90         ClearMemory();
91     }
92
93     return OC_STACK_DELETE_TRANSACTION;
94 }
95
96 OCStackApplicationResult GetProvisioningStatusResponse(void* /*ctx*/, OCDoHandle /*handle*/,
97         OCClientResponse *clientResponse)
98 {
99     // If user stopped the process then return from this function;
100     if (IsSetupStopped())
101     {
102         ErrorCallback(DEVICE_NOT_PROVISIONED);
103         ClearMemory();
104         return OC_STACK_DELETE_TRANSACTION;
105     }
106
107     if (!ValidateEnrolleeResponse(clientResponse))
108     {
109         ErrorCallback(DEVICE_NOT_PROVISIONED);
110         ClearMemory();
111         return OC_STACK_DELETE_TRANSACTION;
112     }
113
114     OCRepPayload *input = (OCRepPayload *) (clientResponse->payload);
115
116     char resUri[MAX_URI_LENGTH] = { '\0' };
117
118     OIC_LOG_V(DEBUG, ES_WIFI_PROV_TAG, "resUri = %s", clientResponse->resourceUri);
119
120     OICStrcpy(resUri, sizeof(resUri), clientResponse->resourceUri);
121
122     while (input)
123     {
124         int64_t ps;
125         if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_PS, &ps))
126         {
127
128             if (ps == ES_PS_NEED_PROVISIONING)
129             {
130                 input = input->next;
131                 continue;
132             }
133             else
134             {
135                 ErrorCallback(DEVICE_NOT_PROVISIONED);
136                 ClearMemory();
137                 return OC_STACK_DELETE_TRANSACTION;
138             }
139         }
140
141         LogProvisioningResponse(input->values);
142         input = input->next;
143     }
144
145     char query[OIC_STRING_MAX_VALUE] =
146     { '\0' };
147
148 #ifdef REMOTE_ARDUINO_ENROLEE
149     //Arduino Enrollee needs mediator application provide IP and port55555 which is specific
150     // to Arduino WiFi enrollee
151     // REMOTE_ARDUINO_ENROLEE has to be defined if Mediator is being tested with Arduino
152     snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY, clientResponse->addr->addr, IP_PORT,
153             resUri);
154 #else
155     snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY, clientResponse->addr->addr,
156             clientResponse->addr->port, resUri);
157 #endif
158
159     if (ProvisionEnrollee(OC_HIGH_QOS, query, OC_RSRVD_ES_URI_PROV, clientResponse->addr, 0)
160             != OC_STACK_OK)
161     {
162         OIC_LOG(INFO, ES_WIFI_PROV_TAG, "GetProvisioningStatusResponse received NULL clientResponse");
163
164         ErrorCallback(DEVICE_NOT_PROVISIONED);
165         ClearMemory();
166         return OC_STACK_DELETE_TRANSACTION;
167     }
168
169     return OC_STACK_KEEP_TRANSACTION;
170
171 }
172
173 OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char *query,
174         const OCDevAddr *destination)
175 {
176     OCStackResult ret = OC_STACK_ERROR;
177     OCHeaderOption options[MAX_HEADER_OPTIONS];
178
179     OIC_LOG(DEBUG, ES_WIFI_PROV_TAG, "Inside GetProvisioningStatus");
180
181     uint8_t option0[] =
182     { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
183     uint8_t option1[] =
184     { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
185     memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
186     options[0].protocolID = OC_COAP_ID;
187     options[0].optionID = 2048;
188     memcpy(options[0].optionData, option0, sizeof(option0));
189     options[0].optionLength = 10;
190     options[1].protocolID = OC_COAP_ID;
191     options[1].optionID = 3000;
192     memcpy(options[1].optionData, option1, sizeof(option1));
193     options[1].optionLength = 10;
194
195     ret = InvokeOCDoResource(query, OC_REST_GET, destination, qos, GetProvisioningStatusResponse,
196     NULL, options, 2);
197     return ret;
198 }
199
200 // This is a function called back when a device is discovered
201 OCStackApplicationResult FindProvisioningResourceResponse(void* /*ctx*/, OCDoHandle /*handle*/,
202         OCClientResponse *clientResponse)
203 {
204
205     OIC_LOG_V(INFO, ES_WIFI_PROV_TAG, "Entering FindProvisioningResourceResponse %s",
206             clientResponse->devAddr.addr);
207
208     // If user stopped the process then return from this function;
209     if (IsSetupStopped())
210     {
211         ErrorCallback(DEVICE_NOT_PROVISIONED);
212         ClearMemory();
213         return OC_STACK_DELETE_TRANSACTION;
214     }
215
216     if (!ValidateFindResourceResponse(clientResponse))
217     {
218         ErrorCallback(DEVICE_NOT_PROVISIONED);
219         return OC_STACK_DELETE_TRANSACTION;
220     }
221
222     char szQueryUri[64] =
223     { 0 };
224
225     OCDiscoveryPayload *discoveryPayload = (OCDiscoveryPayload *) (clientResponse->payload);
226
227     OIC_LOG_V(DEBUG, ES_WIFI_PROV_TAG, "resUri = %s", discoveryPayload->resources->uri);
228
229 #ifdef REMOTE_ARDUINO_ENROLEE
230     //Arduino Enrollee needs mediator application provide IP and port55555 which is specific
231     // to Arduino WiFi enrollee
232     // REMOTE_ARDUINO_ENROLEE has to be defined if Mediator is being tested with Arduino
233     snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,
234             clientResponse->addr->addr,
235             IP_PORT,
236             discoveryPayload->resources->uri);
237 #else
238     snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,
239             clientResponse->devAddr.addr, clientResponse->devAddr.port,
240             discoveryPayload->resources->uri);
241 #endif
242
243     OIC_LOG_V(DEBUG, ES_WIFI_PROV_TAG, "query before GetProvisioningStatus call = %s", szQueryUri);
244
245     if (GetProvisioningStatus(OC_HIGH_QOS, szQueryUri, &clientResponse->devAddr) != OC_STACK_OK)
246     {
247         ErrorCallback(DEVICE_NOT_PROVISIONED);
248         return OC_STACK_DELETE_TRANSACTION;
249     }
250
251     return OC_STACK_KEEP_TRANSACTION;
252
253 }
254
255 bool ValidateEasySetupParams(const ProvConfig */*netInfo*/, WiFiOnboadingConnection *onboardConn,
256         OCProvisioningStatusCB provisioningStatusCallback)
257 {
258
259     if (onboardConn == NULL || strlen(onboardConn->ipAddress) == 0)
260     {
261         OIC_LOG(ERROR, ES_WIFI_PROV_TAG, "Request URI is NULL");
262         return false;
263     }
264
265     if (provisioningStatusCallback == NULL)
266     {
267         OIC_LOG(ERROR, ES_WIFI_PROV_TAG, "ProvisioningStatusCallback is NULL");
268         return false;
269     }
270
271     return true;
272
273 }
274