Implemented JSON Serialization using Cereal Library
[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                     }
61
62                     try
63                     {
64                         m_secure = false;
65                         int secureTemp;
66                         ar(cereal::make_nvp(OC::Key::SECUREKEY, secureTemp));
67                         m_secure = secureTemp != 0;
68
69                         m_port = -1;
70                         ar(cereal::make_nvp(OC::Key::PORTKEY, m_port));
71                     }
72                     catch(cereal::Exception&)
73                     {}
74
75                     try
76                     {
77                         ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes));
78                     }
79                     catch(cereal::Exception&)
80                     {}
81                     try
82                     {
83                         ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces));
84                     }
85                     catch(cereal::Exception&)
86                     {}
87                 }
88
89                 bool m_observable;
90                 std::vector<std::string> m_resourceTypes;
91                 std::vector<std::string> m_interfaces;
92                 bool m_secure;
93                 int m_port;
94             };
95
96             public:
97             ListenResourceContainer() : m_loaded(false)
98             {}
99
100             private:
101             friend class cereal::access;
102             friend class ListenOCContainer;
103
104             template <class Archive>
105             void serialize(Archive& ar)
106             {
107                 try
108                 {
109                     ar(cereal::make_nvp(OC::Key::URIKEY, m_uri));
110                     m_loaded=true;
111                 }
112                 catch(cereal::Exception&)
113                 {}
114                 try
115                 {
116                     ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props));
117                     m_loaded=true;
118                 }
119                 catch(cereal::Exception&)
120                 {}
121             }
122
123
124             std::string m_uri;
125             bool m_loaded;
126             ListenResourcePropertiesContainer m_props;
127
128             bool loaded() const
129             {
130                 return m_loaded;
131             }
132
133             bool observable() const
134             {
135                 return m_props.m_observable;
136             }
137
138             OCSecureType secureType() const
139             {
140                 return m_props.m_secure?OCSecureType::IPv4Secure :OCSecureType::IPv4;
141             }
142
143             int port() const
144             {
145                 return m_props.m_port;
146             }
147
148             std::vector<std::string> resourceTypes() const
149             {
150                 return m_props.m_resourceTypes;
151             }
152
153             std::vector<std::string> interfaces() const
154             {
155                 return m_props.m_interfaces;
156             }
157         };
158
159         private:
160             friend class cereal::access;
161             template <class Archive>
162             void serialize(Archive& ar)
163             {
164                 std::vector<ListenResourceContainer> resources;
165                 ar(resources);
166             }
167         public:
168             ListenOCContainer(std::weak_ptr<IClientWrapper> cw, const OCDevAddr& address,
169                     std::stringstream& json):
170                 m_clientWrapper(cw), m_address(address)
171             {
172                 LoadFromJson(json);
173             }
174
175             const std::vector<std::shared_ptr<OCResource>>& Resources() const
176             {
177                 return m_resources;
178             }
179
180         private:
181             std::string ConvertOCAddrToString(OCSecureType sec, int secureport)
182             {
183                 uint8_t addr1;
184                 uint8_t addr2;
185                 uint8_t addr3;
186                 uint8_t addr4;
187                 uint16_t port;
188
189                 ostringstream os;
190
191                 if(sec== OCSecureType::IPv4)
192                 {
193                     os<<"coap://";
194                 }
195                 else if(sec == OCSecureType::IPv4Secure)
196                 {
197                     os<<"coaps://";
198                 }
199                 else
200                 {
201                     oclog() << "ConvertOCAddrToString():  invalid SecureType"<<std::flush;
202                     throw ResourceInitException(false, false, false, false, false, true);
203                 }
204
205                 if(0== OCDevAddrToIPv4Addr(&m_address, &addr1, &addr2, &addr3, &addr4))
206                 {
207                     // nothing to do, successful case.
208                 }
209                 else
210                 {
211                     oclog() << "ConvertOCAddrToString(): Invalid Ip"
212                         << std::flush;
213                     throw ResourceInitException(false, false, false, false, false, true);
214                 }
215
216                 os<<static_cast<int>(addr1)<<'.'
217                     <<static_cast<int>(addr2)<<'.'
218                     <<static_cast<int>(addr3)<<'.'
219                     <<static_cast<int>(addr4);
220
221                 if(sec == OCSecureType::IPv4Secure && secureport>0 && secureport<=65535)
222                 {
223                     port = static_cast<uint16_t>(secureport);
224                 }
225                 else if(sec == OCSecureType::IPv4 && 0==OCDevAddrToPort(&m_address, &port))
226                 {
227                     // nothing to do, this is a successful case
228                 }
229                 else
230                 {
231                     oclog() << "ConvertOCAddrToString() : Invalid Port"
232                             <<std::flush;
233                     throw ResourceInitException(false, false, false, false, true, false);
234                 }
235
236                 os <<":"<< static_cast<int>(port);
237
238                 return os.str();
239             }
240
241             void LoadFromJson(std::stringstream& json)
242             {
243                 cereal::JSONInputArchive archive(json);
244
245                 std::vector<ListenResourceContainer> resources;
246                 archive(cereal::make_nvp(OC::Key::OCKEY, resources));
247
248                 m_resources.clear();
249
250                 for(const auto& res : resources)
251                 {
252                     try
253                     {
254                         if(res.loaded())
255                         {
256                             m_resources.push_back(std::shared_ptr<OCResource>(
257                                 new OCResource(m_clientWrapper,
258                                     ConvertOCAddrToString(res.secureType(),res.port()),
259                                     res.m_uri, res.observable(), res.resourceTypes(),
260                                     res.interfaces())));
261                         }
262
263                     }
264                     catch(ResourceInitException& e)
265                     {
266                         oclog() << "listenCallback(): failed to create resource: " << e.what()
267                                 << std::flush;
268                     }
269                 }
270             }
271             std::vector<std::shared_ptr<OC::OCResource>> m_resources;
272             std::weak_ptr<IClientWrapper> m_clientWrapper;
273             OCDevAddr m_address;
274     };
275 }