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