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