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 OIC_LOG(DEBUG, TAG, "Resource Directory send successful...");
59 OIC_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 OIC_LOG(DEBUG, TAG, "Successfully published resources.");
72 if (OC_STACK_OK == OCStopMulticastServer())
74 OIC_LOG_V(DEBUG, TAG, "Stopped receiving the multicast traffic.");
78 OIC_LOG_V(DEBUG, TAG, "Failed stopping the multicast traffic.");
84 static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB clientCB)
86 OIC_LOG_V(DEBUG, TAG, "\tAddress of the RD: %s:%d", clientResponse->devAddr.addr,
87 clientResponse->devAddr.port);
89 OIC_LOG_PAYLOAD(DEBUG, clientResponse->payload);
91 // TODO: Multiple Resource Directory will have different biasFactor,
92 // needs to cache here detail
93 // and after certain timeout then decide based on the biasFactor.
94 //if (biasFactor > 75)
97 clientCB(clientResponse->devAddr.addr, clientResponse->devAddr.port);
101 static OCStackApplicationResult handleDiscoverCB(void *ctx,
102 __attribute__((unused)) OCDoHandle handle, OCClientResponse *clientResponse)
104 OIC_LOG(DEBUG, TAG, "Found Resource Directory");
105 OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
107 OCRDClientContextCB *cb = (OCRDClientContextCB *)ctx;
110 OIC_LOG(ERROR, TAG, "RD Context Invalid Parameters.");
114 if (cb->context != (void *) DEFAULT_CONTEXT_VALUE)
116 OIC_LOG(ERROR, TAG, "RD Context Invalid Context Value Parameters.");
122 OIC_LOG_V(DEBUG, TAG, "Callback Context for DISCOVER query received successfully :%d.", clientResponse->result);
123 if (clientResponse->result == OC_STACK_OK)
125 retreiveRDDetails(clientResponse, cb->cbFunc);
129 OIC_LOG(ERROR, TAG, "Discovery of RD Failed");
134 OIC_LOG(ERROR, TAG, "No client response.");
142 OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor)
146 OIC_LOG(DEBUG, TAG, "No callback function specified.");
147 return OC_STACK_INVALID_CALLBACK;
150 /* Start a discovery query*/
151 char queryUri[MAX_URI_LENGTH] = { '\0' };
152 snprintf(queryUri, MAX_URI_LENGTH, "coap://%s%s", OC_MULTICAST_PREFIX, OC_RSRVD_RD_URI);
154 OIC_LOG_V(DEBUG, TAG, "Querying RD: %s\n", queryUri);
156 OCRDClientContextCB *cbContext = (OCRDClientContextCB *)OICCalloc(1, sizeof(OCRDClientContextCB));
159 OIC_LOG(ERROR, TAG, "Failed allocating memory.");
160 return OC_STACK_NO_MEMORY;
163 cbContext->context = (void *)DEFAULT_CONTEXT_VALUE;
164 cbContext->cbFunc = cbBiasFactor;
166 OCCallbackData cbData;
167 cbData.cb = handleDiscoverCB;
168 cbData.context = (void *)(cbContext);
171 return sendRequest(OC_REST_DISCOVER, queryUri, NULL, NULL, cbData);
174 static OCStackResult createStringLL(uint8_t numElements, OCResourceHandle handle,
175 const char* (*getValue)(OCResourceHandle handle, uint8_t i), OCStringLL **stringLL)
177 for (uint8_t i = 0; i < numElements; ++i)
179 const char *value = getValue(handle, i);
182 *stringLL = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
185 OIC_LOG(ERROR, TAG, "Failed allocating memory.");
186 return OC_STACK_NO_MEMORY;
188 (*stringLL)->value = OICStrdup(value);
189 if (!(*stringLL)->value)
191 OIC_LOG(ERROR, TAG, "Failed copying to OCStringLL.");
192 return OC_STACK_NO_MEMORY;
197 OCStringLL *cur = *stringLL;
202 cur->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
205 OIC_LOG(ERROR, TAG, "Failed allocating memory.");
206 return OC_STACK_NO_MEMORY;
208 cur->next->value = OICStrdup(value);
209 if (!cur->next->value)
211 OIC_LOG(ERROR, TAG, "Failed copying to OCStringLL.");
212 return OC_STACK_NO_MEMORY;
219 OCStackResult OCRDPublish(char *addr, uint16_t port, int numArg, ... )
223 OIC_LOG(ERROR, TAG, "RD address not specified.");
224 return OC_STACK_INVALID_PARAM;
227 char targetUri[MAX_URI_LENGTH];
228 snprintf(targetUri, MAX_URI_LENGTH, "coap://%s:%d%s?rt=%s", addr, port,
229 OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
230 OIC_LOG_V(DEBUG, TAG, "Target URI : %s", targetUri);
232 // Gather all resources locally and do publish
233 OCCallbackData cbData = { 0 };
234 cbData.cb = &handlePublishCB;
236 cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
238 OCTagsPayload *tagsPayload = NULL;
239 OCLinksPayload *linksPayload = NULL;
240 OCStringLL *rt = NULL;
241 OCStringLL *itf = NULL;
242 OCStringLL *mt = NULL;
244 OCRDPayload *rdPayload = OCRDPayloadCreate();
250 const unsigned char *id = (unsigned char*) OCGetServerInstanceIDString();
251 tagsPayload = OCCopyTagsResources(NULL, id,
252 NULL, OC_DISCOVERABLE, 0, 0, NULL, NULL, OC_RD_PUBLISH_TTL);
259 va_start (arguments, numArg);
261 for (int j = 0 ; j < numArg; j++)
263 OCResourceHandle handle = va_arg(arguments, OCResourceHandle);
266 rt = itf = mt = NULL;
267 const char *uri = OCGetResourceUri(handle);
269 if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement))
271 OCStackResult res = createStringLL(numElement, handle, OCGetResourceTypeName, &rt);
272 if (res != OC_STACK_OK || !rt)
278 if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement))
280 OCStackResult res = createStringLL(numElement, handle, OCGetResourceInterfaceName, &itf);
281 if (res != OC_STACK_OK || !itf)
287 mt = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
292 mt->value = OICStrdup("application/json");
300 linksPayload = OCCopyLinksResources(uri, rt, itf, NULL, 0, NULL,
309 OCLinksPayload *temp = linksPayload;
314 temp->next = OCCopyLinksResources(uri, rt, itf, NULL, 0, NULL,
321 OCFreeOCStringLL(rt);
322 OCFreeOCStringLL(itf);
323 OCFreeOCStringLL(mt);
328 rdPayload->rdPublish = OCCopyCollectionResource(tagsPayload, linksPayload);
329 if (!rdPayload->rdPublish)
334 OCTagsLog(DEBUG, rdPayload->rdPublish->tags);
335 OCLinksLog(DEBUG, rdPayload->rdPublish->setLinks);
337 OCDevAddr rdAddr = { 0 };
338 OICStrcpy(rdAddr.addr, MAX_ADDR_STR_SIZE, addr);
341 OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
343 return sendRequest(OC_REST_POST, targetUri, &rdAddr, (OCPayload *)rdPayload, cbData);
346 OIC_LOG(ERROR, TAG, "Failed allocating memory.");
350 OCFreeOCStringLL(rt);
354 OCFreeOCStringLL(itf);
358 OCFreeOCStringLL(mt);
362 OCFreeTagsResource(tagsPayload);
366 OCFreeLinksResource(linksPayload);
368 OCRDPayloadDestroy(rdPayload);
369 return OC_STACK_NO_MEMORY;