Correct observe callback function in occlient.
[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         if (clientResponse->sequenceNumber <= MAX_SEQUENCE_NUMBER)
293         {
294             if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
295             {
296                 cout << "This also serves as a registration confirmation" << endl;
297             }
298
299             cout << "\nStackResult: " << getResult(clientResponse->result);
300             cout << "\nSEQUENCE NUMBER: " << clientResponse->sequenceNumber;
301             cout << "\nCallback Context for OBSERVE notification recvd successfully ";
302             //OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
303             gNumObserveNotifies++;
304
305             if (gNumObserveNotifies == 15) //large number to test observing in DELETE case.
306             {
307                 if (g_testCase == TEST_OBS_REQ_NON || g_testCase == TEST_OBS_REQ_CON)
308                 {
309                     if (OCCancel(gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
310                     {
311                         cout << "Observe cancel error" << endl;
312                     }
313                     return OC_STACK_DELETE_TRANSACTION;
314                 }
315                 else if (g_testCase == TEST_OBS_REQ_NON_CANCEL_IMM)
316                 {
317                     if (OCCancel(gObserveDoHandle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK)
318                     {
319                         cout << "\nObserve cancel error";
320                     }
321                 }
322             }
323         }
324         else
325         {
326             OIC_LOG(INFO, TAG, "No observe option header is returned in the response.");
327             OIC_LOG(INFO, TAG, "For a registration request, it means the registration failed");
328             return OC_STACK_DELETE_TRANSACTION;
329         }
330     }
331     else
332     {
333         cout << "\nobsReqCB received Null clientResponse";
334     }
335     return OC_STACK_KEEP_TRANSACTION;
336 }
337 #ifdef WITH_PRESENCE
338 OCStackApplicationResult presenceCB(void* ctx, OCDoHandle /*handle*/,
339                                     OCClientResponse * clientResponse)
340 {
341     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
342     {
343         cout << "\nCallback Context for Presence recvd successfully";
344     }
345
346     if (clientResponse)
347     {
348         cout << "\nStackResult: " << getResult(clientResponse->result);
349         cout << "\nNONCE NUMBER: " << clientResponse->sequenceNumber;
350         cout << "\nCallback Context for Presence notification recvd successfully ";
351         //OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
352         gNumPresenceNotifies++;
353         if (gNumPresenceNotifies == 20)
354         {
355             if (OCCancel(gPresenceHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
356             {
357                 cout << "\nPresence cancel error";
358             }
359             return OC_STACK_DELETE_TRANSACTION;
360         }
361     }
362     else
363     {
364         cout << "\npresenceCB received Null clientResponse";
365     }
366     return OC_STACK_KEEP_TRANSACTION;
367 }
368 #endif
369
370 // This is a function called back when a device is discovered
371 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
372                                         OCClientResponse * clientResponse)
373 {
374     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
375     {
376         cout << "\nCallback Context for DISCOVER query recvd successfully";
377     }
378
379     if (clientResponse)
380     {
381         if (NULL == clientResponse->payload)
382         {
383             cout << "\nPayload is NULL, No resources found";
384             return OC_STACK_KEEP_TRANSACTION;
385         }
386
387         cout << "\nStackResult: " << getResult(clientResponse->result);
388
389         std::string connectionType = getConnectivityType (clientResponse->connType);
390         cout << "\nDiscovered on " << connectionType.c_str();
391         cout << "\nDevice ======> Discovered ";
392         cout << clientResponse->devAddr.addr;
393         if (CT_ADAPTER_IP == clientResponse->connType)
394         {
395             cout << ":" << clientResponse->devAddr.port;
396         }
397         //OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
398         cout << "\nConnectivity type: " << clientResponse->connType;
399         g_connType = clientResponse->connType;
400         g_serverAddr = clientResponse->devAddr;
401         parseClientResponse(clientResponse);
402
403         switch(g_testCase)
404         {
405             case TEST_GET_REQ_NON:
406                 InitGetRequest(OC_LOW_QOS, 0, 0);
407                 break;
408             case TEST_GET_REQ_NON_WITH_FILTERS:
409                 InitGetRequest(OC_LOW_QOS, 0, 1);
410                 break;
411             case TEST_PUT_REQ_NON:
412                 InitPutRequest(OC_LOW_QOS);
413                 break;
414             case TEST_POST_REQ_NON:
415                 InitPostRequest(OC_LOW_QOS);
416                 break;
417             case TEST_DELETE_REQ_NON:
418                 InitDeleteRequest(OC_LOW_QOS);
419                 break;
420             case TEST_OBS_REQ_NON:
421             case TEST_OBS_REQ_NON_CANCEL_IMM:
422                 InitObserveRequest(OC_LOW_QOS);
423                 break;
424             case TEST_GET_UNAVAILABLE_RES_REQ_NON:
425                 InitGetRequestToUnavailableResource(OC_LOW_QOS);
426                 break;
427             case TEST_GET_REQ_CON:
428                 InitGetRequest(OC_HIGH_QOS, 0, 0);
429                 break;
430             case TEST_POST_REQ_CON:
431                 InitPostRequest(OC_HIGH_QOS);
432                 break;
433             case TEST_DELETE_REQ_CON:
434                 InitDeleteRequest(OC_HIGH_QOS);
435                 break;
436             case TEST_OBS_REQ_CON:
437                 InitObserveRequest(OC_HIGH_QOS);
438                 break;
439 #ifdef WITH_PRESENCE
440             case TEST_OBS_PRESENCE:
441             case TEST_OBS_PRESENCE_WITH_FILTER:
442             case TEST_OBS_PRESENCE_WITH_FILTERS:
443             case TEST_OBS_MULTICAST_PRESENCE:
444                 InitPresence();
445                 break;
446 #endif
447             case TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS:
448                 InitGetRequest(OC_LOW_QOS, 1, 0);
449                 break;
450             case TEST_DISCOVER_PLATFORM_REQ:
451                 InitPlatformDiscovery(OC_LOW_QOS);
452                 break;
453             case TEST_DISCOVER_DEV_REQ:
454                 InitDeviceDiscovery(OC_LOW_QOS);
455                 break;
456             default:
457                 PrintUsage();
458                 break;
459         }
460     }
461     else
462     {
463         cout << "\ndiscoveryReqCB received Null clientResponse";
464     }
465     return OC_STACK_KEEP_TRANSACTION;
466 }
467
468 OCStackApplicationResult PlatformDiscoveryReqCB(void* ctx,
469                                                 OCDoHandle /*handle*/,
470                                                 OCClientResponse * clientResponse)
471 {
472     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
473     {
474         cout << "\nCallback Context for Platform DISCOVER query recvd successfully";
475     }
476
477     if (clientResponse)
478     {
479         //OIC_LOG truncates the response as it is too long.
480         //OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
481     }
482     else
483     {
484         cout << "\nPlatformDiscoveryReqCB received Null clientResponse";
485     }
486
487     return (g_unicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
488 }
489
490 OCStackApplicationResult DeviceDiscoveryReqCB(void* ctx, OCDoHandle /*handle*/,
491                                               OCClientResponse * clientResponse)
492 {
493     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
494     {
495         cout << "\nCallback Context for Device DISCOVER query recvd successfully";
496     }
497
498     if (clientResponse)
499     {
500         //OIC_LOG truncates the response as it is too long.
501         cout << "\nDiscovery response: ";
502         cout << clientResponse->payload;
503     }
504     else
505     {
506         cout << "\nPlatformDiscoveryReqCB received Null clientResponse";
507     }
508
509     return (g_unicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
510 }
511
512 #ifdef WITH_PRESENCE
513 int InitPresence()
514 {
515     OCStackResult result = OC_STACK_OK;
516     cout << "\nExecuting " << __func__;
517     std::ostringstream query;
518     std::ostringstream querySuffix;
519     query << OC_RSRVD_PRESENCE_URI;
520     if (g_testCase == TEST_OBS_PRESENCE)
521     {
522         result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_PRESENCE,
523                 OC_LOW_QOS, presenceCB, NULL, 0);
524     }
525     if (g_testCase == TEST_OBS_PRESENCE_WITH_FILTER || g_testCase == TEST_OBS_PRESENCE_WITH_FILTERS)
526     {
527         querySuffix.str("");
528         querySuffix << query.str() << "?rt=core.led";
529         result = InvokeOCDoResource(querySuffix, &g_serverAddr, OC_REST_PRESENCE,
530                 OC_LOW_QOS, presenceCB, NULL, 0);
531     }
532     if (g_testCase == TEST_OBS_PRESENCE_WITH_FILTERS)
533     {
534         if (result == OC_STACK_OK)
535         {
536             querySuffix.str("");
537             querySuffix << query.str() << "?rt=core.fan";
538             result = InvokeOCDoResource(querySuffix, &g_serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
539                     presenceCB, NULL, 0);
540         }
541     }
542     if (g_testCase == TEST_OBS_MULTICAST_PRESENCE)
543     {
544         if (result == OC_STACK_OK)
545         {
546             std::ostringstream multicastPresenceQuery;
547             multicastPresenceQuery.str("");
548             multicastPresenceQuery << "coap://" << OC_MULTICAST_PREFIX << OC_RSRVD_PRESENCE_URI;
549             result = InvokeOCDoResource(multicastPresenceQuery, &g_serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
550                     presenceCB, NULL, 0);
551         }
552     }
553     return result;
554 }
555 #endif
556
557 int InitGetRequestToUnavailableResource(OCQualityOfService qos)
558 {
559     cout << "\nExecuting " << __func__;
560     std::ostringstream query;
561     query << "/SomeUnknownResource";
562     return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
563             getReqCB, NULL, 0));
564 }
565
566 int InitObserveRequest(OCQualityOfService qos)
567 {
568     cout << "\nExecuting " << __func__;
569     std::ostringstream query;
570     query << coapServerResource;
571     return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_OBSERVE,
572               (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
573 }
574
575 int InitPutRequest(OCQualityOfService qos)
576 {
577     cout << "\nExecuting " << __func__;
578     std::ostringstream query;
579     query << coapServerResource;
580     return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
581             putReqCB, NULL, 0));
582 }
583
584 int InitPostRequest(OCQualityOfService qos)
585 {
586     OCStackResult result;
587     cout << "\nExecuting " << __func__;
588     std::ostringstream query;
589     query << coapServerResource;
590
591     // First POST operation (to create an Light instance)
592     result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_POST,
593                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
594                                postReqCB, NULL, 0);
595     if (OC_STACK_OK != result)
596     {
597         // Error can happen if for example, network connectivity is down
598         cout << "\nFirst POST call did not succeed";
599     }
600
601     // Second POST operation (to create an Light instance)
602     result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_POST,
603                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
604                                postReqCB, NULL, 0);
605     if (OC_STACK_OK != result)
606     {
607         cout << "\nSecond POST call did not succeed";
608     }
609
610     // This POST operation will update the original resourced /a/light
611     return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_POST,
612                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
613                                postReqCB, NULL, 0));
614 }
615
616 void* RequestDeleteDeathResourceTask(void* myqos)
617 {
618     sleep (30);//long enough to give the server time to finish deleting the resource.
619     std::ostringstream query;
620     query << coapServerResource;
621
622     cout << "\nExecuting " << __func__;
623
624     // Second DELETE operation to delete the resource that might have been removed already.
625     OCQualityOfService qos;
626     if (myqos == NULL)
627     {
628         qos = OC_LOW_QOS;
629     }
630     else
631     {
632         qos = OC_HIGH_QOS;
633     }
634
635     OCStackResult result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_DELETE,
636                                qos,
637                                deleteReqCB, NULL, 0);
638
639     if (OC_STACK_OK != result)
640     {
641         cout << "\nSecond DELETE call did not succeed";
642     }
643
644     return NULL;
645 }
646
647 int InitDeleteRequest(OCQualityOfService qos)
648 {
649     OCStackResult result;
650     std::ostringstream query;
651     query << coapServerResource;
652
653     cout << "\nExecuting " << __func__;
654
655     // First DELETE operation
656     result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_DELETE,
657                                qos,
658                                deleteReqCB, NULL, 0);
659     if (OC_STACK_OK != result)
660     {
661         // Error can happen if for example, network connectivity is down
662         cout << "\nFirst DELETE call did not succeed";
663     }
664     else
665     {
666         //Create a thread to delete this resource again
667         pthread_t threadId;
668         pthread_create (&threadId, NULL, RequestDeleteDeathResourceTask, (void*)qos);
669     }
670
671     cout << "\nExit  " << __func__;
672     return result;
673 }
674
675 int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions, bool getWithQuery)
676 {
677
678     OCHeaderOption options[MAX_HEADER_OPTIONS];
679
680     cout << "\nExecuting " << __func__;
681     std::ostringstream query;
682     query << coapServerResource;
683
684     // ocserver is written to only process "power<X" query.
685     if (getWithQuery)
686     {
687         cout << "\nUsing query power<30";
688         query << "?power<50";
689     }
690
691     if (withVendorSpecificHeaderOptions)
692     {
693         uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
694         uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
695         memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
696         options[0].protocolID = OC_COAP_ID;
697         options[0].optionID = 2048;
698         memcpy(options[0].optionData, option0, sizeof(option0));
699         options[0].optionLength = 10;
700         options[1].protocolID = OC_COAP_ID;
701         options[1].optionID = 3000;
702         memcpy(options[1].optionData, option1, sizeof(option1));
703         options[1].optionLength = 10;
704     }
705     if (withVendorSpecificHeaderOptions)
706     {
707         return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_GET,
708                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, options, 2));
709     }
710     else
711     {
712         return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_GET,
713                 (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, NULL, 0));
714     }
715 }
716
717 int InitPlatformDiscovery(OCQualityOfService qos)
718 {
719     cout << "\nExecuting " << __func__;
720
721     OCStackResult ret;
722     OCCallbackData cbData;
723     char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
724
725     snprintf(szQueryUri, sizeof (szQueryUri) - 1, PLATFORM_DISCOVERY_QUERY, g_discoveryAddr);
726
727     cbData.cb = PlatformDiscoveryReqCB;
728     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
729     cbData.cd = NULL;
730
731     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
732                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
733                        &cbData, NULL, 0);
734     if (ret != OC_STACK_OK)
735     {
736         cout << "\nOCStack device error";
737     }
738
739     return ret;
740 }
741
742 int InitDeviceDiscovery(OCQualityOfService qos)
743 {
744     cout << "\nExecuting " << __func__;
745
746     OCStackResult ret;
747     OCCallbackData cbData;
748     char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
749
750     snprintf(szQueryUri, sizeof (szQueryUri) - 1, DEVICE_DISCOVERY_QUERY, g_discoveryAddr);
751
752     cbData.cb = DeviceDiscoveryReqCB;
753     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
754     cbData.cd = NULL;
755
756     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
757                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
758                        &cbData, NULL, 0);
759     if (ret != OC_STACK_OK)
760     {
761         cout << "\nOCStack device error";
762     }
763
764     return ret;
765 }
766
767 int InitDiscovery(OCQualityOfService qos)
768 {
769     OCStackResult ret;
770     OCCallbackData cbData;
771     char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
772
773     snprintf(szQueryUri, sizeof (szQueryUri) - 1, RESOURCE_DISCOVERY_QUERY, g_discoveryAddr);
774
775     cbData.cb = discoveryReqCB;
776     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
777     cbData.cd = NULL;
778
779     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
780                        (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
781                        &cbData, NULL, 0);
782     if (ret != OC_STACK_OK)
783     {
784         cout << "\nOCStack resource error";
785     }
786     return ret;
787 }
788
789 void *GMainLoopThread(void *param)
790 {
791
792     if (g_unicastDiscovery == 0 && g_testCase == TEST_DISCOVER_DEV_REQ)
793     {
794         InitDeviceDiscovery(OC_LOW_QOS);
795     }
796     else if (g_unicastDiscovery == 0 && g_testCase == TEST_DISCOVER_PLATFORM_REQ)
797     {
798         InitPlatformDiscovery(OC_LOW_QOS);
799     }
800     else
801     {
802         InitDiscovery(OC_LOW_QOS);
803     }
804
805     while (!gQuitFlag)
806     {
807         if (OCProcess() != OC_STACK_OK)
808         {
809             cout << "\nOCStack process error";
810             return NULL;
811         }
812 #ifndef ROUTING_GATEWAY
813         sleep(1);
814 #endif
815     }
816
817     if (g_mainloop)
818     {
819         g_main_loop_quit(g_mainloop);
820     }
821     return NULL;
822 }
823
824 int main(int argc, char* argv[])
825 {
826     int opt;
827
828     g_mainloop = g_main_loop_new(NULL, FALSE);
829     if(!g_mainloop)
830     {
831         printf("g_main_loop_new failed\n");
832         return 0;
833     }
834
835     while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
836     {
837         switch(opt)
838         {
839             case 'u':
840                 g_unicastDiscovery = atoi(optarg);
841                 break;
842             case 't':
843                 g_testCase = atoi(optarg);
844                 break;
845             case 'c':
846                 g_connectivity = atoi(optarg);
847                 break;
848             default:
849                 PrintUsage();
850                 return -1;
851         }
852     }
853
854     if ((g_unicastDiscovery != 0 && g_unicastDiscovery != 1) ||
855             (g_testCase < TEST_DISCOVER_REQ || g_testCase >= MAX_TESTS) ||
856             (g_connectivity < CT_ADAPTER_DEFAULT || g_connectivity >= MAX_CT))
857     {
858         PrintUsage();
859         return -1;
860     }
861
862     cout << "\nEntering occlient main loop...\n";
863
864     if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
865     {
866         cout << "\nOCStack init error";
867         return 0;
868     }
869
870 #ifdef ROUTING_GATEWAY
871     /*
872      * Before invoking Discover resource, we process the gateway requests
873      * and form the routing table.
874      */
875     for (int index = 0; index < MAX_NUM_GATEWAY_REQUEST; index++)
876     {
877         if (OCProcess() != OC_STACK_OK)
878         {
879             OIC_LOG(ERROR, TAG, "OCStack process error");
880             return 0;
881         }
882         usleep(SLEEP_DURATION);
883     }
884 #endif
885
886     if (g_connectivity == CT_ADAPTER_DEFAULT || g_connectivity == CT_IP)
887     {
888         g_connType = CT_ADAPTER_IP;
889     }
890     else if(g_connectivity == CT_EDR)
891     {
892         cout << "\nSelected EDR Adapter\n";
893         g_connType = CT_ADAPTER_RFCOMM_BTEDR;
894     }
895     else
896     {
897         cout << "\nDefault Connectivity type selected...";
898         PrintUsage();
899     }
900
901     g_discoveryAddr[0] = '\0';
902
903     if (g_unicastDiscovery)
904     {
905         cout << "\nEnter address of Server hosting resource as given below:";
906         cout << "\nIP Adapter: 192.168.0.15:45454(IP:Port)";
907         cout << "\nEDR/BLE Adapter: AB:BC:CD:DE:EF:FG(MAC Address)";
908         cout << "\nInput:  ";
909
910         if (fgets(g_discoveryAddr, sizeof (g_discoveryAddr), stdin))
911         {
912             //Strip newline char from unicastAddr
913             StripNewLineChar(g_discoveryAddr);
914         }
915         else
916         {
917             cout << "\n!! Bad input for IPV4 address. !!";
918             return OC_STACK_INVALID_PARAM;
919         }
920     }
921
922
923     // Break from loop with Ctrl+C
924     OIC_LOG(INFO, TAG, "Entering occlient main loop...");
925     signal(SIGINT, handleSigInt);
926
927     int result = pthread_create(&g_thread, NULL, GMainLoopThread, (void *)NULL);
928     if (result < 0)
929     {
930         printf("pthread_create failed in initialize\n");
931         return 0;
932     }
933
934     g_main_loop_run(g_mainloop);
935
936     cout << "\nExiting occlient main loop...\n";
937
938     if (OCStop() != OC_STACK_OK)
939     {
940         cout << "\nOCStack stop error\n";
941     }
942
943     return 0;
944 }
945
946 std::string getConnectivityType (OCConnectivityType connType)
947 {
948     switch (connType & CT_MASK_ADAPTER)
949     {
950         case CT_ADAPTER_IP:
951             return "IP";
952
953         case CT_IP_USE_V4:
954             return "IPv4";
955
956         case CT_IP_USE_V6:
957             return "IPv6";
958
959         case CT_ADAPTER_GATT_BTLE:
960             return "GATT";
961
962         case CT_ADAPTER_RFCOMM_BTEDR:
963             return "RFCOMM";
964
965         default:
966             return "Incorrect connectivity";
967     }
968 }
969
970 std::string getQueryStrForGetPut(OCClientResponse * /*clientResponse*/)
971 {
972     return "/a/light";
973 }
974
975 void parseClientResponse(OCClientResponse * clientResponse)
976 {
977     coapServerResource = getQueryStrForGetPut(clientResponse);
978 }
979