a02610d3b26b24be2b23b4bb20d552357564a39d
[iotivity.git] / service / easy-setup / enrollee / src / resourcehandler.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 #include "resourcehandler.h"
22
23 #include <stdio.h>
24
25 #include "ocpayload.h"
26 #include "oic_string.h"
27
28 /**
29  * @var ES_RH_TAG
30  * @brief Logging tag for module name.
31  */
32 #define ES_RH_TAG "ES_RH"
33 //-----------------------------------------------------------------------------
34 // Private variables
35 //-----------------------------------------------------------------------------
36
37 /**
38  * @var gProvResource
39  * @brief Structure for holding the Provisioning status and target information required to
40  * connect to the target network
41  */
42 static ProvResource gProvResource;
43
44 /**
45  * @var gNetResource
46  * @brief Structure forr holding the Provisioning status of network information
47  */
48 static NetResource gNetResource;
49
50 //-----------------------------------------------------------------------------
51 // Private internal function prototypes
52 //-----------------------------------------------------------------------------
53 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest *ehRequest,
54         void *callback);
55 const char *getResult(OCStackResult result);
56 OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest, OCRepPayload** payload);
57 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, OCRepPayload** payload);
58 OCEntityHandlerResult ProcessPostRequest(OCEntityHandlerRequest *ehRequest, OCRepPayload** payload);
59 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest);
60
61 ResourceEventCallback gNetworkInfoProvEventCb = NULL;
62
63 void RegisterResourceEventCallBack(ResourceEventCallback cb)
64 {
65     gNetworkInfoProvEventCb = cb;
66 }
67
68 void UnRegisterResourceEventCallBack()
69 {
70     if (gNetworkInfoProvEventCb)
71     {
72         gNetworkInfoProvEventCb = NULL;
73     }
74 }
75
76 void GetTargetNetworkInfoFromProvResource(char *name, char *pass)
77 {
78     if (name != NULL && pass != NULL)
79     {
80         OICStrcpy(name, sizeof(name), gProvResource.tnn);
81         OICStrcpy(pass, sizeof(pass), gProvResource.cd);
82     }
83 }
84
85 OCStackResult CreateProvisioningResource(bool isSecured)
86 {
87     gProvResource.ps = ES_PS_NEED_PROVISIONING;
88     gProvResource.tr = ES_PS_TRIGGER_INIT_VALUE;
89
90     gProvResource.tnt = CT_ADAPTER_IP;
91     OICStrcpy(gProvResource.tnn, sizeof(gProvResource.tnn), "Unknown");
92     OICStrcpy(gProvResource.cd, sizeof(gProvResource.cd), "Unknown");
93
94     OCStackResult res = OC_STACK_ERROR;
95     if (isSecured)
96     {
97         res = OCCreateResource(&gProvResource.handle, OC_RSRVD_ES_PROV_RES_TYPE,
98         OC_RSRVD_INTERFACE_DEFAULT,
99         OC_RSRVD_ES_URI_PROV, OCEntityHandlerCb,
100         NULL, OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
101     }
102     else
103     {
104         res = OCCreateResource(&gProvResource.handle, OC_RSRVD_ES_PROV_RES_TYPE,
105         OC_RSRVD_INTERFACE_DEFAULT,
106         OC_RSRVD_ES_URI_PROV, OCEntityHandlerCb,
107         NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
108     }
109
110     OIC_LOG_V(INFO, ES_RH_TAG, "Created Prov resource with result: %s", getResult(res));
111     return res;
112 }
113
114 OCStackResult DeleteProvisioningResource()
115 {
116     OCStackResult res = OCDeleteResource(gProvResource.handle);
117     if (res != OC_STACK_OK)
118     {
119         OIC_LOG_V(INFO, ES_RH_TAG, "Deleting Prov resource error with result: %s", getResult(res));
120     }
121
122     return res;
123 }
124
125 OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest, OCRepPayload **payload)
126 {
127     OCEntityHandlerResult ehResult = OC_EH_ERROR;
128     if (!ehRequest)
129     {
130         OIC_LOG(ERROR, ES_RH_TAG, "Request is Null");
131         return ehResult;
132     }
133     if (ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
134     {
135         OIC_LOG(ERROR, ES_RH_TAG, "Incoming payload not a representation");
136         return ehResult;
137     }
138
139     OCRepPayload *getResp = constructResponse(ehRequest);
140     if (!getResp)
141     {
142         OIC_LOG(ERROR, ES_RH_TAG, "constructResponse failed");
143         return OC_EH_ERROR;
144     }
145
146     *payload = getResp;
147     ehResult = OC_EH_OK;
148
149     return ehResult;
150 }
151
152 OCEntityHandlerResult ProcessPostRequest(OCEntityHandlerRequest *ehRequest, OCRepPayload** payload)
153 {
154     OIC_LOG(INFO, ES_RH_TAG, "ProcessPostRequest enter");
155     OCEntityHandlerResult ehResult = OC_EH_ERROR;
156     if (ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
157     {
158         OIC_LOG(ERROR, ES_RH_TAG, "Incoming payload not a representation");
159         return ehResult;
160     }
161
162     OCRepPayload* input = (OCRepPayload*) (ehRequest->payload);
163     if (!input)
164     {
165         OIC_LOG(ERROR, ES_RH_TAG, "Failed to parse");
166         return ehResult;
167     }
168
169     int64_t tr;
170     if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_TR, &tr))
171     {
172         // Triggering
173         gProvResource.tr = tr;
174     }
175
176     //ES_PS_PROVISIONING_COMPLETED state indicates that already provisioning is completed.
177     // A new request for provisioning means overriding existing network provisioning information.
178     if (gProvResource.ps == ES_PS_PROVISIONING_COMPLETED && tr == ES_PS_TRIGGER_CONNECTION)
179     {
180         OIC_LOG(DEBUG, ES_RH_TAG, "Provisioning already completed."
181                 "Tiggering the network connection");
182
183         if (gNetworkInfoProvEventCb)
184         {
185             gNetworkInfoProvEventCb(ES_RECVTRIGGEROFPROVRES);
186             ehResult = OC_EH_OK;
187         }
188         else
189         {
190             OIC_LOG(ERROR, ES_RH_TAG, "gNetworkInfoProvEventCb is NULL."
191                     "Network handler not registered. Failed to connect to the network");
192             ehResult = OC_EH_ERROR;
193         }
194
195         return ehResult;
196     }
197     else if (gProvResource.ps == ES_PS_PROVISIONING_COMPLETED)
198     {
199         OIC_LOG(DEBUG, ES_RH_TAG, "Provisioning already completed. "
200                 "This a request to override the existing the network provisioning information");
201     }
202     else
203     {
204         OIC_LOG(DEBUG, ES_RH_TAG, "Provisioning the network information to the Enrollee.");
205     }
206
207     OICStrcpy(gProvResource.tnn, sizeof(gProvResource.tnn), "");
208     OICStrcpy(gProvResource.cd, sizeof(gProvResource.cd), "");
209
210     char* tnn;
211     if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_TNN, &tnn))
212     {
213         OICStrcpy(gProvResource.tnn, sizeof(gProvResource.tnn), tnn);
214         OIC_LOG(INFO, ES_RH_TAG, "got ssid");
215     }
216
217     OIC_LOG_V(INFO, ES_RH_TAG, "gProvResource.tnn %s", gProvResource.tnn);
218
219     char* cd;
220     if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_CD, &cd))
221     {
222         OICStrcpy(gProvResource.cd, sizeof(gProvResource.cd), cd);
223         OIC_LOG(INFO, ES_RH_TAG, "got password");
224     }OIC_LOG_V(INFO, ES_RH_TAG, "gProvResource.cd %s", gProvResource.cd);
225
226     gProvResource.ps = ES_PS_PROVISIONING_COMPLETED;
227
228     OIC_LOG_V(INFO, ES_RH_TAG, "gProvResource.ps %lld", gProvResource.ps);
229
230     OCRepPayload *getResp = constructResponse(ehRequest);
231     if (!getResp)
232     {
233         OIC_LOG(ERROR, ES_RH_TAG, "constructResponse failed");
234         return OC_EH_ERROR;
235     }
236
237     *payload = getResp;
238     ehResult = OC_EH_OK;
239
240     return ehResult;
241 }
242
243 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest * /*ehRequest*/,
244         OCRepPayload** /*payload*/)
245 {
246     OCEntityHandlerResult ehResult = OC_EH_ERROR;
247
248     return ehResult;
249 }
250
251 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
252 {
253     OCRepPayload* payload = OCRepPayloadCreate();
254     if (!payload)
255     {
256         OIC_LOG(ERROR, ES_RH_TAG, "Failed to allocate Payload");
257         return NULL;
258     }
259
260     if (ehRequest->resource == gProvResource.handle)
261     {
262         OIC_LOG(INFO, ES_RH_TAG, "constructResponse prov res");
263         OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_PROV);
264         OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_PS, gProvResource.ps);
265         OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_TNT, gProvResource.tnt);
266     }
267     else if (ehRequest->requestHandle == gNetResource.handle)
268     {
269
270         OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_NET);
271         OCRepPayloadSetPropInt(payload, "ant", gNetResource.ant[0]);
272     }
273     return payload;
274 }
275
276 /**
277  * This is the entity handler for the registered resource.
278  * This is invoked by OCStack whenever it recevies a request for this resource.
279  */
280 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
281         OCEntityHandlerRequest* entityHandlerRequest, void *callback)
282 {
283     (void) callback;
284     OCEntityHandlerResult ehRet = OC_EH_OK;
285     OCEntityHandlerResponse response =
286     { 0, 0, OC_EH_ERROR, 0, 0,
287     { },
288     { 0 }, false };
289     OCRepPayload* payload = NULL;
290
291     if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
292     {
293         if (OC_REST_GET == entityHandlerRequest->method)
294         {
295             OIC_LOG(INFO, ES_RH_TAG, "Received GET request");
296             ehRet = ProcessGetRequest(entityHandlerRequest, &payload);
297         }
298         else if (OC_REST_PUT == entityHandlerRequest->method)
299         {
300             OIC_LOG(INFO, ES_RH_TAG, "Received PUT request");
301
302             //PUT request will be handled in the internal implementation
303             if (gProvResource.handle != NULL
304                     && entityHandlerRequest->resource == gProvResource.handle)
305             {
306                 ehRet = ProcessPutRequest(entityHandlerRequest, &payload);
307             }
308             else
309             {
310                 OIC_LOG(ERROR, ES_RH_TAG, "Cannot process put");
311                 ehRet = OC_EH_ERROR;
312             }
313         }
314         else if (OC_REST_POST == entityHandlerRequest->method)
315         {
316             OIC_LOG(INFO, ES_RH_TAG, "Received OC_REST_POST from client");
317             if (gProvResource.handle != NULL
318                     && entityHandlerRequest->resource == gProvResource.handle)
319             {
320                 ehRet = ProcessPostRequest(entityHandlerRequest, &payload);
321             }
322             else
323             {
324                 OIC_LOG(ERROR, ES_RH_TAG, "Cannot process put");
325                 ehRet = OC_EH_ERROR;
326             }
327         }
328
329         if (ehRet == OC_EH_OK)
330         {
331             // Format the response.  Note this requires some info about the request
332             response.requestHandle = entityHandlerRequest->requestHandle;
333             response.resourceHandle = entityHandlerRequest->resource;
334             response.ehResult = ehRet;
335             //response uses OCPaylod while all get,put methodes use OCRepPayload
336             response.payload = (OCPayload*) (payload);
337             response.numSendVendorSpecificHeaderOptions = 0;
338             memset(response.sendVendorSpecificHeaderOptions, 0,
339                     sizeof(response.sendVendorSpecificHeaderOptions));
340             memset(response.resourceUri, 0, sizeof(response.resourceUri));
341             // Indicate that response is NOT in a persistent buffer
342             response.persistentBufferFlag = 0;
343
344             // Send the response
345             if (OCDoResponse(&response) != OC_STACK_OK)
346             {
347                 OIC_LOG(ERROR, ES_RH_TAG, "Error sending response");
348                 ehRet = OC_EH_ERROR;
349             }
350         }
351     }
352
353     return ehRet;
354 }
355
356 const char *getResult(OCStackResult result)
357 {
358     switch (result)
359     {
360         case OC_STACK_OK:
361             return "OC_STACK_OK";
362         case OC_STACK_INVALID_URI:
363             return "OC_STACK_INVALID_URI";
364         case OC_STACK_INVALID_QUERY:
365             return "OC_STACK_INVALID_QUERY";
366         case OC_STACK_INVALID_IP:
367             return "OC_STACK_INVALID_IP";
368         case OC_STACK_INVALID_PORT:
369             return "OC_STACK_INVALID_PORT";
370         case OC_STACK_INVALID_CALLBACK:
371             return "OC_STACK_INVALID_CALLBACK";
372         case OC_STACK_INVALID_METHOD:
373             return "OC_STACK_INVALID_METHOD";
374         case OC_STACK_NO_MEMORY:
375             return "OC_STACK_NO_MEMORY";
376         case OC_STACK_COMM_ERROR:
377             return "OC_STACK_COMM_ERROR";
378         case OC_STACK_INVALID_PARAM:
379             return "OC_STACK_INVALID_PARAM";
380         case OC_STACK_NOTIMPL:
381             return "OC_STACK_NOTIMPL";
382         case OC_STACK_NO_RESOURCE:
383             return "OC_STACK_NO_RESOURCE";
384         case OC_STACK_RESOURCE_ERROR:
385             return "OC_STACK_RESOURCE_ERROR";
386         case OC_STACK_SLOW_RESOURCE:
387             return "OC_STACK_SLOW_RESOURCE";
388         case OC_STACK_NO_OBSERVERS:
389             return "OC_STACK_NO_OBSERVERS";
390         case OC_STACK_ERROR:
391             return "OC_STACK_ERROR";
392         default:
393             return "UNKNOWN";
394     }
395 }
396