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