OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bfd_rest_client.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 CodiLime, Inc. All rights reserved.
3  */
4 
6 
7 #include <string>
8 #include <boost/asio/ip/address.hpp>
9 #include <rapidjson/document.h>
10 
11 #include "base/logging.h"
13 
14 namespace BFD {
15 
16 const REST::JsonConfig RESTClient::kDefaultConfig(
17  /* .address = */ boost::asio::ip::address::from_string("0.0.0.0"),
18  /* .desired_min_tx_interval = */ boost::posix_time::milliseconds(100),
19  /* .required_min_tx_interval = */ boost::posix_time::milliseconds(500),
20  /* .detection_time_multiplier = */ 3
21 );
22 
23 RESTClient::RESTClient(const boost::asio::ip::tcp::endpoint& ep,
24  EventManager* evm) :
25  http_client_(new HttpClient(evm)), ep_(ep), long_poll_connection_(NULL),
26  error_(false), stopped_(false) {
27 }
28 
30  Stop();
31  // TODO(bfd) clean up inheritance mess in HttpClient
33 }
34 
36  return !stopped_ && !error_ && client_id_.is_initialized();
37 }
38 
40  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
42 }
43 
45  const std::string url = "Session";
46  const std::string request = "{}";
47 
48  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
49 
50  http_client_->Init();
52  long_poll_connection_->HttpPut(request, url,
54  this, _1, _2));
55 
56  while (!error_ && !is_initialized_non_locking()) {
57  cond_var_.wait(lock);
58  }
59 }
60 
62  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
63  if (stopped_)
64  return;
65  stopped_ = true;
66  LOG(DEBUG, "Stopping bfd client: " << ep_);
67  lock.unlock();
69 }
70 
72  Stop();
73  error_ = true;
74 }
75 
76 bool RESTClient::AddBFDHost(const boost::asio::ip::address& remote_address,
77  AddBFDHostCb cb) {
78  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
80  return false;
81 
82  std::string url = "Session/" +
83  boost::lexical_cast<std::string>(client_id_.get()) + "/IpConnection";
85  config.address = remote_address;
87  std::string request;
88  config.EncodeJsonString(&request);
89  connection->HttpPut(request, url, boost::bind(
90  &RESTClient::CreateSessionCallback, _1, _2, connection, cb));
91  return true;
92 }
93 
94 bool RESTClient::DeleteBFDHost(const boost::asio::ip::address& remote_address,
95  DeleteBFDHostCb cb) {
96  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
98  return false;
99 
100  std::string url = "Session/" +
101  boost::lexical_cast<std::string>(client_id_.get()) + "/IpConnection/" +
102  boost::lexical_cast<std::string>(remote_address);
104  connection->HttpDelete(url,
105  boost::bind(&RESTClient::DeleteSessionCallback, _1, _2,
106  connection, cb));
107  return true;
108 }
109 
110 bool RESTClient::GetSession(const boost::asio::ip::address& remote_address,
111  GetSessionCb cb) {
112  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
114  return false;
115 
116  std::string url = "Session/" +
117  boost::lexical_cast<std::string>(client_id_.get()) + "/IpConnection/" +
118  boost::lexical_cast<std::string>(remote_address);
120  connection->HttpGet(url, boost::bind(&RESTClient::GetBFDConnectionCallback,
121  _1, _2, connection, cb));
122  return true;
123 }
124 
126  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
127 
129  return false;
130 
131  std::string url = "Session/" +
132  boost::lexical_cast<std::string>(client_id_.get()) + "/Monitor";
134  connection->HttpGet(url, boost::bind(&RESTClient::MonitorCallback,
135  _1, _2, connection, cb));
136  return true;
137 }
138 
139 void RESTClient::CreateSessionCallback(const std::string& response,
140  const boost::system::error_code& ec,
141  HttpConnection* connection,
142  AddBFDHostCb cb) {
143  if (!ec) {
144  LOG(DEBUG, "CreateSession server response: " << response);
145  } else {
146  LOG(ERROR, "CreateSession: Error: "
147  << ec.value() << " " << ec.message());
148  }
149 
150  connection->client()->RemoveConnection(connection);
151  cb(ec);
152 }
153 
154 void RESTClient::DeleteSessionCallback(const std::string& response,
155  const boost::system::error_code& ec,
156  HttpConnection* connection,
157  DeleteBFDHostCb cb) {
158  if (!ec) {
159  LOG(DEBUG, "DeleteSession server response: " << response);
160  } else {
161  LOG(ERROR, "DeleteSession: Error: "
162  << ec.value() << " " << ec.message());
163  }
164 
165  connection->client()->RemoveConnection(connection);
166  cb(ec);
167 }
168 
169 void RESTClient::GetBFDConnectionCallback(const std::string& response,
170  const boost::system::error_code& ec,
171  HttpConnection* connection,
172  GetSessionCb cb) {
173  REST::JsonState state;
174  boost::system::error_code return_ec = ec;
175 
176  if (!ec) {
177  LOG(DEBUG, "GetBFDConnection server response: " << response);
178  if (!state.ParseFromJsonString(response)) {
179  return_ec =
180  boost::system::error_code(boost::system::errc::protocol_error,
181  boost::system::system_category());
182  }
183  } else {
184  LOG(ERROR, "GetBFDConnection Error: "
185  << ec.value() << " " << ec.message());
186  }
187 
188  connection->client()->RemoveConnection(connection);
189  cb(state, return_ec);
190 }
191 
192 void RESTClient::CreateRESTClientSessionCallback(const std::string& response,
193  const boost::system::error_code& ec) {
194  tbb::interface5::unique_lock<tbb::mutex> lock(mutex_);
195 
196  if (!ec) {
197  if (!response.empty()) {
198  LOG(DEBUG, "Server response: " << response);
199  contrail_rapidjson::Document document;
200  document.Parse<0>(response.c_str());
201  if (document.HasParseError() ||
202  !document.IsObject() ||
203  !document.HasMember("client-id") ||
204  !document["client-id"].IsInt()) {
205  LOG(ERROR, "Unable to parse server response");
206  SetError();
207  } else {
208  client_id_ = document["client-id"].GetInt();
209  }
210  }
211  } else {
212  LOG(ERROR, "CreateRESTClientSessionCallback " << ep_ << " Error: "
213  << ec.value() << " " << ec.message());
214  SetError();
215  }
216 
217  cond_var_.notify_all();
218 }
219 
220 void RESTClient::MonitorCallback(const std::string& response,
221  const boost::system::error_code& ec,
222  HttpConnection* connection,
223  MonitorCb cb) {
224  REST::JsonStateMap states;
225  boost::system::error_code return_ec = ec;
226 
227  if (!ec) {
228  LOG(DEBUG, "MonitorCallback server response: " << response);
229  if (!states.ParseFromJsonString(response)) {
230  return_ec =
231  boost::system::error_code(boost::system::errc::protocol_error,
232  boost::system::system_category());
233  }
234  } else {
235  LOG(ERROR, "MonitorCallback Error: " << ec.value() << " "
236  << ec.message());
237  }
238 
239  connection->client()->RemoveConnection(connection);
240  cb(states, return_ec);
241 }
242 
243 } // namespace BFD
static void DeleteSessionCallback(const std::string &response, const boost::system::error_code &ec, HttpConnection *connection, DeleteBFDHostCb cb)
void Init()
Definition: http_client.cc:422
boost::function< void(boost::system::error_code)> DeleteBFDHostCb
boost::function< void(const REST::JsonState &state, boost::system::error_code)> GetSessionCb
bool AddBFDHost(const boost::asio::ip::address &remote_address, AddBFDHostCb cb)
int HttpGet(const std::string &path, HttpCb)
Definition: http_client.cc:135
HttpConnection * CreateConnection(boost::asio::ip::tcp::endpoint)
Definition: http_client.cc:454
bool ParseFromJsonString(const std::string &json)
static void GetBFDConnectionCallback(const std::string &response, const boost::system::error_code &ec, HttpConnection *connection, GetSessionCb cb)
bool is_initialized_non_locking()
static void MonitorCallback(const std::string &response, const boost::system::error_code &ec, HttpConnection *connection, MonitorCb cb)
bool GetSession(const boost::asio::ip::address &remote_address, GetSessionCb cb)
static void CreateSessionCallback(const std::string &response, const boost::system::error_code &ec, HttpConnection *connection, AddBFDHostCb cb)
tbb::mutex mutex_
tbb::interface5::condition_variable cond_var_
int HttpDelete(const std::string &path, HttpCb)
Definition: http_client.cc:196
HttpConnection * long_poll_connection_
boost::asio::ip::tcp::endpoint ep_
RESTClient(const boost::asio::ip::tcp::endpoint &ep, EventManager *evm)
void RemoveConnection(HttpConnection *)
Definition: http_client.cc:473
boost::function< void(const REST::JsonStateMap &new_states, boost::system::error_code)> MonitorCb
boost::function< void(boost::system::error_code)> AddBFDHostCb
static void DeleteServer(TcpServer *server)
Definition: tcp_server.cc:656
bool Monitor(MonitorCb cb)
virtual ~RESTClient()
bool DeleteBFDHost(const boost::asio::ip::address &remote_address, DeleteBFDHostCb cb)
HttpClient * client()
Definition: http_client.h:98
static const REST::JsonConfig kDefaultConfig
int HttpPut(const std::string &put_string, const std::string &path, HttpCb)
Definition: http_client.cc:162
#define LOG(_Level, _Msg)
Definition: logging.h:33
void CreateRESTClientSessionCallback(const std::string &response, const boost::system::error_code &ec)
void Shutdown()
Definition: http_client.cc:406
HttpClient * http_client_
boost::asio::ip::address address
boost::optional< ClientId > client_id_
static EventManager evm