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