//Function to print the headerOptions received from the server void printHeaderOptions(const HeaderOptions& headerOptions) { for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it) { if(it->getOptionID() == API_VERSION) { std::cout << "Server API version in GET response: " << it->getOptionData() << std::endl; } } }
void InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[], const HeaderOptions& headerOptions) { int i = 0; for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it) { options[i].protocolID = OC_COAP_ID; options[i].optionID = static_cast<uint16_t>(it->getOptionID()); options[i].optionLength = (it->getOptionData()).length() + 1; memcpy(options[i].optionData, (it->getOptionData()).c_str(), (it->getOptionData()).length() + 1); i++; } }
OCStackResult InProcClientWrapper::CancelObserveResource( OCDoHandle handle, const std::string& host, // unused const std::string& uri, // unused const HeaderOptions& headerOptions, QualityOfService QoS) { OCStackResult result; auto cLock = m_csdkLock.lock(); if(cLock) { std::lock_guard<std::recursive_mutex> lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), assembleHeaderOptions(options, headerOptions), headerOptions.size()); } else { result = OC_STACK_ERROR; } return result; }
OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle, const OCDevAddr& devAddr, const std::string& uri, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, ObserveCallback& callback, QualityOfService QoS) { if(!callback) { return OC_STACK_INVALID_PARAM; } OCStackResult result; ClientCallbackContext::ObserveContext* ctx = new ClientCallbackContext::ObserveContext(callback); OCCallbackData cbdata( static_cast<void*>(ctx), observeResourceCallback, [](void* c){delete static_cast<ClientCallbackContext::ObserveContext*>(c);} ); OCMethod method; if (observeType == ObserveType::Observe) { method = OC_REST_OBSERVE; } else if (observeType == ObserveType::ObserveAll) { method = OC_REST_OBSERVE_ALL; } else { method = OC_REST_OBSERVE_ALL; } std::string url = assembleSetResourceUri(uri, queryParams).c_str(); auto cLock = m_csdkLock.lock(); if(cLock) { std::lock_guard<std::recursive_mutex> lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; result = OCDoResource(handle, method, url.c_str(), &devAddr, nullptr, CT_DEFAULT, static_cast<OCQualityOfService>(QoS), &cbdata, assembleHeaderOptions(options, headerOptions), headerOptions.size()); } else { delete ctx; return OC_STACK_ERROR; } return result; }
void parseServerHeaderOptions(OCClientResponse* clientResponse, HeaderOptions& serverHeaderOptions) { if(clientResponse) { // Parse header options from server uint16_t optionID; std::string optionData; for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++) { optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID; optionData = reinterpret_cast<const char*> (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData); HeaderOption::OCHeaderOption headerOption(optionID, optionData); serverHeaderOptions.push_back(headerOption); } } else { // clientResponse is invalid // TODO check proper logging std::cout << " Invalid response " << std::endl; } }
OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle, const std::string& host, const std::string& uri, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, ObserveCallback& callback, QualityOfService QoS) { OCStackResult result; OCCallbackData cbdata = {0}; ClientCallbackContext::ObserveContext* ctx = new ClientCallbackContext::ObserveContext(); ctx->callback = callback; cbdata.context = static_cast<void*>(ctx); cbdata.cb = &observeResourceCallback; cbdata.cd = [](void* c) { delete static_cast<ClientCallbackContext::ObserveContext*>(c); }; OCMethod method; if (observeType == ObserveType::Observe) { method = OC_REST_OBSERVE; } else if (observeType == ObserveType::ObserveAll) { method = OC_REST_OBSERVE_ALL; } else { method = OC_REST_OBSERVE_ALL; } auto cLock = m_csdkLock.lock(); if(cLock) { std::ostringstream os; os << host << assembleSetResourceUri(uri, queryParams).c_str(); std::lock_guard<std::recursive_mutex> lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; assembleHeaderOptions(options, headerOptions); result = OCDoResource(handle, method, os.str().c_str(), nullptr, nullptr, static_cast<OCQualityOfService>(QoS), &cbdata, options, headerOptions.size()); } else { delete ctx; return OC_STACK_ERROR; } return result; }
OCStackResult InProcClientWrapper::PutResourceRepresentation( const OCDevAddr& devAddr, const std::string& uri, const OCRepresentation& rep, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, PutCallback& callback, QualityOfService QoS) { if(!callback) { return OC_STACK_INVALID_PARAM; } OCStackResult result; ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback); OCCallbackData cbdata( static_cast<void*>(ctx), setResourceCallback, [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);} ); std::string url = assembleSetResourceUri(uri, queryParams).c_str(); auto cLock = m_csdkLock.lock(); if(cLock) { std::lock_guard<std::recursive_mutex> lock(*cLock); OCDoHandle handle; OCHeaderOption options[MAX_HEADER_OPTIONS]; result = OCDoResource(&handle, OC_REST_PUT, url.c_str(), &devAddr, assembleSetResourcePayload(rep), CT_DEFAULT, static_cast<OCQualityOfService>(QoS), &cbdata, assembleHeaderOptions(options, headerOptions), headerOptions.size()); } else { delete ctx; result = OC_STACK_ERROR; } return result; }
OCStackResult InProcClientWrapper::DeleteResource( const OCDevAddr& devAddr, const std::string& uri, const HeaderOptions& headerOptions, DeleteCallback& callback, QualityOfService /*QoS*/) { if(!callback) { return OC_STACK_INVALID_PARAM; } OCStackResult result; ClientCallbackContext::DeleteContext* ctx = new ClientCallbackContext::DeleteContext(callback); OCCallbackData cbdata( static_cast<void*>(ctx), deleteResourceCallback, [](void* c){delete static_cast<ClientCallbackContext::DeleteContext*>(c);} ); auto cLock = m_csdkLock.lock(); if(cLock) { OCHeaderOption options[MAX_HEADER_OPTIONS]; std::lock_guard<std::recursive_mutex> lock(*cLock); result = OCDoResource(nullptr, OC_REST_DELETE, uri.c_str(), &devAddr, nullptr, CT_DEFAULT, static_cast<OCQualityOfService>(m_cfg.QoS), &cbdata, assembleHeaderOptions(options, headerOptions), headerOptions.size()); } else { delete ctx; result = OC_STACK_ERROR; } return result; }
OCStackResult InProcClientWrapper::GetResourceRepresentation( const OCDevAddr& devAddr, const std::string& resourceUri, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, GetCallback& callback, QualityOfService QoS) { if (!callback) { return OC_STACK_INVALID_PARAM; } OCStackResult result; ClientCallbackContext::GetContext* ctx = new ClientCallbackContext::GetContext(callback); OCCallbackData cbdata; cbdata.context = static_cast<void*>(ctx), cbdata.cb = getResourceCallback; cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;}; std::string uri = assembleSetResourceUri(resourceUri, queryParams); auto cLock = m_csdkLock.lock(); if (cLock) { std::lock_guard<std::recursive_mutex> lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; result = OCDoResource( nullptr, OC_REST_GET, uri.c_str(), &devAddr, nullptr, CT_DEFAULT, static_cast<OCQualityOfService>(QoS), &cbdata, assembleHeaderOptions(options, headerOptions), headerOptions.size()); } else { delete ctx; result = OC_STACK_ERROR; } return result; }
OCStackResult InProcClientWrapper::ListenForMQTopic( const OCDevAddr& devAddr, const std::string& resourceUri, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, FindCallback& callback, QualityOfService QoS) { oclog() << "ListenForMQTopic()" << std::flush; if (!callback) { return OC_STACK_INVALID_PARAM; } ClientCallbackContext::ListenContext* context = new ClientCallbackContext::ListenContext(callback, shared_from_this()); OCCallbackData cbdata; cbdata.context = static_cast<void*>(context), cbdata.cb = listenMQCallback; cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext*)c;}; std::string uri = assembleSetResourceUri(resourceUri, queryParams); OCStackResult result = OC_STACK_ERROR; auto cLock = m_csdkLock.lock(); if (cLock) { std::lock_guard<std::recursive_mutex> lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; result = OCDoResource( nullptr, OC_REST_GET, uri.c_str(), &devAddr, nullptr, CT_DEFAULT, static_cast<OCQualityOfService>(QoS), &cbdata, assembleHeaderOptions(options, headerOptions), headerOptions.size()); } else { delete context; } return result; }
OCStackResult InProcClientWrapper::PutResourceRepresentation(const std::string& host, const std::string& uri, const OCRepresentation& rep, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, PutCallback& callback, QualityOfService QoS) { OCStackResult result; OCCallbackData cbdata = {0}; ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(); ctx->callback = callback; cbdata.cb = &setResourceCallback; cbdata.cd = [](void* c) { delete static_cast<ClientCallbackContext::SetContext*>(c); }; cbdata.context = static_cast<void*>(ctx); // TODO: in the future the cstack should be combining these two strings! ostringstream os; os << host << assembleSetResourceUri(uri, queryParams).c_str(); // TODO: end of above auto cLock = m_csdkLock.lock(); if(cLock) { std::lock_guard<std::recursive_mutex> lock(*cLock); OCDoHandle handle; OCHeaderOption options[MAX_HEADER_OPTIONS]; assembleHeaderOptions(options, headerOptions); result = OCDoResource(&handle, OC_REST_PUT, os.str().c_str(), nullptr, assembleSetResourcePayload(rep).c_str(), static_cast<OCQualityOfService>(QoS), &cbdata, options, headerOptions.size()); } else { delete ctx; result = OC_STACK_ERROR; } return result; }
OCStackResult InProcClientWrapper::DeleteResource(const std::string& host, const std::string& uri, const HeaderOptions& headerOptions, DeleteCallback& callback, QualityOfService QoS) { OCStackResult result; OCCallbackData cbdata = {0}; ClientCallbackContext::DeleteContext* ctx = new ClientCallbackContext::DeleteContext(); ctx->callback = callback; cbdata.cb = &deleteResourceCallback; cbdata.cd = [](void* c) { delete static_cast<ClientCallbackContext::DeleteContext*>(c); }; cbdata.context = static_cast<void*>(ctx); ostringstream os; os << host << uri; auto cLock = m_csdkLock.lock(); if(cLock) { OCHeaderOption options[MAX_HEADER_OPTIONS]; OCDoHandle handle; assembleHeaderOptions(options, headerOptions); std::lock_guard<std::recursive_mutex> lock(*cLock); result = OCDoResource(&handle, OC_REST_DELETE, os.str().c_str(), nullptr, nullptr, static_cast<OCQualityOfService>(m_cfg.QoS), &cbdata, options, headerOptions.size()); } else { delete ctx; result = OC_STACK_ERROR; } return result; }
OCStackResult InProcServerWrapper::sendResponse( const std::shared_ptr<OCResourceResponse> pResponse) { auto cLock = m_csdkLock.lock(); OCStackResult result = OC_STACK_ERROR; if(!pResponse) { result = OC_STACK_MALFORMED_RESPONSE; throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE); } else { OCEntityHandlerResponse response; // OCRepPayload* payLoad = pResponse->getPayload(); HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions(); response.requestHandle = pResponse->getRequestHandle(); response.resourceHandle = pResponse->getResourceHandle(); response.ehResult = pResponse->getResponseResult(); response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload()); response.persistentBufferFlag = 0; response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size(); int i = 0; for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it) { response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID; response.sendVendorSpecificHeaderOptions[i].optionID = static_cast<uint16_t>(it->getOptionID()); response.sendVendorSpecificHeaderOptions[i].optionLength = (it->getOptionData()).length() + 1; std::string optionData = it->getOptionData(); std::copy(optionData.begin(), optionData.end(), response.sendVendorSpecificHeaderOptions[i].optionData); response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()] = '\0'; i++; } if(OC_EH_RESOURCE_CREATED == response.ehResult) { pResponse->getNewResourceUri().copy(response.resourceUri, sizeof (response.resourceUri) - 1); response.resourceUri[pResponse->getNewResourceUri().length()] = '\0'; } if(cLock) { std::lock_guard<std::recursive_mutex> lock(*cLock); result = OCDoResponse(&response); } else { OICFree(response.payload); result = OC_STACK_ERROR; } if(result != OC_STACK_OK) { oclog() << "Error sending response\n"; } return result; } }
void formResourceRequest(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest, std::shared_ptr<OCResourceRequest> pRequest) { if(pRequest && entityHandlerRequest) { pRequest->setRequestHandle(entityHandlerRequest->requestHandle); pRequest->setResourceHandle(entityHandlerRequest->resource); pRequest->setMessageID(entityHandlerRequest->messageID); } if(flag & OC_REQUEST_FLAG) { pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag); if(entityHandlerRequest) { if(entityHandlerRequest->query) { OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams( entityHandlerRequest->query); if(qp.size() > 0) { pRequest->setQueryParams(qp); } } if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0) { //Set the header options here. uint16_t optionID; std::string optionData; HeaderOptions headerOptions; for(int i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++) { optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID; optionData = reinterpret_cast<const char*> (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData); HeaderOption::OCHeaderOption headerOption(optionID, optionData); headerOptions.push_back(headerOption); } pRequest->setHeaderOptions(headerOptions); } if(OC_REST_GET == entityHandlerRequest->method) { pRequest->setRequestType(OC::PlatformCommands::GET); } else if(OC_REST_PUT == entityHandlerRequest->method) { pRequest->setRequestType(OC::PlatformCommands::PUT); pRequest->setPayload(entityHandlerRequest->payload); } else if(OC_REST_POST == entityHandlerRequest->method) { pRequest->setRequestType(OC::PlatformCommands::POST); pRequest->setPayload(entityHandlerRequest->payload); } else if(OC_REST_DELETE == entityHandlerRequest->method) { pRequest->setRequestType(OC::PlatformCommands::DELETE); } } } if(flag & OC_OBSERVE_FLAG) { pRequest->setRequestHandlerFlag( OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag); if(entityHandlerRequest) { OC::ObservationInfo observationInfo; observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action; observationInfo.obsId = entityHandlerRequest->obsInfo.obsId; observationInfo.connectivityType = static_cast<OCConnectivityType>( (entityHandlerRequest->devAddr.adapter << CT_ADAPTER_SHIFT) | (entityHandlerRequest->devAddr.flags & CT_MASK_FLAGS)); observationInfo.address = entityHandlerRequest->devAddr.addr; observationInfo.port = entityHandlerRequest->devAddr.port; pRequest->setObservationInfo(observationInfo); } } }
void foundDevice(std::shared_ptr<OCResource> resource) { using namespace OC::OCPlatform; if(resource && resource->uri() == "/device") { std::cout << "Discovered a device object"<<std::endl; std::cout << "\tHost: "<<resource->host()<<std::endl; std::cout << "\tURI: "<<resource->uri() <<std::endl; } // we have now found a resource, so lets create a few resource objects // for the other resources that we KNOW are associated with the intel.fridge // server, and query them. std::vector<std::string> lightTypes = {"intel.fridge.light"}; std::vector<std::string> ifaces = {DEFAULT_INTERFACE}; OCResource::Ptr light = constructResourceObject(resource->host(), "/light", m_connectivityType, false, lightTypes, ifaces); if(!light) { std::cout << "Error: Light Resource Object construction returned null\n"; return; } std::vector<std::string> doorTypes = {"intel.fridge.door"}; OCResource::Ptr leftdoor = constructResourceObject(resource->host(), "/door/left", m_connectivityType, false, doorTypes, ifaces); if(!leftdoor) { std::cout << "Error: Left Door Resource Object construction returned null\n"; return; } OCResource::Ptr rightdoor = constructResourceObject(resource->host(), "/door/right", m_connectivityType, false, doorTypes, ifaces); if(!rightdoor) { std::cout << "Error: Right Door Resource Object construction returned null\n"; return; } OCResource::Ptr randomdoor = constructResourceObject(resource->host(), "/door/random", m_connectivityType, false, doorTypes, ifaces); if(!randomdoor) { std::cout << "Error: Random Door Resource Object construction returned null\n"; return; } // Set header options with API version and token HeaderOptions headerOptions; try { // Set API version and client token HeaderOption::OCHeaderOption apiVersion(API_VERSION, "v.1.0"); HeaderOption::OCHeaderOption clientToken(TOKEN, "21ae43gf"); headerOptions.push_back(apiVersion); headerOptions.push_back(clientToken); } catch(OCException& e) { std::cout << "Error creating HeaderOption: " << e.what() << std::endl; } // Setting header options will send above options in all requests // Header options are set per resource. // Below, header options are set only for device resource resource->setHeaderOptions(headerOptions); ++m_callsMade; resource->get(QueryParamsMap(), GetCallback( std::bind(&ClientFridge::getResponse, this, "Device", PH::_1, PH::_2, PH::_3, resource, 0) )); ++m_callsMade; light->get(QueryParamsMap(), GetCallback( std::bind(&ClientFridge::getResponse, this, "Fridge Light", PH::_1, PH::_2, PH::_3, light, 1) )); ++m_callsMade; leftdoor->get(QueryParamsMap(), GetCallback( std::bind(&ClientFridge::getResponse, this, "Left Door", PH::_1, PH::_2, PH::_3, leftdoor, 2) )); ++m_callsMade; rightdoor->get(QueryParamsMap(), GetCallback( std::bind(&ClientFridge::getResponse, this, "Right Door", PH::_1, PH::_2, PH::_3, rightdoor, 3) )); ++m_callsMade; randomdoor->get(QueryParamsMap(), GetCallback( std::bind(&ClientFridge::getResponse, this, "Random Door", PH::_1, PH::_2, PH::_3, randomdoor, 4) )); ++m_callsMade; resource->deleteResource(DeleteCallback( std::bind(&ClientFridge::deleteResponse, this, "Device", PH::_1, PH::_2, resource, 0) )); }
virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request) { OCEntityHandlerResult ehResult = OC_EH_ERROR; if(request) { // Get the header options from the request HeaderOptions headerOptions = request->getHeaderOptions(); std::string clientAPIVersion; std::string clientToken; // Search the header options map and look for API version and Client token for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it) { uint16_t optionID = it->getOptionID(); if(optionID == API_VERSION) { clientAPIVersion = it->getOptionData(); std::cout << " Client API version: " << clientAPIVersion << std::endl; } else if(optionID == TOKEN) { clientToken = it->getOptionData(); std::cout << " Client token: " << clientToken << std::endl; } else { std::cout << " Invalid header option " << std::endl; } } // In this case Server entity handler verifies API version // and client token. If they are valid, client requests are handled. if(clientAPIVersion == FRIDGE_CLIENT_API_VERSION && clientToken == FRIDGE_CLIENT_TOKEN) { HeaderOptions serverHeaderOptions; try { // Set API version from server side HeaderOption::OCHeaderOption apiVersion(API_VERSION, FRIDGE_CLIENT_API_VERSION); serverHeaderOptions.push_back(apiVersion); } catch(OCException& e) { std::cout << "Error creating HeaderOption in server: " << e.what() << std::endl; } if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) { auto pResponse = std::make_shared<OC::OCResourceResponse>(); pResponse->setRequestHandle(request->getRequestHandle()); pResponse->setResourceHandle(request->getResourceHandle()); pResponse->setHeaderOptions(serverHeaderOptions); if(request->getRequestType() == "GET") { std::cout<<"DeviceResource Get Request"<<std::endl; pResponse->setErrorCode(200); pResponse->setResponseResult(OC_EH_OK); pResponse->setResourceRepresentation(get(), ""); if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) { ehResult = OC_EH_OK; } } else if(request->getRequestType() == "DELETE") { std::cout<<"DeviceResource Delete Request"<<std::endl; if(deleteDeviceResource() == OC_STACK_OK) { pResponse->setErrorCode(200); pResponse->setResponseResult(OC_EH_RESOURCE_DELETED); ehResult = OC_EH_OK; } else { pResponse->setResponseResult(OC_EH_ERROR); ehResult = OC_EH_ERROR; } OCPlatform::sendResponse(pResponse); } else { std::cout <<"DeviceResource unsupported request type " << request->getRequestType() << std::endl; pResponse->setResponseResult(OC_EH_ERROR); OCPlatform::sendResponse(pResponse); ehResult = OC_EH_ERROR; } } else { std::cout << "DeviceResource unsupported request flag" <<std::endl; } } else { std::cout << "Unsupported/invalid header options/values" << std::endl; } } return ehResult; }