Merge branch 'resource-container'
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / occlient.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 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 "occlient.h"
31 #include "ocpayload.h"
32 #include "payload_logging.h"
33
34 #ifdef ROUTING_GATEWAY
35 /**
36  * Maximum number of gateway requests to form the routing table.
37  */
38 #define MAX_NUM_GATEWAY_REQUEST 20
39
40 /**
41  * Sleep duration after every OCProcess().
42  */
43 #define SLEEP_DURATION 100000
44 #endif
45 // Tracking user input
46 static int UnicastDiscovery = 0;
47 static int TestCase = 0;
48 static int Connectivity = 0;
49
50 static const char *DEVICE_DISCOVERY_QUERY = "%s/oic/d";
51 static const char *PLATFORM_DISCOVERY_QUERY = "%s/oic/p";
52 static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res";
53
54 //The following variable determines the interface protocol (IPv4, IPv6, etc)
55 //to be used for sending unicast messages. Default set to IP dual stack.
56 static OCConnectivityType ConnType = CT_ADAPTER_IP;
57 static OCDevAddr serverAddr;
58 static char discoveryAddr[100];
59 static std::string coapServerResource = "/a/light";
60
61 void StripNewLineChar(char* str);
62
63 #ifdef WITH_PRESENCE
64 // The handle for observe registration
65 OCDoHandle gPresenceHandle;
66 #endif
67 // After this crosses a threshold client deregisters for further notifications
68 int gNumObserveNotifies = 0;
69
70 #ifdef WITH_PRESENCE
71 int gNumPresenceNotifies = 0;
72 #endif
73
74 int gQuitFlag = 0;
75 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
76 void handleSigInt(int signum)
77 {
78     if (signum == SIGINT)
79     {
80         gQuitFlag = 1;
81     }
82 }
83
84 OCPayload* putPayload()
85 {
86     OCRepPayload* payload = OCRepPayloadCreate();
87
88     if (!payload)
89     {
90         std::cout << "Failed to create put payload object"<<std::endl;
91         std::exit(1);
92     }
93
94     OCRepPayloadSetPropInt(payload, "power", 15);
95     OCRepPayloadSetPropBool(payload, "state", true);
96
97     return (OCPayload*) payload;
98 }
99
100 static void PrintUsage()
101 {
102     OIC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1..17> -c <0|1>");
103     OIC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
104     OIC_LOG(INFO, TAG, "-c 0 : Use Default connectivity(IP)");
105     OIC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type");
106     OIC_LOG(INFO, TAG, "-t 1  :  Discover Resources");
107     OIC_LOG(INFO, TAG, "-t 2  :  Discover Resources and Initiate Nonconfirmable Get Request");
108     OIC_LOG(INFO, TAG, "-t 3  :  Discover Resources and Initiate Nonconfirmable Get Request"
109             " with query filter.");
110     OIC_LOG(INFO, TAG, "-t 4  :  Discover Resources and Initiate Nonconfirmable Put Requests");
111     OIC_LOG(INFO, TAG, "-t 5  :  Discover Resources and Initiate Nonconfirmable Post Requests");
112     OIC_LOG(INFO, TAG, "-t 6  :  Discover Resources and Initiate Nonconfirmable Delete Requests");
113     OIC_LOG(INFO, TAG, "-t 7  :  Discover Resources and Initiate Nonconfirmable Observe Requests");
114     OIC_LOG(INFO, TAG, "-t 8  :  Discover Resources and Initiate Nonconfirmable Get Request "\
115             "for a resource which is unavailable");
116     OIC_LOG(INFO, TAG, "-t 9  :  Discover Resources and Initiate Confirmable Get Request");
117     OIC_LOG(INFO, TAG, "-t 10 :  Discover Resources and Initiate Confirmable Post Request");
118     OIC_LOG(INFO, TAG, "-t 11 :  Discover Resources and Initiate Confirmable Delete Requests");
119     OIC_LOG(INFO, TAG, "-t 12 :  Discover Resources and Initiate Confirmable Observe Requests"\
120             " and cancel with Low QoS");
121
122 #ifdef WITH_PRESENCE
123     OIC_LOG(INFO, TAG, "-t 13 :  Discover Resources and Initiate Nonconfirmable presence");
124     OIC_LOG(INFO, TAG, "-t 14 :  Discover Resources and Initiate Nonconfirmable presence with "\
125             "filter");
126     OIC_LOG(INFO, TAG, "-t 15 :  Discover Resources and Initiate Nonconfirmable presence with "\
127             "2 filters");
128     OIC_LOG(INFO, TAG, "-t 16 :  Discover Resources and Initiate Nonconfirmable multicast presence.");
129 #endif
130
131     OIC_LOG(INFO, TAG, "-t 17 :  Discover Resources and Initiate Nonconfirmable Observe Requests "\
132             "then cancel immediately with High QOS");
133     OIC_LOG(INFO, TAG, "-t 18 :  Discover Resources and Initiate Nonconfirmable Get Request and "\
134             "add  vendor specific header options");
135     OIC_LOG(INFO, TAG, "-t 19 :  Discover Platform");
136     OIC_LOG(INFO, TAG, "-t 20 :  Discover Devices");
137 }
138
139 OCStackResult InvokeOCDoResource(std::ostringstream &query,
140                                  OCDevAddr *remoteAddr,
141                                  OCMethod method,
142                                  OCQualityOfService qos,
143                                  OCClientResponseHandler cb,
144                                  OCHeaderOption * options,
145                                  uint8_t numOptions)
146 {
147     OCStackResult ret;
148     OCCallbackData cbData;
149     OCDoHandle handle;
150
151     cbData.cb = cb;
152     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
153     cbData.cd = NULL;
154
155     ret = OCDoResource(&handle, method, query.str().c_str(), remoteAddr,
156                        (method == OC_REST_PUT) ? putPayload() : NULL,
157                        (ConnType), qos, &cbData, options, numOptions);
158
159     if (ret != OC_STACK_OK)
160     {
161         OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
162     }
163 #ifdef WITH_PRESENCE
164     else if (method == OC_REST_PRESENCE)
165     {
166         gPresenceHandle = handle;
167     }
168 #endif
169
170     return ret;
171 }
172
173 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
174                                   OCClientResponse * clientResponse)
175 {
176     if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
177     {
178         OIC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
179     }
180
181     if (clientResponse)
182     {
183         OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
184         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
185         OIC_LOG(INFO, TAG, ("=============> Put Response"));
186     }
187     else
188     {
189         OIC_LOG_V(INFO, TAG, "putReqCB received Null clientResponse");
190     }
191     return OC_STACK_DELETE_TRANSACTION;
192 }
193
194 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle /*handle*/,
195                                    OCClientResponse *clientResponse)
196 {
197     if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
198     {
199         OIC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
200     }
201
202     if (clientResponse)
203     {
204         OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
205         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
206         OIC_LOG(INFO, TAG, ("=============> Post Response"));
207     }
208     else
209     {
210         OIC_LOG_V(INFO, TAG, "postReqCB received Null clientResponse");
211     }
212     return OC_STACK_DELETE_TRANSACTION;
213 }
214
215 OCStackApplicationResult deleteReqCB(void *ctx,
216                                      OCDoHandle /*handle*/,
217                                      OCClientResponse *clientResponse)
218 {
219     if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
220     {
221         OIC_LOG(INFO, TAG, "Callback Context for DELETE recvd successfully");
222     }
223
224     if (clientResponse)
225     {
226         OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
227         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
228         OIC_LOG(INFO, TAG, ("=============> Delete Response"));
229     }
230     else
231     {
232         OIC_LOG_V(INFO, TAG, "deleteReqCB received Null clientResponse");
233     }
234     return OC_STACK_DELETE_TRANSACTION;
235 }
236
237 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
238                                   OCClientResponse * clientResponse)
239 {
240     if (clientResponse == NULL)
241     {
242         OIC_LOG(INFO, TAG, "getReqCB received NULL clientResponse");
243         return   OC_STACK_DELETE_TRANSACTION;
244     }
245
246     if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
247     {
248         OIC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
249     }
250
251     OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
252     OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
253     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
254     OIC_LOG(INFO, TAG, ("=============> Get Response"));
255
256     if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
257     {
258         OIC_LOG (INFO, TAG, "Received vendor specific options");
259         uint8_t i = 0;
260         OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions;
261         for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
262         {
263             if (((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
264             {
265                 OIC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
266                         ((OCHeaderOption)rcvdOptions[i]).optionID );
267
268                 OIC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
269                     MAX_HEADER_OPTION_DATA_LENGTH);
270             }
271         }
272     }
273     return OC_STACK_DELETE_TRANSACTION;
274 }
275
276 OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle,
277                                   OCClientResponse * clientResponse)
278 {
279     if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
280     {
281         OIC_LOG(INFO, TAG, "Callback Context for OBS query recvd successfully");
282     }
283
284     if (clientResponse)
285     {
286         OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
287         OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
288         OIC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d",
289                 gNumObserveNotifies);
290         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
291         OIC_LOG(INFO, TAG, ("=============> Obs Response"));
292         gNumObserveNotifies++;
293         if (gNumObserveNotifies > 15) //large number to test observing in DELETE case.
294         {
295             if (TestCase == TEST_OBS_REQ_NON || TestCase == TEST_OBS_REQ_CON)
296             {
297                 OIC_LOG(ERROR, TAG, "Cancelling with LOW QOS");
298                 if (OCCancel (handle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
299                 {
300                     OIC_LOG(ERROR, TAG, "Observe cancel error");
301                 }
302                 return OC_STACK_DELETE_TRANSACTION;
303             }
304             else if (TestCase == TEST_OBS_REQ_NON_CANCEL_IMM)
305             {
306                 OIC_LOG(ERROR, TAG, "Cancelling with HIGH QOS");
307                 if (OCCancel (handle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK)
308                 {
309                     OIC_LOG(ERROR, TAG, "Observe cancel error");
310                 }
311             }
312         }
313         if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
314         {
315             OIC_LOG(INFO, TAG, "This also serves as a registration confirmation");
316         }
317         else if (clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
318         {
319             OIC_LOG(INFO, TAG, "This also serves as a deregistration confirmation");
320             return OC_STACK_DELETE_TRANSACTION;
321         }
322         else if (clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
323         {
324             OIC_LOG(INFO, TAG, "This also tells you that registration/deregistration failed");
325             return OC_STACK_DELETE_TRANSACTION;
326         }
327     }
328     else
329     {
330         OIC_LOG_V(INFO, TAG, "obsReqCB received Null clientResponse");
331     }
332     return OC_STACK_KEEP_TRANSACTION;
333 }
334 #ifdef WITH_PRESENCE
335 OCStackApplicationResult presenceCB(void* ctx, OCDoHandle /*handle*/,
336                                     OCClientResponse * clientResponse)
337 {
338     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
339     {
340         OIC_LOG(INFO, TAG, "Callback Context for Presence recvd successfully");
341     }
342
343     if (clientResponse)
344     {
345         OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
346         OIC_LOG_V(INFO, TAG, "Callback Context for Presence notification recvd successfully %d",
347                 gNumPresenceNotifies);
348         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
349         OIC_LOG(INFO, TAG, ("=============> Presence Response"));
350         gNumPresenceNotifies++;
351         if (gNumPresenceNotifies == 20)
352         {
353             if (OCCancel(gPresenceHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
354             {
355                 OIC_LOG(ERROR, TAG, "Presence cancel error");
356             }
357             return OC_STACK_DELETE_TRANSACTION;
358         }
359     }
360     else
361     {
362         OIC_LOG_V(INFO, TAG, "presenceCB received Null clientResponse");
363     }
364     return OC_STACK_KEEP_TRANSACTION;
365 }
366 #endif
367
368 // This is a function called back when a device is discovered
369 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
370                                         OCClientResponse * clientResponse)
371 {
372     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
373     {
374         OIC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
375     }
376
377     if (clientResponse)
378     {
379         OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
380
381         std::string connectionType = getConnectivityType (clientResponse->connType);
382         OIC_LOG_V(INFO, TAG, "Discovered on %s", connectionType.c_str());
383         OIC_LOG_V(INFO, TAG,
384                 "Device =============> Discovered @ %s:%d",
385                 clientResponse->devAddr.addr,
386                 clientResponse->devAddr.port);
387         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
388
389         ConnType = clientResponse->connType;
390         serverAddr = clientResponse->devAddr;
391
392         OCDiscoveryPayload *payload = (OCDiscoveryPayload*) clientResponse->payload;
393         if (!payload)
394         {
395             return OC_STACK_DELETE_TRANSACTION;
396         }
397
398         OCResourcePayload *resource = (OCResourcePayload*) payload->resources;
399         if (!resource)
400         {
401             OIC_LOG_V (INFO, TAG, "No resources in payload");
402             return OC_STACK_DELETE_TRANSACTION;
403         }
404         coapServerResource =  resource->uri;
405
406         switch(TestCase)
407         {
408             case TEST_GET_REQ_NON:
409                 InitGetRequest(OC_LOW_QOS, 0, 0);
410                 break;
411             case TEST_GET_REQ_NON_WITH_FILTERS:
412                 InitGetRequest(OC_LOW_QOS, 0, 1);
413                 break;
414             case TEST_PUT_REQ_NON:
415                 InitPutRequest(OC_LOW_QOS);
416                 break;
417             case TEST_POST_REQ_NON:
418                 InitPostRequest(OC_LOW_QOS);
419                 break;
420             case TEST_DELETE_REQ_NON:
421                 InitDeleteRequest(OC_LOW_QOS);
422                 break;
423             case TEST_OBS_REQ_NON:
424             case TEST_OBS_REQ_NON_CANCEL_IMM:
425                 InitObserveRequest(OC_LOW_QOS);
426                 break;
427             case TEST_GET_UNAVAILABLE_RES_REQ_NON:
428                 InitGetRequestToUnavailableResource(OC_LOW_QOS);
429                 break;
430             case TEST_GET_REQ_CON:
431                 InitGetRequest(OC_HIGH_QOS, 0, 0);
432                 break;
433             case TEST_POST_REQ_CON:
434                 InitPostRequest(OC_HIGH_QOS);
435                 break;
436             case TEST_DELETE_REQ_CON:
437                 InitDeleteRequest(OC_HIGH_QOS);
438                 break;
439             case TEST_OBS_REQ_CON:
440                 InitObserveRequest(OC_HIGH_QOS);
441                 break;
442 #ifdef WITH_PRESENCE
443             case TEST_OBS_PRESENCE:
444             case TEST_OBS_PRESENCE_WITH_FILTER:
445             case TEST_OBS_PRESENCE_WITH_FILTERS:
446             case TEST_OBS_MULTICAST_PRESENCE:
447                 InitPresence();
448                 break;
449 #endif
450             case TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS:
451                 InitGetRequest(OC_LOW_QOS, 1, 0);
452                 break;
453             case TEST_DISCOVER_PLATFORM_REQ:
454                 InitPlatformDiscovery(OC_LOW_QOS);
455                 break;
456             case TEST_DISCOVER_DEV_REQ:
457                 InitDeviceDiscovery(OC_LOW_QOS);
458                 break;
459             default:
460                 PrintUsage();
461                 break;
462         }
463     }
464     else
465     {
466         OIC_LOG_V(INFO, TAG, "discoveryReqCB received Null clientResponse");
467     }
468     return OC_STACK_KEEP_TRANSACTION;
469 }
470
471 OCStackApplicationResult PlatformDiscoveryReqCB(void* ctx,
472                                                 OCDoHandle /*handle*/,
473                                                 OCClientResponse * clientResponse)
474 {
475     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
476     {
477         OIC_LOG(INFO, TAG, "Callback Context for Platform DISCOVER query recvd successfully");
478     }
479
480     if (clientResponse)
481     {
482         OIC_LOG(INFO, TAG, ("Discovery Response:"));
483         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
484     }
485     else
486     {
487         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
488     }
489
490     return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
491 }
492
493 OCStackApplicationResult DeviceDiscoveryReqCB(void* ctx, OCDoHandle /*handle*/,
494                                               OCClientResponse * clientResponse)
495 {
496     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
497     {
498         OIC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully");
499     }
500
501     if (clientResponse)
502     {
503         OIC_LOG(INFO, TAG, ("Discovery Response:"));
504         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
505     }
506     else
507     {
508         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
509     }
510
511     return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
512 }
513
514 #ifdef WITH_PRESENCE
515 int InitPresence()
516 {
517     OCStackResult result = OC_STACK_OK;
518     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
519     std::ostringstream query;
520     std::ostringstream querySuffix;
521     query << OC_RSRVD_PRESENCE_URI;
522     if (TestCase == TEST_OBS_PRESENCE)
523     {
524         result = InvokeOCDoResource(query, &serverAddr, OC_REST_PRESENCE,
525                 OC_LOW_QOS, presenceCB, NULL, 0);
526     }
527     if (TestCase == TEST_OBS_PRESENCE_WITH_FILTER || TestCase == TEST_OBS_PRESENCE_WITH_FILTERS)
528     {
529         querySuffix.str("");
530         querySuffix << query.str() << "?rt=core.led";
531         result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE,
532                 OC_LOW_QOS, presenceCB, NULL, 0);
533     }
534     if (TestCase == TEST_OBS_PRESENCE_WITH_FILTERS)
535     {
536         if (result == OC_STACK_OK)
537         {
538             querySuffix.str("");
539             querySuffix << query.str() << "?rt=core.fan";
540             result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
541                     presenceCB, NULL, 0);
542         }
543     }
544     if (TestCase == TEST_OBS_MULTICAST_PRESENCE)
545     {
546         if (result == OC_STACK_OK)
547         {
548             std::ostringstream multicastPresenceQuery;
549             multicastPresenceQuery.str("");
550             multicastPresenceQuery << "coap://" << OC_MULTICAST_PREFIX << OC_RSRVD_PRESENCE_URI;
551             result = InvokeOCDoResource(multicastPresenceQuery, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
552                     presenceCB, NULL, 0);
553         }
554     }
555     return result;
556 }
557 #endif
558
559 int InitGetRequestToUnavailableResource(OCQualityOfService qos)
560 {
561     std::ostringstream query;
562     query << "/SomeUnknownResource";
563     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
564     return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
565             getReqCB, NULL, 0));
566 }
567
568 int InitObserveRequest(OCQualityOfService qos)
569 {
570     std::ostringstream query;
571     query << coapServerResource;
572     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
573     return (InvokeOCDoResource(query, &serverAddr, OC_REST_OBSERVE,
574               (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
575 }
576
577 int InitPutRequest(OCQualityOfService qos)
578 {
579     std::ostringstream query;
580     query << coapServerResource;
581     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
582     return (InvokeOCDoResource(query, &serverAddr, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
583             putReqCB, NULL, 0));
584 }
585
586 int InitPostRequest(OCQualityOfService qos)
587 {
588     OCStackResult result;
589
590     std::ostringstream query;
591     query << coapServerResource;
592
593     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
594     // First POST operation (to create an Light instance)
595     result = InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
596                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
597                                postReqCB, NULL, 0);
598     if (OC_STACK_OK != result)
599     {
600         // Error can happen if for example, network connectivity is down
601         OIC_LOG(INFO, TAG, "First POST call did not succeed");
602     }
603
604     // Second POST operation (to create an Light instance)
605     result = InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
606                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
607                                postReqCB, NULL, 0);
608     if (OC_STACK_OK != result)
609     {
610         OIC_LOG(INFO, TAG, "Second POST call did not succeed");
611     }
612
613     // This POST operation will update the original resourced /a/light
614     return (InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
615                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
616                                postReqCB, NULL, 0));
617 }
618
619 void* RequestDeleteDeathResourceTask(void* myqos)
620 {
621     sleep (30);//long enough to give the server time to finish deleting the resource.
622     std::ostringstream query;
623     query << coapServerResource;
624
625     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
626
627     // Second DELETE operation to delete the resource that might have been removed already.
628     OCQualityOfService qos;
629     if (myqos == NULL)
630     {
631         qos = OC_LOW_QOS;
632     }
633     else
634     {
635         qos = OC_HIGH_QOS;
636     }
637
638     OCStackResult result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE,
639                                qos,
640                                deleteReqCB, NULL, 0);
641
642     if (OC_STACK_OK != result)
643     {
644         OIC_LOG(INFO, TAG, "Second DELETE call did not succeed");
645     }
646
647     return NULL;
648 }
649
650 int InitDeleteRequest(OCQualityOfService qos)
651 {
652     OCStackResult result;
653     std::ostringstream query;
654     query << coapServerResource;
655
656     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
657
658     // First DELETE operation
659     result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE,
660                                qos,
661                                deleteReqCB, NULL, 0);
662     if (OC_STACK_OK != result)
663     {
664         // Error can happen if for example, network connectivity is down
665         OIC_LOG(INFO, TAG, "First DELETE call did not succeed");
666     }
667     else
668     {
669         //Create a thread to delete this resource again
670         pthread_t threadId;
671         pthread_create (&threadId, NULL, RequestDeleteDeathResourceTask, (void*)qos);
672     }
673
674     OIC_LOG_V(INFO, TAG, "\n\nExit  %s", __func__);
675     return result;
676 }
677
678 int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions, bool getWithQuery)
679 {
680
681     OCHeaderOption options[MAX_HEADER_OPTIONS];
682
683     std::ostringstream query;
684     query << coapServerResource;
685
686     // ocserver is written to only process "power<X" query.
687     if (getWithQuery)
688     {
689         OIC_LOG(INFO, TAG, "Using query power<50");
690         query << "?power<50";
691     }
692     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
693
694     if (withVendorSpecificHeaderOptions)
695     {
696         uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
697         uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
698         memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
699         options[0].protocolID = OC_COAP_ID;
700         options[0].optionID = 2048;
701         memcpy(options[0].optionData, option0, sizeof(option0));
702         options[0].optionLength = 10;
703         options[1].protocolID = OC_COAP_ID;
704         options[1].optionID = 3000;
705         memcpy(options[1].optionData, option1, sizeof(option1));
706         options[1].optionLength = 10;
707     }
708     if (withVendorSpecificHeaderOptions)
709     {
710         return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET,
711                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, options, 2));
712     }
713     else
714     {
715         return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET,
716                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, NULL, 0));
717     }
718 }
719
720 int InitPlatformDiscovery(OCQualityOfService qos)
721 {
722     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
723
724     OCStackResult ret;
725     OCCallbackData cbData;
726     char szQueryUri[64] = { 0 };
727
728     snprintf(szQueryUri, sizeof (szQueryUri) - 1, PLATFORM_DISCOVERY_QUERY, discoveryAddr);
729
730     cbData.cb = PlatformDiscoveryReqCB;
731     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
732     cbData.cd = NULL;
733
734     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
735                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
736                        &cbData, NULL, 0);
737     if (ret != OC_STACK_OK)
738     {
739         OIC_LOG(ERROR, TAG, "OCStack device error");
740     }
741
742     return ret;
743 }
744
745 int InitDeviceDiscovery(OCQualityOfService qos)
746 {
747     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
748
749     OCStackResult ret;
750     OCCallbackData cbData;
751     char szQueryUri[100] = { 0 };
752
753     snprintf(szQueryUri, sizeof (szQueryUri) - 1, DEVICE_DISCOVERY_QUERY, discoveryAddr);
754
755     cbData.cb = DeviceDiscoveryReqCB;
756     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
757     cbData.cd = NULL;
758
759     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
760                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
761                        &cbData, NULL, 0);
762     if (ret != OC_STACK_OK)
763     {
764         OIC_LOG(ERROR, TAG, "OCStack device error");
765     }
766
767     return ret;
768 }
769
770 int InitDiscovery(OCQualityOfService qos)
771 {
772     OCStackResult ret;
773     OCCallbackData cbData;
774     char szQueryUri[100] = { 0 };
775
776     snprintf(szQueryUri, sizeof (szQueryUri) - 1, RESOURCE_DISCOVERY_QUERY, discoveryAddr);
777
778     cbData.cb = discoveryReqCB;
779     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
780     cbData.cd = NULL;
781
782     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
783                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
784                        &cbData, NULL, 0);
785     if (ret != OC_STACK_OK)
786     {
787         OIC_LOG(ERROR, TAG, "OCStack resource error");
788     }
789     return ret;
790 }
791
792 int main(int argc, char* argv[])
793 {
794     int opt;
795
796     while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
797     {
798         switch(opt)
799         {
800             case 'u':
801                 UnicastDiscovery = atoi(optarg);
802                 break;
803             case 't':
804                 TestCase = atoi(optarg);
805                 break;
806             case 'c':
807                 Connectivity = atoi(optarg);
808                 break;
809             default:
810                 PrintUsage();
811                 return -1;
812         }
813     }
814
815     if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
816             (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) ||
817             (Connectivity < CT_ADAPTER_DEFAULT || Connectivity >= MAX_CT))
818     {
819         PrintUsage();
820         return -1;
821     }
822
823     if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
824     {
825         OIC_LOG(ERROR, TAG, "OCStack init error");
826         return 0;
827     }
828
829 #ifdef ROUTING_GATEWAY
830     /*
831      * Before invoking Discover resource, we process the gateway requests
832      * and form the routing table.
833      */
834     for (int index = 0; index < MAX_NUM_GATEWAY_REQUEST; index++)
835     {
836         if (OC_STACK_OK != OCProcess())
837         {
838             OIC_LOG(ERROR, TAG, "OCStack process error");
839             return 0;
840         }
841         usleep(SLEEP_DURATION);
842     }
843 #endif
844     if (Connectivity == CT_ADAPTER_DEFAULT || Connectivity == CT_IP)
845     {
846         ConnType = CT_ADAPTER_IP;
847     }
848     else
849     {
850         OIC_LOG(INFO, TAG, "Default Connectivity type selected...");
851         PrintUsage();
852     }
853
854     discoveryAddr[0] = '\0';
855
856     if (UnicastDiscovery)
857     {
858         OIC_LOG(INFO, TAG, "Enter IP address of server with optional port number");
859         OIC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
860         OIC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
861
862         if (fgets(discoveryAddr, sizeof (discoveryAddr), stdin))
863         {
864             //Strip newline char from ipv4addr
865             StripNewLineChar(discoveryAddr);
866         }
867         else
868         {
869             OIC_LOG(ERROR, TAG, "!! Bad input for IP address. !!");
870             return OC_STACK_INVALID_PARAM;
871         }
872     }
873
874     if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_DEV_REQ)
875     {
876         InitDeviceDiscovery(OC_LOW_QOS);
877     }
878     else if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_PLATFORM_REQ)
879     {
880         InitPlatformDiscovery(OC_LOW_QOS);
881     }
882     else
883     {
884         InitDiscovery(OC_LOW_QOS);
885     }
886
887     // Break from loop with Ctrl+C
888     OIC_LOG(INFO, TAG, "Entering occlient main loop...");
889     signal(SIGINT, handleSigInt);
890     while (!gQuitFlag)
891     {
892
893         if (OCProcess() != OC_STACK_OK)
894         {
895             OIC_LOG(ERROR, TAG, "OCStack process error");
896             return 0;
897         }
898 #ifndef ROUTING_GATEAWAY
899         sleep(1);
900 #endif
901     }
902     OIC_LOG(INFO, TAG, "Exiting occlient main loop...");
903
904     if (OCStop() != OC_STACK_OK)
905     {
906         OIC_LOG(ERROR, TAG, "OCStack stop error");
907     }
908
909     return 0;
910 }
911
912 std::string getConnectivityType (OCConnectivityType connType)
913 {
914     switch (connType & CT_MASK_ADAPTER)
915     {
916         case CT_ADAPTER_IP:
917             return "IP";
918
919         case CT_IP_USE_V4:
920             return "IPv4";
921
922         case CT_IP_USE_V6:
923             return "IPv6";
924
925         case CT_ADAPTER_GATT_BTLE:
926             return "GATT";
927
928         case CT_ADAPTER_RFCOMM_BTEDR:
929             return "RFCOMM";
930
931         default:
932             return "Incorrect connectivity";
933     }
934 }