Imported Upstream version 0.9.2
[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     OCRepPayload* payload = OCRepPayloadCreate();
164
165     OC_LOG_V(INFO, TAG, "Callback for Room");
166     PrintReceivedMsgInfo(flag, ehRequest );
167
168     if(ehRequest && flag == OC_REQUEST_FLAG )
169     {
170         std::string query = (const char*)ehRequest->query;
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             ret = OC_EH_ERROR;
315         }
316     }
317     else if (ehRequest && flag == OC_OBSERVE_FLAG)
318     {
319         gLightUnderObservation = 1;
320     }
321     return ret;
322 }
323
324 OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag,
325         OCEntityHandlerRequest * ehRequest,void* callbackParam)
326 {
327     OCEntityHandlerResult ret = OC_EH_OK;
328     OCEntityHandlerResponse response;
329     OCRepPayload* payload = OCRepPayloadCreate();
330
331     OC_LOG_V(INFO, TAG, "Callback for Light");
332     PrintReceivedMsgInfo(flag, ehRequest );
333
334     if(ehRequest && flag == OC_REQUEST_FLAG)
335     {
336         if(OC_REST_GET == ehRequest->method)
337         {
338             OCRepPayloadSetUri(payload, gLightResourceUri);
339             OCRepPayloadSetPropBool(payload, "state", false);
340             OCRepPayloadSetPropInt(payload, "power", 0);
341         }
342         else if(OC_REST_PUT == ehRequest->method)
343         {
344             OCRepPayloadSetUri(payload, gLightResourceUri);
345             OCRepPayloadSetPropBool(payload, "state", true);
346             OCRepPayloadSetPropInt(payload, "power", 0);
347         }
348         else
349         {
350             OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
351                     ehRequest->method);
352             ret = OC_EH_ERROR;
353         }
354
355         if (ret == OC_EH_OK)
356         {
357             // Format the response.  Note this requires some info about the request
358             response.requestHandle = ehRequest->requestHandle;
359             response.resourceHandle = ehRequest->resource;
360             response.ehResult = ret;
361             response.payload = reinterpret_cast<OCPayload*>(payload);
362             response.numSendVendorSpecificHeaderOptions = 0;
363             memset(response.sendVendorSpecificHeaderOptions,
364                     0, sizeof response.sendVendorSpecificHeaderOptions);
365             memset(response.resourceUri, 0, sizeof response.resourceUri);
366             // Indicate that response is NOT in a persistent buffer
367             response.persistentBufferFlag = 0;
368
369             // Send the response
370             if (OCDoResponse(&response) != OC_STACK_OK)
371             {
372                 OC_LOG(ERROR, TAG, "Error sending response");
373                 ret = OC_EH_ERROR;
374             }
375         }
376     }
377     else if (ehRequest && flag == OC_OBSERVE_FLAG)
378     {
379         gLightUnderObservation = 1;
380     }
381
382     return ret;
383 }
384
385 OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
386         OCEntityHandlerRequest * ehRequest, void* callback)
387 {
388     OCEntityHandlerResult ret = OC_EH_OK;
389     OCEntityHandlerResponse response;
390     OCRepPayload* payload = OCRepPayloadCreate();
391
392     OC_LOG_V(INFO, TAG, "Callback for Fan");
393     PrintReceivedMsgInfo(flag, ehRequest );
394
395     if(ehRequest && flag == OC_REQUEST_FLAG)
396     {
397         if(OC_REST_GET == ehRequest->method)
398         {
399             OCRepPayloadSetUri(payload, gFanResourceUri);
400             OCRepPayloadSetPropBool(payload, "state", true);
401             OCRepPayloadSetPropInt(payload, "speed", 10);
402         }
403         else if(OC_REST_PUT == ehRequest->method)
404         {
405             OCRepPayloadSetUri(payload, gFanResourceUri);
406             OCRepPayloadSetPropBool(payload, "state", false);
407             OCRepPayloadSetPropInt(payload, "speed", 0);
408         }
409         else
410         {
411             OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
412                     ehRequest->method);
413             ret = OC_EH_ERROR;
414         }
415
416         if (ret == OC_EH_OK)
417         {
418             // Format the response.  Note this requires some info about the request
419             response.requestHandle = ehRequest->requestHandle;
420             response.resourceHandle = ehRequest->resource;
421             response.ehResult = ret;
422             response.payload = reinterpret_cast<OCPayload*>(payload);
423             response.numSendVendorSpecificHeaderOptions = 0;
424             memset(response.sendVendorSpecificHeaderOptions,
425                     0, sizeof response.sendVendorSpecificHeaderOptions);
426             memset(response.resourceUri, 0, sizeof response.resourceUri);
427             // Indicate that response is NOT in a persistent buffer
428             response.persistentBufferFlag = 0;
429
430             // Send the response
431             if (OCDoResponse(&response) != OC_STACK_OK)
432             {
433                 OC_LOG(ERROR, TAG, "Error sending response");
434                 ret = OC_EH_ERROR;
435             }
436         }
437
438     }
439     else if (ehRequest && flag == OC_OBSERVE_FLAG)
440     {
441         gLightUnderObservation = 1;
442     }
443
444     return ret;
445 }
446
447 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
448 void handleSigInt(int signum)
449 {
450     if (signum == SIGINT)
451     {
452         gQuitFlag = 1;
453     }
454 }
455
456 void *ChangeLightRepresentation (void *param)
457 {
458     (void)param;
459     OCStackResult result = OC_STACK_ERROR;
460
461     while (!gQuitFlag)
462     {
463         sleep(10);
464         light.power += 5;
465         if (gLightUnderObservation)
466         {
467             OC_LOG_V(INFO, TAG,
468                 " =====> Notifying stack of new power level %d\n", light.power);
469             result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
470             if (OC_STACK_NO_OBSERVERS == result)
471             {
472                 gLightUnderObservation = 0;
473             }
474         }
475     }
476     return NULL;
477 }
478
479 int main(int argc, char* argv[])
480 {
481     pthread_t threadId;
482     int opt;
483
484     while ((opt = getopt(argc, argv, "t:")) != -1)
485     {
486         switch(opt)
487         {
488         case 't':
489             TEST = atoi(optarg);
490             break;
491         default:
492             PrintUsage();
493             return -1;
494         }
495     }
496     if(TEST <= TEST_INVALID || TEST >= MAX_TESTS)
497     {
498         PrintUsage();
499         return -1;
500     }
501
502     OC_LOG(DEBUG, TAG, "OCServer is starting...");
503
504     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
505     {
506         OC_LOG(ERROR, TAG, "OCStack init error");
507         return 0;
508     }
509
510     OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
511
512     /*
513      * Declare and create the example resource: light
514      */
515     createResources();
516
517     /*
518      * Create a thread for changing the representation of the light
519      */
520     pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
521
522     // Break from loop with Ctrl-C
523     OC_LOG(INFO, TAG, "Entering ocserver main loop...");
524     signal(SIGINT, handleSigInt);
525     while (!gQuitFlag)
526     {
527         if (OCProcess() != OC_STACK_OK)
528         {
529             OC_LOG(ERROR, TAG, "OCStack process error");
530             return 0;
531         }
532         sleep(2);
533     }
534
535     /*
536      * Cancel the light thread and wait for it to terminate
537      */
538     pthread_cancel(threadId);
539     pthread_join(threadId, NULL);
540
541     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
542
543     if (OCStop() != OC_STACK_OK)
544     {
545         OC_LOG(ERROR, TAG, "OCStack process error");
546     }
547
548     return 0;
549 }
550
551 void createResources()
552 {
553     light.state = false;
554
555     OCResourceHandle fan;
556     OCStackResult res = OCCreateResource(&fan,
557             "core.fan",
558             OC_RSRVD_INTERFACE_DEFAULT,
559             "/a/fan",
560             OCEntityHandlerFanCb,
561             NULL,
562             OC_DISCOVERABLE|OC_OBSERVABLE);
563     OC_LOG_V(INFO, TAG, "Created fan resource with result: %s", getResult(res));
564
565     OCResourceHandle light;
566     res = OCCreateResource(&light,
567             "core.light",
568             OC_RSRVD_INTERFACE_DEFAULT,
569             "/a/light",
570             OCEntityHandlerLightCb,
571             NULL,
572             OC_DISCOVERABLE|OC_OBSERVABLE);
573     OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
574
575     OCResourceHandle room;
576
577     if(TEST == TEST_APP_COLL_EH)
578     {
579         res = OCCreateResource(&room,
580                 "core.room",
581                 OC_RSRVD_INTERFACE_BATCH,
582                 "/a/room",
583                 OCEntityHandlerRoomCb,
584                 NULL,
585                 OC_DISCOVERABLE);
586     }
587     else
588     {
589         res = OCCreateResource(&room,
590                 "core.room",
591                 OC_RSRVD_INTERFACE_BATCH,
592                 "/a/room",
593                 NULL,
594                 NULL,
595                 OC_DISCOVERABLE);
596     }
597
598     OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
599     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_LL);
600     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_DEFAULT);
601
602     res = OCBindResource(room, light);
603     OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
604
605     res = OCBindResource(room, fan);
606     OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
607 }
608