Add pthread_join() in case of failure of ca_thread_pool_add_task()
[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 #include <getopt.h>
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 = CT_ADAPTER_IP;
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 IP" << std::endl;
67     std::cout << "-c 0 : Send message with IP" << std::endl;
68 }
69
70 // Callback to presence
71 void presenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress)
72 {
73     std::cout << "Received presence notification from : " << hostAddress << std::endl;
74     std::cout << "In presenceHandler: ";
75
76     switch(result)
77     {
78         case OC_STACK_OK:
79             std::cout << "Nonce# " << nonce << std::endl;
80             break;
81         case OC_STACK_PRESENCE_STOPPED:
82             std::cout << "Presence Stopped\n";
83             break;
84         case OC_STACK_PRESENCE_TIMEOUT:
85             std::cout << "Presence Timeout\n";
86             break;
87         default:
88             std::cout << "Error\n";
89             break;
90     }
91 }
92
93 // Callback to found resources
94 void foundResource(std::shared_ptr<OCResource> resource)
95 {
96     std::lock_guard<std::mutex> lock(resourceLock);
97     if(curResource)
98     {
99         std::cout << "Found another resource, ignoring"<<std::endl;
100         return;
101     }
102
103     std::string resourceURI;
104     std::string hostAddress;
105     try
106     {
107         // Do some operations with resource object.
108         if(resource)
109         {
110             std::cout<<"DISCOVERED Resource:"<<std::endl;
111             // Get the resource URI
112             resourceURI = resource->uri();
113             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
114
115             // Get the resource host address
116             hostAddress = resource->host();
117             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
118
119             // Get the resource types
120             std::cout << "\tList of resource types: " << std::endl;
121             for(auto &resourceTypes : resource->getResourceTypes())
122             {
123                 std::cout << "\t\t" << resourceTypes << std::endl;
124             }
125
126             // Get the resource interfaces
127             std::cout << "\tList of resource interfaces: " << std::endl;
128             for(auto &resourceInterfaces : resource->getResourceInterfaces())
129             {
130                 std::cout << "\t\t" << resourceInterfaces << std::endl;
131             }
132
133             if(resourceURI == "/a/light")
134             {
135                 OCStackResult result = OC_STACK_OK;
136                 curResource = resource;
137                 OCPlatform::OCPresenceHandle presenceHandle = nullptr;
138
139                 if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL)
140                 {
141                     result = OCPlatform::subscribePresence(presenceHandle, hostAddress,
142                             connectivityType, &presenceHandler);
143                     if(result == OC_STACK_OK)
144                     {
145                         std::cout<< "Subscribed to unicast address: " << hostAddress << std::endl;
146                     }
147                     else
148                     {
149                         std::cout<< "Failed to subscribe to unicast address:" << hostAddress
150                                 << std::endl;
151                     }
152                 }
153                 if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTER ||
154                         TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS)
155                 {
156                     result = OCPlatform::subscribePresence(presenceHandle, hostAddress,
157                             "core.light", connectivityType, &presenceHandler);
158                     if(result == OC_STACK_OK)
159                     {
160                         std::cout<< "Subscribed to unicast address: " << hostAddress;
161                     }
162                     else
163                     {
164                         std::cout<< "Failed to subscribe to unicast address: " << hostAddress;
165                     }
166                     std::cout << " with resource type \"core.light\"." << std::endl;
167                 }
168                 if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS)
169                 {
170                     result = OCPlatform::subscribePresence(presenceHandle, hostAddress, "core.fan",
171                             connectivityType, &presenceHandler);
172                     if(result == OC_STACK_OK)
173                     {
174                         std::cout<< "Subscribed to unicast address: " << hostAddress;
175                     }
176                     else
177                     {
178                         std::cout<< "Failed to subscribe to unicast address: " << hostAddress;
179                     }
180                     std::cout << " with resource type \"core.fan\"." << std::endl;
181                 }
182             }
183         }
184         else
185         {
186             // Resource is invalid
187             std::cout << "Resource is invalid" << std::endl;
188         }
189
190     }
191     catch(std::exception& e)
192     {
193         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
194         //log(e.what());
195     }
196 }
197
198 int main(int argc, char* argv[]) {
199
200     std::ostringstream requestURI;
201
202     int opt;
203
204     int optionSelected;
205
206     try
207     {
208         while ((opt = getopt(argc, argv, "t:c:")) != -1)
209         {
210             switch(opt)
211             {
212                 case 't':
213                     TEST_CASE = std::stoi(optarg);
214                     break;
215                 case 'c':
216                     std::size_t inputValLen;
217                     optionSelected = std::stoi(optarg, &inputValLen);
218
219                     if(inputValLen == strlen(optarg))
220                     {
221                         if(optionSelected == 0)
222                         {
223                             std::cout << "Using IP."<< std::endl;
224                             connectivityType = CT_ADAPTER_IP;
225                         }
226                         else
227                         {
228                             std::cout << "Invalid connectivity type selected. Using default IP"
229                                 << std::endl;
230                         }
231                     }
232                     else
233                     {
234                         std::cout << "Invalid connectivity type selected. Using default IP"
235                             << std::endl;
236                     }
237                     break;
238                 default:
239                     printUsage();
240                     return -1;
241             }
242         }
243     }
244     catch(std::exception& )
245     {
246         std::cout << "Invalid input argument. Using IP as connectivity type"
247             << std::endl;
248     }
249
250     if(TEST_CASE >= MAX_TESTS || TEST_CASE <= 0)
251     {
252         printUsage();
253         return -1;
254     }
255
256     // Create PlatformConfig object
257     PlatformConfig cfg {
258         OC::ServiceType::InProc,
259         OC::ModeType::Client,
260         "0.0.0.0",
261         0,
262         OC::QualityOfService::LowQos
263     };
264
265     OCPlatform::Configure(cfg);
266
267     try
268     {
269         std::cout << "Created Platform..."<<std::endl;
270
271         OCPlatform::OCPresenceHandle presenceHandle = nullptr;
272         OCStackResult result = OC_STACK_OK;
273
274         if(TEST_CASE == TEST_MULTICAST_PRESENCE_NORMAL)
275         {
276             result = OCPlatform::subscribePresence(presenceHandle,
277                                                    "",
278                                                    connectivityType,
279                                                    presenceHandler);
280
281             if(result == OC_STACK_OK)
282             {
283                 std::cout << "Subscribed to multicast presence." << std::endl;
284             }
285             else
286             {
287                 std::cout << "Failed to subscribe to multicast presence." << std::endl;
288             }
289         }
290         else if(TEST_CASE == TEST_MULTICAST_PRESENCE_WITH_FILTER)
291         {
292             result = OCPlatform::subscribePresence(presenceHandle,
293                                                    "", "core.light",
294                                                    connectivityType,
295                                                    &presenceHandler);
296             if(result == OC_STACK_OK)
297             {
298                 std::cout << "Subscribed to multicast presence with resource type";
299             }
300             else
301             {
302                 std::cout << "Failed to subscribe to multicast presence with resource type";
303             }
304             std::cout << "\"core.light\"." << std::endl;
305         }
306         else if(TEST_CASE == TEST_MULTICAST_PRESENCE_WITH_FILTERS)
307         {
308             result = OCPlatform::subscribePresence(presenceHandle,
309                                                    "", "core.light",
310                                                    connectivityType,
311                                                    &presenceHandler);
312             if(result == OC_STACK_OK)
313             {
314                 std::cout << "Subscribed to multicast presence with resource type";
315             }
316             else
317             {
318                 std::cout << "Failed to subscribe to multicast presence with resource type";
319             }
320             std::cout << "\"core.light\"." << std::endl;
321
322             result = OCPlatform::subscribePresence(presenceHandle,
323                                                    "", "core.fan",
324                                                    connectivityType,
325                                                    &presenceHandler);
326             if(result == OC_STACK_OK)
327             {
328                 std::cout<< "Subscribed to multicast presence with resource type";
329             }
330             else
331             {
332                 std::cout << "Failed to subscribe to multicast presence with resource type.";
333             }
334             std::cout << "\"core.fan\"." << std::endl;
335         }
336         else
337         {
338             // Find all resources
339             requestURI << OC_RSRVD_WELL_KNOWN_URI;
340
341             result = OCPlatform::findResource("", requestURI.str(),
342                     CT_DEFAULT, &foundResource);
343             if(result == OC_STACK_OK)
344             {
345                 std::cout << "Finding Resource... " << std::endl;
346             }
347             else
348             {
349                 std::cout << "Failed to request to find resource(s)." << std::endl;
350             }
351         }
352         //
353         // A condition variable will free the mutex it is given, then do a non-
354         // intensive block until 'notify' is called on it.  In this case, since we
355         // don't ever call cv.notify, this should be a non-processor intensive version
356         // of while(true);
357         std::mutex blocker;
358         std::condition_variable cv;
359         std::unique_lock<std::mutex> lock(blocker);
360         cv.wait(lock);
361
362     }
363     catch(OCException& e)
364     {
365         oclog() << "Exception in main: "<< e.what();
366     }
367
368     return 0;
369 }
370
371