39627df03f0afdef863344e472cf961a53dd0f44
[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     OCStackResult ret = OCDoResource(
114         &handle,
115         method,
116         query.str().c_str(),
117         &responseAddr,
118         (method == OC_REST_PUT) ? putPayload() : NULL,
119         CT_ADAPTER_REMOTE_ACCESS,
120         qos,
121         &cbData,
122         options,
123         numOptions);
124
125     if (ret != OC_STACK_OK)
126     {
127         OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
128     }
129     else if (method == OC_REST_OBSERVE || method == OC_REST_OBSERVE_ALL)
130     {
131         gObserveDoHandle = handle;
132     }
133 #ifdef WITH_PRESENCE
134     else if (method == OC_REST_PRESENCE)
135     {
136         gPresenceHandle = handle;
137     }
138 #endif
139
140     return ret;
141 }
142
143 OCStackApplicationResult restRequestCB(void* ctx,
144         OCDoHandle handle, OCClientResponse * clientResponse)
145 {
146     if(clientResponse == NULL)
147     {
148         OIC_LOG(INFO, TAG, "Received NULL response");
149         return   OC_STACK_DELETE_TRANSACTION;
150     }
151     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
152     {
153         OIC_LOG(INFO, TAG, "Callback Context recvd successfully");
154     }
155
156     OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
157     OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
158     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
159
160     if(clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
161     {
162         OIC_LOG (INFO, TAG, "Received vendor specific options. Ignoring");
163     }
164     SET_BUT_NOT_USED(handle);
165     return OC_STACK_DELETE_TRANSACTION;
166 }
167
168 OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
169 {
170     if(!clientResponse)
171     {
172         OIC_LOG_V(INFO, TAG, "obsReqCB received NULL response");
173     }
174     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
175     {
176         OIC_LOG(INFO, TAG, "Callback Context recvd successfully");
177     }
178     OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
179     OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
180     OIC_LOG_V(INFO, TAG, "OBSERVE notification %d recvd", gNumObserveNotifies);
181     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
182
183     gNumObserveNotifies++;
184     if (gNumObserveNotifies == maxNotification)
185     {
186         if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
187         {
188             OIC_LOG(ERROR, TAG, "Observe cancel error");
189         }
190         return OC_STACK_DELETE_TRANSACTION;
191     }
192     if (gNumObserveNotifies == 1 && TEST_CASE == TEST_OBS_REQ_NON_CANCEL_IMM)
193     {
194         if (OCCancel (gObserveDoHandle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK)
195         {
196             OIC_LOG(ERROR, TAG, "Observe cancel error");
197         }
198     }
199     if(clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
200     {
201         OIC_LOG(INFO, TAG, "Registration confirmed");
202     }
203     else if(clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
204     {
205         OIC_LOG(INFO, TAG, "de-registration confirmed");
206         return OC_STACK_DELETE_TRANSACTION;
207     }
208     else if(clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
209     {
210         OIC_LOG(INFO, TAG, "Registration/deregistration failed");
211         return OC_STACK_DELETE_TRANSACTION;
212     }
213
214     SET_BUT_NOT_USED(handle);
215     return OC_STACK_KEEP_TRANSACTION;
216 }
217 #ifdef WITH_PRESENCE
218 OCStackApplicationResult presenceCB(void* ctx,
219         OCDoHandle handle, OCClientResponse * clientResponse)
220 {
221     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
222     {
223         OIC_LOG(INFO, TAG, "Callback Context recvd successfully");
224     }
225
226     if (clientResponse)
227     {
228         OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
229         OIC_LOG_V(INFO, TAG, "NONCE NUMBER: %u", clientResponse->sequenceNumber);
230         OIC_LOG_V(INFO, TAG, "PRESENCE notification %d recvd", gNumPresenceNotifies);
231         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
232
233         gNumPresenceNotifies++;
234         if (gNumPresenceNotifies == maxNotification)
235         {
236             if (OCCancel(gPresenceHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
237             {
238                 OIC_LOG(ERROR, TAG, "Presence cancel error");
239             }
240             return OC_STACK_DELETE_TRANSACTION;
241         }
242     }
243     else
244     {
245         OIC_LOG_V(INFO, TAG, "presenceCB received Null clientResponse");
246     }
247     SET_BUT_NOT_USED(handle);
248     return OC_STACK_KEEP_TRANSACTION;
249 }
250 #endif
251
252 // This is a function called back when a device is discovered
253 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
254         OCClientResponse * clientResponse)
255 {
256     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
257     {
258         OIC_LOG(INFO, TAG, "DISCOVER  callback recvd");
259     }
260
261     if (!clientResponse)
262     {
263         OIC_LOG_V(INFO, TAG, "discoveryReqCB received Null clientResponse");
264     }
265
266     OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
267     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
268
269     responseAddr = clientResponse->devAddr;
270
271     switch(TEST_CASE)
272     {
273         OIC_LOG_V(INFO, TAG, "TEST_CASE %u\n", TEST_CASE);
274         case TEST_GET_REQ_NON:
275             InitGetRequest(OC_LOW_QOS);
276             break;
277         case TEST_PUT_REQ_NON:
278             InitPutRequest(OC_LOW_QOS);
279             break;
280         case TEST_POST_REQ_NON:
281             InitPostRequest(OC_LOW_QOS);
282             break;
283         case TEST_DELETE_REQ_NON:
284             InitDeleteRequest(OC_LOW_QOS);
285             break;
286         case TEST_OBS_REQ_NON:
287         case TEST_OBS_REQ_NON_CANCEL_IMM:
288             InitObserveRequest(OC_LOW_QOS);
289             break;
290         default:
291             PrintUsage();
292             break;
293     }
294     SET_BUT_NOT_USED(handle);
295     return OC_STACK_KEEP_TRANSACTION;
296 }
297
298 OCStackApplicationResult PlatformDiscoveryReqCB (void* ctx, OCDoHandle handle,
299                 OCClientResponse * clientResponse)
300 {
301     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
302     {
303         OIC_LOG(INFO, TAG, "Callback Context for Platform DISCOVER query recvd successfully");
304     }
305
306     if(clientResponse)
307     {
308         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
309     }
310     else
311     {
312         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
313     }
314
315     SET_BUT_NOT_USED(handle);
316     return OC_STACK_DELETE_TRANSACTION;
317 }
318
319 OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle handle,
320         OCClientResponse * clientResponse)
321 {
322     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
323     {
324         OIC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully");
325     }
326
327     if(clientResponse)
328     {
329         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
330     }
331     else
332     {
333         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
334     }
335
336     SET_BUT_NOT_USED(handle);
337     return OC_STACK_DELETE_TRANSACTION;
338 }
339
340 int InitObserveRequest(OCQualityOfService qos)
341 {
342     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
343     std::ostringstream query;
344     query << coapServerResource;
345     return (InvokeOCDoResource(query,
346             OC_REST_OBSERVE, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
347 }
348
349 int InitPutRequest(OCQualityOfService qos)
350 {
351     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
352     std::ostringstream query;
353     query << coapServerResource;
354     return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
355             restRequestCB, NULL, 0));
356 }
357
358 int InitPostRequest(OCQualityOfService qos)
359 {
360     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
361     std::ostringstream query;
362     query << coapServerResource;
363     // First POST operation (to create an Light instance)
364     OCStackResult result = InvokeOCDoResource(query, OC_REST_POST,
365                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
366                                restRequestCB, NULL, 0);
367     if (OC_STACK_OK != result)
368     {
369         // Error can happen if for example, network connectivity is down
370         OIC_LOG(INFO, TAG, "First POST call did not succeed");
371     }
372
373     // Second POST operation (to create an Light instance)
374     result = InvokeOCDoResource(query, OC_REST_POST,
375                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
376                                restRequestCB, NULL, 0);
377     if (OC_STACK_OK != result)
378     {
379         OIC_LOG(INFO, TAG, "Second POST call did not succeed");
380     }
381
382     // This POST operation will update the original resourced /a/light
383     return (InvokeOCDoResource(query, OC_REST_POST,
384                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
385                                restRequestCB, NULL, 0));
386 }
387
388 int InitDeleteRequest(OCQualityOfService qos)
389 {
390     std::ostringstream query;
391     query << coapServerResource;
392     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
393
394     // First DELETE operation
395     OCStackResult result = InvokeOCDoResource(query, OC_REST_DELETE,
396                                qos,
397                                restRequestCB, NULL, 0);
398     if (OC_STACK_OK != result)
399     {
400         // Error can happen if for example, network connectivity is down
401         OIC_LOG(INFO, TAG, "DELETE call did not succeed");
402     }
403     return result;
404 }
405
406 int InitGetRequest(OCQualityOfService qos)
407 {
408     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
409     std::ostringstream query;
410     query << coapServerResource;
411     return (InvokeOCDoResource(query, OC_REST_GET,
412                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, restRequestCB, NULL, 0));
413 }
414
415 int InitDiscovery(OCQualityOfService qos)
416 {
417     OCCallbackData cbData;
418     cbData.cb       = discoveryReqCB;
419     cbData.context  = (void*)DEFAULT_CONTEXT_VALUE;
420     cbData.cd       = NULL;
421
422     OCDevAddr dest;
423     dest.adapter    = OC_ADAPTER_REMOTE_ACCESS;
424     dest.flags      = OC_DEFAULT_FLAGS;
425     strncpy (dest.addr, remoteServerJabberID, MAX_ADDR_STR_SIZE - 1);
426
427     OCStackResult ret = OCDoResource(NULL,
428                 OC_REST_GET,
429                 MULTICAST_RESOURCE_DISCOVERY_QUERY,
430                 &dest,
431                 NULL,
432                 CT_ADAPTER_REMOTE_ACCESS,
433                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
434                 &cbData,
435                 NULL,
436                 0
437             );
438
439     if (ret != OC_STACK_OK)
440     {
441         OIC_LOG_V(ERROR, TAG, "Error %u in OCDoResource with discovery", ret);
442     }
443     return ret;
444 }
445
446 static void jidbound(char *jid)
447 {
448     OIC_LOG_V(INFO, TAG, "\n\n    Bound JID: %s\n\n", jid);
449 }
450
451 int main(int argc, char* argv[])
452 {
453     char host[] = "localhost";
454     char user[] = "test1";
455     char pass[] = "intel123";
456     char empstr[] = "";
457     OCRAInfo_t rainfo = {};
458
459     rainfo.hostname = host;
460     rainfo.port = 5222;
461     rainfo.xmpp_domain = host;
462     rainfo.username = user;
463     rainfo.password = pass;
464     rainfo.resource = empstr;
465     rainfo.user_jid = empstr;
466     rainfo.jidbound = jidbound;
467
468     int opt = 0;
469     while ((opt = getopt(argc, argv, "t:s:p:d:u:w:r:j:")) != -1)
470     {
471         switch(opt)
472         {
473             case 't':
474                 TEST_CASE = atoi(optarg);
475                 break;
476             case 's':
477                 rainfo.hostname = optarg;
478                 break;
479             case 'p':
480                 rainfo.port = atoi(optarg);
481                 break;
482             case 'd':
483                 rainfo.xmpp_domain = optarg;
484                 break;
485             case 'u':
486                 rainfo.username = optarg;
487                 break;
488             case 'w':
489                 rainfo.password = optarg;
490                 break;
491             case 'j':
492                 rainfo.user_jid = optarg;
493                 break;
494             case 'r':
495                 rainfo.resource = optarg;
496                 break;
497             default:
498                 PrintUsage();
499                 return -1;
500         }
501     }
502
503     if (OCSetRAInfo(&rainfo) != OC_STACK_OK)
504     {
505         OIC_LOG(ERROR, TAG, "Error initiating remote access adapter");
506         return 0;
507     }
508
509     if ((TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS))
510     {
511         PrintUsage();
512         return -1;
513     }
514
515     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
516     {
517         OIC_LOG(ERROR, TAG, "OCStack init error");
518         return 0;
519     }
520
521     OIC_LOG(INFO, TAG, "Enter JID of remote server");
522     if (fgets(remoteServerJabberID, MAX_ADDR_STR_SIZE, stdin))
523     {
524         StripNewLineChar(remoteServerJabberID);
525     }
526     else
527     {
528         OIC_LOG(ERROR, TAG, "Bad input for jabberID");
529         return OC_STACK_INVALID_PARAM;
530     }
531
532     InitDiscovery(OC_LOW_QOS);
533
534     // Break from loop with Ctrl+C
535     OIC_LOG(INFO, TAG, "Press CTRL+C to stop the stack");
536     signal(SIGINT, handleSigInt);
537     while (!gQuitFlag)
538     {
539         if (OCProcess() != OC_STACK_OK)
540         {
541             OIC_LOG(ERROR, TAG, "OCStack process error");
542             return 0;
543         }
544
545         sleep(2);
546     }
547     OIC_LOG(INFO, TAG, "Exiting ocremoteaccessclient main loop...");
548
549     if (OCStop() != OC_STACK_OK)
550     {
551         OIC_LOG(ERROR, TAG, "OCStack stop error");
552     }
553
554     return 0;
555 }