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