1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include "rd_client.h"
24 #include "oic_string.h"
25 #include "oic_malloc.h"
26 #include "payload_logging.h"
28 #include "rdpayload.h"
29 #include "ocpayload.h"
31 #define DEFAULT_CONTEXT_VALUE 0x99
32 #define OC_RD_PUBLISH_TTL 86400
34 #define TAG PCF("RDClient")
36 static OCStackResult sendRequest(OCMethod method, char *uri, OCDevAddr *addr,
37 OCPayload *payload, OCCallbackData cbData)
42 result = OCDoResource(&handle,
53 if (result == OC_STACK_OK)
55 OC_LOG(DEBUG, TAG, "Resource Directory send successful...");
59 OC_LOG(ERROR, TAG, "Resource Directory send failed...");
65 static OCStackApplicationResult handlePublishCB(__attribute__((unused))void *ctx,
66 __attribute__((unused)) OCDoHandle handle,
67 __attribute__((unused)) OCClientResponse *clientResponse)
69 OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
70 OC_LOG(DEBUG, TAG, "Successfully published resources.");
72 if (OC_STACK_OK == OCStopMulticastServer())
74 OC_LOG_V(DEBUG, TAG, "Stopped receiving the multicast traffic.");
78 OC_LOG_V(DEBUG, TAG, "Failed stopping the multicast traffic.");
84 static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB clientCB)
86 OC_LOG_V(DEBUG, TAG, "\tAddress of the RD: %s:%d", clientResponse->devAddr.addr,
87 clientResponse->devAddr.port);
89 OCRDPayload *payload = (OCRDPayload *) clientResponse->payload;
90 OC_LOG_PAYLOAD(DEBUG, (OCPayload *) payload);
92 // TODO: Multiple Resource Directory will have different biasFactor,
93 // needs to cache here detail
94 // and after certain timeout then decide based on the biasFactor.
95 //if (biasFactor > 75)
98 clientCB(clientResponse->devAddr.addr, clientResponse->devAddr.port);
102 static OCStackApplicationResult handleDiscoverCB(void *ctx,
103 __attribute__((unused)) OCDoHandle handle, OCClientResponse *clientResponse)
105 OC_LOG(DEBUG, TAG, "Found Resource Directory");
106 OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
108 OCRDClientContextCB *cb = (OCRDClientContextCB *)ctx;
111 OC_LOG(ERROR, TAG, "RD Context Invalid Parameters.");
115 if (cb->context != (void *) DEFAULT_CONTEXT_VALUE)
117 OC_LOG(ERROR, TAG, "RD Context Invalid Context Value Parameters.");
121 OC_LOG_V(DEBUG, TAG, "Callback Context for DISCOVER query received successfully :%d.", clientResponse->result);
123 if (clientResponse && clientResponse->result == OC_STACK_OK)
125 retreiveRDDetails(clientResponse, cb->cbFunc);
129 OC_LOG(ERROR, TAG, "Discovery of RD Failed");
137 OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor)
141 OC_LOG(DEBUG, TAG, "No callback function specified.");
142 return OC_STACK_INVALID_CALLBACK;
145 /* Start a discovery query*/
146 char queryUri[MAX_URI_LENGTH] = { '\0' };
147 snprintf(queryUri, MAX_URI_LENGTH, "coap://%s%s", OC_MULTICAST_PREFIX, OC_RSRVD_RD_URI);
149 OC_LOG_V(DEBUG, TAG, "Querying RD: %s\n", queryUri);
151 OCRDClientContextCB *cbContext = (OCRDClientContextCB *)OICCalloc(1, sizeof(OCRDClientContextCB));
154 OC_LOG(ERROR, TAG, "Failed allocating memory.");
155 return OC_STACK_NO_MEMORY;
158 cbContext->context = (void *)DEFAULT_CONTEXT_VALUE;
159 cbContext->cbFunc = cbBiasFactor;
161 OCCallbackData cbData;
162 cbData.cb = handleDiscoverCB;
163 cbData.context = (void *)(cbContext);
166 return sendRequest(OC_REST_DISCOVER, queryUri, NULL, NULL, cbData);
169 static OCStackResult createStringLL(uint8_t numElements, OCResourceHandle handle,
170 const char* (*getValue)(OCResourceHandle handle, uint8_t i), OCStringLL **stringLL)
172 for (uint8_t i = 0; i < numElements; ++i)
174 const char *value = getValue(handle, i);
177 *stringLL = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
180 OC_LOG(ERROR, TAG, "Failed allocating memory.");
181 return OC_STACK_NO_MEMORY;
183 (*stringLL)->value = OICStrdup(value);
184 if (!(*stringLL)->value)
186 OC_LOG(ERROR, TAG, "Failed copying to OCStringLL.");
187 return OC_STACK_NO_MEMORY;
192 OCStringLL *cur = *stringLL;
197 cur->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
200 OC_LOG(ERROR, TAG, "Failed allocating memory.");
201 return OC_STACK_NO_MEMORY;
203 cur->next->value = OICStrdup(value);
204 if (!cur->next->value)
206 OC_LOG(ERROR, TAG, "Failed copying to OCStringLL.");
207 return OC_STACK_NO_MEMORY;
214 OCStackResult OCRDPublish(char *addr, uint16_t port, int numArg, ... )
218 OC_LOG(ERROR, TAG, "RD address not specified.");
219 return OC_STACK_INVALID_PARAM;
222 char targetUri[MAX_URI_LENGTH];
223 snprintf(targetUri, MAX_URI_LENGTH, "coap://%s:%d%s?rt=%s", addr, port,
224 OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
225 OC_LOG_V(DEBUG, TAG, "Target URI : %s", targetUri);
227 // Gather all resources locally and do publish
228 OCCallbackData cbData = { 0 };
229 cbData.cb = &handlePublishCB;
231 cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
233 OCTagsPayload *tagsPayload = NULL;
234 OCLinksPayload *linksPayload = NULL;
235 OCStringLL *rt = NULL;
236 OCStringLL *itf = NULL;
237 OCStringLL *mt = NULL;
239 OCRDPayload *rdPayload = OCRDPayloadCreate();
245 const unsigned char *id = (unsigned char*) OCGetServerInstanceIDString();
246 tagsPayload = OCCopyTagsResources(NULL, id,
247 NULL, OC_DISCOVERABLE, 0, 0, NULL, NULL, OC_RD_PUBLISH_TTL);
254 va_start (arguments, numArg);
256 for (int j = 0 ; j < numArg; j++)
258 OCResourceHandle handle = va_arg(arguments, OCResourceHandle);
261 rt = itf = mt = NULL;
262 const char *uri = OCGetResourceUri(handle);
264 if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement))
266 OCStackResult res = createStringLL(numElement, handle, OCGetResourceTypeName, &rt);
267 if (res != OC_STACK_OK || !rt)
274 if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement))
276 OCStackResult res = createStringLL(numElement, handle, OCGetResourceInterfaceName, &itf);
277 if (res != OC_STACK_OK || !itf)
284 mt = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
290 mt->value = OICStrdup("application/json");
299 linksPayload = OCCopyLinksResources(uri, rt, itf, NULL, 0, NULL,
308 OCLinksPayload *temp = linksPayload;
313 temp->next = OCCopyLinksResources(uri, rt, itf, NULL, 0, NULL,
320 OCFreeOCStringLL(rt);
321 OCFreeOCStringLL(itf);
322 OCFreeOCStringLL(mt);
327 rdPayload->rdPublish = OCCopyCollectionResource(tagsPayload, linksPayload);
328 if (!rdPayload->rdPublish)
333 OCDevAddr rdAddr = { 0 };
334 OICStrcpy(rdAddr.addr, MAX_ADDR_STR_SIZE, addr);
337 OC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
339 return sendRequest(OC_REST_POST, targetUri, &rdAddr, (OCPayload *)rdPayload, cbData);
342 OC_LOG(ERROR, TAG, "Failed allocating memory.");
343 OCFreeOCStringLL(rt);
344 OCFreeOCStringLL(itf);
345 OCFreeOCStringLL(mt);
346 OCFreeTagsResource(tagsPayload);
347 OCFreeLinksResource(linksPayload);
348 OCRDPayloadDestroy(rdPayload);
349 return OC_STACK_NO_MEMORY;