1 //******************************************************************
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
4 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
6 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
12 // http://www.apache.org/licenses/LICENSE-2.0
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
20 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
32 #include "oic_malloc.h"
35 #include "ocpayload.h"
39 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
41 const int URI_MAXSIZE = 19;
42 static const char* DEFAULT_DB_FILE_PATH = "/opt/usr/etc/oic_svr_db_server.dat";
44 static int gObserveNotifyType = 3;
45 static int gSecure = 0;
48 int gLightUnderObservation = 0;
50 static GMainLoop *g_mainloop = NULL;
53 static LightResource Light;
54 // This variable determines instance number of the Light resource.
55 // Used by POST method to create a new instance of Light resource.
56 static int gCurrLightInstance = 0;
58 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
60 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
63 static int stopPresenceCount = 10;
64 #define numPresenceResources (2)
67 char *gResourceUri= (char *)"/a/light";
68 const char *dateOfManufacture = "2016-01-15";
69 const char *deviceName = "myDeviceName";
70 const char *deviceUUID = "51b55ddc-ccbb-4cb3-a57f-494eeca13a21";
71 const char *firmwareVersion = "myFirmwareVersion";
72 const char *manufacturerName = "myName";
73 const char *operatingSystemVersion = "myOS";
74 const char *hardwareVersion = "myHardwareVersion";
75 const char *platformID = "0A3E0D6F-DBF5-404E-8719-D6880042463A";
76 const char *manufacturerLink = "https://www.iotivity.org";
77 const char *modelNumber = "myModelNumber";
78 const char *platformVersion = "myPlatformVersion";
79 const char *supportLink = "https://www.iotivity.org";
80 const char *version = "myVersion";
81 const char *systemTime = "2015-05-15T11.04";
82 const char *specVersion = "core.1.1.0";
83 const char *dataModelVersions = "res.1.1.0,sh.1.1.0";
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;
90 OCPlatformInfo platformInfo;
91 OCDeviceInfo deviceInfo;
93 OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
95 OCRepPayload* payload = OCRepPayloadCreate();
98 cout << "Failed to allocate Payload";
102 OCRepPayloadSetUri(payload, uri);
103 OCRepPayloadSetPropBool(payload, "state", state);
104 OCRepPayloadSetPropInt(payload, "power", power);
109 //This function takes the request as an input and returns the response
110 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
112 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
114 cout << "Incoming payload not a representation";
118 OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
120 LightResource *currLightResource = &Light;
122 if (ehRequest->resource == gLightInstance[0].handle)
124 currLightResource = &gLightInstance[0];
125 gResourceUri = (char *) "a/light/0";
127 else if (ehRequest->resource == gLightInstance[1].handle)
129 currLightResource = &gLightInstance[1];
130 gResourceUri = (char *) "a/light/1";
133 if(OC_REST_PUT == ehRequest->method)
135 // Get pointer to query
137 if(OCRepPayloadGetPropInt(input, "power", &pow))
139 currLightResource->power =pow;
143 if(OCRepPayloadGetPropBool(input, "state", &state))
145 currLightResource->state = state;
149 return getPayload(gResourceUri, currLightResource->power, currLightResource->state);
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.
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,
162 bool checkIfQueryForPowerPassed(char * query)
164 if (query && strncmp(query, "power<", strlen("power<")) == 0)
166 char * pointerToOperator = strstr(query, "<");
168 if (pointerToOperator)
170 int powerRequested = atoi(pointerToOperator + 1);
171 if (Light.power > powerRequested)
173 cout << "\nCurrent power: "<< Light.power << "Requested: " << powerRequested;
182 * Application should validate and process these as desired.
184 OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest)
186 cout << "\nReceived query %s" << entityHandlerRequest->query;
187 cout << "\nNot processing query";
191 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
192 OCRepPayload **payload)
194 OCEntityHandlerResult ehResult;
195 bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query);
197 // Empty payload if the query has no match.
200 OCRepPayload *getResp = constructResponse(ehRequest);
203 cout << "\nconstructResponse failed";
218 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
219 OCRepPayload** payload)
221 OCEntityHandlerResult ehResult;
222 OCRepPayload *putResp = constructResponse(ehRequest);
226 cout << "\nFailed to construct response";
236 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
237 OCEntityHandlerResponse *response, OCRepPayload** payload)
239 OCEntityHandlerResult ehResult = OC_EH_OK;
240 OCRepPayload *respPLPost_light = nullptr;
243 * The entity handler determines how to process a POST request.
244 * Per the REST paradigm, POST can also be used to update representation of existing
245 * resource or create a new resource.
246 * In the sample below, if the POST is for /a/light then a new instance of the Light
247 * resource is created with default representation (if representation is included in
248 * POST payload it can be used as initial values) as long as the instance is
249 * lesser than max new instance count. Once max instance count is reached, POST on
250 * /a/light updated the representation of /a/light (just like PUT).
253 if (ehRequest->resource == Light.handle)
255 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
257 // Create new Light instance
258 char newLightUri[URI_MAXSIZE];
259 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
261 respPLPost_light = OCRepPayloadCreate();
262 OCRepPayloadSetUri(respPLPost_light, gResourceUri);
263 OCRepPayloadSetPropString(respPLPost_light, "createduri", newLightUri);
265 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
267 cout << "\nCreated new Light instance";
268 gLightInstance[gCurrLightInstance].state = 0;
269 gLightInstance[gCurrLightInstance].power = 0;
270 gCurrLightInstance++;
271 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
272 ehResult = OC_EH_RESOURCE_CREATED;
277 // Update repesentation of /a/light
280 respPLPost_light = constructResponse(ehRequest);
285 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
287 if (ehRequest->resource == gLightInstance[i].handle)
289 gLightInstance[i].state = true;
290 gLightInstance[i].power = 22;
293 respPLPost_light = constructResponse(ehRequest);
298 respPLPost_light = constructResponse(ehRequest);
304 if ((respPLPost_light != NULL))
306 *payload = respPLPost_light;
310 cout << "\n Payload was NULL";
311 ehResult = OC_EH_ERROR;
317 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
319 if(ehRequest == NULL)
321 cout << "\nThe ehRequest is NULL";
324 OCEntityHandlerResult ehResult = OC_EH_OK;
326 cout << "\nExecuting " << __func__ << " for resource " << ehRequest->resource;
329 * In the sample below, the application will:
330 * 1a. pass the delete request to the c stack
331 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
332 * (e.g. send observers notification, remove observers...)
333 * 1c. the c stack returns with the result whether the request is fullfilled.
334 * 2. optionally, app removes observers out of its array 'interestedObservers'
337 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
339 //Step 1: Ask stack to do the work.
340 OCStackResult result = OCDeleteResource(ehRequest->resource);
342 if (result == OC_STACK_OK)
344 cout << "\nDelete Resource operation succeeded.";
347 //Step 2: clear observers who wanted to observe this resource at the app level.
348 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
350 if (interestedObservers[i].resourceHandle == ehRequest->resource)
352 interestedObservers[i].valid = false;
353 interestedObservers[i].observationId = 0;
354 interestedObservers[i].resourceHandle = NULL;
358 else if (result == OC_STACK_NO_RESOURCE)
360 cout << "\nThe resource doesn't exist or it might have been deleted.";
361 ehResult = OC_EH_RESOURCE_DELETED;
365 cout << "\nEncountered error from OCDeleteResource().";
366 ehResult = OC_EH_ERROR;
369 else if (ehRequest->resource != Light.handle)
371 //Let's this app not supporting DELETE on some resources so
372 //consider the DELETE request is received for a non-support resource.
373 cout << "\nThe request is received for a non-support resource.";
374 ehResult = OC_EH_FORBIDDEN;
380 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest)
382 cout << "\nExecuting " << __func__;
384 return OC_EH_RESOURCE_NOT_FOUND;
387 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
389 cout << "\nReceived observation registration request with observation Id "
390 << ehRequest->obsInfo.obsId;
391 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
393 if (interestedObservers[i].valid == false)
395 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
396 interestedObservers[i].valid = true;
397 gLightUnderObservation = 1;
403 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
405 bool clientStillObserving = false;
407 cout << "\nReceived observation deregistration request for observation Id "
408 << ehRequest->obsInfo.obsId;
409 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
411 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
413 interestedObservers[i].valid = false;
415 if (interestedObservers[i].valid == true)
417 // Even if there is one single client observing we continue notifying entity handler
418 clientStillObserving = true;
421 if (clientStillObserving == false)
422 gLightUnderObservation = 0;
425 OCEntityHandlerResult
426 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
427 OCEntityHandlerRequest *entityHandlerRequest, char* uri, void* callbackParam)
429 cout << "\nInside device default entity handler - flags: " << flag << ", uri: %s" << uri;
431 OCEntityHandlerResult ehResult = OC_EH_OK;
432 OCEntityHandlerResponse response;
435 if (!entityHandlerRequest)
437 cout << "\nInvalid request pointer";
440 // Initialize certain response fields
441 response.numSendVendorSpecificHeaderOptions = 0;
442 memset(response.sendVendorSpecificHeaderOptions, 0,
443 sizeof response.sendVendorSpecificHeaderOptions);
444 memset(response.resourceUri, 0, sizeof response.resourceUri);
445 OCRepPayload* payload = nullptr;
448 if (flag & OC_REQUEST_FLAG)
450 cout << "\nFlag includes OC_REQUEST_FLAG";
452 if (entityHandlerRequest->resource == NULL)
454 cout << "\nReceived request from client to a non-existing resource";
455 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
457 else if (OC_REST_GET == entityHandlerRequest->method)
459 cout << "\nReceived OC_REST_GET from client";
460 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
462 else if (OC_REST_PUT == entityHandlerRequest->method)
464 cout << "\nReceived OC_REST_PUT from client";
465 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
467 else if (OC_REST_DELETE == entityHandlerRequest->method)
469 cout << "\nReceived OC_REST_DELETE from client";
470 ehResult = ProcessDeleteRequest (entityHandlerRequest);
474 cout << "\nReceived unsupported method " << entityHandlerRequest->method
476 ehResult = OC_EH_ERROR;
478 // If the result isn't an error or forbidden, send response
479 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
481 // Format the response. Note this requires some info about the request
482 response.requestHandle = entityHandlerRequest->requestHandle;
483 response.resourceHandle = entityHandlerRequest->resource;
484 response.ehResult = ehResult;
485 response.payload = reinterpret_cast<OCPayload*>(payload);
486 // Indicate that response is NOT in a persistent buffer
487 response.persistentBufferFlag = 0;
490 if (OCDoResponse(&response) != OC_STACK_OK)
492 cout << "\nError sending response";
493 ehResult = OC_EH_ERROR;
497 if (flag & OC_OBSERVE_FLAG)
499 cout << "\nFlag includes OC_OBSERVE_FLAG";
500 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
502 cout << "\nReceived OC_OBSERVE_REGISTER from client";
504 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
506 cout << "\nReceived OC_OBSERVE_DEREGISTER from client";
510 OCPayloadDestroy(response.payload);
514 OCEntityHandlerResult
515 OCNOPEntityHandlerCb (OCEntityHandlerFlag flag,
516 OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
518 // This is callback is associated with the 2 presence notification
519 // resources. They are non-operational.
523 OCEntityHandlerResult
524 OCEntityHandlerCb (OCEntityHandlerFlag flag,
525 OCEntityHandlerRequest *entityHandlerRequest, void* callback)
527 cout << "\nInside entity handler - flags: " << flag;
529 OCEntityHandlerResult ehResult = OC_EH_OK;
530 OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
533 if (!entityHandlerRequest)
535 cout << "\nInvalid request pointer";
539 // Initialize certain response fields
540 response.numSendVendorSpecificHeaderOptions = 0;
541 memset(response.sendVendorSpecificHeaderOptions,
542 0, sizeof response.sendVendorSpecificHeaderOptions);
543 memset(response.resourceUri, 0, sizeof response.resourceUri);
544 OCRepPayload* payload = nullptr;
546 if (flag & OC_REQUEST_FLAG)
548 cout << "\n=================================\n";
549 cout << "\nFlag includes OC_REQUEST_FLAG\n";
551 if (OC_REST_GET == entityHandlerRequest->method)
553 cout << "\nReceived OC_REST_GET from client";
554 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
555 cout << "\n=================================\n";
557 else if (OC_REST_PUT == entityHandlerRequest->method)
559 cout << "\nReceived OC_REST_PUT from client";
560 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
561 cout << "\n=================================\n";
563 else if (OC_REST_POST == entityHandlerRequest->method)
565 cout << "\nReceived OC_REST_POST from client";
566 ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
567 cout << "\n=================================\n";
569 else if (OC_REST_DELETE == entityHandlerRequest->method)
571 cout << "\nReceived OC_REST_DELETE from client";
572 ehResult = ProcessDeleteRequest (entityHandlerRequest);
573 cout << "\n=================================\n";
577 cout << "\nReceived unsupported method " << entityHandlerRequest->method << " from client";
578 ehResult = OC_EH_ERROR;
580 // If the result isn't an error or forbidden, send response
581 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
583 // Format the response. Note this requires some info about the request
584 response.requestHandle = entityHandlerRequest->requestHandle;
585 response.resourceHandle = entityHandlerRequest->resource;
586 response.ehResult = ehResult;
587 response.payload = reinterpret_cast<OCPayload*>(payload);
588 // Indicate that response is NOT in a persistent buffer
589 response.persistentBufferFlag = 0;
591 // Handle vendor specific options
592 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
593 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
595 cout << "\nReceived vendor specific options";
597 OCHeaderOption * rcvdOptions =
598 entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
599 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
601 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
603 cout << "\nReceived option with ID " << ((OCHeaderOption)rcvdOptions[i]).optionID;
606 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
607 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
608 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
609 sendOptions[0].protocolID = OC_COAP_ID;
610 sendOptions[0].optionID = 2248;
611 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
612 sendOptions[0].optionLength = 10;
613 sendOptions[1].protocolID = OC_COAP_ID;
614 sendOptions[1].optionID = 2600;
615 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
616 sendOptions[1].optionLength = 10;
617 response.numSendVendorSpecificHeaderOptions = 2;
621 if (OCDoResponse(&response) != OC_STACK_OK)
623 cout << "\nError sending response";
624 ehResult = OC_EH_ERROR;
628 if (flag & OC_OBSERVE_FLAG)
630 cout << "\nFlag includes OC_OBSERVE_FLAG";
632 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
634 cout << "\nReceived OC_OBSERVE_REGISTER from client";
635 ProcessObserveRegister (entityHandlerRequest);
637 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
639 cout << "\nReceived OC_OBSERVE_DEREGISTER from client";
640 ProcessObserveDeregister (entityHandlerRequest);
644 OCPayloadDestroy(response.payload);
648 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
649 void handleSigInt(int signum)
651 if (signum == SIGINT)
657 void *ChangeLightRepresentation (void *param)
660 OCStackResult result = OC_STACK_ERROR;
663 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
664 OCObservationId obsNotify[numNotifies];
670 if (gLightUnderObservation)
672 cout << "\n=====> Notifying stack of new power level" << Light.power;
673 if (gObserveNotifyType == 1)
675 // Notify list of observers. Alternate observers on the list will be notified.
677 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
679 if (interestedObservers[i].valid == true)
681 obsNotify[j] = interestedObservers[i].observationId;
686 OCRepPayload* payload = getPayload(gResourceUri, Light.power, Light.state);
687 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
689 OCRepPayloadDestroy(payload);
691 else if (gObserveNotifyType == 0)
693 // Notifying all observers
694 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
695 if (OC_STACK_NO_OBSERVERS == result)
697 cout << "\n=====> No more observers exist, stop sending observations";
698 gLightUnderObservation = 0;
703 cout << "\nIncorrect notification type selected";
707 if(stopPresenceCount > 0)
709 cout << "\n=====> Counting down to stop presence " << stopPresenceCount;
711 if(!stopPresenceCount--)
713 cout << "\n=====> stopping presence";
722 void *presenceNotificationGenerator(void *param)
726 OCDoHandle presenceNotificationHandles[numPresenceResources];
727 OCStackResult res = OC_STACK_OK;
729 std::array<std::string, numPresenceResources> presenceNotificationResources { {
730 std::string("core.fan"),
731 std::string("core.led") } };
732 std::array<std::string, numPresenceResources> presenceNotificationUris { {
733 std::string("/a/fan"),
734 std::string("/a/led") } };
736 for(int i=0; i<numPresenceResources; i++)
738 if(res == OC_STACK_OK)
742 uint8_t resourceProperties = OC_DISCOVERABLE | OC_OBSERVABLE;
745 resourceProperties |= OC_SECURE;
748 res = OCCreateResource(&presenceNotificationHandles[i],
749 presenceNotificationResources.at(i).c_str(),
750 OC_RSRVD_INTERFACE_DEFAULT,
751 presenceNotificationUris.at(i).c_str(),
752 OCNOPEntityHandlerCb,
756 if(res != OC_STACK_OK)
758 cout << "\nPresence Notification Generator failed[" << getResult(res)
759 << "] to create resource " << presenceNotificationResources.at(i).c_str();
762 cout << "\nCreated " << presenceNotificationUris[i].c_str() << " for presence notification";
765 for(int i=0; i<numPresenceResources; i++)
767 if(res == OC_STACK_OK)
769 res = OCDeleteResource(presenceNotificationHandles[i]);
771 if(res != OC_STACK_OK)
773 cout << "\nPresence Notification Generator failed to delete resource"
774 << presenceNotificationResources.at(i).c_str();
777 cout << "\nDeleted " << presenceNotificationUris[i].c_str() << " for presence notification";
783 int createLightResource (char *uri, LightResource *lightResource)
787 cout << "\nResource URI cannot be NULL";
791 lightResource->state = false;
792 lightResource->power= 0;
794 uint8_t resourceProperties = OC_DISCOVERABLE | OC_OBSERVABLE;
797 resourceProperties |= OC_SECURE;
800 OCStackResult res = OCCreateResource(&(lightResource->handle),
807 cout << "\nCreated Light resource with result " << getResult(res);
812 void DeletePlatformInfo()
814 free (platformInfo.platformID);
815 free (platformInfo.manufacturerName);
816 free (platformInfo.manufacturerUrl);
817 free (platformInfo.modelNumber);
818 free (platformInfo.dateOfManufacture);
819 free (platformInfo.platformVersion);
820 free (platformInfo.operatingSystemVersion);
821 free (platformInfo.hardwareVersion);
822 free (platformInfo.firmwareVersion);
823 free (platformInfo.supportUrl);
824 free (platformInfo.systemTime);
827 void DeleteDeviceInfo()
829 free (deviceInfo.deviceName);
830 free (deviceInfo.specVersion);
831 OCFreeOCStringLL (deviceInfo.dataModelVersions);
834 bool DuplicateString(char** targetString, const char* sourceString)
842 *targetString = (char *) malloc(strlen(sourceString) + 1);
846 strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
853 OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerName,
854 const char *manufacturerUrl, const char *modelNumber, const char *dateOfManufacture,
855 const char *platformVersion, const char* operatingSystemVersion, const char* hardwareVersion,
856 const char *firmwareVersion, const char* supportUrl, const char* systemTime)
861 if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_PLATFORM_NAME_LENGTH))
863 return OC_STACK_INVALID_PARAM;
866 if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_PLATFORM_URL_LENGTH))
868 return OC_STACK_INVALID_PARAM;
871 if(!DuplicateString(&platformInfo.platformID, platformID))
876 if(!DuplicateString(&platformInfo.manufacturerName, manufacturerName))
881 if(!DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl))
886 if(!DuplicateString(&platformInfo.modelNumber, modelNumber))
891 if(!DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture))
896 if(!DuplicateString(&platformInfo.platformVersion, platformVersion))
901 if(!DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion))
906 if(!DuplicateString(&platformInfo.hardwareVersion, hardwareVersion))
911 if(!DuplicateString(&platformInfo.firmwareVersion, firmwareVersion))
916 if(!DuplicateString(&platformInfo.supportUrl, supportUrl))
921 if(!DuplicateString(&platformInfo.systemTime, systemTime))
931 DeletePlatformInfo();
932 return OC_STACK_ERROR;
935 OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersions)
937 if(!DuplicateString(&deviceInfo.deviceName, deviceName))
939 return OC_STACK_ERROR;
941 if(!DuplicateString(&deviceInfo.specVersion, specVersion))
943 return OC_STACK_ERROR;
945 OCFreeOCStringLL(deviceInfo.dataModelVersions);
946 deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions);
947 if (!deviceInfo.dataModelVersions)
949 return OC_STACK_ERROR;
954 static void PrintUsage()
956 cout << "\nUsage : ocserver -o <0|1> -s <0|1>";
957 cout << "\n-o 0 : Notify all observers";
958 cout << "\n-o 1 : Notify list of observers";
959 cout << "\n-s 0 : Non secure resource";
960 cout << "\n-s 1 : Secure resource";
963 void *GMainLoopThread(void *param)
968 if (OCProcess() != OC_STACK_OK)
970 cout << "\nOCStack process error";
973 #ifndef ROUTING_GATEWAY
980 g_main_loop_quit(g_mainloop);
985 static FILE *server_fopen(const char */*path*/, const char *mode)
987 return fopen(DEFAULT_DB_FILE_PATH, mode);
990 int main(int argc, char* argv[])
993 pthread_t threadId_presence;
996 g_mainloop = g_main_loop_new(NULL, FALSE);
999 printf("g_main_loop_new failed\n");
1003 while ((opt = getopt(argc, argv, "o:s:")) != -1)
1008 gObserveNotifyType = atoi(optarg);
1011 gSecure = atoi(optarg);
1019 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1) &&
1020 (gSecure != 0) && (gSecure != 1))
1026 cout << "\nOCServer is starting...";
1028 OCPersistentStorage ps{ server_fopen, fread, fwrite, fclose, unlink };
1029 OCRegisterPersistentStorageHandler(&ps);
1031 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
1033 cout << "\nOCStack init error";
1037 #ifdef WITH_PRESENCE
1038 if (OCStartPresence(0) != OC_STACK_OK)
1040 cout << "\nOCStack presence/discovery error";
1045 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
1047 OCStackResult registrationResult =
1048 SetPlatformInfo(platformID, manufacturerName, manufacturerLink, modelNumber,
1049 dateOfManufacture, platformVersion, operatingSystemVersion, hardwareVersion,
1050 firmwareVersion, supportLink, systemTime);
1052 if (registrationResult != OC_STACK_OK)
1054 cout << "\nPlatform info setting failed locally!";
1055 exit (EXIT_FAILURE);
1058 registrationResult = OCSetPlatformInfo(platformInfo);
1060 if (registrationResult != OC_STACK_OK)
1062 cout << "\nPlatform Registration failed!";
1063 exit (EXIT_FAILURE);
1066 registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersions);
1068 if (registrationResult != OC_STACK_OK)
1070 cout << "\nDevice info setting failed locally!";
1071 exit (EXIT_FAILURE);
1074 OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.d.tv");
1076 registrationResult = OCSetDeviceInfo(deviceInfo);
1078 if (registrationResult != OC_STACK_OK)
1080 cout << "\nDevice Registration failed!";
1081 exit (EXIT_FAILURE);
1085 * Declare and create the example resource: Light
1087 createLightResource(gResourceUri, &Light);
1089 // Initialize observations data structure for the resource
1090 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
1092 interestedObservers[i].valid = false;
1096 * Create a thread for changing the representation of the Light
1098 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
1101 * Create a thread for generating changes that cause presence notifications
1102 * to be sent to clients
1105 #ifdef WITH_PRESENCE
1106 pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
1109 // Break from loop with Ctrl-C
1110 cout << "\nEntering ocserver main loop...";
1112 DeletePlatformInfo();
1115 signal(SIGINT, handleSigInt);
1117 int result = pthread_create(&g_thread, NULL, GMainLoopThread, (void *)NULL);
1120 printf("pthread_create failed in initialize\n");
1124 g_main_loop_run(g_mainloop);
1127 * Cancel the Light thread and wait for it to terminate
1129 pthread_cancel(threadId);
1130 pthread_join(threadId, NULL);
1131 pthread_cancel(threadId_presence);
1132 pthread_join(threadId_presence, NULL);
1134 cout << "\nExiting ocserver main loop...\n";
1136 if (OCStop() != OC_STACK_OK)
1138 cout << "\nOCStack process error";