[Win32] Add secure provisioning and stack samples
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / sample / sampleserver_justworks.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 :  This sample server is generated based on ocserverbasicops.cpp
22 ///////////////////////////////////////////////////////////////////////
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <pthread.h>
29 #include "ocstack.h"
30 #include "ocpayload.h"
31
32 #include <unistd.h>
33 #if defined(_WIN32)
34 #include <windows.h>
35 /** @todo stop-gap for naming issue. Windows.h does not like us to use ERROR */
36 #ifdef ERROR
37 #undef ERROR
38 #endif //ERROR
39 #endif //_WIN32
40 #include "logger.h"
41
42
43 #define TAG "SAMPLE_JUSTWORKS"
44
45 int gQuitFlag = 0;
46
47 /* Structure to represent a LED resource */
48 typedef struct LEDRESOURCE{
49     OCResourceHandle handle;
50     bool state;
51     int power;
52 } LEDResource;
53
54 static LEDResource LED;
55 // This variable determines instance number of the LED resource.
56 // Used by POST method to create a new instance of LED resource.
57 static int gCurrLedInstance = 0;
58 #define SAMPLE_MAX_NUM_POST_INSTANCE  2
59 static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
60
61 char *gResourceUri= (char *)"/a/led";
62
63 //Secure Virtual Resource database for Iotivity Server
64 //It contains Server's Identity and the PSK credentials
65 //of other devices which the server trusts
66 static char CRED_FILE[] = "oic_svr_db_server_justworks.dat";
67
68 /* Function that creates a new LED resource by calling the
69  * OCCreateResource() method.
70  */
71 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
72
73 /* This method converts the payload to JSON format */
74 OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
75
76 /* Following methods process the PUT, GET, POST
77  * requests
78  */
79 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
80                                          OCRepPayload **payload);
81 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
82                                          OCRepPayload **payload);
83 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
84                                         OCEntityHandlerResponse *response,
85                                         OCRepPayload **payload);
86
87 /* Entity Handler callback functions */
88 OCEntityHandlerResult
89 OCEntityHandlerCb (OCEntityHandlerFlag flag,
90         OCEntityHandlerRequest *entityHandlerRequest,
91         void* callbackParam);
92
93 const char *getResult(OCStackResult result) {
94     switch (result) {
95     case OC_STACK_OK:
96         return "OC_STACK_OK";
97     case OC_STACK_RESOURCE_CREATED:
98         return "OC_STACK_RESOURCE_CREATED";
99     case OC_STACK_RESOURCE_DELETED:
100         return "OC_STACK_RESOURCE_DELETED";
101     case OC_STACK_INVALID_URI:
102         return "OC_STACK_INVALID_URI";
103     case OC_STACK_INVALID_QUERY:
104         return "OC_STACK_INVALID_QUERY";
105     case OC_STACK_INVALID_IP:
106         return "OC_STACK_INVALID_IP";
107     case OC_STACK_INVALID_PORT:
108         return "OC_STACK_INVALID_PORT";
109     case OC_STACK_INVALID_CALLBACK:
110         return "OC_STACK_INVALID_CALLBACK";
111     case OC_STACK_INVALID_METHOD:
112         return "OC_STACK_INVALID_METHOD";
113     case OC_STACK_NO_MEMORY:
114         return "OC_STACK_NO_MEMORY";
115     case OC_STACK_COMM_ERROR:
116         return "OC_STACK_COMM_ERROR";
117     case OC_STACK_INVALID_PARAM:
118         return "OC_STACK_INVALID_PARAM";
119     case OC_STACK_NOTIMPL:
120         return "OC_STACK_NOTIMPL";
121     case OC_STACK_NO_RESOURCE:
122         return "OC_STACK_NO_RESOURCE";
123     case OC_STACK_RESOURCE_ERROR:
124         return "OC_STACK_RESOURCE_ERROR";
125     case OC_STACK_SLOW_RESOURCE:
126         return "OC_STACK_SLOW_RESOURCE";
127     case OC_STACK_NO_OBSERVERS:
128         return "OC_STACK_NO_OBSERVERS";
129     #ifdef WITH_PRESENCE
130     case OC_STACK_PRESENCE_STOPPED:
131         return "OC_STACK_PRESENCE_STOPPED";
132     #endif
133     case OC_STACK_ERROR:
134         return "OC_STACK_ERROR";
135     default:
136         return "UNKNOWN";
137     }
138 }
139
140 OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
141 {
142     OCRepPayload* payload = OCRepPayloadCreate();
143     if(!payload)
144     {
145         OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
146         return NULL;
147     }
148
149     OCRepPayloadSetUri(payload, uri);
150     OCRepPayloadSetPropBool(payload, "state", state);
151     OCRepPayloadSetPropInt(payload, "power", power);
152
153     return payload;
154 }
155
156 //This function takes the request as an input and returns the response
157 OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
158 {
159     if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
160     {
161         OIC_LOG(ERROR, TAG, "Incoming payload not a representation");
162         return NULL;
163     }
164
165     OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
166
167     LEDResource *currLEDResource = &LED;
168
169     if (ehRequest->resource == gLedInstance[0].handle)
170     {
171         currLEDResource = &gLedInstance[0];
172         gResourceUri = (char *) "/a/led/0";
173     }
174     else if (ehRequest->resource == gLedInstance[1].handle)
175     {
176         currLEDResource = &gLedInstance[1];
177         gResourceUri = (char *) "/a/led/1";
178     }
179
180     if(OC_REST_PUT == ehRequest->method)
181     {
182         // Get pointer to query
183         int64_t pow;
184         if(OCRepPayloadGetPropInt(input, "power", &pow))
185         {
186             currLEDResource->power =pow;
187         }
188
189         bool state;
190         if(OCRepPayloadGetPropBool(input, "state", &state))
191         {
192             currLEDResource->state = state;
193         }
194     }
195
196     return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
197 }
198
199 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
200         OCRepPayload **payload)
201 {
202     OCEntityHandlerResult ehResult;
203
204     OCRepPayload *getResp = constructResponse(ehRequest);
205
206     if(getResp)
207     {
208         *payload = getResp;
209         ehResult = OC_EH_OK;
210     }
211     else
212     {
213         ehResult = OC_EH_ERROR;
214     }
215
216     return ehResult;
217 }
218
219 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
220         OCRepPayload **payload)
221 {
222     OCEntityHandlerResult ehResult;
223
224     OCRepPayload *putResp = constructResponse(ehRequest);
225
226     if(putResp)
227     {
228         *payload = putResp;
229         ehResult = OC_EH_OK;
230     }
231     else
232     {
233         ehResult = OC_EH_ERROR;
234     }
235
236     return ehResult;
237 }
238
239 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
240         OCEntityHandlerResponse *response, OCRepPayload **payload)
241 {
242     OCRepPayload *respPLPost_led = NULL;
243     OCEntityHandlerResult ehResult = OC_EH_OK;
244
245     /*
246      * The entity handler determines how to process a POST request.
247      * Per the REST paradigm, POST can also be used to update representation of existing
248      * resource or create a new resource.
249      * In the sample below, if the POST is for /a/led then a new instance of the LED
250      * resource is created with default representation (if representation is included in
251      * POST payload it can be used as initial values) as long as the instance is
252      * lesser than max new instance count. Once max instance count is reached, POST on
253      * /a/led updated the representation of /a/led (just like PUT)
254      */
255
256     if (ehRequest->resource == LED.handle)
257     {
258         if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
259         {
260             // Create new LED instance
261             char newLedUri[15] = "/a/led/";
262             int newLedUriLength = strlen(newLedUri);
263             snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
264
265             respPLPost_led = OCRepPayloadCreate();
266             OCRepPayloadSetUri(respPLPost_led, gResourceUri);
267             OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
268
269             if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
270             {
271                 OIC_LOG (INFO, TAG, "Created new LED instance");
272                 gLedInstance[gCurrLedInstance].state = 0;
273                 gLedInstance[gCurrLedInstance].power = 0;
274                 gCurrLedInstance++;
275                 strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
276                 ehResult = OC_EH_RESOURCE_CREATED;
277             }
278         }
279         else
280         {
281             respPLPost_led = constructResponse(ehRequest);
282         }
283     }
284     else
285     {
286         for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
287         {
288             if (ehRequest->resource == gLedInstance[i].handle)
289             {
290                 if (i == 0)
291                 {
292                     respPLPost_led = constructResponse(ehRequest);
293                     break;
294                 }
295                 else if (i == 1)
296                 {
297                     respPLPost_led = constructResponse(ehRequest);
298                 }
299             }
300         }
301     }
302
303     if (respPLPost_led != NULL)
304     {
305         *payload = respPLPost_led;
306         ehResult = OC_EH_OK;
307     }
308     else
309     {
310         OIC_LOG_V (INFO, TAG, "Payload was NULL");
311         ehResult = OC_EH_ERROR;
312     }
313
314     return ehResult;
315 }
316
317 OCEntityHandlerResult
318 OCEntityHandlerCb (OCEntityHandlerFlag flag,
319         OCEntityHandlerRequest *entityHandlerRequest,
320         void* callbackParam)
321 {
322     OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
323     (void)callbackParam;
324     OCEntityHandlerResult ehResult = OC_EH_ERROR;
325
326     OCEntityHandlerResponse response;
327     memset(&response, 0, sizeof(response));
328
329     // Validate pointer
330     if (!entityHandlerRequest)
331     {
332         OIC_LOG (ERROR, TAG, "Invalid request pointer");
333         return OC_EH_ERROR;
334     }
335
336     OCRepPayload* payload = NULL;
337
338     if (flag & OC_REQUEST_FLAG)
339     {
340         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
341         if (entityHandlerRequest)
342         {
343             if (OC_REST_GET == entityHandlerRequest->method)
344             {
345                 OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
346                 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
347             }
348             else if (OC_REST_PUT == entityHandlerRequest->method)
349             {
350                 OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
351                 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
352             }
353             else if (OC_REST_POST == entityHandlerRequest->method)
354             {
355                 OIC_LOG (INFO, TAG, "Received OC_REST_POST from client");
356                 ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
357             }
358             else
359             {
360                 OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
361                         entityHandlerRequest->method);
362                 ehResult = OC_EH_ERROR;
363             }
364
365             if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
366             {
367                 // Format the response.  Note this requires some info about the request
368                 response.requestHandle = entityHandlerRequest->requestHandle;
369                 response.resourceHandle = entityHandlerRequest->resource;
370                 response.ehResult = ehResult;
371                 response.payload = (OCPayload*)(payload);
372                 response.numSendVendorSpecificHeaderOptions = 0;
373                 memset(response.sendVendorSpecificHeaderOptions, 0,
374                        sizeof(response.sendVendorSpecificHeaderOptions));
375                 memset(response.resourceUri, 0, sizeof(response.resourceUri));
376                 // Indicate that response is NOT in a persistent buffer
377                 response.persistentBufferFlag = 0;
378
379                 // Send the response
380                 if (OCDoResponse(&response) != OC_STACK_OK)
381                 {
382                     OIC_LOG(ERROR, TAG, "Error sending response");
383                     ehResult = OC_EH_ERROR;
384                 }
385             }
386         }
387     }
388
389     OCPayloadDestroy(response.payload);
390     return ehResult;
391 }
392
393 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
394 void handleSigInt(int signum)
395 {
396     if (signum == SIGINT)
397     {
398         gQuitFlag = 1;
399     }
400 }
401
402 FILE* server_fopen(const char *path, const char *mode)
403 {
404     (void)path;
405     return fopen(CRED_FILE, mode);
406 }
407
408 int main()
409 {
410     struct timespec timeout;
411
412     OIC_LOG(DEBUG, TAG, "OCServer is starting...");
413
414     // Initialize Persistent Storage for SVR database
415     OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
416
417     OCRegisterPersistentStorageHandler(&ps);
418
419     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
420     {
421         OIC_LOG(ERROR, TAG, "OCStack init error");
422         return 0;
423     }
424
425     /*
426      * Declare and create the example resource: LED
427      */
428     createLEDResource(gResourceUri, &LED, false, 0);
429
430     timeout.tv_sec  = 0;
431     timeout.tv_nsec = 100000000L;
432
433     // Break from loop with Ctrl-C
434     OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
435     signal(SIGINT, handleSigInt);
436     while (!gQuitFlag)
437     {
438         if (OCProcess() != OC_STACK_OK)
439         {
440             OIC_LOG(ERROR, TAG, "OCStack process error");
441             return 0;
442         }
443 #if defined(_WIN32)
444         Sleep(100);
445 #else
446         nanosleep(&timeout, NULL);
447 #endif //defined(_WIN32)
448     }
449
450     OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
451
452     if (OCStop() != OC_STACK_OK)
453     {
454         OIC_LOG(ERROR, TAG, "OCStack process error");
455     }
456
457     return 0;
458 }
459
460 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
461 {
462     if (!uri)
463     {
464         OIC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
465         return -1;
466     }
467
468     ledResource->state = resourceState;
469     ledResource->power= resourcePower;
470     OCStackResult res = OCCreateResource(&(ledResource->handle),
471             "core.led",
472             OC_RSRVD_INTERFACE_DEFAULT,
473             uri,
474             OCEntityHandlerCb,
475             NULL,
476             OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
477     OIC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
478
479     return 0;
480 }