Merge branch 'master' into notification-service
[platform/upstream/iotivity.git] / service / easy-setup / enrollee / src / resourcehandler.c
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, MAXSSIDLEN, gProvResource.tnn);
81         OICStrcpy(pass, MAXNETCREDLEN, 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     char* tnn;
170     if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_TNN, &tnn))
171     {
172         OICStrcpy(gProvResource.tnn, sizeof(gProvResource.tnn), tnn);
173         OIC_LOG_V(INFO, ES_RH_TAG, "gProvResource.tnn %s", gProvResource.tnn);
174
175         gProvResource.ps = ES_PS_PROVISIONING_COMPLETED;
176     }
177
178     char* cd;
179     if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_CD, &cd))
180     {
181         OICStrcpy(gProvResource.cd, sizeof(gProvResource.cd), cd);
182         OIC_LOG_V(INFO, ES_RH_TAG, "gProvResource.cd %s", gProvResource.cd);
183     }
184
185     OIC_LOG_V(INFO, ES_RH_TAG, "gProvResource.ps %lld", gProvResource.ps);
186
187     int64_t tr;
188     if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_TR, &tr))
189     {
190         // Triggering
191         gProvResource.tr = tr;
192     }
193
194     //ES_PS_PROVISIONING_COMPLETED state indicates that already provisioning is completed.
195     // A new request for provisioning means overriding existing network provisioning information.
196     if (gProvResource.ps == ES_PS_PROVISIONING_COMPLETED && tr == ES_PS_TRIGGER_CONNECTION)
197     {
198         OIC_LOG(DEBUG, ES_RH_TAG, "Provisioning already completed."
199                 "Tiggering the network connection");
200
201         if (gNetworkInfoProvEventCb)
202         {
203             gNetworkInfoProvEventCb(ES_RECVTRIGGEROFPROVRES);
204             ehResult = OC_EH_OK;
205         }
206         else
207         {
208             gProvResource.tr = ES_PS_TRIGGER_INIT_VALUE;
209             OIC_LOG(ERROR, ES_RH_TAG, "gNetworkInfoProvEventCb is NULL."
210                     "Network handler not registered. Failed to connect to the network");
211             ehResult = OC_EH_ERROR;
212         }
213
214         return ehResult;
215     }
216     else if (gProvResource.ps == ES_PS_PROVISIONING_COMPLETED)
217     {
218         OIC_LOG(DEBUG, ES_RH_TAG, "Provisioning already completed. "
219                 "This a request to override the existing the network provisioning information");
220     }
221     else
222     {
223         OIC_LOG(DEBUG, ES_RH_TAG, "Provisioning the network information to the Enrollee.");
224     }
225
226     OCRepPayload *getResp = constructResponse(ehRequest);
227     if (!getResp)
228     {
229         OIC_LOG(ERROR, ES_RH_TAG, "constructResponse failed");
230         return OC_EH_ERROR;
231     }
232
233     *payload = getResp;
234     ehResult = OC_EH_OK;
235
236     return ehResult;
237 }
238
239 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest * ehRequest,
240         OCRepPayload** payload)
241 {
242     OCEntityHandlerResult ehResult = OC_EH_ERROR;
243
244     return ehResult;
245 }
246
247 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
248 {
249     OCRepPayload* payload = OCRepPayloadCreate();
250     if (!payload)
251     {
252         OIC_LOG(ERROR, ES_RH_TAG, "Failed to allocate Payload");
253         return NULL;
254     }
255
256     if (ehRequest->resource == gProvResource.handle)
257     {
258         OIC_LOG(INFO, ES_RH_TAG, "constructResponse prov res");
259         OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_PROV);
260         OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_PS, gProvResource.ps);
261         OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_TNT, gProvResource.tnt);
262     }
263     else if (ehRequest->requestHandle == gNetResource.handle)
264     {
265
266         OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_NET);
267         OCRepPayloadSetPropInt(payload, "ant", gNetResource.ant[0]);
268     }
269     return payload;
270 }
271
272 /**
273  * This is the entity handler for the registered resource.
274  * This is invoked by OCStack whenever it recevies a request for this resource.
275  */
276 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
277         OCEntityHandlerRequest* entityHandlerRequest, void *callback)
278 {
279     (void) callback;
280     OCEntityHandlerResult ehRet = OC_EH_OK;
281     OCEntityHandlerResponse response =
282     { 0, 0, OC_EH_ERROR, 0, 0,
283     { },
284     { 0 }, false };
285     OCRepPayload* payload = NULL;
286
287     if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
288     {
289         if (OC_REST_GET == entityHandlerRequest->method)
290         {
291             OIC_LOG(INFO, ES_RH_TAG, "Received GET request");
292             ehRet = ProcessGetRequest(entityHandlerRequest, &payload);
293         }
294         else if (OC_REST_PUT == entityHandlerRequest->method)
295         {
296             OIC_LOG(INFO, ES_RH_TAG, "Received PUT request");
297
298             //PUT request will be handled in the internal implementation
299             if (gProvResource.handle != NULL
300                     && entityHandlerRequest->resource == gProvResource.handle)
301             {
302                 ehRet = ProcessPutRequest(entityHandlerRequest, &payload);
303             }
304             else
305             {
306                 OIC_LOG(ERROR, ES_RH_TAG, "Cannot process put");
307                 ehRet = OC_EH_ERROR;
308             }
309         }
310         else if (OC_REST_POST == entityHandlerRequest->method)
311         {
312             OIC_LOG(INFO, ES_RH_TAG, "Received OC_REST_POST from client");
313             if (gProvResource.handle != NULL
314                     && entityHandlerRequest->resource == gProvResource.handle)
315             {
316                 ehRet = ProcessPostRequest(entityHandlerRequest, &payload);
317             }
318             else
319             {
320                 OIC_LOG(ERROR, ES_RH_TAG, "Cannot process put");
321                 ehRet = OC_EH_ERROR;
322             }
323         }
324
325         if (ehRet == OC_EH_OK)
326         {
327             // Format the response.  Note this requires some info about the request
328             response.requestHandle = entityHandlerRequest->requestHandle;
329             response.resourceHandle = entityHandlerRequest->resource;
330             response.ehResult = ehRet;
331             //response uses OCPaylod while all get,put methodes use OCRepPayload
332             response.payload = (OCPayload*) (payload);
333             response.numSendVendorSpecificHeaderOptions = 0;
334             memset(response.sendVendorSpecificHeaderOptions, 0,
335                     sizeof(response.sendVendorSpecificHeaderOptions));
336             memset(response.resourceUri, 0, sizeof(response.resourceUri));
337             // Indicate that response is NOT in a persistent buffer
338             response.persistentBufferFlag = 0;
339
340             // Send the response
341             if (OCDoResponse(&response) != OC_STACK_OK)
342             {
343                 OIC_LOG(ERROR, ES_RH_TAG, "Error sending response");
344                 ehRet = OC_EH_ERROR;
345             }
346         }
347     }
348
349     return ehRet;
350 }
351
352 const char *getResult(OCStackResult result)
353 {
354     switch (result)
355     {
356         case OC_STACK_OK:
357             return "OC_STACK_OK";
358         case OC_STACK_INVALID_URI:
359             return "OC_STACK_INVALID_URI";
360         case OC_STACK_INVALID_QUERY:
361             return "OC_STACK_INVALID_QUERY";
362         case OC_STACK_INVALID_IP:
363             return "OC_STACK_INVALID_IP";
364         case OC_STACK_INVALID_PORT:
365             return "OC_STACK_INVALID_PORT";
366         case OC_STACK_INVALID_CALLBACK:
367             return "OC_STACK_INVALID_CALLBACK";
368         case OC_STACK_INVALID_METHOD:
369             return "OC_STACK_INVALID_METHOD";
370         case OC_STACK_NO_MEMORY:
371             return "OC_STACK_NO_MEMORY";
372         case OC_STACK_COMM_ERROR:
373             return "OC_STACK_COMM_ERROR";
374         case OC_STACK_INVALID_PARAM:
375             return "OC_STACK_INVALID_PARAM";
376         case OC_STACK_NOTIMPL:
377             return "OC_STACK_NOTIMPL";
378         case OC_STACK_NO_RESOURCE:
379             return "OC_STACK_NO_RESOURCE";
380         case OC_STACK_RESOURCE_ERROR:
381             return "OC_STACK_RESOURCE_ERROR";
382         case OC_STACK_SLOW_RESOURCE:
383             return "OC_STACK_SLOW_RESOURCE";
384         case OC_STACK_NO_OBSERVERS:
385             return "OC_STACK_NO_OBSERVERS";
386         case OC_STACK_ERROR:
387             return "OC_STACK_ERROR";
388         default:
389             return "UNKNOWN";
390     }
391 }
392