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