replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / ocservercoll.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH 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
22 #include "iotivity_config.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include <string>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #ifdef HAVE_WINDOWS_H
31 #include <windows.h>
32 #endif
33 #include <signal.h>
34 #ifdef HAVE_PTHREAD_H
35 #include <pthread.h>
36 #endif
37 #include <ocstack.h>
38 #include <logger.h>
39 #include <getopt.h>
40 #include "ocpayload.h"
41 #include "common.h"
42
43 #define TAG PCF("ocservercontainer")
44
45 volatile sig_atomic_t gQuitFlag = 0;
46 int gLightUnderObservation = 0;
47 void createResources();
48 typedef struct LIGHTRESOURCE{
49     OCResourceHandle handle;
50     bool state;
51     int power;
52 } LightResource;
53
54 static LightResource light;
55
56 char *gLightResourceUri= (char *)"/a/light";
57 char *gRoomResourceUri= (char *)"/a/room";
58 char *gFanResourceUri= (char *)"/a/fan";
59
60 typedef enum
61 {
62     TEST_INVALID = 0,
63     TEST_DEFAULT_COLL_EH,
64     TEST_APP_COLL_EH,
65     MAX_TESTS
66 } SERVER_TEST;
67
68 void PrintUsage()
69 {
70     OIC_LOG(INFO, TAG, "Usage : ocservercoll -t <Test Case>");
71     OIC_LOG(INFO, TAG,
72             "Test Case 1 : Create room resource with default collection entity handler.");
73     OIC_LOG(INFO, TAG,
74             "Test Case 2 : Create room resource with application collection entity handler.");
75 }
76
77 unsigned static int TEST = TEST_INVALID;
78
79 static void
80 PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
81 {
82     const char* typeOfMessage;
83     const char* typeOfMethod;
84
85     switch (flag)
86     {
87         case OC_REQUEST_FLAG:
88             typeOfMessage = "OC_REQUEST_FLAG";
89             break;
90         case OC_OBSERVE_FLAG:
91             typeOfMessage = "OC_OBSERVE_FLAG";
92             break;
93         default:
94             typeOfMessage = "UNKNOWN";
95     }
96
97     if (ehRequest == NULL)
98     {
99         typeOfMethod = "UNKNOWN";
100     }
101     else if (ehRequest->method == OC_REST_GET)
102     {
103         typeOfMethod = "OC_REST_GET";
104     }
105     else
106     {
107         typeOfMethod = "OC_REST_PUT";
108     }
109
110     OIC_LOG_V(INFO, TAG, "Receiving message type: %s, method %s", typeOfMessage,
111             typeOfMethod);
112 }
113
114 //The only case when this entity handler is for a non-existing resource.
115 OCEntityHandlerResult
116 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
117         OCEntityHandlerRequest *entityHandlerRequest, char* uri, void* /*callbackParam*/)
118 {
119     OIC_LOG_V(INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
120
121     OCEntityHandlerResult ehResult = OC_EH_OK;
122     OCEntityHandlerResponse response;
123
124     if (!entityHandlerRequest)
125     {
126         OIC_LOG(ERROR, TAG, "Invalid request pointer");
127         return OC_EH_ERROR;
128     }
129
130     if (entityHandlerRequest->resource == NULL)
131     {
132         OIC_LOG(INFO, TAG, "Received request from client to a non-existing resource");
133         ehResult = OC_EH_RESOURCE_NOT_FOUND;
134     }
135     else
136     {
137         OIC_LOG_V(INFO, TAG, "Device Handler: Received unsupported request from client %d",
138                         entityHandlerRequest->method);
139         ehResult = OC_EH_ERROR;
140     }
141
142     if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
143     {
144         // Format the response.  Note this requires some info about the request
145         response.requestHandle = entityHandlerRequest->requestHandle;
146         response.resourceHandle = entityHandlerRequest->resource;
147         response.ehResult = ehResult;
148         response.payload = nullptr;
149         response.numSendVendorSpecificHeaderOptions = 0;
150         memset(response.sendVendorSpecificHeaderOptions,
151                 0, sizeof response.sendVendorSpecificHeaderOptions);
152         // Indicate that response is NOT in a persistent buffer
153         response.persistentBufferFlag = 0;
154
155         // Send the response
156         if (OCDoResponse(&response) != OC_STACK_OK)
157         {
158             OIC_LOG(ERROR, TAG, "Error sending response");
159             ehResult = OC_EH_ERROR;
160         }
161     }
162     return ehResult;
163 }
164
165 OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
166                                             OCEntityHandlerRequest * ehRequest,
167                                             void* /*callback*/)
168 {
169     OCEntityHandlerResult ret = OC_EH_OK;
170     OCEntityHandlerResponse response;
171
172     OIC_LOG_V(INFO, TAG, "Callback for Room");
173     PrintReceivedMsgInfo(flag, ehRequest );
174
175     if(ehRequest && flag == OC_REQUEST_FLAG )
176     {
177         std::string query = (const char*)ehRequest->query;
178         OCRepPayload* payload = OCRepPayloadCreate();
179
180         if(OC_REST_GET == ehRequest->method)
181         {
182             if(query.find(OC_RSRVD_INTERFACE_DEFAULT) != std::string::npos)
183             {
184                 OCRepPayloadSetUri(payload, gRoomResourceUri);
185                 OCRepPayloadSetPropString(payload, "name", "John's Room");
186
187                 OCRepPayload *tempPayload = OCRepPayloadCreate();
188                 OCRepPayloadSetUri(tempPayload, gLightResourceUri);
189                 OCRepPayloadAppend(payload, tempPayload);
190
191                 OCRepPayload *tempPayload2 = OCRepPayloadCreate();
192                 OCRepPayloadSetUri(tempPayload2, gFanResourceUri);
193                 OCRepPayloadAppend(payload, tempPayload2);
194             }
195             else if(query.find(OC_RSRVD_INTERFACE_LL) != std::string::npos)
196             {
197                 OCRepPayloadSetUri(payload, gRoomResourceUri);
198
199                 OCRepPayload *tempPayload = OCRepPayloadCreate();
200                 OCRepPayloadSetUri(tempPayload, gLightResourceUri);
201                 OCRepPayloadAppend(payload, tempPayload);
202
203                 OCRepPayload *tempPayload2 = OCRepPayloadCreate();
204                 OCRepPayloadSetUri(tempPayload2, gFanResourceUri);
205                 OCRepPayloadAppend(payload, tempPayload2);
206             }
207             else if(query.find(OC_RSRVD_INTERFACE_BATCH) != std::string::npos)
208             {
209
210                 OCRepPayloadSetUri(payload, gRoomResourceUri);
211
212                 OCRepPayload *tempPayload = OCRepPayloadCreate();
213                 OCRepPayloadSetUri(tempPayload, gLightResourceUri);
214                 OCRepPayloadSetPropBool(tempPayload, "state", false);
215                 OCRepPayloadSetPropInt(tempPayload, "power", 0);
216                 OCRepPayloadAppend(payload, tempPayload);
217
218                 OCRepPayload *tempPayload2 = OCRepPayloadCreate();
219                 OCRepPayloadSetUri(tempPayload2, gFanResourceUri);
220                 OCRepPayloadSetPropBool(tempPayload2, "state", true);
221                 OCRepPayloadSetPropInt(tempPayload2, "speed", 10);
222                 OCRepPayloadAppend(payload, tempPayload2);
223             }
224             if (ret == OC_EH_OK)
225             {
226                 // Format the response.  Note this requires some info about the request
227                 response.requestHandle = ehRequest->requestHandle;
228                 response.resourceHandle = ehRequest->resource;
229                 response.ehResult = ret;
230                 response.payload = reinterpret_cast<OCPayload*>(payload);
231                 response.numSendVendorSpecificHeaderOptions = 0;
232                 memset(response.sendVendorSpecificHeaderOptions,
233                         0, sizeof response.sendVendorSpecificHeaderOptions);
234                 memset(response.resourceUri, 0, sizeof response.resourceUri);
235                 // Indicate that response is NOT in a persistent buffer
236                 response.persistentBufferFlag = 0;
237                 // Send the response
238                 if (OCDoResponse(&response) != OC_STACK_OK)
239                 {
240                     OIC_LOG(ERROR, TAG, "Error sending response");
241                     ret = OC_EH_ERROR;
242                 }
243             }
244         }
245         else if(OC_REST_PUT == ehRequest->method)
246         {
247             if(query.find(OC_RSRVD_INTERFACE_DEFAULT) != std::string::npos)
248             {
249                 if(ret != OC_EH_ERROR)
250                 {
251                     OCRepPayloadSetUri(payload, gRoomResourceUri);
252                     OCRepPayloadSetPropString(payload, "name", "John's Room");
253                 }
254             }
255             if(query.find(OC_RSRVD_INTERFACE_LL) != std::string::npos)
256             {
257                 if(ret != OC_EH_ERROR)
258                 {
259                     OCRepPayloadSetUri(payload, gRoomResourceUri);
260                 }
261                 if(ret != OC_EH_ERROR)
262                 {
263                     OCRepPayload *tempPayload = OCRepPayloadCreate();
264                     OCRepPayloadSetUri(tempPayload, gLightResourceUri);
265                     OCRepPayloadAppend(payload, tempPayload);
266                 }
267                 if(ret != OC_EH_ERROR)
268                 {
269                     OCRepPayload *tempPayload = OCRepPayloadCreate();
270                     OCRepPayloadSetUri(tempPayload, gFanResourceUri);
271                     OCRepPayloadAppend(payload, tempPayload);
272                 }
273             }
274             if(query.find(OC_RSRVD_INTERFACE_BATCH ) != std::string::npos)
275             {
276                 if(ret != OC_EH_ERROR)
277                 {
278                     OCRepPayloadSetUri(payload, gRoomResourceUri);
279                 }
280                 if(ret != OC_EH_ERROR)
281                 {
282                     OCRepPayload *tempPayload = OCRepPayloadCreate();
283                     OCRepPayloadSetUri(tempPayload, gLightResourceUri);
284                     OCRepPayloadSetPropBool(tempPayload, "state", true);
285                     OCRepPayloadSetPropInt(tempPayload, "power", 0);
286                     OCRepPayloadAppend(payload, tempPayload);
287                 }
288                 if(ret != OC_EH_ERROR)
289                 {
290                     OCRepPayload *tempPayload = OCRepPayloadCreate();
291                     OCRepPayloadSetUri(tempPayload, gFanResourceUri);
292                     OCRepPayloadSetPropBool(tempPayload, "state", false);
293                     OCRepPayloadSetPropInt(tempPayload, "speed", 0);
294                     OCRepPayloadAppend(payload, tempPayload);
295                 }
296             }
297             if (ret == OC_EH_OK)
298             {
299                 // Format the response.  Note this requires some info about the request
300                 response.requestHandle = ehRequest->requestHandle;
301                 response.resourceHandle = ehRequest->resource;
302                 response.ehResult = ret;
303                 response.payload = reinterpret_cast<OCPayload*>(payload);
304                 response.numSendVendorSpecificHeaderOptions = 0;
305                 memset(response.sendVendorSpecificHeaderOptions,
306                         0, sizeof response.sendVendorSpecificHeaderOptions);
307                 memset(response.resourceUri, 0, sizeof response.resourceUri);
308                 // Indicate that response is NOT in a persistent buffer
309                 response.persistentBufferFlag = 0;
310                 // Send the response
311                 if (OCDoResponse(&response) != OC_STACK_OK)
312                 {
313                     OIC_LOG(ERROR, TAG, "Error sending response");
314                     ret = OC_EH_ERROR;
315                 }
316             }
317         }
318         else
319         {
320             OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
321                     ehRequest->method);
322             ret = OC_EH_ERROR;
323         }
324         OCRepPayloadDestroy(payload);
325     }
326     else if (ehRequest && flag == OC_OBSERVE_FLAG)
327     {
328         gLightUnderObservation = 1;
329     }
330     return ret;
331 }
332
333 OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag,
334         OCEntityHandlerRequest * ehRequest,void* /*callbackParam*/)
335 {
336     OCEntityHandlerResult ret = OC_EH_OK;
337     OCEntityHandlerResponse response;
338
339     OIC_LOG_V(INFO, TAG, "Callback for Light");
340     PrintReceivedMsgInfo(flag, ehRequest );
341
342     if(ehRequest && flag == OC_REQUEST_FLAG)
343     {
344         OCRepPayload* payload = OCRepPayloadCreate();
345         if(OC_REST_GET == ehRequest->method)
346         {
347             OCRepPayloadSetUri(payload, gLightResourceUri);
348             OCRepPayloadSetPropBool(payload, "state", false);
349             OCRepPayloadSetPropInt(payload, "power", 0);
350         }
351         else if(OC_REST_PUT == ehRequest->method)
352         {
353             OCRepPayloadSetUri(payload, gLightResourceUri);
354             OCRepPayloadSetPropBool(payload, "state", true);
355             OCRepPayloadSetPropInt(payload, "power", 0);
356         }
357         else
358         {
359             OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
360                     ehRequest->method);
361             ret = OC_EH_ERROR;
362         }
363
364         if (ret == OC_EH_OK)
365         {
366             // Format the response.  Note this requires some info about the request
367             response.requestHandle = ehRequest->requestHandle;
368             response.resourceHandle = ehRequest->resource;
369             response.ehResult = ret;
370             response.payload = reinterpret_cast<OCPayload*>(payload);
371             response.numSendVendorSpecificHeaderOptions = 0;
372             memset(response.sendVendorSpecificHeaderOptions,
373                     0, sizeof response.sendVendorSpecificHeaderOptions);
374             memset(response.resourceUri, 0, sizeof response.resourceUri);
375             // Indicate that response is NOT in a persistent buffer
376             response.persistentBufferFlag = 0;
377
378             // Send the response
379             if (OCDoResponse(&response) != OC_STACK_OK)
380             {
381                 OIC_LOG(ERROR, TAG, "Error sending response");
382                 ret = OC_EH_ERROR;
383             }
384         }
385         OCRepPayloadDestroy(payload);
386     }
387     else if (ehRequest && flag == OC_OBSERVE_FLAG)
388     {
389         gLightUnderObservation = 1;
390     }
391
392     return ret;
393 }
394
395 OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
396         OCEntityHandlerRequest * ehRequest, void* /*callback*/)
397 {
398     OCEntityHandlerResult ret = OC_EH_OK;
399     OCEntityHandlerResponse response;
400
401     OIC_LOG_V(INFO, TAG, "Callback for Fan");
402     PrintReceivedMsgInfo(flag, ehRequest );
403
404     if(ehRequest && flag == OC_REQUEST_FLAG)
405     {
406         OCRepPayload* payload = OCRepPayloadCreate();
407
408         if(OC_REST_GET == ehRequest->method)
409         {
410             OCRepPayloadSetUri(payload, gFanResourceUri);
411             OCRepPayloadSetPropBool(payload, "state", true);
412             OCRepPayloadSetPropInt(payload, "speed", 10);
413         }
414         else if(OC_REST_PUT == ehRequest->method)
415         {
416             OCRepPayloadSetUri(payload, gFanResourceUri);
417             OCRepPayloadSetPropBool(payload, "state", false);
418             OCRepPayloadSetPropInt(payload, "speed", 0);
419         }
420         else
421         {
422             OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
423                     ehRequest->method);
424             ret = OC_EH_ERROR;
425         }
426
427         if (ret == OC_EH_OK)
428         {
429             // Format the response.  Note this requires some info about the request
430             response.requestHandle = ehRequest->requestHandle;
431             response.resourceHandle = ehRequest->resource;
432             response.ehResult = ret;
433             response.payload = reinterpret_cast<OCPayload*>(payload);
434             response.numSendVendorSpecificHeaderOptions = 0;
435             memset(response.sendVendorSpecificHeaderOptions,
436                     0, sizeof response.sendVendorSpecificHeaderOptions);
437             memset(response.resourceUri, 0, sizeof response.resourceUri);
438             // Indicate that response is NOT in a persistent buffer
439             response.persistentBufferFlag = 0;
440
441             // Send the response
442             if (OCDoResponse(&response) != OC_STACK_OK)
443             {
444                 OIC_LOG(ERROR, TAG, "Error sending response");
445                 ret = OC_EH_ERROR;
446             }
447         }
448         OCRepPayloadDestroy(payload);
449
450     }
451     else if (ehRequest && flag == OC_OBSERVE_FLAG)
452     {
453         gLightUnderObservation = 1;
454     }
455
456     return ret;
457 }
458
459 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
460 void handleSigInt(int signum)
461 {
462     if (signum == SIGINT)
463     {
464         gQuitFlag = 1;
465     }
466 }
467
468 void *ChangeLightRepresentation (void *param)
469 {
470     (void)param;
471     OCStackResult result = OC_STACK_ERROR;
472
473     while (!gQuitFlag)
474     {
475         sleep(10);
476         light.power += 5;
477         if (gLightUnderObservation)
478         {
479             OIC_LOG_V(INFO, TAG,
480                 " =====> Notifying stack of new power level %d\n", light.power);
481             result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
482             if (OC_STACK_NO_OBSERVERS == result)
483             {
484                 gLightUnderObservation = 0;
485             }
486         }
487     }
488     return NULL;
489 }
490
491 int main(int argc, char* argv[])
492 {
493     pthread_t threadId;
494     int opt;
495
496     while ((opt = getopt(argc, argv, "t:")) != -1)
497     {
498         switch(opt)
499         {
500         case 't':
501             TEST = atoi(optarg);
502             break;
503         default:
504             PrintUsage();
505             return -1;
506         }
507     }
508     if(TEST <= TEST_INVALID || TEST >= MAX_TESTS)
509     {
510         PrintUsage();
511         return -1;
512     }
513
514     OIC_LOG(DEBUG, TAG, "OCServer is starting...");
515
516     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
517     {
518         OIC_LOG(ERROR, TAG, "OCStack init error");
519         return 0;
520     }
521
522     OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
523
524     /*
525      * Declare and create the example resource: light
526      */
527     createResources();
528
529     /*
530      * Create a thread for changing the representation of the light
531      */
532     pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
533
534     // Break from loop with Ctrl-C
535     OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
536     signal(SIGINT, handleSigInt);
537     while (!gQuitFlag)
538     {
539         if (OCProcess() != OC_STACK_OK)
540         {
541             OIC_LOG(ERROR, TAG, "OCStack process error");
542             return 0;
543         }
544         sleep(2);
545     }
546
547     /*
548      * Cancel the light thread and wait for it to terminate
549      */
550 #ifdef HAVE_PTHREAD_H
551     pthread_cancel(threadId);
552     pthread_join(threadId, NULL);
553 #endif
554
555     OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
556
557     if (OCStop() != OC_STACK_OK)
558     {
559         OIC_LOG(ERROR, TAG, "OCStack process error");
560     }
561
562     return 0;
563 }
564
565 void createResources()
566 {
567     light.state = false;
568
569     OCResourceHandle fan;
570     OCStackResult res = OCCreateResource(&fan,
571             "core.fan",
572             OC_RSRVD_INTERFACE_DEFAULT,
573             "/a/fan",
574             OCEntityHandlerFanCb,
575             NULL,
576             OC_DISCOVERABLE|OC_OBSERVABLE);
577     OIC_LOG_V(INFO, TAG, "Created fan resource with result: %s", getResult(res));
578
579     OCResourceHandle light;
580     res = OCCreateResource(&light,
581             "core.light",
582             OC_RSRVD_INTERFACE_DEFAULT,
583             "/a/light",
584             OCEntityHandlerLightCb,
585             NULL,
586             OC_DISCOVERABLE|OC_OBSERVABLE);
587     OIC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
588
589     OCResourceHandle room;
590
591     if(TEST == TEST_APP_COLL_EH)
592     {
593         res = OCCreateResource(&room,
594                 "core.room",
595                 OC_RSRVD_INTERFACE_BATCH,
596                 "/a/room",
597                 OCEntityHandlerRoomCb,
598                 NULL,
599                 OC_DISCOVERABLE);
600     }
601     else
602     {
603         res = OCCreateResource(&room,
604                 "core.room",
605                 OC_RSRVD_INTERFACE_BATCH,
606                 "/a/room",
607                 NULL,
608                 NULL,
609                 OC_DISCOVERABLE);
610     }
611
612     OIC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
613     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_LL);
614     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_DEFAULT);
615
616     res = OCBindResource(room, light);
617     OIC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
618
619     res = OCBindResource(room, fan);
620     OIC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
621 }
622