Line data Source code
1 : /*
2 : * Copyright (c) 2014 CodiLime, Inc. All rights reserved.
3 : */
4 :
5 : #include <vector>
6 : #include <boost/foreach.hpp>
7 : #include <boost/assign/list_of.hpp>
8 : #include "base/address_util.h"
9 :
10 : #include "rapidjson/document.h"
11 : #include "rapidjson/writer.h"
12 : #include "rapidjson/stringbuffer.h"
13 :
14 : #include "bfd/rest_api/bfd_json_config.h"
15 :
16 : namespace BFD {
17 : namespace REST {
18 :
19 3 : static bool IsIPAddressValid(const char* addr) {
20 3 : boost::system::error_code ec;
21 3 : AddressFromString(addr, &ec);
22 3 : return !ec;
23 : }
24 :
25 14 : bool JsonData::ParseFromJsonString(const std::string& json) {
26 14 : contrail_rapidjson::Document document;
27 14 : document.Parse<0>(json.c_str());
28 28 : return ParseFromJsonDocument(document);
29 14 : }
30 :
31 1 : void JsonData::EncodeJsonString(std::string* json) {
32 1 : contrail_rapidjson::Document document;
33 1 : EncodeJsonDocument(&document, &document.GetAllocator());
34 1 : contrail_rapidjson::StringBuffer strbuf;
35 1 : contrail_rapidjson::Writer<contrail_rapidjson::StringBuffer> writer(strbuf);
36 1 : document.Accept(writer);
37 1 : *json = strbuf.GetString();
38 1 : }
39 :
40 14 : bool JsonData::AreConstraintsMet(const std::vector<Constraint>& constraints,
41 : const contrail_rapidjson::Value& document) {
42 14 : if (!document.IsObject())
43 2 : return false;
44 :
45 50 : BOOST_FOREACH(const struct Constraint& constraint, constraints) {
46 51 : if (!document.HasMember(constraint.member_name) ||
47 23 : !(document[constraint.member_name].*(constraint.typecheck_func))())
48 9 : return false;
49 : }
50 3 : return true;
51 : }
52 :
53 14 : JsonConfig::JsonConfig()
54 14 : {}
55 :
56 0 : JsonConfig::JsonConfig(boost::asio::ip::address address,
57 : TimeInterval desired_min_tx_interval,
58 : TimeInterval required_min_rx_interval,
59 0 : int detection_time_multiplier)
60 0 : : address(address),
61 0 : desired_min_tx_interval(desired_min_tx_interval),
62 0 : required_min_rx_interval(required_min_rx_interval),
63 0 : detection_time_multiplier(detection_time_multiplier)
64 0 : {}
65 :
66 14 : bool JsonConfig::ValidateJsonDocument(const contrail_rapidjson::Value& document) {
67 : static const std::vector<Constraint> constraints = boost::assign::list_of
68 2 : (Constraint("Address", &contrail_rapidjson::Value::IsString) )
69 1 : (Constraint("DesiredMinTxInterval", &contrail_rapidjson::Value::IsInt))
70 1 : (Constraint("RequiredMinRxInterval", &contrail_rapidjson::Value::IsInt))
71 15 : (Constraint("DetectionMultiplier", &contrail_rapidjson::Value::IsInt));
72 17 : return AreConstraintsMet(constraints, document) &&
73 17 : IsIPAddressValid(document["Address"].GetString());
74 : }
75 :
76 14 : bool JsonConfig::ParseFromJsonDocument(const contrail_rapidjson::Value& document) {
77 14 : if (ValidateJsonDocument(document)) {
78 : using boost::posix_time::microseconds;
79 :
80 2 : boost::system::error_code ec;
81 2 : address = AddressFromString(document["Address"].GetString(), &ec);
82 2 : desired_min_tx_interval =
83 2 : microseconds(document["DesiredMinTxInterval"].GetInt());
84 2 : required_min_rx_interval =
85 2 : microseconds(document["RequiredMinRxInterval"].GetInt());
86 2 : detection_time_multiplier =
87 2 : document["DetectionMultiplier"].GetInt();
88 2 : return true;
89 : }
90 12 : return false;
91 : }
92 :
93 1 : void JsonConfig::EncodeJsonDocument(contrail_rapidjson::Value* document,
94 : contrail_rapidjson::Value::AllocatorType *allocator) {
95 1 : document->SetObject();
96 1 : std::string address_str = address.to_string();
97 1 : contrail_rapidjson::Value address_val(address_str.c_str(), *allocator);
98 1 : document->AddMember("Address", address_val, *allocator);
99 :
100 1 : document->AddMember("DesiredMinTxInterval",
101 : desired_min_tx_interval.total_microseconds(), *allocator);
102 1 : document->AddMember("RequiredMinRxInterval",
103 : required_min_rx_interval.total_microseconds(), *allocator);
104 1 : document->AddMember("DetectionMultiplier",
105 : detection_time_multiplier, *allocator);
106 1 : }
107 :
108 0 : bool JsonState::ValidateJsonDocument(const contrail_rapidjson::Value& document) {
109 : const std::vector<Constraint> constraints = boost::assign::list_of
110 0 : (Constraint("LocalSessionState", &contrail_rapidjson::Value::IsString))
111 0 : (Constraint("RemoteSessionState", &contrail_rapidjson::Value::IsString))
112 0 : (Constraint("RemoteMinRxInterval", &contrail_rapidjson::Value::IsInt))
113 0 : (Constraint("LocalDiscriminator", &contrail_rapidjson::Value::IsInt))
114 0 : (Constraint("RemoteDiscriminator", &contrail_rapidjson::Value::IsInt));
115 0 : return AreConstraintsMet(constraints, document) &&
116 : // Check whether these strings are convertible to BFD states.
117 0 : BFDStateFromString(document["LocalSessionState"].GetString()) &&
118 0 : BFDStateFromString(document["RemoteSessionState"].GetString());
119 0 : }
120 :
121 0 : bool JsonState::ParseFromJsonDocument(const contrail_rapidjson::Value& document) {
122 0 : if (!session_config.ParseFromJsonDocument(document))
123 0 : return false;
124 :
125 0 : if (ValidateJsonDocument(document)) {
126 : using boost::posix_time::microseconds;
127 :
128 0 : remote_min_rx_interval =
129 0 : microseconds(document["RemoteMinRxInterval"].GetInt());
130 0 : local_discriminator =
131 0 : document["LocalDiscriminator"].GetInt();
132 0 : remote_discriminator =
133 0 : document["RemoteDiscriminator"].GetInt();
134 0 : bfd_local_state =
135 0 : *BFDStateFromString(document["LocalSessionState"].GetString());
136 0 : bfd_remote_state =
137 0 : *BFDStateFromString(document["RemoteSessionState"].GetString());
138 0 : return true;
139 : }
140 0 : return false;
141 : }
142 :
143 0 : void JsonState::EncodeJsonDocument(contrail_rapidjson::Value* document,
144 : contrail_rapidjson::Value::AllocatorType *allocator) {
145 0 : document->SetObject();
146 0 : session_config.EncodeJsonDocument(document, allocator);
147 :
148 : std::string local_session_state_str
149 0 : = boost::lexical_cast<std::string>(bfd_local_state);
150 : contrail_rapidjson::Value local_session_state_val(local_session_state_str.c_str(),
151 0 : *allocator);
152 0 : document->AddMember("LocalSessionState", local_session_state_val,
153 : *allocator);
154 :
155 : std::string remote_session_state_str =
156 0 : boost::lexical_cast<std::string>(bfd_remote_state);
157 : contrail_rapidjson::Value remote_session_state_val(remote_session_state_str.c_str(),
158 0 : *allocator);
159 0 : document->AddMember("RemoteSessionState", remote_session_state_val,
160 : *allocator);
161 0 : document->AddMember("LocalDiscriminator", local_discriminator,
162 : *allocator);
163 0 : document->AddMember("RemoteDiscriminator", remote_discriminator,
164 : *allocator);
165 0 : document->AddMember("RemoteMinRxInterval",
166 : remote_min_rx_interval.total_microseconds(),
167 : *allocator);
168 0 : }
169 :
170 0 : bool JsonStateNotification::ValidateJsonDocument(
171 : const contrail_rapidjson::Value& document) {
172 : const std::vector<Constraint> constraints = boost::assign::list_of
173 0 : (Constraint("Address", &contrail_rapidjson::Value::IsString))
174 0 : (Constraint("SessionState", &contrail_rapidjson::Value::IsString));
175 0 : return AreConstraintsMet(constraints, document) &&
176 0 : IsIPAddressValid(document["Address"].GetString()) &&
177 0 : BFDStateFromString(document["SessionState"].GetString());
178 0 : }
179 :
180 0 : bool JsonStateNotification::ParseFromJsonDocument(const contrail_rapidjson::Value
181 : &document) {
182 0 : if (ValidateJsonDocument(document)) {
183 :
184 0 : boost::system::error_code ec;
185 0 : address = AddressFromString(document["Address"].GetString(), &ec);
186 0 : state =
187 0 : *BFDStateFromString(document["SessionState"].GetString());
188 0 : return true;
189 : }
190 0 : return false;
191 : }
192 :
193 0 : void JsonStateNotification::EncodeJsonDocument(contrail_rapidjson::Value* document,
194 : contrail_rapidjson::Value::AllocatorType *allocator) {
195 0 : document->SetObject();
196 0 : std::string address_str = address.to_string();
197 0 : contrail_rapidjson::Value address_val(address_str.c_str(), *allocator);
198 0 : document->AddMember("Address", address_val, *allocator);
199 :
200 0 : std::string session_state_str = boost::lexical_cast<std::string>(state);
201 0 : contrail_rapidjson::Value session_state_val(session_state_str.c_str(), *allocator);
202 0 : document->AddMember("SessionState", session_state_val, *allocator);
203 0 : }
204 :
205 0 : void JsonStateNotificationList::EncodeJsonDocument(contrail_rapidjson::Value* document,
206 : contrail_rapidjson::Value::AllocatorType *allocator) {
207 0 : document->SetArray();
208 0 : for (std::vector<JsonStateNotification>::iterator it =
209 0 : notifications.begin(); it != notifications.end(); ++it) {
210 0 : contrail_rapidjson::Value notification;
211 0 : it->EncodeJsonDocument(¬ification, allocator);
212 0 : document->PushBack(notification, *allocator);
213 0 : }
214 0 : }
215 :
216 0 : bool JsonStateNotificationList::ValidateJsonDocument(
217 : const contrail_rapidjson::Value& document) {
218 0 : return true;
219 : }
220 :
221 0 : bool JsonStateNotificationList::ParseFromJsonDocument(
222 : const contrail_rapidjson::Value& document) {
223 0 : return false;
224 : }
225 :
226 0 : void JsonStateMap::EncodeJsonDocument(contrail_rapidjson::Value* document,
227 : contrail_rapidjson::Value::AllocatorType* allocator) {
228 0 : document->SetObject();
229 :
230 0 : for (StateMap::iterator it = states.begin(); it != states.end(); ++it) {
231 0 : std::string address_str = it->first.to_string();
232 0 : contrail_rapidjson::Value address_val(address_str.c_str(), *allocator);
233 :
234 : std::string session_state_str =
235 0 : boost::lexical_cast<std::string>(it->second);
236 : contrail_rapidjson::Value session_state_val(session_state_str.c_str(),
237 0 : *allocator);
238 :
239 0 : document->AddMember(address_val, session_state_val, *allocator);
240 0 : }
241 0 : }
242 :
243 0 : bool JsonStateMap::ValidateJsonDocument(const contrail_rapidjson::Value& document) {
244 0 : if (!document.IsObject())
245 0 : return false;
246 :
247 0 : for (contrail_rapidjson::Value::ConstMemberIterator it = document.MemberBegin();
248 0 : it != document.MemberEnd(); ++it) {
249 : using boost::system::error_code;
250 :
251 0 : if (!it->name.IsString() || !it->value.IsString())
252 0 : return false;
253 :
254 0 : error_code ec;
255 0 : if (ec.failed())
256 0 : return false;
257 0 : if (!BFDStateFromString(it->value.GetString()))
258 0 : return false;
259 : }
260 0 : return true;
261 : }
262 :
263 0 : bool JsonStateMap::ParseFromJsonDocument(
264 : const contrail_rapidjson::Value& document) {
265 0 : if (!ValidateJsonDocument(document))
266 0 : return false;
267 :
268 0 : states.clear();
269 :
270 0 : for (contrail_rapidjson::Value::ConstMemberIterator
271 0 : it = document.MemberBegin(); it != document.MemberEnd(); ++it) {
272 0 : boost::system::error_code ec;
273 : boost::asio::ip::address address =
274 0 : AddressFromString(it->name.GetString(), &ec);
275 0 : BFDState state = *BFDStateFromString(it->value.GetString());
276 0 : states[address] = state;
277 : }
278 0 : return true;
279 : }
280 :
281 : } // namespace REST
282 : } // namespace BFD
283 :
|