[IOT-1612] Fix OCRDPublishWithDeviceId() to publish with a specific id
[platform/upstream/iotivity.git] / resource / csdk / resource-directory / src / rd_client.c
1 //******************************************************************
2 //
3 // Copyright 2016 Samsung Electronics 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 a
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 #include "rd_client.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27 #include "octypes.h"
28 #include "ocstack.h"
29 #include "ocpayload.h"
30 #include "payload_logging.h"
31
32 #define TAG "RD_CLIENT"
33
34 #ifdef RD_CLIENT
35
36 OCStackResult OCRDDiscover(OCConnectivityType connectivityType, OCCallbackData *cbBiasFactor,
37                            OCQualityOfService qos)
38 {
39     if (!cbBiasFactor || !cbBiasFactor->cb)
40     {
41         OIC_LOG(DEBUG, TAG, "No callback function specified.");
42         return OC_STACK_INVALID_CALLBACK;
43     }
44
45     /* Start a discovery query*/
46     char queryUri[MAX_URI_LENGTH] = { '\0' };
47     snprintf(queryUri, MAX_URI_LENGTH, "coap://%s%s", OC_MULTICAST_PREFIX, OC_RSRVD_RD_URI);
48     OIC_LOG_V(DEBUG, TAG, "Querying RD: %s\n", queryUri);
49
50     return OCDoResource(NULL, OC_REST_DISCOVER, queryUri, NULL, NULL, connectivityType, qos,
51                         cbBiasFactor, NULL, 0);
52 }
53
54 OCStackResult OCRDPublish(const char *host, OCConnectivityType connectivityType,
55                           OCResourceHandle *resourceHandles, uint8_t nHandles,
56                           OCCallbackData *cbData, OCQualityOfService qos)
57 {
58     // Validate input parameters.
59     if (!host)
60     {
61         return OC_STACK_INVALID_IP;
62     }
63
64     if (!cbData || !cbData->cb)
65     {
66         return OC_STACK_INVALID_CALLBACK;
67     }
68
69     // Get Device ID from stack.
70     const unsigned char *id = (const unsigned char *) OCGetServerInstanceIDString();
71
72     return OCRDPublishWithDeviceId(host, id, connectivityType, resourceHandles, nHandles,
73                                    cbData, qos);
74 }
75
76 OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id,
77                                       OCConnectivityType connectivityType,
78                                       OCResourceHandle *resourceHandles, uint8_t nHandles,
79                                       OCCallbackData *cbData, OCQualityOfService qos)
80 {
81     // Validate input parameters.
82     if (!host || !cbData || !cbData->cb || !id)
83     {
84         return OC_STACK_INVALID_CALLBACK;
85     }
86
87     OIC_LOG_V(DEBUG, TAG, "Publish Resource to RD with device id [%s]", id);
88
89     OCResourceHandle *pubResHandle = resourceHandles;
90     OCResourceHandle defaultResHandles[OIC_RD_DEFAULT_RESOURCE] = { 0 };
91     uint8_t nPubResHandles = nHandles;
92
93     // if resource handles is null, "/oic/p" and "/oic/d" resource will be published to RD.
94     if (!pubResHandle)
95     {
96         // get "/oic/d" and "/oic/p" resource handle from stack.
97         defaultResHandles[0] = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
98         defaultResHandles[1] = OCGetResourceHandleAtUri(OC_RSRVD_PLATFORM_URI);
99
100         for (uint8_t j = 0; j < OIC_RD_DEFAULT_RESOURCE; j++)
101         {
102             if (defaultResHandles[j])
103             {
104                 OIC_LOG_V(DEBUG, TAG, "Add virtual resource(%s) to resource handle list",
105                           OCGetResourceUri(defaultResHandles[j]));
106             }
107         }
108
109         pubResHandle = defaultResHandles;
110         nPubResHandles = OIC_RD_DEFAULT_RESOURCE;
111     }
112
113     char targetUri[MAX_URI_LENGTH] = { 0 };
114     snprintf(targetUri, MAX_URI_LENGTH, "%s%s?rt=%s", host,
115              OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
116     OIC_LOG_V(DEBUG, TAG, "Target URI: %s", targetUri);
117
118     OCRepPayload *rdPayload =  (OCRepPayload *)OCRepPayloadCreate();
119     if (!rdPayload)
120     {
121         return OC_STACK_NO_MEMORY;
122     }
123
124     OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_ID, id);
125     OCRepPayloadSetPropInt(rdPayload, OC_RSRVD_DEVICE_TTL, OIC_RD_PUBLISH_TTL);
126
127     OCRepPayload **linkArr = OICCalloc(nPubResHandles, sizeof(OCRepPayload *));
128     if (!linkArr)
129     {
130        OCRepPayloadDestroy(rdPayload);
131        return OC_STACK_NO_MEMORY;
132     }
133     size_t dimensions[MAX_REP_ARRAY_DEPTH] = {nPubResHandles, 0, 0};
134
135     for (uint8_t j = 0; j < nPubResHandles; j++)
136     {
137         OCResourceHandle handle = pubResHandle[j];
138         if (handle)
139         {
140             OCRepPayload *link = OCRepPayloadCreate();
141
142             const char *uri = OCGetResourceUri(handle);
143             if (uri)
144             {
145                 OCRepPayloadSetPropString(link, OC_RSRVD_HREF, uri);
146             }
147
148             uint8_t numElement = 0;
149             if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement))
150             {
151                 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
152                 char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
153                 for (uint8_t i = 0; i < numElement; ++i)
154                 {
155                     const char *value = OCGetResourceTypeName(handle, i);
156                     OIC_LOG_V(DEBUG, TAG, "value: %s", value);
157                     rt[i] = OICStrdup(value);
158                 }
159                 OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
160             }
161
162             numElement = 0;
163             if (OC_STACK_OK == OCGetNumberOfResourceInterfaces(handle, &numElement))
164             {
165                 size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
166                 char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
167                 for (uint8_t i = 0; i < numElement; ++i)
168                 {
169                     const char *value = OCGetResourceInterfaceName(handle, i);
170                     OIC_LOG_V(DEBUG, TAG, "value: %s", value);
171                     itf[i] = OICStrdup(value);
172                 }
173                 OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_INTERFACE, itf, ifDim);
174             }
175
176             uint8_t ins = 0;
177             if (OC_STACK_OK == OCGetResourceIns(handle, &ins))
178             {
179                 OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins);
180             }
181
182             size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
183             char **mediaType = (char **)OICMalloc(sizeof(char *) * 1);
184             if (!mediaType)
185             {
186                 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
187
188                 for(uint8_t i = 0; i < nPubResHandles; i++)
189                 {
190                     OCRepPayloadDestroy(linkArr[i]);
191                 }
192                 OICFree(linkArr);
193                 OCRepPayloadDestroy(rdPayload);
194                 return OC_STACK_NO_MEMORY;
195             }
196
197             mediaType[0] = OICStrdup(DEFAULT_MESSAGE_TYPE);
198             OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_MEDIA_TYPE, mediaType, mtDim);
199
200             OCResourceProperty p = OCGetResourceProperties(handle);
201             p = (OCResourceProperty) ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE));
202             OCRepPayload *policy = OCRepPayloadCreate();
203             OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, p);
204             OCRepPayloadSetPropObjectAsOwner(link, OC_RSRVD_POLICY, policy);
205
206             linkArr[j] = link;
207         }
208     }
209
210     OCRepPayloadSetPropObjectArray(rdPayload, OC_RSRVD_LINKS, (const OCRepPayload **)linkArr, dimensions);
211     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
212
213     for (uint8_t i = 0; i < nPubResHandles; i++)
214     {
215         OCRepPayloadDestroy(linkArr[i]);
216     }
217     OICFree(linkArr);
218
219     return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)rdPayload,
220                         connectivityType, qos, cbData, NULL, 0);
221 }
222
223 OCStackResult OCRDDelete(const char *host, OCConnectivityType connectivityType,
224                          OCResourceHandle *resourceHandles, uint8_t nHandles,
225                          OCCallbackData *cbData, OCQualityOfService qos)
226 {
227     // Validate input parameters
228     if (!host)
229     {
230         return OC_STACK_INVALID_IP;
231     }
232
233     if (!cbData || !cbData->cb)
234     {
235         return OC_STACK_INVALID_CALLBACK;
236     }
237
238     const unsigned char *id = (const unsigned char *) OCGetServerInstanceIDString();
239
240     return OCRDDeleteWithDeviceId(host, id, connectivityType, resourceHandles, nHandles,
241                                   cbData, qos);
242 }
243
244 OCStackResult OCRDDeleteWithDeviceId(const char *host, const unsigned char *id,
245                                      OCConnectivityType connectivityType,
246                                      OCResourceHandle *resourceHandles, uint8_t nHandles,
247                                      OCCallbackData *cbData, OCQualityOfService qos)
248 {
249     // Validate input parameters
250     if (!host || !cbData || !cbData->cb || !id)
251     {
252         return OC_STACK_INVALID_CALLBACK;
253     }
254
255     OIC_LOG_V(DEBUG, TAG, "Delete Resource to RD with device id [%s]", id);
256
257     char targetUri[MAX_URI_LENGTH] = { 0 };
258     snprintf(targetUri, MAX_URI_LENGTH, "%s%s?di=%s", host, OC_RSRVD_RD_URI, id);
259
260     uint8_t len = 0;
261     char queryParam[MAX_URI_LENGTH] = { 0 };
262     for (uint8_t j = 0; j < nHandles; j++)
263     {
264         OCResource *handle = (OCResource *) resourceHandles[j];
265         uint8_t ins = 0;
266         OCGetResourceIns(handle, &ins);
267         len += snprintf(queryParam + len, MAX_URI_LENGTH, "&ins=%d", ins);
268         OIC_LOG_V(DEBUG, TAG, "queryParam [%s]", queryParam);
269     }
270
271     OICStrcatPartial(targetUri, sizeof(targetUri), queryParam, strlen(queryParam));
272     OIC_LOG_V(DEBUG, TAG, "Target URI: %s", targetUri);
273
274     return OCDoResource(NULL, OC_REST_DELETE, targetUri, NULL, NULL, connectivityType,
275                         qos, cbData, NULL, 0);
276 }
277
278 #endif