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