Update the folder structure for Enrollee implmentation.
[platform/upstream/iotivity.git] / service / easy-setup / sdk / enrollee / common / src / resourceHandler.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 "resourceHandler.h"
22 #include "cJSON.h"
23
24 PROGMEM const char TAG[] = "resourceHandler";
25
26 ProvResource g_prov;
27 NetResource g_net;
28
29 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag, OCEntityHandlerRequest *);
30 const char *getResult(OCStackResult result);
31
32 OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest, char *payload,
33         uint16_t maxPayloadSize);
34 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, char *payload,
35         uint16_t maxPayloadSize);
36 OCEntityHandlerResult ProcessPostRequest(OCEntityHandlerRequest *ehRequest, char *payload,
37         uint16_t maxPayloadSize);
38 char* constructJsonResponse(OCEntityHandlerRequest *ehRequest);
39
40 int g_flag = 0;
41
42 ResourceEventCallback g_cbForResEvent = NULL;
43
44 void RegisterResourceEventCallBack(ResourceEventCallback cb)
45 {
46     g_cbForResEvent = cb;
47 }
48
49 void GetTargetNetworkInfoFromProvResource(char *name, char *pass)
50 {
51     if (name != NULL && pass != NULL)
52     {
53         sprintf(name, "%s", g_prov.tnn);
54         sprintf(pass, "%s", g_prov.cd);
55     }
56 }
57
58 OCStackResult CreateProvisioningResource()
59 {
60     g_prov.ps = 1; // need to provisioning
61     g_prov.tnt = ES_WIFI;
62     sprintf(g_prov.tnn, "Unknown");
63     sprintf(g_prov.cd, "Unknown");
64
65     OCStackResult res = OCCreateResource(&g_prov.handle, "oic.prov", OC_RSRVD_INTERFACE_DEFAULT,
66             "/oic/prov", OCEntityHandlerCb, OC_DISCOVERABLE | OC_OBSERVABLE);
67
68     OC_LOG_V(INFO, TAG, "Created Prov resource with result: %s", getResult(res));
69
70     return res;
71 }
72
73 OCStackResult CreateNetworkResource()
74 {
75     NetworkInfo netInfo;
76
77     if (getCurrentNetworkInfo(ES_WIFI, &netInfo) != 0)
78     {
79         return OC_STACK_ERROR;
80     }
81
82     if (netInfo.type != ES_WIFI)
83     {
84         return OC_STACK_ERROR;
85     }
86
87     g_net.cnt = (int) netInfo.type;
88     g_net.ant[0] = (int) ES_WIFI;
89     sprintf(g_net.ipaddr, "%d.%d.%d.%d", netInfo.ipaddr[0], netInfo.ipaddr[1], netInfo.ipaddr[2],
90             netInfo.ipaddr[3]);
91     sprintf(g_net.cnn, "%s", netInfo.ssid);
92
93     OC_LOG_V(INFO, TAG, "SSID: %s", g_net.cnn);
94     OC_LOG_V(INFO, TAG, "IP Address: %s", g_net.ipaddr);
95
96     OCStackResult res = OCCreateResource(&g_net.handle, "oic.net", OC_RSRVD_INTERFACE_DEFAULT,
97             "/oic/net", OCEntityHandlerCb, OC_DISCOVERABLE | OC_OBSERVABLE);
98     OC_LOG_V(INFO, TAG, "Created Net resource with result: %s", getResult(res));
99
100     return res;
101 }
102
103 OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest, char *payload,
104         uint16_t maxPayloadSize)
105 {
106     OCEntityHandlerResult ehResult = OC_EH_ERROR;
107
108     char *getResp = constructJsonResponse(ehRequest);
109
110     if (!getResp)
111     {
112         OC_LOG(ERROR, TAG, "constructJsonResponse failed");
113         return OC_EH_ERROR;
114     }
115
116     if (MAX_RESPONSE_LENGTH > strlen(getResp))
117     {
118         strncpy(payload, getResp, strlen(getResp));
119         ehResult = OC_EH_OK;
120     }
121     else
122     {
123         OC_LOG_V(INFO, TAG, "Response buffer: %d bytes is too small", maxPayloadSize);
124         ehResult = OC_EH_ERROR;
125     }
126
127     free(getResp);
128
129     return ehResult;
130 }
131
132 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, char *payload,
133         uint16_t maxPayloadSize)
134 {
135     OCEntityHandlerResult ehResult = OC_EH_ERROR;
136
137     OC_LOG_V(INFO, TAG, "PUT Request Payload: %s", ehRequest->reqJSONPayload);
138
139     // Get cJSON pointer to query
140     cJSON *putJson = cJSON_Parse(ehRequest->reqJSONPayload);
141     if (!putJson)
142     {
143         OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
144         return ehResult;
145     }
146
147     // Get root of JSON payload, then the 1st resource.
148     cJSON* carrier = cJSON_GetObjectItem(putJson, "oic");
149     if (!carrier)
150     {
151         OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
152         return ehResult;
153     }
154     carrier = cJSON_GetArrayItem(carrier, 0);
155     carrier = cJSON_GetObjectItem(carrier, "rep");
156     if (!carrier)
157     {
158         OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
159         return ehResult;
160     }
161
162     cJSON* prop = cJSON_GetObjectItem(carrier, "tnn");
163     if (prop)
164     {
165         sprintf(g_prov.tnn, "%s", prop->valuestring);
166     }
167
168     prop = cJSON_GetObjectItem(carrier, "cd");
169     if (prop)
170     {
171         sprintf(g_prov.cd, "%s", prop->valuestring);
172     }
173
174     cJSON_Delete(putJson);
175
176     // TODO: Now once receiving PUT request, the enrollee start to connect to enroller.
177     g_flag = 1;
178
179     char *getResp = constructJsonResponse(ehRequest);
180
181     if (!getResp)
182     {
183         OC_LOG(ERROR, TAG, "constructJsonResponse failed");
184         return OC_EH_ERROR;
185     }
186
187     if (MAX_RESPONSE_LENGTH > strlen(getResp))
188     {
189         strncpy(payload, getResp, strlen(getResp));
190         ehResult = OC_EH_OK;
191     }
192     else
193     {
194         OC_LOG_V(INFO, TAG, "Response buffer: %d bytes is too small", maxPayloadSize);
195         ehResult = OC_EH_ERROR;
196     }
197
198     free(getResp);
199     return ehResult;
200 }
201
202 OCEntityHandlerResult ProcessPostRequest(OCEntityHandlerRequest *ehRequest, char *payload,
203         uint16_t maxPayloadSize)
204 {
205     OCEntityHandlerResult ehResult = OC_EH_ERROR;
206     OC_LOG_V(INFO, TAG, "PUT Request Payload: %s", ehRequest->reqJSONPayload);
207
208     // Get cJSON pointer to query
209     cJSON *putJson = cJSON_Parse(ehRequest->reqJSONPayload);
210
211     if (!putJson)
212     {
213         OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
214         return ehResult;
215     }
216
217     // Get root of JSON payload, then the 1st resource.
218     cJSON* carrier = cJSON_GetObjectItem(putJson, "oic");
219     if (!carrier)
220     {
221         OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
222         return ehResult;
223     }
224     carrier = cJSON_GetArrayItem(carrier, 0);
225     carrier = cJSON_GetObjectItem(carrier, "rep");
226     if (!carrier)
227     {
228         OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
229         return ehResult;
230     }
231
232     cJSON* prop = cJSON_GetObjectItem(carrier, "tr");
233     if (prop)
234     {
235         // Triggering
236         ehResult = OC_EH_OK;
237     }
238
239     cJSON_Delete(putJson);
240
241     g_flag = 1;
242
243     return ehResult;
244 }
245
246 char* constructJsonResponse(OCEntityHandlerRequest *ehRequest)
247 {
248     cJSON *json = cJSON_CreateObject();
249     cJSON *format;
250     char *jsonResponse;
251     char *JsonResp;
252     char temp_resp[256];
253
254     if (g_prov.handle != NULL && ehRequest->resource == g_prov.handle)
255     {
256         char *uri = (char *) "/oic/prov";
257
258         cJSON_AddStringToObject(json, "href", uri);
259         cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
260         cJSON_AddNumberToObject(format, "ps", g_prov.ps);
261         cJSON_AddNumberToObject(format, "tnt", g_prov.tnt);
262         cJSON_AddStringToObject(format, "tnn", g_prov.tnn);
263         cJSON_AddStringToObject(format, "cd", g_prov.cd);
264
265         jsonResponse = cJSON_Print(json);
266         cJSON_Delete(json);
267     }
268     else if (g_net.handle != NULL && ehRequest->requestHandle == g_net.handle)
269     {
270         char *uri = (char *) "/oic/net";
271
272         cJSON_AddStringToObject(json, "href", uri);
273         cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
274         cJSON_AddNumberToObject(format, "ant", g_net.ant[0]);
275
276         jsonResponse = cJSON_Print(json);
277         cJSON_Delete(json);
278     }
279     else
280     {
281         return jsonResponse;
282     }
283
284     OC_LOG_V(INFO, TAG, "Constructed Response: %s", jsonResponse);
285
286     return jsonResponse;
287 }
288
289 // This is the entity handler for the registered resource.
290 // This is invoked by OCStack whenever it recevies a request for this resource.
291
292 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
293         OCEntityHandlerRequest* entityHandlerRequest)
294 {
295     OCEntityHandlerResult ehRet = OC_EH_OK;
296     OCEntityHandlerResponse response =
297     { 0 };
298     char payload[MAX_RESPONSE_LENGTH] =
299     { 0 };
300
301     if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
302     {
303         if (OC_REST_GET == entityHandlerRequest->method)
304         {
305             OC_LOG_V(INFO, TAG, "Received GET request");
306             ehRet = ProcessGetRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
307         }
308         else if (OC_REST_PUT == entityHandlerRequest->method)
309         {
310             OC_LOG_V(INFO, TAG, "Received PUT request");
311
312             if (g_prov.handle != NULL && entityHandlerRequest->resource == g_prov.handle)
313             {
314                 ehRet = ProcessPutRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
315             }
316             else
317             {
318                 ehRet = OC_EH_ERROR;
319             }
320         }
321         else if (OC_REST_POST == entityHandlerRequest->method)
322         {
323             // TODO: As of now, POST request will be not received.
324             OC_LOG(INFO, TAG, "Received OC_REST_POST from client");
325             //ehRet = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
326         }
327
328         if (ehRet == OC_EH_OK)
329         {
330             // Format the response.  Note this requires some info about the request
331             response.requestHandle = entityHandlerRequest->requestHandle;
332             response.resourceHandle = entityHandlerRequest->resource;
333             response.ehResult = ehRet;
334             response.payload = payload;
335             response.payloadSize = strlen(payload);
336             response.numSendVendorSpecificHeaderOptions = 0;
337             memset(response.sendVendorSpecificHeaderOptions, 0,
338                     sizeof response.sendVendorSpecificHeaderOptions);
339             memset(response.resourceUri, 0, sizeof response.resourceUri);
340             // Indicate that response is NOT in a persistent buffer
341             response.persistentBufferFlag = 0;
342
343             // Send the response
344             if (OCDoResponse(&response) != OC_STACK_OK)
345             {
346                 OC_LOG(ERROR, TAG, "Error sending response");
347                 ehRet = OC_EH_ERROR;
348             }
349         }
350     }
351
352     if (g_flag == 1)
353     {
354         g_cbForResEvent(ES_RECVTRIGGEROFPROVRES);
355         g_flag = 0;
356     }
357
358     return ehRet;
359 }
360
361 const char *getResult(OCStackResult result)
362 {
363     switch (result)
364     {
365         case OC_STACK_OK:
366             return "OC_STACK_OK";
367         case OC_STACK_INVALID_URI:
368             return "OC_STACK_INVALID_URI";
369         case OC_STACK_INVALID_QUERY:
370             return "OC_STACK_INVALID_QUERY";
371         case OC_STACK_INVALID_IP:
372             return "OC_STACK_INVALID_IP";
373         case OC_STACK_INVALID_PORT:
374             return "OC_STACK_INVALID_PORT";
375         case OC_STACK_INVALID_CALLBACK:
376             return "OC_STACK_INVALID_CALLBACK";
377         case OC_STACK_INVALID_METHOD:
378             return "OC_STACK_INVALID_METHOD";
379         case OC_STACK_NO_MEMORY:
380             return "OC_STACK_NO_MEMORY";
381         case OC_STACK_COMM_ERROR:
382             return "OC_STACK_COMM_ERROR";
383         case OC_STACK_INVALID_PARAM:
384             return "OC_STACK_INVALID_PARAM";
385         case OC_STACK_NOTIMPL:
386             return "OC_STACK_NOTIMPL";
387         case OC_STACK_NO_RESOURCE:
388             return "OC_STACK_NO_RESOURCE";
389         case OC_STACK_RESOURCE_ERROR:
390             return "OC_STACK_RESOURCE_ERROR";
391         case OC_STACK_SLOW_RESOURCE:
392             return "OC_STACK_SLOW_RESOURCE";
393         case OC_STACK_NO_OBSERVERS:
394             return "OC_STACK_NO_OBSERVERS";
395         case OC_STACK_ERROR:
396             return "OC_STACK_ERROR";
397         default:
398             return "UNKNOWN";
399     }
400 }
401