replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / ocremoteaccessclient.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH 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 <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <iostream>
27 #include <sstream>
28 #include "ocstack.h"
29 #include "logger.h"
30 #include "ocpayload.h"
31 #include "payload_logging.h"
32 #include "ocremoteaccessclient.h"
33 #include "common.h"
34
35 #define SET_BUT_NOT_USED(x) (void) x
36 // Tracking user input
37 static int TEST_CASE = 0;
38
39 static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
40
41 static std::string coapServerIP = "255.255.255.255";
42 static std::string coapServerPort = "5683";
43 static std::string coapServerResource = "/a/light";
44 static OCDevAddr responseAddr;
45 //Use ipv4addr for both InitDiscovery and InitPlatformOrDeviceDiscovery
46 char remoteServerJabberID[MAX_ADDR_STR_SIZE];
47 static uint16_t maxNotification = 15;
48
49 // The handle for the observe registration
50 OCDoHandle gObserveDoHandle;
51 #ifdef WITH_PRESENCE
52 // The handle for observe registration
53 OCDoHandle gPresenceHandle;
54 #endif
55 // After this crosses a threshold client deregisters for further notifications
56 int gNumObserveNotifies = 0;
57
58 #ifdef WITH_PRESENCE
59 int gNumPresenceNotifies = 0;
60 #endif
61
62 int gQuitFlag = 0;
63 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
64 void handleSigInt(int signum)
65 {
66     if (signum == SIGINT)
67     {
68         gQuitFlag = 1;
69     }
70 }
71
72 OCPayload* putPayload()
73 {
74     OCRepPayload* payload = OCRepPayloadCreate();
75
76     if(!payload)
77     {
78         std::cout << "Failed to create put payload object"<<std::endl;
79         std::exit(1);
80     }
81     OCRepPayloadSetPropInt(payload, "power", 42);
82     OCRepPayloadSetPropBool(payload, "state", true);
83     return (OCPayload*) payload;
84 }
85
86 static void PrintUsage()
87 {
88     OIC_LOG(INFO, TAG, "This sample makes all requests via the remote access adapter");
89     OIC_LOG(INFO, TAG, "Usage : ocremoteaccessclient -t <number>");
90     OIC_LOG(INFO, TAG, "-t 1  :  Discover Resources");
91     OIC_LOG(INFO, TAG, "-t 2  :  Discover & Get");
92     OIC_LOG(INFO, TAG, "-t 3  :  Discover & Put");
93     OIC_LOG(INFO, TAG, "-t 4  :  Discover & Post");
94     OIC_LOG(INFO, TAG, "-t 5  :  Discover & Delete");
95     OIC_LOG(INFO, TAG, "-t 6  :  Discover & Observe");
96     OIC_LOG(INFO, TAG, "-t 7  :  Discover & Observe then cancel immediately with High QOS");
97 }
98
99 OCStackResult InvokeOCDoResource(std::ostringstream &query,
100                                  OCMethod method,
101                                  OCQualityOfService qos,
102                                  OCClientResponseHandler cb,
103                                  OCHeaderOption * options,
104                                  uint8_t numOptions)
105 {
106     OCCallbackData cbData;
107     OCDoHandle handle;
108
109     cbData.cb       = cb;
110     cbData.context  = (void*)DEFAULT_CONTEXT_VALUE;
111     cbData.cd       = NULL;
112
113     OCPayload* payload = (method == OC_REST_PUT) ? putPayload() : NULL;
114
115     OCStackResult ret = OCDoRequest(&handle,
116                                     method,
117                                     query.str().c_str(),
118                                     &responseAddr,
119                                     payload,
120                                     CT_ADAPTER_REMOTE_ACCESS,
121                                     qos,
122                                     &cbData,
123                                     options,
124                                     numOptions);
125
126     OCPayloadDestroy(payload);
127
128     if (ret != OC_STACK_OK)
129     {
130         OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
131     }
132     else if (method == OC_REST_OBSERVE || method == OC_REST_OBSERVE_ALL)
133     {
134         gObserveDoHandle = handle;
135     }
136 #ifdef WITH_PRESENCE
137     else if (method == OC_REST_PRESENCE)
138     {
139         gPresenceHandle = handle;
140     }
141 #endif
142
143     return ret;
144 }
145
146 OCStackApplicationResult restRequestCB(void* ctx,
147         OCDoHandle handle, OCClientResponse * clientResponse)
148 {
149     if(clientResponse == NULL)
150     {
151         OIC_LOG(INFO, TAG, "Received NULL response");
152         return   OC_STACK_DELETE_TRANSACTION;
153     }
154     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
155     {
156         OIC_LOG(INFO, TAG, "Callback Context recvd successfully");
157     }
158
159     OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
160     OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
161     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
162
163     if(clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
164     {
165         OIC_LOG (INFO, TAG, "Received vendor specific options. Ignoring");
166     }
167     SET_BUT_NOT_USED(handle);
168     return OC_STACK_DELETE_TRANSACTION;
169 }
170
171 OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
172 {
173     if(!clientResponse)
174     {
175         OIC_LOG_V(INFO, TAG, "obsReqCB received NULL response");
176     }
177     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
178     {
179         OIC_LOG(INFO, TAG, "Callback Context recvd successfully");
180     }
181     OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
182     OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
183     OIC_LOG_V(INFO, TAG, "OBSERVE notification %d recvd", gNumObserveNotifies);
184     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
185
186     gNumObserveNotifies++;
187     if (gNumObserveNotifies == maxNotification)
188     {
189         if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
190         {
191             OIC_LOG(ERROR, TAG, "Observe cancel error");
192         }
193         return OC_STACK_DELETE_TRANSACTION;
194     }
195     if (gNumObserveNotifies == 1 && TEST_CASE == TEST_OBS_REQ_NON_CANCEL_IMM)
196     {
197         if (OCCancel (gObserveDoHandle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK)
198         {
199             OIC_LOG(ERROR, TAG, "Observe cancel error");
200         }
201     }
202     if(clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
203     {
204         OIC_LOG(INFO, TAG, "Registration confirmed");
205     }
206     else if(clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
207     {
208         OIC_LOG(INFO, TAG, "de-registration confirmed");
209         return OC_STACK_DELETE_TRANSACTION;
210     }
211     else if(clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
212     {
213         OIC_LOG(INFO, TAG, "Registration/deregistration failed");
214         return OC_STACK_DELETE_TRANSACTION;
215     }
216
217     SET_BUT_NOT_USED(handle);
218     return OC_STACK_KEEP_TRANSACTION;
219 }
220 #ifdef WITH_PRESENCE
221 OCStackApplicationResult presenceCB(void* ctx,
222         OCDoHandle handle, OCClientResponse * clientResponse)
223 {
224     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
225     {
226         OIC_LOG(INFO, TAG, "Callback Context recvd successfully");
227     }
228
229     if (clientResponse)
230     {
231         OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
232         OIC_LOG_V(INFO, TAG, "NONCE NUMBER: %u", clientResponse->sequenceNumber);
233         OIC_LOG_V(INFO, TAG, "PRESENCE notification %d recvd", gNumPresenceNotifies);
234         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
235
236         gNumPresenceNotifies++;
237         if (gNumPresenceNotifies == maxNotification)
238         {
239             if (OCCancel(gPresenceHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
240             {
241                 OIC_LOG(ERROR, TAG, "Presence cancel error");
242             }
243             return OC_STACK_DELETE_TRANSACTION;
244         }
245     }
246     else
247     {
248         OIC_LOG_V(INFO, TAG, "presenceCB received Null clientResponse");
249     }
250     SET_BUT_NOT_USED(handle);
251     return OC_STACK_KEEP_TRANSACTION;
252 }
253 #endif
254
255 // This is a function called back when a device is discovered
256 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
257         OCClientResponse * clientResponse)
258 {
259     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
260     {
261         OIC_LOG(INFO, TAG, "DISCOVER  callback recvd");
262     }
263
264     if (!clientResponse)
265     {
266         OIC_LOG_V(INFO, TAG, "discoveryReqCB received Null clientResponse");
267     }
268
269     OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
270     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
271
272     responseAddr = clientResponse->devAddr;
273
274     switch(TEST_CASE)
275     {
276         OIC_LOG_V(INFO, TAG, "TEST_CASE %u\n", TEST_CASE);
277         case TEST_GET_REQ_NON:
278             InitGetRequest(OC_LOW_QOS);
279             break;
280         case TEST_PUT_REQ_NON:
281             InitPutRequest(OC_LOW_QOS);
282             break;
283         case TEST_POST_REQ_NON:
284             InitPostRequest(OC_LOW_QOS);
285             break;
286         case TEST_DELETE_REQ_NON:
287             InitDeleteRequest(OC_LOW_QOS);
288             break;
289         case TEST_OBS_REQ_NON:
290         case TEST_OBS_REQ_NON_CANCEL_IMM:
291             InitObserveRequest(OC_LOW_QOS);
292             break;
293         default:
294             PrintUsage();
295             break;
296     }
297     SET_BUT_NOT_USED(handle);
298     return OC_STACK_KEEP_TRANSACTION;
299 }
300
301 OCStackApplicationResult PlatformDiscoveryReqCB (void* ctx, OCDoHandle handle,
302                 OCClientResponse * clientResponse)
303 {
304     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
305     {
306         OIC_LOG(INFO, TAG, "Callback Context for Platform DISCOVER query recvd successfully");
307     }
308
309     if(clientResponse)
310     {
311         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
312     }
313     else
314     {
315         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
316     }
317
318     SET_BUT_NOT_USED(handle);
319     return OC_STACK_DELETE_TRANSACTION;
320 }
321
322 OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle handle,
323         OCClientResponse * clientResponse)
324 {
325     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
326     {
327         OIC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully");
328     }
329
330     if(clientResponse)
331     {
332         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
333     }
334     else
335     {
336         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
337     }
338
339     SET_BUT_NOT_USED(handle);
340     return OC_STACK_DELETE_TRANSACTION;
341 }
342
343 int InitObserveRequest(OCQualityOfService qos)
344 {
345     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
346     std::ostringstream query;
347     query << coapServerResource;
348     return (InvokeOCDoResource(query,
349             OC_REST_OBSERVE, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
350 }
351
352 int InitPutRequest(OCQualityOfService qos)
353 {
354     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
355     std::ostringstream query;
356     query << coapServerResource;
357     return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
358             restRequestCB, NULL, 0));
359 }
360
361 int InitPostRequest(OCQualityOfService qos)
362 {
363     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
364     std::ostringstream query;
365     query << coapServerResource;
366     // First POST operation (to create an Light instance)
367     OCStackResult result = InvokeOCDoResource(query, OC_REST_POST,
368                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
369                                restRequestCB, NULL, 0);
370     if (OC_STACK_OK != result)
371     {
372         // Error can happen if for example, network connectivity is down
373         OIC_LOG(INFO, TAG, "First POST call did not succeed");
374     }
375
376     // Second POST operation (to create an Light instance)
377     result = InvokeOCDoResource(query, OC_REST_POST,
378                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
379                                restRequestCB, NULL, 0);
380     if (OC_STACK_OK != result)
381     {
382         OIC_LOG(INFO, TAG, "Second POST call did not succeed");
383     }
384
385     // This POST operation will update the original resourced /a/light
386     return (InvokeOCDoResource(query, OC_REST_POST,
387                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
388                                restRequestCB, NULL, 0));
389 }
390
391 int InitDeleteRequest(OCQualityOfService qos)
392 {
393     std::ostringstream query;
394     query << coapServerResource;
395     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
396
397     // First DELETE operation
398     OCStackResult result = InvokeOCDoResource(query, OC_REST_DELETE,
399                                qos,
400                                restRequestCB, NULL, 0);
401     if (OC_STACK_OK != result)
402     {
403         // Error can happen if for example, network connectivity is down
404         OIC_LOG(INFO, TAG, "DELETE call did not succeed");
405     }
406     return result;
407 }
408
409 int InitGetRequest(OCQualityOfService qos)
410 {
411     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
412     std::ostringstream query;
413     query << coapServerResource;
414     return (InvokeOCDoResource(query, OC_REST_GET,
415                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, restRequestCB, NULL, 0));
416 }
417
418 int InitDiscovery(OCQualityOfService qos)
419 {
420     OCCallbackData cbData;
421     cbData.cb       = discoveryReqCB;
422     cbData.context  = (void*)DEFAULT_CONTEXT_VALUE;
423     cbData.cd       = NULL;
424
425     OCDevAddr dest;
426     dest.adapter    = OC_ADAPTER_REMOTE_ACCESS;
427     dest.flags      = OC_DEFAULT_FLAGS;
428     strncpy (dest.addr, remoteServerJabberID, MAX_ADDR_STR_SIZE - 1);
429
430     OCStackResult ret = OCDoRequest(NULL,
431                                     OC_REST_GET,
432                                     MULTICAST_RESOURCE_DISCOVERY_QUERY,
433                                     &dest,
434                                     NULL,
435                                     CT_ADAPTER_REMOTE_ACCESS,
436                                     (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
437                                     &cbData,
438                                     NULL,
439                                     0);
440
441     if (ret != OC_STACK_OK)
442     {
443         OIC_LOG_V(ERROR, TAG, "Error %u in OCDoResource with discovery", ret);
444     }
445     return ret;
446 }
447
448 static void jidbound(char *jid)
449 {
450     OIC_LOG_V(INFO, TAG, "\n\n    Bound JID: %s\n\n", jid);
451 }
452
453 int main(int argc, char* argv[])
454 {
455     char host[] = "localhost";
456     char user[] = "test1";
457     char pass[] = "intel123";
458     char empstr[] = "";
459     OCRAInfo_t rainfo = {};
460
461     rainfo.hostname = host;
462     rainfo.port = 5222;
463     rainfo.xmpp_domain = host;
464     rainfo.username = user;
465     rainfo.password = pass;
466     rainfo.resource = empstr;
467     rainfo.user_jid = empstr;
468     rainfo.jidbound = jidbound;
469
470     int opt = 0;
471     while ((opt = getopt(argc, argv, "t:s:p:d:u:w:r:j:")) != -1)
472     {
473         switch(opt)
474         {
475             case 't':
476                 TEST_CASE = atoi(optarg);
477                 break;
478             case 's':
479                 rainfo.hostname = optarg;
480                 break;
481             case 'p':
482                 rainfo.port = atoi(optarg);
483                 break;
484             case 'd':
485                 rainfo.xmpp_domain = optarg;
486                 break;
487             case 'u':
488                 rainfo.username = optarg;
489                 break;
490             case 'w':
491                 rainfo.password = optarg;
492                 break;
493             case 'j':
494                 rainfo.user_jid = optarg;
495                 break;
496             case 'r':
497                 rainfo.resource = optarg;
498                 break;
499             default:
500                 PrintUsage();
501                 return -1;
502         }
503     }
504
505     if (OCSetRAInfo(&rainfo) != OC_STACK_OK)
506     {
507         OIC_LOG(ERROR, TAG, "Error initiating remote access adapter");
508         return 0;
509     }
510
511     if ((TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS))
512     {
513         PrintUsage();
514         return -1;
515     }
516
517     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
518     {
519         OIC_LOG(ERROR, TAG, "OCStack init error");
520         return 0;
521     }
522
523     OIC_LOG(INFO, TAG, "Enter JID of remote server");
524     if (fgets(remoteServerJabberID, MAX_ADDR_STR_SIZE, stdin))
525     {
526         StripNewLineChar(remoteServerJabberID);
527     }
528     else
529     {
530         OIC_LOG(ERROR, TAG, "Bad input for jabberID");
531         return OC_STACK_INVALID_PARAM;
532     }
533
534     InitDiscovery(OC_LOW_QOS);
535
536     // Break from loop with Ctrl+C
537     OIC_LOG(INFO, TAG, "Press CTRL+C to stop the stack");
538     signal(SIGINT, handleSigInt);
539     while (!gQuitFlag)
540     {
541         if (OCProcess() != OC_STACK_OK)
542         {
543             OIC_LOG(ERROR, TAG, "OCStack process error");
544             return 0;
545         }
546
547         sleep(2);
548     }
549     OIC_LOG(INFO, TAG, "Exiting ocremoteaccessclient main loop...");
550
551     if (OCStop() != OC_STACK_OK)
552     {
553         OIC_LOG(ERROR, TAG, "OCStack stop error");
554     }
555
556     return 0;
557 }