Imported Upstream version 1.1.0
[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         int found = 0;
400         while (resource)
401         {
402             if(resource->uri && strcmp(resource->uri, coapServerResource.c_str()) == 0)
403             {
404                 found = 1;
405                 break;
406             }
407             resource = resource->next;
408         }
409
410         if(!found)
411         {
412             OIC_LOG_V (INFO, TAG, "No /a/light in payload");
413             return OC_STACK_KEEP_TRANSACTION;
414         }
415
416         switch(TestCase)
417         {
418             case TEST_GET_REQ_NON:
419                 InitGetRequest(OC_LOW_QOS, 0, 0);
420                 break;
421             case TEST_GET_REQ_NON_WITH_FILTERS:
422                 InitGetRequest(OC_LOW_QOS, 0, 1);
423                 break;
424             case TEST_PUT_REQ_NON:
425                 InitPutRequest(OC_LOW_QOS);
426                 break;
427             case TEST_POST_REQ_NON:
428                 InitPostRequest(OC_LOW_QOS);
429                 break;
430             case TEST_DELETE_REQ_NON:
431                 InitDeleteRequest(OC_LOW_QOS);
432                 break;
433             case TEST_OBS_REQ_NON:
434             case TEST_OBS_REQ_NON_CANCEL_IMM:
435                 InitObserveRequest(OC_LOW_QOS);
436                 break;
437             case TEST_GET_UNAVAILABLE_RES_REQ_NON:
438                 InitGetRequestToUnavailableResource(OC_LOW_QOS);
439                 break;
440             case TEST_GET_REQ_CON:
441                 InitGetRequest(OC_HIGH_QOS, 0, 0);
442                 break;
443             case TEST_POST_REQ_CON:
444                 InitPostRequest(OC_HIGH_QOS);
445                 break;
446             case TEST_DELETE_REQ_CON:
447                 InitDeleteRequest(OC_HIGH_QOS);
448                 break;
449             case TEST_OBS_REQ_CON:
450                 InitObserveRequest(OC_HIGH_QOS);
451                 break;
452 #ifdef WITH_PRESENCE
453             case TEST_OBS_PRESENCE:
454             case TEST_OBS_PRESENCE_WITH_FILTER:
455             case TEST_OBS_PRESENCE_WITH_FILTERS:
456             case TEST_OBS_MULTICAST_PRESENCE:
457                 InitPresence();
458                 break;
459 #endif
460             case TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS:
461                 InitGetRequest(OC_LOW_QOS, 1, 0);
462                 break;
463             case TEST_DISCOVER_PLATFORM_REQ:
464                 InitPlatformDiscovery(OC_LOW_QOS);
465                 break;
466             case TEST_DISCOVER_DEV_REQ:
467                 InitDeviceDiscovery(OC_LOW_QOS);
468                 break;
469             default:
470                 PrintUsage();
471                 break;
472         }
473     }
474     else
475     {
476         OIC_LOG_V(INFO, TAG, "discoveryReqCB received Null clientResponse");
477     }
478     return OC_STACK_KEEP_TRANSACTION;
479 }
480
481 OCStackApplicationResult PlatformDiscoveryReqCB(void* ctx,
482                                                 OCDoHandle /*handle*/,
483                                                 OCClientResponse * clientResponse)
484 {
485     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
486     {
487         OIC_LOG(INFO, TAG, "Callback Context for Platform DISCOVER query recvd successfully");
488     }
489
490     if (clientResponse)
491     {
492         OIC_LOG(INFO, TAG, ("Discovery Response:"));
493         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
494     }
495     else
496     {
497         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
498     }
499
500     return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
501 }
502
503 OCStackApplicationResult DeviceDiscoveryReqCB(void* ctx, OCDoHandle /*handle*/,
504                                               OCClientResponse * clientResponse)
505 {
506     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
507     {
508         OIC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully");
509     }
510
511     if (clientResponse)
512     {
513         OIC_LOG(INFO, TAG, ("Discovery Response:"));
514         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
515     }
516     else
517     {
518         OIC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
519     }
520
521     return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
522 }
523
524 #ifdef WITH_PRESENCE
525 int InitPresence()
526 {
527     OCStackResult result = OC_STACK_OK;
528     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
529     std::ostringstream query;
530     std::ostringstream querySuffix;
531     query << OC_RSRVD_PRESENCE_URI;
532     if (TestCase == TEST_OBS_PRESENCE)
533     {
534         result = InvokeOCDoResource(query, &serverAddr, OC_REST_PRESENCE,
535                 OC_LOW_QOS, presenceCB, NULL, 0);
536     }
537     if (TestCase == TEST_OBS_PRESENCE_WITH_FILTER || TestCase == TEST_OBS_PRESENCE_WITH_FILTERS)
538     {
539         querySuffix.str("");
540         querySuffix << query.str() << "?rt=core.led";
541         result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE,
542                 OC_LOW_QOS, presenceCB, NULL, 0);
543     }
544     if (TestCase == TEST_OBS_PRESENCE_WITH_FILTERS)
545     {
546         if (result == OC_STACK_OK)
547         {
548             querySuffix.str("");
549             querySuffix << query.str() << "?rt=core.fan";
550             result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
551                     presenceCB, NULL, 0);
552         }
553     }
554     if (TestCase == TEST_OBS_MULTICAST_PRESENCE)
555     {
556         if (result == OC_STACK_OK)
557         {
558             std::ostringstream multicastPresenceQuery;
559             multicastPresenceQuery.str("");
560             multicastPresenceQuery << "coap://" << OC_MULTICAST_PREFIX << OC_RSRVD_PRESENCE_URI;
561             result = InvokeOCDoResource(multicastPresenceQuery, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
562                     presenceCB, NULL, 0);
563         }
564     }
565     return result;
566 }
567 #endif
568
569 int InitGetRequestToUnavailableResource(OCQualityOfService qos)
570 {
571     std::ostringstream query;
572     query << "/SomeUnknownResource";
573     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
574     return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
575             getReqCB, NULL, 0));
576 }
577
578 int InitObserveRequest(OCQualityOfService qos)
579 {
580     std::ostringstream query;
581     query << coapServerResource;
582     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
583     return (InvokeOCDoResource(query, &serverAddr, OC_REST_OBSERVE,
584               (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
585 }
586
587 int InitPutRequest(OCQualityOfService qos)
588 {
589     std::ostringstream query;
590     query << coapServerResource;
591     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
592     return (InvokeOCDoResource(query, &serverAddr, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
593             putReqCB, NULL, 0));
594 }
595
596 int InitPostRequest(OCQualityOfService qos)
597 {
598     OCStackResult result;
599
600     std::ostringstream query;
601     query << coapServerResource;
602
603     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
604     // First 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         // Error can happen if for example, network connectivity is down
611         OIC_LOG(INFO, TAG, "First POST call did not succeed");
612     }
613
614     // Second POST operation (to create an Light instance)
615     result = InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
616                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
617                                postReqCB, NULL, 0);
618     if (OC_STACK_OK != result)
619     {
620         OIC_LOG(INFO, TAG, "Second POST call did not succeed");
621     }
622
623     // This POST operation will update the original resourced /a/light
624     return (InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
625                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
626                                postReqCB, NULL, 0));
627 }
628
629 void* RequestDeleteDeathResourceTask(void* myqos)
630 {
631     sleep (30);//long enough to give the server time to finish deleting the resource.
632     std::ostringstream query;
633     query << coapServerResource;
634
635     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
636
637     // Second DELETE operation to delete the resource that might have been removed already.
638     OCQualityOfService qos;
639     if (myqos == NULL)
640     {
641         qos = OC_LOW_QOS;
642     }
643     else
644     {
645         qos = OC_HIGH_QOS;
646     }
647
648     OCStackResult result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE,
649                                qos,
650                                deleteReqCB, NULL, 0);
651
652     if (OC_STACK_OK != result)
653     {
654         OIC_LOG(INFO, TAG, "Second DELETE call did not succeed");
655     }
656
657     return NULL;
658 }
659
660 int InitDeleteRequest(OCQualityOfService qos)
661 {
662     OCStackResult result;
663     std::ostringstream query;
664     query << coapServerResource;
665
666     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
667
668     // First DELETE operation
669     result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE,
670                                qos,
671                                deleteReqCB, NULL, 0);
672     if (OC_STACK_OK != result)
673     {
674         // Error can happen if for example, network connectivity is down
675         OIC_LOG(INFO, TAG, "First DELETE call did not succeed");
676     }
677     else
678     {
679         //Create a thread to delete this resource again
680         pthread_t threadId;
681         pthread_create (&threadId, NULL, RequestDeleteDeathResourceTask, (void*)qos);
682     }
683
684     OIC_LOG_V(INFO, TAG, "\n\nExit  %s", __func__);
685     return result;
686 }
687
688 int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions, bool getWithQuery)
689 {
690
691     OCHeaderOption options[MAX_HEADER_OPTIONS];
692
693     std::ostringstream query;
694     query << coapServerResource;
695
696     // ocserver is written to only process "power<X" query.
697     if (getWithQuery)
698     {
699         OIC_LOG(INFO, TAG, "Using query power<50");
700         query << "?power<50";
701     }
702     OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
703
704     if (withVendorSpecificHeaderOptions)
705     {
706         uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
707         uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
708         memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
709         options[0].protocolID = OC_COAP_ID;
710         options[0].optionID = 2048;
711         memcpy(options[0].optionData, option0, sizeof(option0));
712         options[0].optionLength = 10;
713         options[1].protocolID = OC_COAP_ID;
714         options[1].optionID = 3000;
715         memcpy(options[1].optionData, option1, sizeof(option1));
716         options[1].optionLength = 10;
717     }
718     if (withVendorSpecificHeaderOptions)
719     {
720         return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET,
721                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, options, 2));
722     }
723     else
724     {
725         return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET,
726                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, NULL, 0));
727     }
728 }
729
730 int InitPlatformDiscovery(OCQualityOfService qos)
731 {
732     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
733
734     OCStackResult ret;
735     OCCallbackData cbData;
736     char szQueryUri[64] = { 0 };
737
738     snprintf(szQueryUri, sizeof (szQueryUri) - 1, PLATFORM_DISCOVERY_QUERY, discoveryAddr);
739
740     cbData.cb = PlatformDiscoveryReqCB;
741     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
742     cbData.cd = NULL;
743
744     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
745                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
746                        &cbData, NULL, 0);
747     if (ret != OC_STACK_OK)
748     {
749         OIC_LOG(ERROR, TAG, "OCStack device error");
750     }
751
752     return ret;
753 }
754
755 int InitDeviceDiscovery(OCQualityOfService qos)
756 {
757     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
758
759     OCStackResult ret;
760     OCCallbackData cbData;
761     char szQueryUri[100] = { 0 };
762
763     snprintf(szQueryUri, sizeof (szQueryUri) - 1, DEVICE_DISCOVERY_QUERY, discoveryAddr);
764
765     cbData.cb = DeviceDiscoveryReqCB;
766     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
767     cbData.cd = NULL;
768
769     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
770                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
771                        &cbData, NULL, 0);
772     if (ret != OC_STACK_OK)
773     {
774         OIC_LOG(ERROR, TAG, "OCStack device error");
775     }
776
777     return ret;
778 }
779
780 int InitDiscovery(OCQualityOfService qos)
781 {
782     OCStackResult ret;
783     OCCallbackData cbData;
784     char szQueryUri[100] = { 0 };
785
786     snprintf(szQueryUri, sizeof (szQueryUri) - 1, RESOURCE_DISCOVERY_QUERY, discoveryAddr);
787
788     cbData.cb = discoveryReqCB;
789     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
790     cbData.cd = NULL;
791
792     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
793                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
794                        &cbData, NULL, 0);
795     if (ret != OC_STACK_OK)
796     {
797         OIC_LOG(ERROR, TAG, "OCStack resource error");
798     }
799     return ret;
800 }
801
802 int main(int argc, char* argv[])
803 {
804     int opt;
805
806     while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
807     {
808         switch(opt)
809         {
810             case 'u':
811                 UnicastDiscovery = atoi(optarg);
812                 break;
813             case 't':
814                 TestCase = atoi(optarg);
815                 break;
816             case 'c':
817                 Connectivity = atoi(optarg);
818                 break;
819             default:
820                 PrintUsage();
821                 return -1;
822         }
823     }
824
825     if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
826             (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) ||
827             (Connectivity < CT_ADAPTER_DEFAULT || Connectivity >= MAX_CT))
828     {
829         PrintUsage();
830         return -1;
831     }
832
833     if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
834     {
835         OIC_LOG(ERROR, TAG, "OCStack init error");
836         return 0;
837     }
838
839 #ifdef ROUTING_GATEWAY
840     /*
841      * Before invoking Discover resource, we process the gateway requests
842      * and form the routing table.
843      */
844     for (int index = 0; index < MAX_NUM_GATEWAY_REQUEST; index++)
845     {
846         if (OC_STACK_OK != OCProcess())
847         {
848             OIC_LOG(ERROR, TAG, "OCStack process error");
849             return 0;
850         }
851         usleep(SLEEP_DURATION);
852     }
853 #endif
854     if (Connectivity == CT_ADAPTER_DEFAULT || Connectivity == CT_IP)
855     {
856         ConnType = CT_ADAPTER_IP;
857     }
858     else
859     {
860         OIC_LOG(INFO, TAG, "Default Connectivity type selected...");
861         PrintUsage();
862     }
863
864     discoveryAddr[0] = '\0';
865
866     if (UnicastDiscovery)
867     {
868         OIC_LOG(INFO, TAG, "Enter IP address of server with optional port number");
869         OIC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
870         OIC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
871
872         if (fgets(discoveryAddr, sizeof (discoveryAddr), stdin))
873         {
874             //Strip newline char from ipv4addr
875             StripNewLineChar(discoveryAddr);
876         }
877         else
878         {
879             OIC_LOG(ERROR, TAG, "!! Bad input for IP address. !!");
880             return OC_STACK_INVALID_PARAM;
881         }
882     }
883
884     if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_DEV_REQ)
885     {
886         InitDeviceDiscovery(OC_LOW_QOS);
887     }
888     else if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_PLATFORM_REQ)
889     {
890         InitPlatformDiscovery(OC_LOW_QOS);
891     }
892     else
893     {
894         InitDiscovery(OC_LOW_QOS);
895     }
896
897     // Break from loop with Ctrl+C
898     OIC_LOG(INFO, TAG, "Entering occlient main loop...");
899     signal(SIGINT, handleSigInt);
900     while (!gQuitFlag)
901     {
902
903         if (OCProcess() != OC_STACK_OK)
904         {
905             OIC_LOG(ERROR, TAG, "OCStack process error");
906             return 0;
907         }
908 #ifndef ROUTING_GATEAWAY
909         sleep(1);
910 #endif
911     }
912     OIC_LOG(INFO, TAG, "Exiting occlient main loop...");
913
914     if (OCStop() != OC_STACK_OK)
915     {
916         OIC_LOG(ERROR, TAG, "OCStack stop error");
917     }
918
919     return 0;
920 }
921
922 std::string getConnectivityType (OCConnectivityType connType)
923 {
924     switch (connType & CT_MASK_ADAPTER)
925     {
926         case CT_ADAPTER_IP:
927             return "IP";
928
929         case CT_IP_USE_V4:
930             return "IPv4";
931
932         case CT_IP_USE_V6:
933             return "IPv6";
934
935         case CT_ADAPTER_GATT_BTLE:
936             return "GATT";
937
938         case CT_ADAPTER_RFCOMM_BTEDR:
939             return "RFCOMM";
940
941         default:
942             return "Incorrect connectivity";
943     }
944 }