Merge branch 'notification-service'
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / ocserver.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 "iotivity_config.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include <string>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #ifdef HAVE_WINDOWS_H
31 #include <windows.h>
32 #endif
33 #include <signal.h>
34 #ifdef HAVE_PTHREAD_H
35 #include <pthread.h>
36 #endif
37 #include <array>
38 #include "oic_malloc.h"
39 #include <getopt.h>
40 #include "ocstack.h"
41 #include "logger.h"
42 #include "ocpayload.h"
43 #include "ocserver.h"
44 #include "common.h"
45
46 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
47 // 9 + 9 + 1 = 19
48 const int URI_MAXSIZE = 19;
49
50 static int gObserveNotifyType = 3;
51
52 int gQuitFlag = 0;
53 int gLightUnderObservation = 0;
54
55 static LightResource Light;
56 // This variable determines instance number of the Light resource.
57 // Used by POST method to create a new instance of Light resource.
58 static int gCurrLightInstance = 0;
59
60 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
61
62 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
63
64 pthread_t threadId_observe;
65 pthread_t threadId_presence;
66
67 static bool observeThreadStarted = false;
68
69 #ifdef WITH_PRESENCE
70 #define numPresenceResources (2)
71 #endif
72
73 char *gResourceUri= (char *)"/a/light";
74 const char *dateOfManufacture = "myDateOfManufacture";
75 const char *deviceName = "myDeviceName";
76 const char *deviceUUID = "myDeviceUUID";
77 const char *firmwareVersion = "myFirmwareVersion";
78 const char *manufacturerName = "myName";
79 const char *operatingSystemVersion = "myOS";
80 const char *hardwareVersion = "myHardwareVersion";
81 const char* platformID = "myPlatformID";
82 const char *manufacturerUrl = "myManufacturerUrl";
83 const char *modelNumber = "myModelNumber";
84 const char *platformVersion = "myPlatformVersion";
85 const char *supportUrl = "mySupportUrl";
86 const char *version = "myVersion";
87 const char *systemTime = "2015-05-15T11.04";
88 const char *specVersion = "myDeviceSpecVersion";
89 const char *dataModelVersions = "myDeviceModelVersions";
90
91 // Entity handler should check for resourceTypeName and ResourceInterface in order to GET
92 // the existence of a known resource
93 const char *resourceTypeName = "core.light";
94 const char *resourceInterface = OC_RSRVD_INTERFACE_DEFAULT;
95
96 OCPlatformInfo platformInfo;
97 OCDeviceInfo deviceInfo;
98
99 OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
100 {
101     OCRepPayload* payload = OCRepPayloadCreate();
102     if(!payload)
103     {
104         OIC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
105         return nullptr;
106     }
107
108     OCRepPayloadSetUri(payload, uri);
109     OCRepPayloadSetPropBool(payload, "state", state);
110     OCRepPayloadSetPropInt(payload, "power", power);
111
112     return payload;
113 }
114
115 //This function takes the request as an input and returns the response
116 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
117 {
118     if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
119     {
120         OIC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
121         return nullptr;
122     }
123
124     OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
125
126     LightResource *currLightResource = &Light;
127
128     if (ehRequest->resource == gLightInstance[0].handle)
129     {
130         currLightResource = &gLightInstance[0];
131         gResourceUri = (char *) "a/light/0";
132     }
133     else if (ehRequest->resource == gLightInstance[1].handle)
134     {
135         currLightResource = &gLightInstance[1];
136         gResourceUri = (char *) "a/light/1";
137     }
138
139     if(OC_REST_PUT == ehRequest->method)
140     {
141         // Get pointer to query
142         int64_t pow;
143         if(OCRepPayloadGetPropInt(input, "power", &pow))
144         {
145             currLightResource->power =pow;
146         }
147
148         bool state;
149         if(OCRepPayloadGetPropBool(input, "state", &state))
150         {
151             currLightResource->state = state;
152         }
153     }
154
155     return getPayload(gResourceUri, currLightResource->power, currLightResource->state);
156 }
157
158 /*
159  * Very simple example of query parsing.
160  * The query may have multiple filters separated by ';'.
161  * It is upto the entity handler to parse the query for the individual filters,
162  * VALIDATE them and respond as it sees fit.
163
164  * This function only returns false if the query is exactly "power<X" and
165  * current power is greater than X. If X cannot be parsed for an int,
166  * true is returned.
167  */
168 bool checkIfQueryForPowerPassed(char * query)
169 {
170     if (query && strncmp(query, "power<", strlen("power<")) == 0)
171     {
172         char * pointerToOperator = strstr(query, "<");
173
174         if (pointerToOperator)
175         {
176             int powerRequested = atoi(pointerToOperator + 1);
177             if (Light.power > powerRequested)
178             {
179                 OIC_LOG_V(INFO, TAG, "Current power: %d. Requested: <%d", Light.power
180                             , powerRequested);
181                 return false;
182             }
183         }
184     }
185     return true;
186 }
187
188 /*
189  * Application should validate and process these as desired.
190  */
191 OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest)
192 {
193     OIC_LOG_V(INFO, TAG, PCF("Received query %s"), entityHandlerRequest->query);
194     OIC_LOG(INFO, TAG, PCF("Not processing query"));
195     return OC_EH_OK;
196 }
197
198 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
199         OCRepPayload **payload)
200 {
201     OCEntityHandlerResult ehResult;
202     bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query);
203
204     // Empty payload if the query has no match.
205     if (queryPassed)
206     {
207         OCRepPayload *getResp = constructResponse(ehRequest);
208         if(!getResp)
209         {
210             OIC_LOG(ERROR, TAG, "constructResponse failed");
211             return OC_EH_ERROR;
212         }
213
214         *payload = getResp;
215         ehResult = OC_EH_OK;
216     }
217     else
218     {
219         ehResult = OC_EH_OK;
220     }
221
222     return ehResult;
223 }
224
225 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
226         OCRepPayload** payload)
227 {
228     OCEntityHandlerResult ehResult;
229     OCRepPayload *putResp = constructResponse(ehRequest);
230
231     if(!putResp)
232     {
233         OIC_LOG(ERROR, TAG, "Failed to construct Json response");
234         return OC_EH_ERROR;
235     }
236
237     *payload = putResp;
238     ehResult = OC_EH_OK;
239
240     return ehResult;
241 }
242
243 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
244         OCEntityHandlerResponse *response, OCRepPayload** payload)
245 {
246     OCEntityHandlerResult ehResult = OC_EH_OK;
247     OCRepPayload *respPLPost_light = nullptr;
248
249     /*
250      * The entity handler determines how to process a POST request.
251      * Per the REST paradigm, POST can also be used to update representation of existing
252      * resource or create a new resource.
253      * In the sample below, if the POST is for /a/light then a new instance of the Light
254      * resource is created with default representation (if representation is included in
255      * POST payload it can be used as initial values) as long as the instance is
256      * lesser than max new instance count. Once max instance count is reached, POST on
257      * /a/light updated the representation of /a/light (just like PUT)
258      */
259
260     if (ehRequest->resource == Light.handle)
261     {
262         if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
263         {
264             // Create new Light instance
265             char newLightUri[URI_MAXSIZE];
266             snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
267
268             respPLPost_light = OCRepPayloadCreate();
269             OCRepPayloadSetUri(respPLPost_light, gResourceUri);
270             OCRepPayloadSetPropString(respPLPost_light, "createduri", newLightUri);
271
272             if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
273             {
274                 OIC_LOG (INFO, TAG, "Created new Light instance\n");
275                 gLightInstance[gCurrLightInstance].state = 0;
276                 gLightInstance[gCurrLightInstance].power = 0;
277                 gCurrLightInstance++;
278                 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
279                 ehResult = OC_EH_RESOURCE_CREATED;
280             }
281         }
282         else
283         {
284             // Update repesentation of /a/light
285             Light.state = true;
286             Light.power = 11;
287             respPLPost_light = constructResponse(ehRequest);
288         }
289     }
290     else
291     {
292         for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
293         {
294             if (ehRequest->resource == gLightInstance[i].handle)
295             {
296                 gLightInstance[i].state = true;
297                 gLightInstance[i].power = 22;
298                 if (i == 0)
299                 {
300                     respPLPost_light = constructResponse(ehRequest);
301                     break;
302                 }
303                 else if (i == 1)
304                 {
305                     respPLPost_light = constructResponse(ehRequest);
306                 }
307             }
308         }
309     }
310
311     if ((respPLPost_light != NULL))
312     {
313         *payload = respPLPost_light;
314     }
315     else
316     {
317         OIC_LOG(INFO, TAG, "Payload was NULL");
318         ehResult = OC_EH_ERROR;
319     }
320
321     return ehResult;
322 }
323
324 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
325 {
326     if(ehRequest == NULL)
327     {
328         OIC_LOG(INFO, TAG, "The ehRequest is NULL");
329         return OC_EH_ERROR;
330     }
331     OCEntityHandlerResult ehResult = OC_EH_OK;
332
333     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %p ", __func__, ehRequest->resource);
334
335     /*
336      * In the sample below, the application will:
337      * 1a. pass the delete request to the c stack
338      * 1b. internally, the c stack figures out what needs to be done and does it accordingly
339      *    (e.g. send observers notification, remove observers...)
340      * 1c. the c stack returns with the result whether the request is fullfilled.
341      * 2. optionally, app removes observers out of its array 'interestedObservers'
342      */
343
344     if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
345     {
346         //Step 1: Ask stack to do the work.
347         OCStackResult result = OCDeleteResource(ehRequest->resource);
348
349         if (result == OC_STACK_OK)
350         {
351             OIC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
352             ehResult = OC_EH_OK;
353
354             //Step 2: clear observers who wanted to observe this resource at the app level.
355             for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
356             {
357                 if (interestedObservers[i].resourceHandle == ehRequest->resource)
358                 {
359                     interestedObservers[i].valid = false;
360                     interestedObservers[i].observationId = 0;
361                     interestedObservers[i].resourceHandle = NULL;
362                 }
363             }
364         }
365         else if (result == OC_STACK_NO_RESOURCE)
366         {
367             OIC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
368             ehResult = OC_EH_RESOURCE_DELETED;
369         }
370         else
371         {
372             OIC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
373             ehResult = OC_EH_ERROR;
374         }
375     }
376     else if (ehRequest->resource != Light.handle)
377     {
378         //Let's this app not supporting DELETE on some resources so
379         //consider the DELETE request is received for a non-support resource.
380         OIC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
381         ehResult = OC_EH_FORBIDDEN;
382     }
383
384     return ehResult;
385 }
386
387 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest * /*ehRequest*/)
388 {
389     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
390
391     return OC_EH_RESOURCE_NOT_FOUND;
392 }
393
394 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
395 {
396     OIC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
397             ehRequest->obsInfo.obsId);
398
399     if (!observeThreadStarted)
400     {
401         pthread_create (&threadId_observe, NULL, ChangeLightRepresentation, (void *)NULL);
402         observeThreadStarted = 1;
403     }
404     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
405     {
406         if (interestedObservers[i].valid == false)
407         {
408             interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
409             interestedObservers[i].valid = true;
410             gLightUnderObservation = 1;
411             break;
412         }
413     }
414 }
415
416 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
417 {
418     bool clientStillObserving = false;
419
420     OIC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
421             ehRequest->obsInfo.obsId);
422     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
423     {
424         if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
425         {
426             interestedObservers[i].valid = false;
427         }
428         if (interestedObservers[i].valid == true)
429         {
430             // Even if there is one single client observing we continue notifying entity handler
431             clientStillObserving = true;
432         }
433     }
434     if (clientStillObserving == false)
435         gLightUnderObservation = 0;
436 }
437
438 OCEntityHandlerResult
439 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
440                          OCEntityHandlerRequest *entityHandlerRequest,
441                          char* uri,
442                          void* /*callbackParam*/)
443 {
444     OIC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
445
446     OCEntityHandlerResult ehResult = OC_EH_OK;
447     OCEntityHandlerResponse response;
448
449     // Validate pointer
450     if (!entityHandlerRequest)
451     {
452         OIC_LOG (ERROR, TAG, "Invalid request pointer");
453         return OC_EH_ERROR;
454     }
455     // Initialize certain response fields
456     response.numSendVendorSpecificHeaderOptions = 0;
457     memset(response.sendVendorSpecificHeaderOptions, 0,
458             sizeof response.sendVendorSpecificHeaderOptions);
459     memset(response.resourceUri, 0, sizeof response.resourceUri);
460     OCRepPayload* payload = nullptr;
461
462
463     if (flag & OC_REQUEST_FLAG)
464     {
465         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
466
467         if (entityHandlerRequest->resource == NULL)
468         {
469             OIC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
470             ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
471         }
472         else if (OC_REST_GET == entityHandlerRequest->method)
473         {
474             OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
475             ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
476         }
477         else if (OC_REST_PUT == entityHandlerRequest->method)
478         {
479             OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
480             ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
481         }
482         else if (OC_REST_DELETE == entityHandlerRequest->method)
483         {
484             OIC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
485             ehResult = ProcessDeleteRequest (entityHandlerRequest);
486         }
487         else
488         {
489             OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
490                       entityHandlerRequest->method);
491             ehResult = OC_EH_ERROR;
492         }
493                // If the result isn't an error or forbidden, send response
494         if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
495         {
496             // Format the response.  Note this requires some info about the request
497             response.requestHandle = entityHandlerRequest->requestHandle;
498             response.resourceHandle = entityHandlerRequest->resource;
499             response.ehResult = ehResult;
500             response.payload = reinterpret_cast<OCPayload*>(payload);
501             // Indicate that response is NOT in a persistent buffer
502             response.persistentBufferFlag = 0;
503
504             // Send the response
505             if (OCDoResponse(&response) != OC_STACK_OK)
506             {
507                 OIC_LOG(ERROR, TAG, "Error sending response");
508                 ehResult = OC_EH_ERROR;
509             }
510         }
511     }
512     if (flag & OC_OBSERVE_FLAG)
513     {
514         OIC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
515         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
516         {
517             OIC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
518         }
519         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
520         {
521             OIC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
522         }
523     }
524
525     return ehResult;
526 }
527
528 OCEntityHandlerResult
529 OCNOPEntityHandlerCb (OCEntityHandlerFlag /*flag*/,
530                       OCEntityHandlerRequest * /*entityHandlerRequest*/,
531                       void* /*callbackParam*/)
532 {
533     // This is callback is associated with the 2 presence notification
534     // resources. They are non-operational.
535     return OC_EH_OK;
536 }
537
538 OCEntityHandlerResult
539 OCEntityHandlerCb (OCEntityHandlerFlag flag,
540         OCEntityHandlerRequest *entityHandlerRequest, void* /*callback*/)
541 {
542     OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
543
544     OCEntityHandlerResult ehResult = OC_EH_OK;
545     OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
546
547     // Validate pointer
548     if (!entityHandlerRequest)
549     {
550         OIC_LOG (ERROR, TAG, "Invalid request pointer");
551         return OC_EH_ERROR;
552     }
553
554     // Initialize certain response fields
555     response.numSendVendorSpecificHeaderOptions = 0;
556     memset(response.sendVendorSpecificHeaderOptions,
557             0, sizeof response.sendVendorSpecificHeaderOptions);
558     memset(response.resourceUri, 0, sizeof response.resourceUri);
559     OCRepPayload* payload = nullptr;
560
561     if (flag & OC_REQUEST_FLAG)
562     {
563         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
564
565         if (OC_REST_GET == entityHandlerRequest->method)
566         {
567             OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
568             ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
569         }
570         else if (OC_REST_PUT == entityHandlerRequest->method)
571         {
572             OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
573             ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
574         }
575         else if (OC_REST_POST == entityHandlerRequest->method)
576         {
577             OIC_LOG (INFO, TAG, "Received OC_REST_POST from client");
578             ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
579         }
580         else if (OC_REST_DELETE == entityHandlerRequest->method)
581         {
582             OIC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
583             ehResult = ProcessDeleteRequest (entityHandlerRequest);
584         }
585         else
586         {
587             OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
588                       entityHandlerRequest->method);
589             ehResult = OC_EH_ERROR;
590         }
591         // If the result isn't an error or forbidden, send response
592         if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
593         {
594             // Format the response.  Note this requires some info about the request
595             response.requestHandle = entityHandlerRequest->requestHandle;
596             response.resourceHandle = entityHandlerRequest->resource;
597             response.ehResult = ehResult;
598             response.payload = reinterpret_cast<OCPayload*>(payload);
599             // Indicate that response is NOT in a persistent buffer
600             response.persistentBufferFlag = 0;
601
602             // Handle vendor specific options
603             if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
604                     entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
605             {
606                 OIC_LOG (INFO, TAG, "Received vendor specific options");
607                 uint8_t i = 0;
608                 OCHeaderOption * rcvdOptions =
609                         entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
610                 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
611                 {
612                     if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
613                     {
614                         OIC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
615                                 ((OCHeaderOption)rcvdOptions[i]).optionID );
616
617                         OIC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
618                             MAX_HEADER_OPTION_DATA_LENGTH);
619                     }
620                 }
621                 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
622                 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
623                 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
624                 sendOptions[0].protocolID = OC_COAP_ID;
625                 sendOptions[0].optionID = 2248;
626                 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
627                 sendOptions[0].optionLength = 10;
628                 sendOptions[1].protocolID = OC_COAP_ID;
629                 sendOptions[1].optionID = 2600;
630                 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
631                 sendOptions[1].optionLength = 10;
632                 response.numSendVendorSpecificHeaderOptions = 2;
633             }
634
635             // Send the response
636             if (OCDoResponse(&response) != OC_STACK_OK)
637             {
638                 OIC_LOG(ERROR, TAG, "Error sending response");
639                 ehResult = OC_EH_ERROR;
640             }
641         }
642     }
643     if (flag & OC_OBSERVE_FLAG)
644     {
645         OIC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
646
647         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
648         {
649             OIC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
650             ProcessObserveRegister (entityHandlerRequest);
651         }
652         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
653         {
654             OIC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
655             ProcessObserveDeregister (entityHandlerRequest);
656         }
657     }
658
659     OCPayloadDestroy(response.payload);
660     return ehResult;
661 }
662
663 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
664 void handleSigInt(int signum)
665 {
666     if (signum == SIGINT)
667     {
668         gQuitFlag = 1;
669     }
670 }
671
672 void *ChangeLightRepresentation (void *param)
673 {
674     (void)param;
675     OCStackResult result = OC_STACK_ERROR;
676
677     uint8_t j = 0;
678     OCObservationId obsNotify[(SAMPLE_MAX_NUM_OBSERVATIONS)/2];
679
680     while (!gQuitFlag)
681     {
682         sleep(3);
683         Light.power += 5;
684         if (gLightUnderObservation)
685         {
686             OIC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
687             if (gObserveNotifyType == 1)
688             {
689                 // Notify list of observers. Alternate observers on the list will be notified.
690                 j = 0;
691                 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
692                 {
693                     if (interestedObservers[i].valid == true)
694                     {
695                         obsNotify[j] = interestedObservers[i].observationId;
696                         j++;
697                     }
698                 }
699
700                 OCRepPayload* payload = getPayload(gResourceUri, Light.power, Light.state);
701                 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
702                         payload, OC_NA_QOS);
703                 OCRepPayloadDestroy(payload);
704             }
705             else if (gObserveNotifyType == 0)
706             {
707                 // Notifying all observers
708                 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
709                 if (OC_STACK_NO_OBSERVERS == result)
710                 {
711                     OIC_LOG (INFO, TAG,
712                             "=======> No more observers exist, stop sending observations");
713                     gLightUnderObservation = 0;
714                 }
715             }
716             else
717             {
718                 OIC_LOG (ERROR, TAG, "Incorrect notification type selected");
719             }
720         }
721     }
722     return NULL;
723 }
724
725 #ifdef WITH_PRESENCE
726 void *presenceNotificationGenerator(void *param)
727 {
728     uint8_t secondsBeforePresence = 10;
729     OIC_LOG_V(INFO, TAG, "Will send out presence in %u seconds", secondsBeforePresence);
730     sleep(secondsBeforePresence);
731     (void)param;
732     OCDoHandle presenceNotificationHandles[numPresenceResources];
733     OCStackResult res = OC_STACK_OK;
734
735     std::array<std::string, numPresenceResources> presenceNotificationResources { {
736         std::string("core.fan"),
737         std::string("core.led") } };
738     std::array<std::string, numPresenceResources> presenceNotificationUris { {
739         std::string("/a/fan"),
740         std::string("/a/led") } };
741
742     for(int i=0; i<numPresenceResources; i++)
743     {
744         if(res == OC_STACK_OK)
745         {
746             sleep(1);
747             res = OCCreateResource(&presenceNotificationHandles[i],
748                     presenceNotificationResources.at(i).c_str(),
749                     OC_RSRVD_INTERFACE_DEFAULT,
750                     presenceNotificationUris.at(i).c_str(),
751                     OCNOPEntityHandlerCb,
752                     NULL,
753                     OC_DISCOVERABLE|OC_OBSERVABLE);
754         }
755         if(res != OC_STACK_OK)
756         {
757             OIC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to create resource "
758                     "%s with result %s.", presenceNotificationResources.at(i).c_str(),
759                     getResult(res));
760             break;
761         }
762         OIC_LOG_V(INFO, TAG, PCF("Created %s for presence notification"),
763                                 presenceNotificationUris[i].c_str());
764     }
765     sleep(5);
766     for(int i=0; i<numPresenceResources; i++)
767     {
768         if(res == OC_STACK_OK)
769         {
770             res = OCDeleteResource(presenceNotificationHandles[i]);
771         }
772         if(res != OC_STACK_OK)
773         {
774             OIC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to delete "\
775                     "resource %s.", presenceNotificationResources.at(i).c_str());
776             break;
777         }
778         OIC_LOG_V(INFO, TAG, PCF("Deleted %s for presence notification"),
779                                 presenceNotificationUris[i].c_str());
780     }
781
782     OIC_LOG(INFO, TAG, "================ stopping presence");
783     OCStopPresence();
784
785     return NULL;
786 }
787 #endif
788
789 int createLightResource (char *uri, LightResource *lightResource)
790 {
791     if (!uri)
792     {
793         OIC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
794         return -1;
795     }
796
797     lightResource->state = false;
798     lightResource->power= 0;
799     OCStackResult res = OCCreateResource(&(lightResource->handle),
800             "core.light",
801             "oc.mi.def",
802             uri,
803             OCEntityHandlerCb,
804             NULL,
805             OC_DISCOVERABLE|OC_OBSERVABLE);
806     OIC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
807
808     return 0;
809 }
810
811 void DeletePlatformInfo()
812 {
813     free (platformInfo.platformID);
814     free (platformInfo.manufacturerName);
815     free (platformInfo.manufacturerUrl);
816     free (platformInfo.modelNumber);
817     free (platformInfo.dateOfManufacture);
818     free (platformInfo.platformVersion);
819     free (platformInfo.operatingSystemVersion);
820     free (platformInfo.hardwareVersion);
821     free (platformInfo.firmwareVersion);
822     free (platformInfo.supportUrl);
823     free (platformInfo.systemTime);
824 }
825
826 void DeleteDeviceInfo()
827 {
828     free (deviceInfo.deviceName);
829     free (deviceInfo.specVersion);
830     OCFreeOCStringLL (deviceInfo.dataModelVersions);
831 }
832
833 bool DuplicateString(char** targetString, const char* sourceString)
834 {
835     if(!sourceString)
836     {
837         return false;
838     }
839     else
840     {
841         *targetString = (char *) malloc(strlen(sourceString) + 1);
842
843         if(*targetString)
844         {
845             strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
846             return true;
847         }
848     }
849     return false;
850 }
851
852 OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerName,
853     const char *manufacturerUrl, const char *modelNumber, const char *dateOfManufacture,
854     const char *platformVersion, const char* operatingSystemVersion, const char* hardwareVersion,
855     const char *firmwareVersion, const char* supportUrl, const char* systemTime)
856 {
857
858     bool success = true;
859
860     if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH))
861     {
862         return OC_STACK_INVALID_PARAM;
863     }
864
865     if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH))
866     {
867         return OC_STACK_INVALID_PARAM;
868     }
869
870     if(!DuplicateString(&platformInfo.platformID, platformID))
871     {
872         success = false;
873     }
874
875     if(!DuplicateString(&platformInfo.manufacturerName, manufacturerName))
876     {
877         success = false;
878     }
879
880     if(!DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl))
881     {
882         success = false;
883     }
884
885     if(!DuplicateString(&platformInfo.modelNumber, modelNumber))
886     {
887         success = false;
888     }
889
890     if(!DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture))
891     {
892         success = false;
893     }
894
895     if(!DuplicateString(&platformInfo.platformVersion, platformVersion))
896     {
897         success = false;
898     }
899
900     if(!DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion))
901     {
902         success = false;
903     }
904
905     if(!DuplicateString(&platformInfo.hardwareVersion, hardwareVersion))
906     {
907         success = false;
908     }
909
910     if(!DuplicateString(&platformInfo.firmwareVersion, firmwareVersion))
911     {
912         success = false;
913     }
914
915     if(!DuplicateString(&platformInfo.supportUrl, supportUrl))
916     {
917         success = false;
918     }
919
920     if(!DuplicateString(&platformInfo.systemTime, systemTime))
921     {
922         success = false;
923     }
924
925     if(success)
926     {
927         return OC_STACK_OK;
928     }
929
930     DeletePlatformInfo();
931     return OC_STACK_ERROR;
932 }
933
934 OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersions)
935 {
936     if(!DuplicateString(&deviceInfo.deviceName, deviceName))
937     {
938         return OC_STACK_ERROR;
939     }
940     if(!DuplicateString(&deviceInfo.specVersion, specVersion))
941     {
942         return OC_STACK_ERROR;
943     }
944     OCFreeOCStringLL(deviceInfo.dataModelVersions);
945     deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions);
946     if (!deviceInfo.dataModelVersions)
947     {
948         return OC_STACK_ERROR;
949     }
950     return OC_STACK_OK;
951 }
952
953 static void PrintUsage()
954 {
955     OIC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
956     OIC_LOG(INFO, TAG, "-o 0 : Notify all observers");
957     OIC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
958 }
959
960 #ifdef RA_ADAPTER
961 static void jidbound(char *jid)
962 {
963     OIC_LOG_V(INFO, TAG, "\n\n    Bound JID: %s\n\n", jid);
964 }
965 #endif
966
967 int main(int argc, char* argv[])
968 {
969
970 #ifdef RA_ADAPTER
971     char host[] = "localhost";
972     char user[] = "test1";
973     char pass[] = "intel123";
974     char empstr[] = "";
975     OCRAInfo_t rainfo = {};
976
977     rainfo.hostname = host;
978     rainfo.port = 5222;
979     rainfo.xmpp_domain = host;
980     rainfo.username = user;
981     rainfo.password = pass;
982     rainfo.resource = empstr;
983     rainfo.user_jid = empstr;
984     rainfo.jidbound = jidbound;
985 #endif
986
987     int opt = 0;
988     while ((opt = getopt(argc, argv, "o:s:p:d:u:w:r:j:")) != -1)
989     {
990         switch(opt)
991         {
992             case 'o':
993                 gObserveNotifyType = atoi(optarg);
994                 break;
995 #ifdef RA_ADAPTER
996             case 's':
997                 rainfo.hostname = optarg;
998                 break;
999             case 'p':
1000                 rainfo.port = atoi(optarg);
1001                 break;
1002             case 'd':
1003                 rainfo.xmpp_domain = optarg;
1004                 break;
1005             case 'u':
1006                 rainfo.username = optarg;
1007                 break;
1008             case 'w':
1009                 rainfo.password = optarg;
1010                 break;
1011             case 'j':
1012                 rainfo.user_jid = optarg;
1013                 break;
1014             case 'r':
1015                 rainfo.resource = optarg;
1016                 break;
1017 #endif
1018             default:
1019                 PrintUsage();
1020                 return -1;
1021         }
1022     }
1023
1024     if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
1025     {
1026         PrintUsage();
1027         return -1;
1028     }
1029
1030 #ifdef RA_ADAPTER
1031     OCSetRAInfo(&rainfo);
1032 #endif
1033
1034     OIC_LOG(DEBUG, TAG, "OCServer is starting...");
1035
1036     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
1037     {
1038         OIC_LOG(ERROR, TAG, "OCStack init error");
1039         return 0;
1040     }
1041 #ifdef WITH_PRESENCE
1042     if (OCStartPresence(0) != OC_STACK_OK)
1043     {
1044         OIC_LOG(ERROR, TAG, "OCStack presence/discovery error");
1045         return 0;
1046     }
1047 #endif
1048
1049     OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
1050
1051     OCStackResult registrationResult =
1052         SetPlatformInfo(platformID, manufacturerName, manufacturerUrl, modelNumber,
1053             dateOfManufacture, platformVersion,  operatingSystemVersion,  hardwareVersion,
1054             firmwareVersion,  supportUrl, systemTime);
1055
1056     if (registrationResult != OC_STACK_OK)
1057     {
1058         OIC_LOG(INFO, TAG, "Platform info setting failed locally!");
1059         exit (EXIT_FAILURE);
1060     }
1061
1062     registrationResult = OCSetPlatformInfo(platformInfo);
1063
1064     if (registrationResult != OC_STACK_OK)
1065     {
1066         OIC_LOG(INFO, TAG, "Platform Registration failed!");
1067         exit (EXIT_FAILURE);
1068     }
1069
1070     registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersions);
1071
1072     if (registrationResult != OC_STACK_OK)
1073     {
1074         OIC_LOG(INFO, TAG, "Device info setting failed locally!");
1075         exit (EXIT_FAILURE);
1076     }
1077
1078     OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.d.tv");
1079
1080     registrationResult = OCSetDeviceInfo(deviceInfo);
1081
1082     if (registrationResult != OC_STACK_OK)
1083     {
1084         OIC_LOG(INFO, TAG, "Device Registration failed!");
1085         exit (EXIT_FAILURE);
1086     }
1087
1088     /*
1089      * Declare and create the example resource: Light
1090      */
1091     createLightResource(gResourceUri, &Light);
1092
1093     // Initialize observations data structure for the resource
1094     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
1095     {
1096         interestedObservers[i].valid = false;
1097     }
1098
1099
1100     /*
1101      * Create a thread for generating changes that cause presence notifications
1102      * to be sent to clients
1103      */
1104
1105     #ifdef WITH_PRESENCE
1106     pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
1107     #endif
1108
1109     // Break from loop with Ctrl-C
1110     OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
1111
1112     DeletePlatformInfo();
1113     DeleteDeviceInfo();
1114
1115     signal(SIGINT, handleSigInt);
1116
1117     while (!gQuitFlag)
1118     {
1119         if (OCProcess() != OC_STACK_OK)
1120         {
1121             OIC_LOG(ERROR, TAG, "OCStack process error");
1122             return 0;
1123         }
1124     }
1125
1126     if (observeThreadStarted)
1127     {
1128 #ifdef HAVE_PTHREAD_H
1129         pthread_cancel(threadId_observe);
1130         pthread_join(threadId_observe, NULL);
1131 #endif
1132     }
1133
1134 #ifdef HAVE_PTHREAD_H
1135     pthread_cancel(threadId_presence);
1136     pthread_join(threadId_presence, NULL);
1137 #endif
1138
1139     OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
1140
1141     if (OCStop() != OC_STACK_OK)
1142     {
1143         OIC_LOG(ERROR, TAG, "OCStack process error");
1144     }
1145
1146     return 0;
1147 }