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