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