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