feec1f8fcd8eb09968d8b6b8925be6091a3c7999
[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     const char* typeOfMethod;
126
127     switch (flag)
128     {
129         case OC_REQUEST_FLAG:
130             typeOfMessage = "OC_REQUEST_FLAG";
131             break;
132         case OC_OBSERVE_FLAG:
133             typeOfMessage = "OC_OBSERVE_FLAG";
134             break;
135         default:
136             typeOfMessage = "UNKNOWN";
137     }
138
139     if (ehRequest == NULL)
140     {
141         typeOfMethod = "UNKNOWN";
142     }
143     else if (ehRequest->method == OC_REST_GET)
144     {
145         typeOfMethod = "OC_REST_GET";
146     }
147     else
148     {
149         typeOfMethod = "OC_REST_PUT";
150     }
151
152     OC_LOG_V(INFO, TAG, "Receiving message type: %s, method %s", typeOfMessage,
153             typeOfMethod);
154 }
155
156 OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
157                                             OCEntityHandlerRequest * ehRequest,
158                                             void* callback)
159 {
160     OCEntityHandlerResult ret = OC_EH_OK;
161     OCEntityHandlerResponse response;
162     char payload[MAX_RESPONSE_LENGTH] = {0};
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
171         if(OC_REST_GET == ehRequest->method)
172         {
173             if(query.find(OC_RSRVD_INTERFACE_DEFAULT) != std::string::npos)
174             {
175                 ret = HandleCallback(ehRequest,
176                         rspGetRoomDefault, rspFailureRoom, payload, sizeof(payload));
177                 if(ret != OC_EH_ERROR)
178                 {
179                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
180                     ret = HandleCallback(ehRequest,
181                             rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
182                 }
183                 if(ret != OC_EH_ERROR)
184                 {
185                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
186                     ret = HandleCallback(ehRequest,
187                             rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
188                 }
189             }
190             else if(query.find(OC_RSRVD_INTERFACE_LL) != std::string::npos)
191             {
192                 ret = HandleCallback(ehRequest,
193                         rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
194                 if(ret != OC_EH_ERROR)
195                 {
196                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
197                     ret = HandleCallback(ehRequest,
198                             rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
199                 }
200                 if(ret != OC_EH_ERROR)
201                 {
202                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
203                     ret = HandleCallback(ehRequest,
204                             rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
205                 }
206             }
207             else if(query.find(OC_RSRVD_INTERFACE_BATCH) != std::string::npos)
208             {
209                 ret = HandleCallback(ehRequest,
210                         rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
211                 if(ret != OC_EH_ERROR)
212                 {
213                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
214                     ret = HandleCallback(ehRequest,
215                             rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
216                 }
217                 if(ret != OC_EH_ERROR)
218                 {
219                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
220                     ret = HandleCallback(ehRequest,
221                             rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
222                 }
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 = payload;
231                 response.payloadSize = strlen(payload);
232                 response.numSendVendorSpecificHeaderOptions = 0;
233                 memset(response.sendVendorSpecificHeaderOptions,
234                         0, sizeof response.sendVendorSpecificHeaderOptions);
235                 memset(response.resourceUri, 0, sizeof response.resourceUri);
236                 // Indicate that response is NOT in a persistent buffer
237                 response.persistentBufferFlag = 0;
238                 // Send the response
239                 if (OCDoResponse(&response) != OC_STACK_OK)
240                 {
241                     OC_LOG(ERROR, TAG, "Error sending response");
242                     ret = OC_EH_ERROR;
243                 }
244             }
245         }
246         else if(OC_REST_PUT == ehRequest->method)
247         {
248             if(query.find(OC_RSRVD_INTERFACE_DEFAULT) != std::string::npos)
249             {
250                 if(ret != OC_EH_ERROR)
251                 {
252                     ret = HandleCallback(ehRequest,
253                             rspPutRoomDefault, rspFailureRoom, payload, sizeof(payload));
254                 }
255             }
256             if(query.find(OC_RSRVD_INTERFACE_LL) != std::string::npos)
257             {
258                 if(ret != OC_EH_ERROR)
259                 {
260                     ret = HandleCallback(ehRequest,
261                             rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
262                 }
263                 if(ret != OC_EH_ERROR)
264                 {
265                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
266                     ret = HandleCallback(ehRequest,
267                             rspPutLightCollection, rspFailureLight, payload, sizeof(payload));
268                 }
269                 if(ret != OC_EH_ERROR)
270                 {
271                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
272                     ret = HandleCallback(ehRequest,
273                             rspPutFanCollection, rspFailureFan, payload, sizeof(payload));
274                 }
275             }
276             if(query.find(OC_RSRVD_INTERFACE_BATCH ) != std::string::npos)
277             {
278                 if(ret != OC_EH_ERROR)
279                 {
280                     ret = HandleCallback(ehRequest,
281                             rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
282                 }
283                 if(ret != OC_EH_ERROR)
284                 {
285                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
286                     ret = HandleCallback(ehRequest,
287                             rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
288                 }
289                 if(ret != OC_EH_ERROR)
290                 {
291                     ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
292                     ret = HandleCallback(ehRequest,
293                             rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
294                 }
295             }
296             if (ret == OC_EH_OK)
297             {
298                 // Format the response.  Note this requires some info about the request
299                 response.requestHandle = ehRequest->requestHandle;
300                 response.resourceHandle = ehRequest->resource;
301                 response.ehResult = ret;
302                 response.payload = payload;
303                 response.payloadSize = strlen(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                     OC_LOG(ERROR, TAG, "Error sending response");
314                     ret = OC_EH_ERROR;
315                 }
316             }
317         }
318         else
319         {
320             OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
321                     ehRequest->method);
322             ret = OC_EH_ERROR;
323         }
324     }
325     else if (ehRequest && flag == OC_OBSERVE_FLAG)
326     {
327         gLightUnderObservation = 1;
328     }
329     return ret;
330 }
331
332 OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag,
333         OCEntityHandlerRequest * ehRequest,void* callbackParam)
334 {
335     OCEntityHandlerResult ret = OC_EH_OK;
336     OCEntityHandlerResponse response;
337     char payload[MAX_RESPONSE_LENGTH] = {0};
338
339     OC_LOG_V(INFO, TAG, "Callback for Light");
340     PrintReceivedMsgInfo(flag, ehRequest );
341
342     if(ehRequest && flag == OC_REQUEST_FLAG)
343     {
344         if(OC_REST_GET == ehRequest->method)
345         {
346             ret = HandleCallback(ehRequest,
347                     rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
348         }
349         else if(OC_REST_PUT == ehRequest->method)
350         {
351             ret = HandleCallback(ehRequest,
352                     rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
353         }
354         else
355         {
356             OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
357                     ehRequest->method);
358             ret = OC_EH_ERROR;
359         }
360
361         if (ret == OC_EH_OK)
362         {
363             // Format the response.  Note this requires some info about the request
364             response.requestHandle = ehRequest->requestHandle;
365             response.resourceHandle = ehRequest->resource;
366             response.ehResult = ret;
367             response.payload = payload;
368             response.payloadSize = strlen(payload);
369             response.numSendVendorSpecificHeaderOptions = 0;
370             memset(response.sendVendorSpecificHeaderOptions,
371                     0, sizeof response.sendVendorSpecificHeaderOptions);
372             memset(response.resourceUri, 0, sizeof response.resourceUri);
373             // Indicate that response is NOT in a persistent buffer
374             response.persistentBufferFlag = 0;
375
376             // Send the response
377             if (OCDoResponse(&response) != OC_STACK_OK)
378             {
379                 OC_LOG(ERROR, TAG, "Error sending response");
380                 ret = OC_EH_ERROR;
381             }
382         }
383     }
384     else if (ehRequest && flag == OC_OBSERVE_FLAG)
385     {
386         gLightUnderObservation = 1;
387     }
388
389     return ret;
390 }
391
392 OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
393         OCEntityHandlerRequest * ehRequest, void* callback)
394 {
395     OCEntityHandlerResult ret = OC_EH_OK;
396     OCEntityHandlerResponse response;
397     char payload[MAX_RESPONSE_LENGTH] = {0};
398
399     OC_LOG_V(INFO, TAG, "Callback for Fan");
400     PrintReceivedMsgInfo(flag, ehRequest );
401
402     if(ehRequest && flag == OC_REQUEST_FLAG)
403     {
404         if(OC_REST_GET == ehRequest->method)
405         {
406             ret = HandleCallback(ehRequest, rspGetFanDefault,
407                     rspFailureFan, payload, sizeof(payload));
408         }
409         else if(OC_REST_PUT == ehRequest->method)
410         {
411             ret = HandleCallback(ehRequest, rspPutFanDefault,
412                     rspFailureFan, payload, sizeof(payload));
413         }
414         else
415         {
416             OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
417                     ehRequest->method);
418             ret = OC_EH_ERROR;
419         }
420
421         if (ret == OC_EH_OK)
422         {
423             // Format the response.  Note this requires some info about the request
424             response.requestHandle = ehRequest->requestHandle;
425             response.resourceHandle = ehRequest->resource;
426             response.ehResult = ret;
427             response.payload = payload;
428             response.payloadSize = strlen(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
444     }
445     else if (ehRequest && flag == OC_OBSERVE_FLAG)
446     {
447         gLightUnderObservation = 1;
448     }
449
450     return ret;
451 }
452
453 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
454 void handleSigInt(int signum)
455 {
456     if (signum == SIGINT)
457     {
458         gQuitFlag = 1;
459     }
460 }
461
462 void *ChangeLightRepresentation (void *param)
463 {
464     (void)param;
465     OCStackResult result = OC_STACK_ERROR;
466
467     while (!gQuitFlag)
468     {
469         sleep(10);
470         light.power += 5;
471         if (gLightUnderObservation)
472         {
473             OC_LOG_V(INFO, TAG,
474                 " =====> Notifying stack of new power level %d\n", light.power);
475             result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
476             if (OC_STACK_NO_OBSERVERS == result)
477             {
478                 gLightUnderObservation = 0;
479             }
480         }
481     }
482     return NULL;
483 }
484
485 int main(int argc, char* argv[])
486 {
487     pthread_t threadId;
488     int opt;
489
490     while ((opt = getopt(argc, argv, "t:")) != -1)
491     {
492         switch(opt)
493         {
494         case 't':
495             TEST = atoi(optarg);
496             break;
497         default:
498             PrintUsage();
499             return -1;
500         }
501     }
502     if(TEST <= TEST_INVALID || TEST >= MAX_TESTS)
503     {
504         PrintUsage();
505         return -1;
506     }
507
508     OC_LOG(DEBUG, TAG, "OCServer is starting...");
509
510     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
511     {
512         OC_LOG(ERROR, TAG, "OCStack init error");
513         return 0;
514     }
515
516     /*
517      * Declare and create the example resource: light
518      */
519     createResources();
520
521     /*
522      * Create a thread for changing the representation of the light
523      */
524     pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
525
526     // Break from loop with Ctrl-C
527     OC_LOG(INFO, TAG, "Entering ocserver main loop...");
528     signal(SIGINT, handleSigInt);
529     while (!gQuitFlag)
530     {
531         if (OCProcess() != OC_STACK_OK)
532         {
533             OC_LOG(ERROR, TAG, "OCStack process error");
534             return 0;
535         }
536         sleep(2);
537     }
538
539     /*
540      * Cancel the light thread and wait for it to terminate
541      */
542     pthread_cancel(threadId);
543     pthread_join(threadId, NULL);
544
545     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
546
547     if (OCStop() != OC_STACK_OK)
548     {
549         OC_LOG(ERROR, TAG, "OCStack process error");
550     }
551
552     return 0;
553 }
554 void createResources()
555 {
556     light.state = false;
557
558     OCResourceHandle fan;
559     OCStackResult res = OCCreateResource(&fan,
560             "core.fan",
561             OC_RSRVD_INTERFACE_DEFAULT,
562             "/a/fan",
563             OCEntityHandlerFanCb,
564             NULL,
565             OC_DISCOVERABLE|OC_OBSERVABLE);
566     OC_LOG_V(INFO, TAG, "Created fan resource with result: %s", getResult(res));
567
568     OCResourceHandle light;
569     res = OCCreateResource(&light,
570             "core.light",
571             OC_RSRVD_INTERFACE_DEFAULT,
572             "/a/light",
573             OCEntityHandlerLightCb,
574             NULL,
575             OC_DISCOVERABLE|OC_OBSERVABLE);
576     OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
577
578     OCResourceHandle room;
579
580     if(TEST == TEST_APP_COLL_EH)
581     {
582         res = OCCreateResource(&room,
583                 "core.room",
584                 OC_RSRVD_INTERFACE_BATCH,
585                 "/a/room",
586                 OCEntityHandlerRoomCb,
587                 NULL,
588                 OC_DISCOVERABLE);
589     }
590     else
591     {
592         res = OCCreateResource(&room,
593                 "core.room",
594                 OC_RSRVD_INTERFACE_BATCH,
595                 "/a/room",
596                 NULL,
597                 NULL,
598                 OC_DISCOVERABLE);
599     }
600
601     OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
602     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_LL);
603     OCBindResourceInterfaceToResource(room, OC_RSRVD_INTERFACE_DEFAULT);
604
605     res = OCBindResource(room, light);
606     OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
607
608     res = OCBindResource(room, fan);
609     OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
610 }
611