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