Imported Upstream version 1.2.0
[platform/upstream/iotivity.git] / resource / examples / threadingsample.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 ///
22 /// This sample demonstrates : running one server in main thread, another
23 /// server in a separate thread, and running 2 clients in each thread.
24 ///
25
26 #include "iotivity_config.h"
27
28 #include <memory>
29 #include <iostream>
30 #include <stdexcept>
31 #include <condition_variable>
32 #include <map>
33 #include <vector>
34
35 #include "OCPlatform.h"
36 #include "OCApi.h"
37
38 #ifdef HAVE_WINDOWS_H
39 #include <windows.h>
40 #endif
41
42 using namespace OC;
43
44 static std::ostringstream requestURI;
45
46 struct FooResource
47 {
48     bool m_isFoo;
49     int m_barCount;
50     std::string m_uri;
51     std::string m_resourceType;
52     OCResourceHandle m_resourceHandle;
53     OCRepresentation m_rep;
54
55     FooResource(std::string uri): m_isFoo(true), m_barCount (0),
56                                     m_uri(uri), m_resourceType("core.foo")
57     {
58         m_rep.setUri(m_uri);
59         m_rep.setValue("isFoo", m_isFoo);
60         m_rep.setValue("barCount", m_barCount);
61     }
62
63     bool createResource()
64     {
65         std::string resourceInterface = DEFAULT_INTERFACE;
66
67         uint8_t resourceProperty = OC_DISCOVERABLE;
68
69         EntityHandler eh(std::bind(&FooResource::entityHandler, this,
70                                     std::placeholders::_1));
71         OCStackResult result = OCPlatform::registerResource(m_resourceHandle, m_uri,
72                                     m_resourceType, resourceInterface, eh, resourceProperty);
73         if(OC_STACK_OK != result)
74         {
75             std::cout<<"Resource creation unsuccessful"<<std::endl;
76             return false;
77         }
78
79         return true;
80     }
81
82     OCRepresentation get()
83     {
84         m_rep.setValue("isFoo", m_isFoo);
85         m_rep.setValue("barCount", m_barCount);
86
87         return m_rep;
88     }
89
90     void put(OCRepresentation& rep)
91     {
92         rep.getValue("isFoo", m_isFoo);
93         rep.getValue("barCount", m_barCount);
94     }
95
96     OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
97     {
98         auto pResponse = std::make_shared<OC::OCResourceResponse>();
99         pResponse->setRequestHandle(pRequest->getRequestHandle());
100         pResponse->setResourceHandle(pRequest->getResourceHandle());
101         pResponse->setResourceRepresentation(get(), "");
102         pResponse->setErrorCode(200);
103         pResponse->setResponseResult(OC_EH_OK);
104
105         return OCPlatform::sendResponse(pResponse);
106     }
107
108     OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
109     {
110         std::cout<<"\tConsumer Entity Handler:"<<std::endl;
111         OCEntityHandlerResult ehResult = OC_EH_ERROR;
112
113         if(request)
114         {
115             // Note: Most of the handlers are not here, since this is for demoing client/server
116             // co-process existence. See simpleserver for a more complete example.
117             if(request->getRequestHandlerFlag()  == RequestHandlerFlag::RequestFlag)
118             {
119                 std::cout << "\t\trequestFlag : Request"<<std::endl;
120
121                 if(request->getRequestType() == "GET")
122                 {
123                     std::cout<<"\t\t\trequestType : GET"<<std::endl;
124                     if(OC_STACK_OK == sendResponse(request))
125                     {
126                         ehResult = OC_EH_OK;
127                     }
128                 }
129                 else if (request->getRequestType() == "PUT")
130                 {
131                     std::cout<<"\t\t\trequestType : PUT"<<std::endl;
132
133                     OCRepresentation rep = request->getResourceRepresentation();
134                     put(rep);
135                     if(OC_STACK_OK == sendResponse(request))
136                     {
137                         ehResult = OC_EH_OK;
138                     }
139                 }
140                 else
141                 {
142                     std::cout<<"\t\t\trequestType : UNSUPPORTED: " <<
143                                 request->getRequestType()<<std::endl;
144                 }
145             }
146             else
147             {
148                 std::cout <<"\t\trequestFlag : UNSUPPORTED: ";
149
150                 if(request->getRequestHandlerFlag()== RequestHandlerFlag::ObserverFlag)
151                 {
152                     std::cout<<"ObserverFlag"<<std::endl;
153                 }
154             }
155         }
156         else
157         {
158             std::cout << "Request Invalid!"<<std::endl;
159         }
160
161         return ehResult;
162     }
163 };
164
165 void putResourceInfo(const HeaderOptions& /*headerOptions*/,
166         const OCRepresentation rep, const OCRepresentation /*rep2*/, const int eCode)
167 {
168    bool m_isFoo = false;
169    int m_barCount = 0;
170    std::cout << "In PutResourceInfo" << std::endl;
171
172    std::cout <<"Clientside Put response to get was: "<<std::endl;
173    std::cout <<"ErrorCode: "<<eCode <<std::endl;
174
175    if(eCode == 0)
176    {
177         std::cout<<"Successful Put.  Attributes sent were: "<<std::endl;
178
179         rep.getValue("isFoo", m_isFoo);
180         rep.getValue("barCount", m_barCount);
181
182         std::cout << "\tisFoo: "<< m_isFoo << std::endl;
183         std::cout << "\tbarCount: "<< m_barCount << std::endl;
184
185         std::cout<<"Actual New values are: "<<std::endl;
186
187         rep.getValue("isFoo", m_isFoo);
188         rep.getValue("barCount", m_barCount);
189
190         std::cout << "\tisFoo: "<< m_isFoo << std::endl;
191         std::cout << "\tbarCount: "<< m_barCount << std::endl;
192    }
193 }
194
195 void getResourceInfo(std::shared_ptr<OCResource> resource, const HeaderOptions& /*headerOptions*/,
196             const OCRepresentation rep,
197             const int eCode)
198 {
199     bool m_isFoo = false;
200     int m_barCount = 0;
201     std::cout << "In getResourceInfo" << std::endl;
202
203     std::cout<<"Clientside response to get was: "<<std::endl;
204     std::cout<<"Error Code: "<<eCode<<std::endl;
205
206     if(eCode == 0)
207     {
208         std::cout <<"Successful Get.  Attributes are: "<<std::endl;
209
210         rep.getValue("isFoo", m_isFoo);
211         rep.getValue("barCount", m_barCount);
212
213         std::cout << "\tisFoo: "<< m_isFoo << std::endl;
214         std::cout << "\tbarCount: "<< m_barCount << std::endl;
215
216         std::cout << "Doing a put on q/foo" <<std::endl;
217         OCRepresentation rep2(rep);
218         m_isFoo = false;
219         m_barCount = 211;
220
221         rep2.setValue("isFoo", m_isFoo);
222         rep2.setValue("barCount", m_barCount);
223
224         resource->put(rep2, QueryParamsMap(),
225             PutCallback(std::bind(putResourceInfo, std::placeholders::_1,
226                  rep2, std::placeholders::_2, std::placeholders::_3)));
227     }
228 }
229
230 void printResourceInfo(std::shared_ptr<OCResource> resource)
231 {
232         std::cout << "Found Resource: "<<std::endl;
233         std::cout << "\tHost: "<< resource->host()<<std::endl;
234         std::cout << "\tURI:  "<< resource->uri()<<std::endl;
235
236         // Get the resource types
237         std::cout << "\tList of resource types: " << std::endl;
238         for(auto &resourceTypes : resource->getResourceTypes())
239         {
240             std::cout << "\t\t" << resourceTypes << std::endl;
241         }
242
243         // Get the resource interfaces
244         std::cout << "\tList of resource interfaces: " << std::endl;
245         for(auto &resourceInterfaces : resource->getResourceInterfaces())
246         {
247             std::cout << "\t\t" << resourceInterfaces << std::endl;
248         }
249 }
250
251 void foundResource2(std::shared_ptr<OCResource> resource)
252 {
253     std::cout << "In foundResource2:" << std::endl;
254
255     if(resource && resource->uri() == "/q/foo2")
256     {
257         printResourceInfo(resource);
258
259         std::cout<<"Doing a get on q/foo."<<std::endl;
260
261         resource->get(QueryParamsMap(),
262             GetCallback(std::bind(getResourceInfo, resource,
263             std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
264     }
265     else
266     {
267         std::cout << "foundResource2: Ignoring the resource which doesn't have uri /q/foo2\n";
268     }
269 }
270
271 void foundResource1(std::shared_ptr<OCResource> resource)
272 {
273     std::cout << "In foundResource1:" << std::endl;
274     if(resource && resource->uri() == "/q/foo1")
275     {
276         printResourceInfo(resource);
277     }
278     else
279     {
280         std::cout << "foundResource1: Ignoring the resource which doesn't have uri /q/foo1\n";
281     }
282 }
283
284 void client1()
285 {
286     std::cout << "in client1\n";
287     std::cout<<"result1:" << OCPlatform::findResource("", requestURI.str(),
288             CT_DEFAULT, foundResource1)<< std::endl;
289
290     // A condition variable will free the mutex it is given, then do a non-
291     // intensive block until 'notify' is called on it.  In this case, since we
292     // don't ever call cv.notify, this should be a non-processor intensive version
293     // of while(true);
294     std::mutex blocker;
295     std::condition_variable cv;
296     std::unique_lock<std::mutex> lock(blocker);
297     cv.wait(lock);
298 }
299
300 void client2()
301 {
302     std::cout << "in client2\n";
303     std::cout<<"result2:" << OCPlatform::findResource("",
304                 requestURI.str(),
305                 CT_DEFAULT, foundResource2)<< std::endl;
306
307     // A condition variable will free the mutex it is given, then do a non-
308     // intensive block until 'notify' is called on it.  In this case, since we
309     // don't ever call cv.notify, this should be a non-processor intensive version
310     // of while(true);
311     std::mutex blocker;
312     std::condition_variable cv;
313     std::unique_lock<std::mutex> lock(blocker);
314     cv.wait(lock);
315 }
316
317 void server()
318 {
319     FooResource fooRes("/q/foo2");
320
321     if(!fooRes.createResource())
322     {
323         return;
324     }
325
326     // A condition variable will free the mutex it is given, then do a non-
327     // intensive block until 'notify' is called on it.  In this case, since we
328     // don't ever call cv.notify, this should be a non-processor intensive version
329     // of while(true);
330     std::mutex blocker;
331     std::condition_variable cv;
332     std::unique_lock<std::mutex> lock(blocker);
333     cv.wait(lock);
334 }
335
336 int main(int /*argc*/, char** /*argv[]*/)
337 {
338
339     requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.foo";
340
341     PlatformConfig cfg {
342         OC::ServiceType::InProc,
343         OC::ModeType::Both,
344         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
345         0,         // Uses randomly available port
346         OC::QualityOfService::LowQos
347     };
348
349     OCPlatform::Configure(cfg);
350
351     try
352     {
353         // main thread running as server
354         FooResource fooRes("/q/foo1");
355         if(!fooRes.createResource())
356         {
357             return -1;
358         }
359
360         // Start a server in a seperate thread
361         std::thread t(server);
362         t.detach();
363
364         sleep(10);
365
366         // Start each client in a seperate thread
367         std::thread t1(client1);
368         t1.detach();
369
370         // Start each client in a seperate thread
371         std::thread t2(client2);
372         t2.detach();
373
374         // A condition variable will free the mutex it is given, then do a non-
375         // intensive block until 'notify' is called on it.  In this case, since we
376         // don't ever call cv.notify, this should be a non-processor intensive version
377         // of while(true);
378         std::mutex blocker;
379         std::condition_variable cv;
380         std::unique_lock<std::mutex> lock(blocker);
381         cv.wait(lock);
382     }
383     catch(OCException& e)
384     {
385         std::cout<< "Exception in main: "<<e.what()<<std::endl;
386     }
387
388     return 0;
389 }
390