ed1897581ba6566abd3ee1137dcc6ff8a7de1b5a
[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             OCRepPayloadDestroy(payload);
323             ret = OC_EH_ERROR;
324         }
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         else
386         {
387             OCRepPayloadDestroy(payload);
388         }
389     }
390     else if (ehRequest && flag == OC_OBSERVE_FLAG)
391     {
392         gLightUnderObservation = 1;
393     }
394
395     return ret;
396 }
397
398 OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
399         OCEntityHandlerRequest * ehRequest, void* /*callback*/)
400 {
401     OCEntityHandlerResult ret = OC_EH_OK;
402     OCEntityHandlerResponse response;
403
404     OIC_LOG_V(INFO, TAG, "Callback for Fan");
405     PrintReceivedMsgInfo(flag, ehRequest );
406
407     if(ehRequest && flag == OC_REQUEST_FLAG)
408     {
409         OCRepPayload* payload = OCRepPayloadCreate();
410
411         if(OC_REST_GET == ehRequest->method)
412         {
413             OCRepPayloadSetUri(payload, gFanResourceUri);
414             OCRepPayloadSetPropBool(payload, "state", true);
415             OCRepPayloadSetPropInt(payload, "speed", 10);
416         }
417         else if(OC_REST_PUT == ehRequest->method)
418         {
419             OCRepPayloadSetUri(payload, gFanResourceUri);
420             OCRepPayloadSetPropBool(payload, "state", false);
421             OCRepPayloadSetPropInt(payload, "speed", 0);
422         }
423         else
424         {
425             OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
426                     ehRequest->method);
427             ret = OC_EH_ERROR;
428         }
429
430         if (ret == OC_EH_OK)
431         {
432             // Format the response.  Note this requires some info about the request
433             response.requestHandle = ehRequest->requestHandle;
434             response.resourceHandle = ehRequest->resource;
435             response.ehResult = ret;
436             response.payload = reinterpret_cast<OCPayload*>(payload);
437             response.numSendVendorSpecificHeaderOptions = 0;
438             memset(response.sendVendorSpecificHeaderOptions,
439                     0, sizeof response.sendVendorSpecificHeaderOptions);
440             memset(response.resourceUri, 0, sizeof response.resourceUri);
441             // Indicate that response is NOT in a persistent buffer
442             response.persistentBufferFlag = 0;
443
444             // Send the response
445             if (OCDoResponse(&response) != OC_STACK_OK)
446             {
447                 OIC_LOG(ERROR, TAG, "Error sending response");
448                 ret = OC_EH_ERROR;
449             }
450         }
451         OCRepPayloadDestroy(payload);
452
453     }
454     else if (ehRequest && flag == OC_OBSERVE_FLAG)
455     {
456         gLightUnderObservation = 1;
457     }
458
459     return ret;
460 }
461
462 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
463 void handleSigInt(int signum)
464 {
465     if (signum == SIGINT)
466     {
467         gQuitFlag = 1;
468     }
469 }
470
471 void *ChangeLightRepresentation (void *param)
472 {
473     (void)param;
474     OCStackResult result = OC_STACK_ERROR;
475
476     while (!gQuitFlag)
477     {
478         sleep(10);
479         light.power += 5;
480         if (gLightUnderObservation)
481         {
482             OIC_LOG_V(INFO, TAG,
483                 " =====> Notifying stack of new power level %d\n", light.power);
484             result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
485             if (OC_STACK_NO_OBSERVERS == result)
486             {
487                 gLightUnderObservation = 0;
488             }
489         }
490     }
491     return NULL;
492 }
493
494 int main(int argc, char* argv[])
495 {
496     pthread_t threadId;
497     int opt;
498
499     while ((opt = getopt(argc, argv, "t:")) != -1)
500     {
501         switch(opt)
502         {
503         case 't':
504             TEST = atoi(optarg);
505             break;
506         default:
507             PrintUsage();
508             return -1;
509         }
510     }
511     if(TEST <= TEST_INVALID || TEST >= MAX_TESTS)
512     {
513         PrintUsage();
514         return -1;
515     }
516
517     OIC_LOG(DEBUG, TAG, "OCServer is starting...");
518
519     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
520     {
521         OIC_LOG(ERROR, TAG, "OCStack init error");
522         return 0;
523     }
524
525     OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
526
527     /*
528      * Declare and create the example resource: light
529      */
530     createResources();
531
532     /*
533      * Create a thread for changing the representation of the light
534      */
535     pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
536
537     // Break from loop with Ctrl-C
538     OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
539     signal(SIGINT, handleSigInt);
540     while (!gQuitFlag)
541     {
542         if (OCProcess() != OC_STACK_OK)
543         {
544             OIC_LOG(ERROR, TAG, "OCStack process error");
545             return 0;
546         }
547         sleep(2);
548     }
549
550     /*
551      * Cancel the light thread and wait for it to terminate
552      */
553 #ifdef HAVE_PTHREAD_H
554     pthread_cancel(threadId);
555     pthread_join(threadId, NULL);
556 #endif
557
558     OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
559
560     if (OCStop() != OC_STACK_OK)
561     {
562         OIC_LOG(ERROR, TAG, "OCStack process error");
563     }
564
565     return 0;
566 }
567
568 void createResources()
569 {
570     light.state = false;
571
572     OCResourceHandle fan;
573     OCStackResult res = OCCreateResource(&fan,
574             "core.fan",
575             OC_RSRVD_INTERFACE_DEFAULT,
576             "/a/fan",
577             OCEntityHandlerFanCb,
578             NULL,
579             OC_DISCOVERABLE|OC_OBSERVABLE);
580     OIC_LOG_V(INFO, TAG, "Created fan resource with result: %s", getResult(res));
581
582     OCResourceHandle light;
583     res = OCCreateResource(&light,
584             "core.light",
585             OC_RSRVD_INTERFACE_DEFAULT,
586             "/a/light",
587             OCEntityHandlerLightCb,
588             NULL,
589             OC_DISCOVERABLE|OC_OBSERVABLE);
590     OIC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
591
592     OCResourceHandle room;
593
594     if(TEST == TEST_APP_COLL_EH)
595     {
596         res = OCCreateResource(&room,
597                 "core.room",
598                 OC_RSRVD_INTERFACE_BATCH,
599                 "/a/room",
600                 OCEntityHandlerRoomCb,
601                 NULL,
602                 OC_DISCOVERABLE);
603     }
604     else
605     {
606         res = OCCreateResource(&room,
607                 "core.room",
608                 OC_RSRVD_INTERFACE_BATCH,
609                 "/a/room",
610                 NULL,
611                 NULL,
612                 OC_DISCOVERABLE);
613     }
614
615     OIC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
616     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_LL);
617     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_DEFAULT);
618
619     res = OCBindResource(room, light);
620     OIC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
621
622     res = OCBindResource(room, fan);
623     OIC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
624 }
625