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