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