Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / resource / examples / presenceclient.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 // PresenceClient.cpp : A client example for presence notification
22 //
23 #include <string>
24 #include <cstdlib>
25 #include <pthread.h>
26 #include <mutex>
27 #include <condition_variable>
28
29 #include "OCPlatform.h"
30 #include "OCApi.h"
31
32 using namespace OC;
33
34 std::shared_ptr<OCResource> curResource;
35 std::mutex resourceLock;
36 static int TEST_CASE = 0;
37
38 static OCConnectivityType connectivityType = OC_IPV4;
39
40 /**
41  * List of methods that can be inititated from the client
42  */
43 typedef enum {
44     TEST_UNICAST_PRESENCE_NORMAL = 1,
45     TEST_UNICAST_PRESENCE_WITH_FILTER,
46     TEST_UNICAST_PRESENCE_WITH_FILTERS,
47     TEST_MULTICAST_PRESENCE_NORMAL,
48     TEST_MULTICAST_PRESENCE_WITH_FILTER,
49     TEST_MULTICAST_PRESENCE_WITH_FILTERS,
50     MAX_TESTS
51 } CLIENT_TEST;
52
53 void printUsage()
54 {
55     std::cout << "Usage : presenceclient -t <1|2|3|4|5|6> -c <0|1>" << std::endl;
56     std::cout << "-t 1 : Discover Resources and Initiate Unicast Presence" << std::endl;
57     std::cout << "-t 2 : Discover Resources and Initiate Unicast Presence with Filter"
58               << std::endl;
59     std::cout << "-t 3 : Discover Resources and Initiate Unicast Presence with Two Filters"
60               << std::endl;
61     std::cout << "-t 4 : Discover Resources and Initiate Multicast Presence" << std::endl;
62     std::cout << "-t 5 : Discover Resources and Initiate Multicast Presence with Filter"
63               << std::endl;
64     std::cout << "-t 6 : Discover Resources and Initiate Multicast Presence with two Filters"
65             << std::endl;
66     std::cout<<"ConnectivityType: Default IPv4" << std::endl;
67     std::cout << "-c 0 : Send message with IPv4" << std::endl;
68     std::cout << "-c 1 : Send message with IPv6" << std::endl;
69 }
70
71 // Callback to presence
72 void presenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress)
73 {
74     std::cout << "Received presence notification from : " << hostAddress << std::endl;
75     std::cout << "In presenceHandler: ";
76
77     switch(result)
78     {
79         case OC_STACK_OK:
80             std::cout << "Nonce# " << nonce << std::endl;
81             break;
82         case OC_STACK_PRESENCE_STOPPED:
83             std::cout << "Presence Stopped\n";
84             break;
85         case OC_STACK_PRESENCE_TIMEOUT:
86             std::cout << "Presence Timeout\n";
87             break;
88         default:
89             std::cout << "Error\n";
90             break;
91     }
92 }
93
94 // Callback to found resources
95 void foundResource(std::shared_ptr<OCResource> resource)
96 {
97     std::lock_guard<std::mutex> lock(resourceLock);
98     if(curResource)
99     {
100         std::cout << "Found another resource, ignoring"<<std::endl;
101         return;
102     }
103
104     std::string resourceURI;
105     std::string hostAddress;
106     try
107     {
108         // Do some operations with resource object.
109         if(resource)
110         {
111             std::cout<<"DISCOVERED Resource:"<<std::endl;
112             // Get the resource URI
113             resourceURI = resource->uri();
114             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
115
116             // Get the resource host address
117             hostAddress = resource->host();
118             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
119
120             // Get the resource types
121             std::cout << "\tList of resource types: " << std::endl;
122             for(auto &resourceTypes : resource->getResourceTypes())
123             {
124                 std::cout << "\t\t" << resourceTypes << std::endl;
125             }
126
127             // Get the resource interfaces
128             std::cout << "\tList of resource interfaces: " << std::endl;
129             for(auto &resourceInterfaces : resource->getResourceInterfaces())
130             {
131                 std::cout << "\t\t" << resourceInterfaces << std::endl;
132             }
133
134             if(resourceURI == "/a/light")
135             {
136                 OCStackResult result = OC_STACK_OK;
137                 curResource = resource;
138                 OCPlatform::OCPresenceHandle presenceHandle = nullptr;
139
140                 if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL)
141                 {
142                     result = OCPlatform::subscribePresence(presenceHandle, hostAddress,
143                             connectivityType, &presenceHandler);
144                     if(result == OC_STACK_OK)
145                     {
146                         std::cout<< "Subscribed to unicast address: " << hostAddress << std::endl;
147                     }
148                     else
149                     {
150                         std::cout<< "Failed to subscribe to unicast address:" << hostAddress
151                                 << std::endl;
152                     }
153                 }
154                 if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTER ||
155                         TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS)
156                 {
157                     result = OCPlatform::subscribePresence(presenceHandle, hostAddress,
158                             "core.light", connectivityType, &presenceHandler);
159                     if(result == OC_STACK_OK)
160                     {
161                         std::cout<< "Subscribed to unicast address: " << hostAddress;
162                     }
163                     else
164                     {
165                         std::cout<< "Failed to subscribe to unicast address: " << hostAddress;
166                     }
167                     std::cout << " with resource type \"core.light\"." << std::endl;
168                 }
169                 if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS)
170                 {
171                     result = OCPlatform::subscribePresence(presenceHandle, hostAddress, "core.fan",
172                             connectivityType, &presenceHandler);
173                     if(result == OC_STACK_OK)
174                     {
175                         std::cout<< "Subscribed to unicast address: " << hostAddress;
176                     }
177                     else
178                     {
179                         std::cout<< "Failed to subscribe to unicast address: " << hostAddress;
180                     }
181                     std::cout << " with resource type \"core.fan\"." << std::endl;
182                 }
183             }
184         }
185         else
186         {
187             // Resource is invalid
188             std::cout << "Resource is invalid" << std::endl;
189         }
190
191     }
192     catch(std::exception& e)
193     {
194         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
195         //log(e.what());
196     }
197 }
198
199 int main(int argc, char* argv[]) {
200
201     std::ostringstream requestURI;
202
203     int opt;
204
205     int optionSelected;
206
207     try
208     {
209         while ((opt = getopt(argc, argv, "t:c:")) != -1)
210         {
211             switch(opt)
212             {
213                 case 't':
214                     TEST_CASE = std::stoi(optarg);
215                     break;
216                 case 'c':
217                     std::size_t inputValLen;
218                     optionSelected = std::stoi(optarg, &inputValLen);
219
220                     if(inputValLen == strlen(optarg))
221                     {
222                         if(optionSelected == 0)
223                         {
224                             connectivityType = OC_IPV4;
225                         }
226                         else if(optionSelected == 1)
227                         {
228                             // TODO: re-enable IPv4/IPv6 command line selection when IPv6
229                             // is supported
230                             //connectivityType = OC_IPV6;
231                             connectivityType = OC_IPV4;
232                             std::cout << "IPv6 not currently supported. Using default IPv4"
233                                     << std::endl;
234                         }
235                         else
236                         {
237                             std::cout << "Invalid connectivity type selected. Using default IPv4"
238                                 << std::endl;
239                         }
240                     }
241                     else
242                     {
243                         std::cout << "Invalid connectivity type selected. Using default IPv4"
244                             << std::endl;
245                     }
246                     break;
247                 default:
248                     printUsage();
249                     return -1;
250             }
251         }
252     }
253     catch(std::exception& )
254     {
255         std::cout << "Invalid input argument. Using IPv4 as connectivity type"
256             << std::endl;
257     }
258
259     if(TEST_CASE >= MAX_TESTS || TEST_CASE <= 0)
260     {
261         printUsage();
262         return -1;
263     }
264
265     // Create PlatformConfig object
266     PlatformConfig cfg {
267         OC::ServiceType::InProc,
268         OC::ModeType::Client,
269         "0.0.0.0",
270         0,
271         OC::QualityOfService::LowQos
272     };
273
274     OCPlatform::Configure(cfg);
275
276     try
277     {
278         std::cout << "Created Platform..."<<std::endl;
279
280         OCPlatform::OCPresenceHandle presenceHandle = nullptr;
281         OCStackResult result = OC_STACK_OK;
282
283         std::ostringstream multicastPresenceURI;
284         multicastPresenceURI << "coap://" << OC_MULTICAST_PREFIX;
285
286         if(TEST_CASE == TEST_MULTICAST_PRESENCE_NORMAL)
287         {
288             result = OCPlatform::subscribePresence(presenceHandle,
289                     multicastPresenceURI.str(), connectivityType, presenceHandler);
290
291             if(result == OC_STACK_OK)
292             {
293                 std::cout << "Subscribed to multicast presence." << std::endl;
294             }
295             else
296             {
297                 std::cout << "Failed to subscribe to multicast presence." << std::endl;
298             }
299         }
300         else if(TEST_CASE == TEST_MULTICAST_PRESENCE_WITH_FILTER)
301         {
302             result = OCPlatform::subscribePresence(presenceHandle, multicastPresenceURI.str(), "core.light",
303                     connectivityType, &presenceHandler);
304             if(result == OC_STACK_OK)
305             {
306                 std::cout << "Subscribed to multicast presence with resource type";
307             }
308             else
309             {
310                 std::cout << "Failed to subscribe to multicast presence with resource type";
311             }
312             std::cout << "\"core.light\"." << std::endl;
313         }
314         else if(TEST_CASE == TEST_MULTICAST_PRESENCE_WITH_FILTERS)
315         {
316             result = OCPlatform::subscribePresence(presenceHandle, multicastPresenceURI.str(), "core.light",
317                     connectivityType, &presenceHandler);
318             if(result == OC_STACK_OK)
319             {
320                 std::cout << "Subscribed to multicast presence with resource type";
321             }
322             else
323             {
324                 std::cout << "Failed to subscribe to multicast presence with resource type";
325             }
326             std::cout << "\"core.light\"." << std::endl;
327
328             result = OCPlatform::subscribePresence(presenceHandle, multicastPresenceURI.str(), "core.fan",
329                     connectivityType, &presenceHandler);
330             if(result == OC_STACK_OK)
331             {
332                 std::cout<< "Subscribed to multicast presence with resource type";
333             }
334             else
335             {
336                 std::cout << "Failed to subscribe to multicast presence with resource type.";
337             }
338             std::cout << "\"core.fan\"." << std::endl;
339         }
340         else
341         {
342             // Find all resources
343             requestURI << OC_MULTICAST_DISCOVERY_URI;
344
345             result = OCPlatform::findResource("", requestURI.str(),
346                     OC_ALL, &foundResource);
347             if(result == OC_STACK_OK)
348             {
349                 std::cout << "Finding Resource... " << std::endl;
350             }
351             else
352             {
353                 std::cout << "Failed to request to find resource(s)." << std::endl;
354             }
355         }
356         //
357         // A condition variable will free the mutex it is given, then do a non-
358         // intensive block until 'notify' is called on it.  In this case, since we
359         // don't ever call cv.notify, this should be a non-processor intensive version
360         // of while(true);
361         std::mutex blocker;
362         std::condition_variable cv;
363         std::unique_lock<std::mutex> lock(blocker);
364         cv.wait(lock);
365
366     }
367     catch(OCException& e)
368     {
369         oclog() << "Exception in main: "<< e.what();
370     }
371
372     return 0;
373 }
374
375