Merge branch 'master' into resource-manipulation
[platform/upstream/iotivity.git] / resource / include / OCSerialization.h
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 #include <cereal/cereal.hpp>
22 #include <cereal/types/memory.hpp>
23 #include <cereal/types/vector.hpp>
24 #include <cereal/archives/json.hpp>
25
26 #include <StringConstants.h>
27
28 namespace OC
29 {
30     class ListenOCContainer
31     {
32         private:
33         enum class OCSecureType
34         {
35             IPv4Secure,
36             IPv4
37         };
38
39         class ListenResourceContainer
40         {
41             class ListenResourcePolicyContainer
42             {
43                 friend class cereal::access;
44                 friend class ListenResourceContainer;
45                 friend class ListenResourcePropertiesContainer;
46
47                 template<class Archive>
48                 void serialize(Archive& ar)
49                 {
50                     try
51                     {
52                         m_observable = false;
53                         ar(cereal::make_nvp(OC::Key::BMKEY, m_bm));
54                         // In case of observable
55                         if(m_bm & OC_OBSERVABLE)
56                         {
57                             m_observable = true;
58                         }
59                     }
60                     catch(cereal::Exception&)
61                     {
62                         ar.setNextName(nullptr);
63                     }
64                     try
65                     {
66                         m_secure = false;
67                         int secureTemp;
68                         ar(cereal::make_nvp(OC::Key::SECUREKEY, secureTemp));
69                         m_secure = secureTemp != 0;
70
71                         m_port = -1;
72                         ar(cereal::make_nvp(OC::Key::PORTKEY, m_port));
73                     }
74                     catch(cereal::Exception&)
75                     {
76                        ar.setNextName(nullptr);
77                     }
78
79                  }
80
81                  bool m_observable;
82                  uint8_t m_bm;
83                  bool m_secure;
84                  int m_port;
85             };
86
87             class ListenResourcePropertiesContainer
88             {
89                 friend class cereal::access;
90                 friend class ListenResourceContainer;
91
92                 template<class Archive>
93                 void serialize(Archive& ar)
94                 {
95                     try
96                     {
97                         ar(cereal::make_nvp(OC::Key::POLICYKEY, m_policy));
98
99                     }
100                     catch(cereal::Exception&)
101                     {
102                         // we swallow this exception, since it means the key
103                         // doesn't exist, allowing these to be optional
104                         oclog() << "Invalid POLICYKEY"<<std::flush;
105                         ar.setNextName(nullptr);
106                     }
107
108                     try
109                     {
110                         ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes));
111                     }
112                     catch(cereal::Exception&)
113                     {
114                         ar.setNextName(nullptr);
115                     }
116                     try
117                     {
118                         ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces));
119                     }
120                     catch(cereal::Exception&)
121                     {
122                         ar.setNextName(nullptr);
123                     }
124                 }
125
126                 std::vector<std::string> m_resourceTypes;
127                 std::vector<std::string> m_interfaces;
128                 ListenResourcePolicyContainer m_policy;
129             };
130
131             public:
132             ListenResourceContainer() : m_loaded(false)
133             {}
134
135             private:
136             friend class cereal::access;
137             friend class ListenOCContainer;
138
139             template <class Archive>
140             void serialize(Archive& ar)
141             {
142                 try
143                 {
144                     ar(cereal::make_nvp(OC::Key::URIKEY, m_uri));
145                     m_loaded=true;
146                 }
147                 catch(cereal::Exception&)
148                 {
149                     ar.setNextName(nullptr);
150                 }
151                 try
152                 {
153                     ar(cereal::make_nvp(OC::Key::SERVERIDKEY, m_serverId));
154                     m_loaded=true;
155                 }
156                 catch(cereal::Exception&)
157                 {
158                     ar.setNextName(nullptr);
159                 }
160                 try
161                 {
162                     ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props));
163                     m_loaded=true;
164                 }
165                 catch(cereal::Exception&)
166                 {
167                     ar.setNextName(nullptr);
168                 }
169
170             }
171
172             std::string m_uri;
173             std::string m_serverId;
174             bool m_loaded;
175             ListenResourcePropertiesContainer m_props;
176
177             bool loaded() const
178             {
179                 return m_loaded;
180             }
181
182             bool observable() const
183             {
184                 return m_props.m_policy.m_observable;
185             }
186
187             OCSecureType secureType() const
188             {
189                 return m_props.m_policy.m_secure?OCSecureType::IPv4Secure :OCSecureType::IPv4;
190             }
191
192             int port() const
193             {
194                 return m_props.m_policy.m_port;
195             }
196
197             std::vector<std::string> resourceTypes() const
198             {
199                 return m_props.m_resourceTypes;
200             }
201
202             std::vector<std::string> interfaces() const
203             {
204                 return m_props.m_interfaces;
205             }
206         };
207
208         private:
209             friend class cereal::access;
210             template <class Archive>
211             void serialize(Archive& ar)
212             {
213                 std::vector<ListenResourceContainer> resources;
214                 ar(resources);
215             }
216         public:
217             ListenOCContainer(std::weak_ptr<IClientWrapper> cw, const OCDevAddr& address,
218                     OCConnectivityType connectivityType, std::stringstream& json):
219                 m_clientWrapper(cw), m_address(address), m_connectivityType(connectivityType)
220             {
221                 LoadFromJson(json);
222             }
223
224             const std::vector<std::shared_ptr<OCResource>>& Resources() const
225             {
226                 return m_resources;
227             }
228
229         private:
230             std::string ConvertOCAddrToString(OCSecureType sec, int secureport)
231             {
232                 uint16_t port;
233                 std::ostringstream os;
234
235                 if(sec== OCSecureType::IPv4)
236                 {
237                     os<<"coap://";
238                 }
239                 else if(sec == OCSecureType::IPv4Secure)
240                 {
241                     os<<"coaps://";
242                 }
243                 else
244                 {
245                     oclog() << "ConvertOCAddrToString():  invalid SecureType"<<std::flush;
246                     throw ResourceInitException(false, false, false, false, false, true);
247                 }
248
249                 uint8_t a;
250                 uint8_t b;
251                 uint8_t c;
252                 uint8_t d;
253                 if(OCDevAddrToIPv4Addr(&m_address, &a, &b, &c, &d) != 0)
254                 {
255                     oclog() << "ConvertOCAddrToString(): Invalid Ip"
256                             << std::flush;
257                     throw ResourceInitException(false, false, false, false, false, true);
258                 }
259
260                 os<<static_cast<int>(a)<<"."<<static_cast<int>(b)
261                         <<"."<<static_cast<int>(c)<<"."<<static_cast<int>(d);
262
263                 if(sec == OCSecureType::IPv4Secure && secureport>0 && secureport<=65535)
264                 {
265                     port = static_cast<uint16_t>(secureport);
266                 }
267                 else if(sec == OCSecureType::IPv4 && 0==OCDevAddrToPort(&m_address, &port))
268                 {
269                     // nothing to do, this is a successful case
270                 }
271                 else
272                 {
273                     oclog() << "ConvertOCAddrToString() : Invalid Port"
274                             <<std::flush;
275                     throw ResourceInitException(false, false, false, false, true, false);
276                 }
277
278                 os <<":"<< static_cast<int>(port);
279
280                 return os.str();
281             }
282
283             void LoadFromJson(std::stringstream& json)
284             {
285                 cereal::JSONInputArchive archive(json);
286
287                 std::vector<ListenResourceContainer> resources;
288                 archive(cereal::make_nvp(OC::Key::OCKEY, resources));
289
290                 m_resources.clear();
291
292                 for(const auto& res : resources)
293                 {
294                     try
295                     {
296                         if(res.loaded())
297                         {
298                             m_resources.push_back(std::shared_ptr<OCResource>(
299                                 new OCResource(m_clientWrapper,
300                                     ConvertOCAddrToString(res.secureType(),res.port()),
301                                     res.m_uri, res.m_serverId, m_connectivityType, res.observable(),
302                                     res.resourceTypes(), res.interfaces())));
303                         }
304
305                     }
306                     catch(ResourceInitException& e)
307                     {
308                         oclog() << "listenCallback(): failed to create resource: " << e.what()
309                                 << std::flush;
310                     }
311                 }
312             }
313             std::vector<std::shared_ptr<OC::OCResource>> m_resources;
314             std::weak_ptr<IClientWrapper> m_clientWrapper;
315             OCDevAddr m_address;
316             OCConnectivityType m_connectivityType;
317     };
318 }
319