Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / resource / examples / simpleclientserver.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 provides steps to define an interface for a resource
23 /// (properties and methods) and host this resource on the server.
24 /// Additionally, it'll have a client example to discover it as well.
25 ///
26 #include <memory>
27 #include <iostream>
28 #include <stdexcept>
29 #include <condition_variable>
30 #include <map>
31 #include <vector>
32 #include "OCPlatform.h"
33 #include "OCApi.h"
34 using namespace OC;
35
36 static void printUsage()
37 {
38     std::cout<< "    Usage simpleclientserver <0|1>" << std::endl;
39     std::cout<< "    ConnectivityType: Default IP" << std::endl;
40     std::cout << "   ConnectivityType : 0 - IP" << std::endl;
41 }
42
43 class ClientWorker
44 {
45 private:
46     void putResourceInfo(const HeaderOptions& /*headerOptions*/,
47             const OCRepresentation rep, const OCRepresentation /*rep2*/, const int eCode)
48     {
49        std::cout << "In PutResourceInfo" << std::endl;
50
51        std::cout <<"Clientside Put response to get was: "<<std::endl;
52        std::cout <<"ErrorCode: "<<eCode <<std::endl;
53
54        if(eCode == 0)
55        {
56             std::cout<<"Successful Put.  Attributes sent were: "<<std::endl;
57
58             rep.getValue("isFoo", m_isFoo);
59             rep.getValue("barCount", m_barCount);
60
61             std::cout << "\tisFoo: "<< m_isFoo << std::endl;
62             std::cout << "\tbarCount: "<< m_barCount << std::endl;
63
64             std::cout<<"Actual New values are: "<<std::endl;
65
66             rep.getValue("isFoo", m_isFoo);
67             rep.getValue("barCount", m_barCount);
68
69             std::cout << "\tisFoo: "<< m_isFoo << std::endl;
70             std::cout << "\tbarCount: "<< m_barCount << std::endl;
71
72             m_cv.notify_all();
73        }
74     }
75
76     void getResourceInfo(const HeaderOptions& /*headerOptions*/, const OCRepresentation rep,
77                 const int eCode)
78     {
79         std::cout << "In getResourceInfo" << std::endl;
80
81         std::cout<<"Clientside response to get was: "<<std::endl;
82         std::cout<<"Error Code: "<<eCode<<std::endl;
83
84         if(eCode == 0)
85         {
86             std::cout <<"Successful Get.  Attributes are: "<<std::endl;
87
88             rep.getValue("isFoo", m_isFoo);
89             rep.getValue("barCount", m_barCount);
90
91             std::cout << "\tisFoo: "<< m_isFoo << std::endl;
92             std::cout << "\tbarCount: "<< m_barCount << std::endl;
93
94             std::cout << "Doing a put on q/foo" <<std::endl;
95             OCRepresentation rep2(rep);
96             m_isFoo = false;
97             m_barCount = 211;
98
99             rep2.setValue("isFoo", m_isFoo);
100             rep2.setValue("barCount", m_barCount);
101
102             m_resource->put(rep2, QueryParamsMap(),
103                 PutCallback(std::bind(&ClientWorker::putResourceInfo, this, std::placeholders::_1,
104                      rep2, std::placeholders::_2, std::placeholders::_3)));
105         }
106     }
107
108     void foundResource(std::shared_ptr<OCResource> resource)
109     {
110         std::cout << "In foundResource" << std::endl;
111         if(resource && resource->uri() == "/q/foo")
112         {
113             {
114                 std::lock_guard<std::mutex> lock(m_resourceLock);
115                 if(m_resource)
116                 {
117                     return;
118                 }
119
120                 m_resource = resource;
121             }
122
123             std::cout << "Found Resource: "<<std::endl;
124             std::cout << "\tHost: "<< resource->host()<<std::endl;
125             std::cout << "\tURI:  "<< resource->uri()<<std::endl;
126
127             // Get the resource types
128             std::cout << "\tList of resource types: " << std::endl;
129             for(auto &resourceTypes : resource->getResourceTypes())
130             {
131                 std::cout << "\t\t" << resourceTypes << std::endl;
132             }
133
134             // Get the resource interfaces
135             std::cout << "\tList of resource interfaces: " << std::endl;
136             for(auto &resourceInterfaces : resource->getResourceInterfaces())
137             {
138                 std::cout << "\t\t" << resourceInterfaces << std::endl;
139             }
140
141             std::cout<<"Doing a get on q/foo."<<std::endl;
142
143             resource->get(QueryParamsMap(),
144                 GetCallback(std::bind(&ClientWorker::getResourceInfo, this,
145                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
146         }
147     }
148
149 public:
150     ClientWorker(OCConnectivityType ct):m_connectivityType{ct}
151     {}
152
153     void start()
154     {
155         std::ostringstream requestURI;
156         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.foo";
157
158         std::cout<<"Starting Client find:"<<std::endl;
159         FindCallback f (std::bind(&ClientWorker::foundResource, this, std::placeholders::_1));
160         std::cout<<"result:" <<
161         OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, f)
162         << std::endl;
163
164         std::cout<<"Finding Resource..."<<std::endl;
165
166         {
167             std::unique_lock<std::mutex> lk(m_mutex);
168             m_cv.wait(lk);
169         }
170     }
171 private:
172     std::mutex m_mutex;
173     std::mutex m_resourceLock;
174     std::condition_variable m_cv;
175     std::shared_ptr<OCResource> m_resource;
176     OCConnectivityType m_connectivityType;
177     bool m_isFoo;
178     int m_barCount;
179 };
180
181 struct FooResource
182 {
183     bool m_isFoo;
184     int m_barCount;
185     OCResourceHandle m_resourceHandle;
186     OCRepresentation m_rep;
187
188     FooResource(): m_isFoo(true), m_barCount (0)
189     {
190         m_rep.setUri("/q/foo");
191         m_rep.setValue("isFoo", m_isFoo);
192         m_rep.setValue("barCount", m_barCount);
193     }
194
195     bool createResource()
196     {
197         std::string resourceURI = "/q/foo";
198         std::string resourceTypeName = "core.foo";
199         std::string resourceInterface = DEFAULT_INTERFACE;
200
201         uint8_t resourceProperty = OC_DISCOVERABLE;
202
203         EntityHandler eh(std::bind(&FooResource::entityHandler,
204                     this, std::placeholders::_1));
205         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
206                 resourceURI, resourceTypeName,
207                                     resourceInterface,
208                                     eh, resourceProperty);
209         if(OC_STACK_OK != result)
210         {
211             std::cout<<"Resource creation unsuccessful"<<std::endl;
212             return false;
213         }
214
215         return true;
216     }
217
218     OCRepresentation get()
219     {
220         m_rep.setValue("isFoo", m_isFoo);
221         m_rep.setValue("barCount", m_barCount);
222
223         return m_rep;
224     }
225
226     void put(OCRepresentation& rep)
227     {
228         rep.getValue("isFoo", m_isFoo);
229         rep.getValue("barCount", m_barCount);
230     }
231
232     OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
233     {
234         auto pResponse = std::make_shared<OC::OCResourceResponse>();
235         pResponse->setRequestHandle(pRequest->getRequestHandle());
236         pResponse->setResourceHandle(pRequest->getResourceHandle());
237         pResponse->setResourceRepresentation(get(), "");
238         pResponse->setErrorCode(200);
239         pResponse->setResponseResult(OC_EH_OK);
240
241         return OCPlatform::sendResponse(pResponse);
242     }
243
244     OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
245     {
246         std::cout<<"\tConsumer Entity Handler:"<<std::endl;
247         OCEntityHandlerResult ehResult = OC_EH_ERROR;
248
249         if(request)
250         {
251             // Note: Most of the handlers are not here, since this is for
252             // demoing client/server co-process existence.
253             // See simpleserver for a more complete example.
254             if(request->getRequestHandlerFlag()  == RequestHandlerFlag::RequestFlag)
255             {
256                 std::cout << "\t\trequestFlag : Request"<<std::endl;
257
258                 if(request->getRequestType() == "GET")
259                 {
260                     std::cout<<"\t\t\trequestType : GET"<<std::endl;
261                     if(OC_STACK_OK == sendResponse(request))
262                     {
263                         ehResult = OC_EH_OK;
264                     }
265                 }
266                 else if (request->getRequestType() == "PUT")
267                 {
268                     std::cout<<"\t\t\trequestType : PUT"<<std::endl;
269
270                     OCRepresentation rep = request->getResourceRepresentation();
271                     put(rep);
272                     if(OC_STACK_OK == sendResponse(request))
273                     {
274                         ehResult = OC_EH_OK;
275                     }
276                 }
277                 else
278                 {
279                     std::cout<<"\t\t\trequestType : UNSUPPORTED: "<<
280                             request->getRequestType()<<std::endl;
281                 }
282             }
283             else
284             {
285                 std::cout <<"\t\trequestFlag : UNSUPPORTED: ";
286
287                 if(request->getRequestHandlerFlag()== RequestHandlerFlag::ObserverFlag)
288                 {
289                     std::cout<<"ObserverFlag"<<std::endl;
290                 }
291             }
292         }
293         else
294         {
295             std::cout << "Request Invalid!"<<std::endl;
296         }
297
298         return ehResult;
299     }
300
301 };
302
303 int main(int argc, char* argv[])
304 {
305     OCConnectivityType connectivityType = CT_ADAPTER_IP;
306
307     if(argc == 2)
308     {
309         try
310         {
311             std::size_t inputValLen;
312             int optionSelected = std::stoi(argv[1], &inputValLen);
313
314             if(inputValLen == strlen(argv[1]))
315             {
316                 if(optionSelected == 0)
317                 {
318                     std::cout << "Using IP."<< std::endl;
319                     connectivityType = CT_ADAPTER_IP;
320                 }
321                 else
322                 {
323                     std::cout << "Invalid connectivity type selected. Using default IP" << std::endl;
324                 }
325             }
326             else
327             {
328                 std::cout << "Invalid connectivity type selected. Using default IP" << std::endl;
329             }
330         }
331         catch(std::exception& )
332         {
333             std::cout << "Invalid input argument. Using IP as connectivity type" << std::endl;
334         }
335     }
336     else
337     {
338         printUsage();
339     }
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     FooResource fooRes;
351
352     try
353     {
354
355         if(!fooRes.createResource())
356         {
357             return -1;
358         }
359
360         ClientWorker cw(connectivityType);
361         cw.start();
362     }
363     catch(OCException& e)
364     {
365         std::cout<< "Exception in main: "<<e.what()<<std::endl;
366     }
367
368     return 0;
369 }
370