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