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