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