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