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