replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / provisioning / examples / cloudWrapper.cpp
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 at
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
21 #include "logger.h"
22 #include "occloudprovisioning.h"
23 #include "OCCloudProvisioning.hpp"
24 #include "oic_malloc.h"
25 #include "oic_string.h"
26 #include "utils.h"
27
28 #define TAG "CLOUD-WRAPPER"
29
30 #define MAX_ID_LENGTH       (64)
31 #define MAX_STRING_LENGTH   (256)
32
33 #define UUID_EXAMPLE_1 "9cfbeb8e-5a1e-4d1c-9d01-2ae6fdb"
34 #define UUID_EXAMPLE_2 "123e4567-e89b-12d3-a456-4266554"
35 #define UUID_EXAMPLE_3 "987e6543-e21b-12d3-a456-4266554"
36 #define SUBJECT_ID_EXAMPLE "72616E64-5069-6E44-6576-557569643030"
37
38 #define ACL_ID_EXAMPLE "0f3d9f7fe5491d54077d"
39 #define ACE_ID_EXAMPLE "a0001"
40
41 #define ID_EXAMPLE_1   "78f98b4f25f21e2487e8"
42 #define ID_EXAMPLE_2   "6caa7009386290fd3681"
43
44 #define RESOURCE_URI_EXAMPLE "/a/light/0"
45 #define RESOURCE_TYPE_EXAMPLE "core.light"
46 #define INTERFACE_EXAMPLE "oic.if.baseline"
47
48 //in case of optional parameters absence should be sent NULL
49 #define OPTIONAL(str) (str[0] ? str : NULL)
50
51 using namespace OC;
52
53 /**
54  * Skip special characters from stdin
55  * */
56 static void skipSpecialCharacters()
57 {
58     for( ; 0x20<=getchar(); );  // for removing overflow garbages
59                                 // '0x20<=code' is character region
60 }
61
62 static bool readOptional(const char* description)
63 {
64     if (NULL == description)
65     {
66         return false;
67     }
68
69     printf("Do you want to Enter %s (y/n):\n", description);
70     char temp, choice = 0;
71
72     while(1)
73     {
74         for (int ret = 0; 1 != ret; )
75         {
76             ret = scanf("%c", &temp);
77             skipSpecialCharacters();
78         }
79
80         choice = temp;
81
82         switch (choice)
83         {
84             case 'y': return true;
85             case 'n': return false;
86             default: printf("Wrong value entered. Please press 'y' or 'n'\n");
87         }
88     }
89     return false;
90 }
91
92 /**
93  * Read user input (expect string value)
94  *
95  * @param[out] item           string item to fill
96  * @param[in] length          max allowed string length
97  * @param[in] description     item description
98  * @param[in] example         item example
99  */
100 void readString(char* item, int length, const char* description, const char* example)
101 {
102     char *input = (char*)OICCalloc(length, sizeof(char));
103     if (NULL == input)
104     {
105         OIC_LOG(INFO, TAG, "input is NULL");
106         return;
107     }
108
109     printf("Enter %s (f.e. %s):\n", description, example);
110     char temp[8] = { 0 };
111     snprintf(temp, sizeof(temp), "%%%ds", length - 1);
112
113     for (int ret = 0; 1 != ret; )
114     {
115         ret = scanf(temp, input);
116         skipSpecialCharacters();
117     }
118
119     strncpy(item, input, length);
120     OICFree(input);
121 }
122
123 /**
124  * Read user input (expect string value, but it is optional and can be skipped by user)
125  *
126  * @param[out] item           string item to fill
127  * @param[in] length          max allowed string length
128  * @param[in] description     item description
129  * @param[in] example         item example
130  */
131 static void readOptionalString(char* item, int length, const char* description, const char* example)
132 {
133     if (readOptional(description))
134     {
135         readString(item, length, description, example);
136     }
137 }
138
139 /**
140  * Read user input (expect integer value)
141  *
142  * @param[out] item           integer item to fill
143  * @param[in] description     item description
144  * @param[in] example         item example
145  */
146 void readInteger(int* item, const char* description, const char* example)
147 {
148     int temp;
149
150     printf("Enter %s (f.e. %s):\n", description, example);
151
152     for (int ret = 0; 1 != ret; )
153     {
154         ret = scanf("%d", &temp);
155         skipSpecialCharacters();
156     }
157
158     *item = temp;
159 }
160
161 /**
162  * Read user input (expect array of strings)
163  *
164  * @param[out] list           array of strings structure
165  * @param[in] length          max allowed array item length
166  * @param[in] description     whole array description
167  * @param[in] example         array item example
168  */
169 static void readStringArray(stringArray_t *list, int length, const char* description, const char* example)
170 {
171     int i = 0;
172     int count = 0;
173     char hint[MAX_STRING_LENGTH] = { 0 };
174
175     snprintf(hint, sizeof(hint), "%s items count", description);
176     readInteger(&count, hint, "2");
177
178     char **item = NULL;
179
180     if (0 >= count)
181     {
182         return;
183     }
184
185     item = (char**)OICCalloc(count, sizeof(char*));
186
187     if (NULL == item)
188     {
189         goto no_memory;
190     }
191
192     for (i = 0; i < count; i++)
193     {
194         item[i] = (char*)OICCalloc(length, sizeof(char));
195
196         if (NULL == item[i])
197         {
198             goto no_memory;
199         }
200
201         snprintf(hint, sizeof(hint), "%s %d item", description, i + 1);
202         readString(item[i], length, hint, example);
203     }
204     list->array  = item;
205     list->length = (size_t)count;
206     return;
207
208 no_memory:
209     //free already allocated memory here
210     for (int k = 0; k < i; k++)
211     {
212         OICFree(item[k]);
213     }
214     OICFree(item);
215 }
216
217 /**
218  * Read user input (expect array of strings)
219  * It is optional and can be skipped by user.
220  *
221  * @param[out] list           array of strings structure
222  * @param[in] length          max allowed array item length
223  * @param[in] description     whole array description
224  * @param[in] example         array item example
225  */
226 static void readOptionalStringArray(stringArray_t *list, int length, const char* description, const char* example)
227 {
228     if (readOptional(description))
229     {
230         readStringArray(list, length, description, example);
231     }
232 }
233
234 /**
235  * Copies whole binary file to crl variable
236  *
237  * @param[in] list           array of strings structure
238  * @param[out] crl           byte array to fill
239  * @return                   negative error code
240  * */
241 static int ReadFile(const char *name, OCByteString *crl)
242 {
243     FILE *file = NULL;
244     int length = 0;
245     uint8_t *buffer = NULL;
246     int result = 1;
247     size_t realLen = 0;
248
249     //Open file
250     file = fopen(name, "rb");
251     if (!file)
252     {
253         OIC_LOG_V(ERROR, TAG, "Unable to open file %s", name);
254         return result;
255     }
256
257     //Get file length
258     result = fseek(file, 0, SEEK_END);
259     if (result)
260     {
261         OIC_LOG(ERROR, TAG, "Failed to SEEK_END");
262         goto exit;
263     }
264
265     length = ftell(file);
266     if (length < 0)
267     {
268         OIC_LOG(ERROR, TAG, "Failed to ftell");
269         goto exit;
270     }
271
272     result = fseek(file, 0, SEEK_SET);
273     if (result)
274     {
275         OIC_LOG(ERROR, TAG, "Failed to SEEK_SET");
276         goto exit;
277     }
278
279     //Allocate memory
280     buffer = (uint8_t *)malloc(length);
281     if (!buffer)
282     {
283         OIC_LOG(ERROR, TAG, "Failed to allocate buffer");
284         goto exit;
285     }
286
287     //Read file contents into buffer
288     realLen = fread(buffer, length, 1, file);
289     if (realLen != (size_t)length)
290     {
291         OIC_LOG_V(ERROR, TAG, "Length mismatch: read %zu instead of %d bytes", realLen, length);
292         goto exit;
293     }
294
295     crl->bytes = buffer;
296     crl->len   = (size_t)length;
297
298     result = 0;
299 exit:
300     fclose(file);
301     return 0;
302 }
303
304 OCStackResult OCWrapperCertificateIssueRequest(OCCloudProvisioning& ptr, ResponseCallBack callback)
305 {
306     return ptr.requestCertificate(callback);
307 }
308
309 OCStackResult OCWrapperGetCRL(OCCloudProvisioning& ptr, ResponseCallBack callback)
310 {
311     return ptr.getCRL(callback);
312 }
313
314 OCStackResult OCWrapperPostCRL(OCCloudProvisioning& ptr, ResponseCallBack callback)
315 {
316     OCStackResult result = OC_STACK_ERROR;
317     OCByteString crlData = {0, 0};
318     char filename[64] = {0};
319     char thisUpdate[16] = { 0 };
320     char nextUpdate[16] = { 0 };
321     stringArray_t serialNumbers = {0, 0};
322     stringArray_t *rcsn = 0;
323     OCByteString *crl = 0;
324
325     readString(thisUpdate, sizeof(thisUpdate), "Crl's thisUpdate value", "20160727000000");
326     readString(nextUpdate, sizeof(nextUpdate), "Crl's nextUpdate value", "20161027000000");
327     readOptionalStringArray(&serialNumbers, 16, "Revoked serial numbers", "1234");
328
329     if (NULL == serialNumbers.array)
330     {
331         readString(filename, sizeof(filename),
332                    "filename from which binary Crl in DER format will be read", "crl");
333
334         if (ReadFile(filename, &crlData))
335         {
336             printf("Can't read crl from file %s\n", filename);
337             goto exit;
338         }
339     }
340     rcsn = serialNumbers.array? &serialNumbers : NULL;
341     crl = crlData.bytes? &crlData : NULL;
342
343     result = ptr.postCRL(thisUpdate, nextUpdate, crl, rcsn,
344                              callback);
345 exit:
346     clearStringArray(&serialNumbers);
347     OICFree(crlData.bytes);
348
349     return result;
350 }
351
352 OCStackResult OCWrapperAclIdGetByDevice(OCCloudProvisioning& ptr, AclIdResponseCallBack callback)
353 {
354     char di[MAX_ID_LENGTH] = { 0 };
355
356     readString(di, sizeof(di), "device id", UUID_EXAMPLE_1);
357
358     return ptr.getAclIdByDevice(di, callback);
359 }
360
361 OCStackResult OCWrapperAclIdCreate(const OCDevAddr *endPoint, OCCloudResponseCB callback)
362 {
363     char oid[MAX_ID_LENGTH]  = { 0 };
364     char di[MAX_ID_LENGTH]   = { 0 };
365
366     readString(oid, sizeof(oid), "owner id", UUID_EXAMPLE_2);
367     readString(di, sizeof(di), "device id", UUID_EXAMPLE_1);
368
369     return OCCloudAclIdCreate(NULL, oid, di, endPoint, callback);
370 }
371
372 OCStackResult OCWrapperAclIdDelete(const OCDevAddr *endPoint, OCCloudResponseCB callback)
373 {
374     char aclid[MAX_ID_LENGTH] = { 0 };
375
376     readString(aclid, sizeof(aclid), "acl id", ACL_ID_EXAMPLE);
377
378     return OCCloudAclIdDelete(NULL, aclid, endPoint, callback);
379 }
380
381 OCStackResult OCWrapperAclIndividualGetInfo(OCCloudProvisioning& ptr, ResponseCallBack callback)
382 {
383     char aclid[MAX_ID_LENGTH] = { 0 };
384
385     readString(aclid, sizeof(aclid), "acl id", ACL_ID_EXAMPLE);
386
387     return ptr.getIndividualAclInfo(aclid, callback);
388 }
389
390 OCStackResult OCWrapperAclIndividualUpdateAce(const OCDevAddr *endPoint, OCCloudResponseCB callback)
391 {
392     OCStackResult result = OC_STACK_NO_MEMORY;
393     int i = 0, j = 0;
394     cloudAce_t *aces = NULL;
395
396     char aclid[MAX_ID_LENGTH] = { 0 };
397     readString(aclid, sizeof(aclid), "ace id", ACL_ID_EXAMPLE);
398
399     int acllist_count = 0;
400     readInteger(&acllist_count, "acl list count", "1");
401     if (0 >= acllist_count)
402     {
403         OIC_LOG(ERROR, TAG, "Wrong number of aclList");
404         goto exit;
405     }
406
407     aces = (cloudAce_t*)OICCalloc(acllist_count, sizeof(cloudAce_t));
408     if (!aces)
409     {
410         OIC_LOG(ERROR, TAG, "Can't allocate memory for aces");
411         goto exit;
412     }
413
414     for (i = 0; i < acllist_count; i++)
415     {
416         cloudAce_t *ace = &aces[i];
417         if (i != acllist_count - 1) ace->next = &aces[i + 1];
418
419         char aceid[MAX_ID_LENGTH] = { 0 };
420         char subjectuuid[MAX_ID_LENGTH] = { 0 };
421         int stype = 0;
422         int permission = 0;
423
424         readString(aceid, sizeof(aceid), "ace id", ACE_ID_EXAMPLE);
425         readString(subjectuuid, sizeof(subjectuuid), "subjectuuid", SUBJECT_ID_EXAMPLE);
426         readInteger(&stype, "subject type", "0 â€“ Device, 1 â€“ User, 2 - Group");
427         readInteger(&permission, "permission", "6");
428
429         ace->aceId = OICStrdup(aceid);
430         ace->stype = stype;
431         ace->permission = permission;
432         memcpy(&ace->subjectuuid, subjectuuid, sizeof(OicUuid_t));
433
434         int reslist_count = 0;
435         readInteger(&reslist_count, "resources list count", "1");
436
437         ace->resources = (OicSecRsrc_t*)OICCalloc(reslist_count, sizeof(OicSecRsrc_t));
438         if (!ace->resources)
439         {
440             OIC_LOG(ERROR, TAG, "Can't allocate memory for resources");
441             goto exit;
442         }
443
444         for (j = 0; j < reslist_count; j++)
445         {
446             OicSecRsrc_t *res = &ace->resources[j];
447             if (j != reslist_count - 1) res->next = &ace->resources[j + 1];
448
449             char href[32] = { 0 };
450             readString(href, sizeof(href), "href", RESOURCE_URI_EXAMPLE);
451
452             stringArray_t rt = {0, 0};
453             readStringArray(&rt, MAX_ID_LENGTH, "resource type", RESOURCE_TYPE_EXAMPLE);
454
455             stringArray_t _if = {0, 0};
456             readStringArray(&_if, MAX_ID_LENGTH, "interface", INTERFACE_EXAMPLE);
457
458             res->href = OICStrdup(href);
459             res->types = rt.array;
460             res->typeLen = rt.length;
461             res->interfaces = _if.array;
462             res->interfaceLen = _if.length;
463         }
464     }
465
466     result = OCCloudAclIndividualUpdateAce(NULL, aclid, aces, endPoint, callback);
467 exit:
468     if (aces)
469     {
470         for (int k = 0; k < i; k++)
471         {
472             cloudAce_t *ace = &aces[k];
473             OICFree(ace->aceId);
474
475             if (ace->resources)
476             {
477                 for (int l = 0; l < j; l++)
478                 {
479                     OicSecRsrc_t *res = &ace->resources[l];
480                     OICFree(res->href);
481
482                     stringArray_t rt { res->types, res->typeLen};
483                     clearStringArray(&rt);
484
485                     stringArray_t _if {res->interfaces, res->interfaceLen};
486                     clearStringArray(&_if);
487                 }
488             }
489
490         }
491     }
492     return result;
493 }
494
495 OCStackResult OCWrapperAclIndividualDelete(const OCDevAddr *endPoint, OCCloudResponseCB callback)
496 {
497     char aclid[MAX_ID_LENGTH] = { 0 };
498
499     readString(aclid, sizeof(aclid), "acl id", ACL_ID_EXAMPLE);
500
501     return OCCloudAclIndividualDelete(NULL, aclid, endPoint, callback);
502 }
503
504 OCStackResult OCWrapperAclCreateGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
505 {
506     char gtype[16] = { 0 };
507     char gmid[MAX_ID_LENGTH] = { 0 };
508
509     readString(gtype, sizeof(gtype), "Group type value", "Public");
510     readOptionalString(gmid, sizeof(gmid), "group member id value", UUID_EXAMPLE_2);
511
512     return OCCloudAclCreateGroup(NULL, gtype, OPTIONAL(gmid), endPoint, callback);
513 }
514
515 OCStackResult OCWrapperAclFindMyGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
516 {
517     char mid[MAX_ID_LENGTH]  = { 0 };
518
519     readOptionalString(mid, sizeof(mid), "member id value", UUID_EXAMPLE_2);
520
521     return OCCloudAclFindMyGroup(NULL, OPTIONAL(mid), endPoint, callback);
522 }
523
524 OCStackResult OCWrapperAclDeleteGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
525 {
526     char gid[MAX_ID_LENGTH]  = { 0 };
527     char gmid[MAX_ID_LENGTH] = { 0 };
528
529     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
530
531     readOptionalString(gmid, sizeof(gmid), "group member id value", UUID_EXAMPLE_2);
532
533     return OCCloudAclDeleteGroup(NULL, gid, OPTIONAL(gmid), endPoint, callback);
534 }
535
536 OCStackResult OCWrapperAclJoinToInvitedGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
537 {
538     char gid[MAX_ID_LENGTH]  = { 0 };
539
540     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
541
542     return OCCloudAclJoinToInvitedGroup(NULL, gid, endPoint, callback);
543 }
544
545 OCStackResult OCWrapperAclObserveGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
546 {
547     char gid[MAX_ID_LENGTH]  = { 0 };
548
549     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
550
551     return OCCloudAclObserveGroup(NULL, gid, endPoint, callback);
552 }
553
554 OCStackResult OCWrapperAclShareDeviceIntoGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
555 {
556     OCStackResult result = OC_STACK_NO_MEMORY;
557     char gid[MAX_ID_LENGTH]  = { 0 };
558     stringArray_t midlist = {0,0};
559     stringArray_t dilist = {0,0};
560
561     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
562
563     readStringArray(&midlist, MAX_ID_LENGTH, "member id list", UUID_EXAMPLE_2);
564
565     readStringArray(&dilist, MAX_ID_LENGTH, "device list", UUID_EXAMPLE_1);
566
567     result = OCCloudAclShareDeviceIntoGroup(NULL, gid, &midlist, &dilist, endPoint, callback);
568
569     clearStringArray(&midlist);
570     clearStringArray(&dilist);
571
572     return result;
573 }
574
575 OCStackResult OCWrapperAclDeleteDeviceFromGroup(const OCDevAddr *endPoint, OCCloudResponseCB callback)
576 {
577     OCStackResult result = OC_STACK_NO_MEMORY;
578     char gid[MAX_ID_LENGTH]  = { 0 };
579     stringArray_t midlist = {0,0};
580     stringArray_t dilist = {0,0};
581
582     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
583
584     readStringArray(&midlist, MAX_ID_LENGTH, "member id list", UUID_EXAMPLE_2);
585
586     readStringArray(&dilist, MAX_ID_LENGTH, "device list", UUID_EXAMPLE_1);
587
588     result = OCCloudAclDeleteDeviceFromGroup(NULL, gid, &midlist, &dilist, endPoint, callback);
589
590     clearStringArray(&midlist);
591     clearStringArray(&dilist);
592
593     return result;
594 }
595
596 OCStackResult OCWrapperAclGroupGetInfo(const OCDevAddr *endPoint, OCCloudResponseCB callback)
597 {
598     char gid[MAX_ID_LENGTH]  = { 0 };
599     char mid[MAX_ID_LENGTH]  = { 0 };
600
601     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
602
603     readOptionalString(mid, sizeof(mid), "member id value", UUID_EXAMPLE_2);
604
605     return OCCloudAclGroupGetInfo(NULL, gid, OPTIONAL(mid), endPoint, callback);
606 }
607
608 OCStackResult OCWrapperAclInviteUser(const OCDevAddr *endPoint, OCCloudResponseCB callback)
609 {
610     OCStackResult result = OC_STACK_NO_MEMORY;
611     char uid[MAX_ID_LENGTH]  = { 0 };
612     stringArray_t midlist = {0,0};
613     stringArray_t gidlist = {0,0};
614
615     readOptionalString(uid, sizeof(uid), "user id value", UUID_EXAMPLE_2);
616
617     readStringArray(&gidlist, MAX_ID_LENGTH, "group id list", UUID_EXAMPLE_1);
618
619     readStringArray(&midlist, MAX_ID_LENGTH, "member id list", UUID_EXAMPLE_2);
620
621     result = OCCloudAclInviteUser(NULL, OPTIONAL(uid), &gidlist, &midlist, endPoint, callback);
622
623     clearStringArray(&midlist);
624     clearStringArray(&gidlist);
625
626     return result;
627 }
628
629 OCStackResult OCWrapperAclGetInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback)
630 {
631     char uid[MAX_ID_LENGTH]  = { 0 };
632
633     readOptionalString(uid, sizeof(uid), "user uuid value", UUID_EXAMPLE_2);
634
635     return OCCloudAclGetInvitation(NULL, OPTIONAL(uid), endPoint, callback);
636 }
637
638 OCStackResult OCWrapperAclDeleteInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback)
639 {
640     char uid[MAX_ID_LENGTH]  = { 0 };
641     char gid[MAX_ID_LENGTH]  = { 0 };
642
643     readOptionalString(uid, sizeof(uid), "user uuid value", UUID_EXAMPLE_2);
644     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
645
646     return OCCloudAclDeleteInvitation(NULL, OPTIONAL(uid), gid, endPoint, callback);
647 }
648
649 OCStackResult OCWrapperAclCancelInvitation(const OCDevAddr *endPoint, OCCloudResponseCB callback)
650 {
651     char uid[MAX_ID_LENGTH]  = { 0 };
652     char gid[MAX_ID_LENGTH]  = { 0 };
653     char mid[MAX_ID_LENGTH]  = { 0 };
654
655     readOptionalString(uid, sizeof(uid), "user uuid value", UUID_EXAMPLE_2);
656
657     readString(gid, sizeof(gid), "Group id value", ID_EXAMPLE_1);
658     readString(mid, sizeof(mid), "member id value", ID_EXAMPLE_1);
659
660     return OCCloudAclCancelInvitation(NULL, OPTIONAL(uid), gid, mid, endPoint, callback);
661 }
662
663 OCStackResult OCWrapperAclPolicyCheck(const OCDevAddr *endPoint, OCCloudResponseCB callback)
664 {
665     char sid[MAX_ID_LENGTH] = { 0 };
666     char di[MAX_ID_LENGTH]  = { 0 };
667     char rm[16]  = { 0 };
668     char user_uri[32] = { 0 };
669
670     readString(sid, sizeof(sid), "subject id", UUID_EXAMPLE_1);
671     readString(di, sizeof(di), "device id", UUID_EXAMPLE_2);
672     readString(rm, sizeof(rm), "request method", "GET or POST or DELETE");
673     readString(user_uri, sizeof(user_uri), "request uri", RESOURCE_URI_EXAMPLE);
674
675     return OCCloudAclPolicyCheck(NULL, sid, di, rm, user_uri, endPoint, callback);
676 }