23 #ifndef IridiumShoreSBD20150508H 24 #define IridiumShoreSBD20150508H 26 #include <boost/asio.hpp> 27 #include <boost/bind.hpp> 28 #include <boost/enable_shared_from_this.hpp> 29 #include <boost/signals2.hpp> 31 #include "goby/common/time.h" 32 #include "goby/util/binary.h" 41 static boost::shared_ptr<RUDICSConnection> create(boost::asio::io_service& io_service)
43 return boost::shared_ptr<RUDICSConnection>(
new RUDICSConnection(io_service));
46 boost::asio::ip::tcp::socket& socket() {
return socket_; }
50 remote_endpoint_str_ = boost::lexical_cast<std::string>(socket_.remote_endpoint());
56 socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
62 boost::asio::async_read_until(socket_, buffer_,
'\r',
63 boost::bind(&RUDICSConnection::handle_read,
this, _1, _2));
66 void write_start(
const std::string& data)
68 boost::asio::async_write(socket_, boost::asio::buffer(data),
69 boost::bind(&RUDICSConnection::handle_write,
this, _1, _2));
75 using goby::common::logger::DEBUG1;
76 glog.is(DEBUG1) &&
glog <<
"Disconnecting from: " << remote_endpoint_str_ << std::endl;
79 void add_packet_failure()
82 using goby::common::logger::DEBUG1;
83 const int max_packet_failures = 3;
84 if (++packet_failures_ >= max_packet_failures)
86 glog.is(DEBUG1) &&
glog <<
"More than " << max_packet_failures <<
" bad RUDICS packets." 92 boost::signals2::signal<void(
const std::string& line,
93 boost::shared_ptr<RUDICSConnection> connection)>
95 boost::signals2::signal<void(boost::shared_ptr<RUDICSConnection> connection)> disconnect_signal;
97 const std::string& remote_endpoint_str() {
return remote_endpoint_str_; }
101 : socket_(io_service), remote_endpoint_str_(
"Unknown"), packet_failures_(0)
105 void handle_write(
const boost::system::error_code& error,
size_t bytes_transferred)
110 using goby::common::logger::WARN;
111 glog.is(WARN) &&
glog <<
"Error writing to TCP connection: " << error << std::endl;
112 disconnect_signal(shared_from_this());
116 void handle_read(
const boost::system::error_code& error,
size_t bytes_transferred)
119 using goby::common::logger::DEBUG1;
120 using goby::common::logger::WARN;
123 std::istream istrm(&buffer_);
125 std::getline(istrm, line,
'\r');
126 line_signal(line +
"\r", shared_from_this());
131 if (error == boost::asio::error::eof)
133 glog.is(DEBUG1) &&
glog <<
"Connection reached EOF" << std::endl;
135 else if (error == boost::asio::error::operation_aborted)
137 glog.is(DEBUG1) &&
glog <<
"Read operation aborted (socket closed)" << std::endl;
141 glog.is(WARN) &&
glog <<
"Error reading from TCP connection: " << error
145 disconnect_signal(shared_from_this());
150 boost::asio::ip::tcp::socket socket_;
151 boost::asio::streambuf buffer_;
152 std::string remote_endpoint_str_;
153 int packet_failures_;
159 RUDICSServer(boost::asio::io_service& io_service,
int port)
160 : acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))
165 std::set<boost::shared_ptr<RUDICSConnection> >& connections() {
return connections_; }
167 boost::signals2::signal<void(boost::shared_ptr<RUDICSConnection> connection)> connect_signal;
169 void disconnect(boost::shared_ptr<RUDICSConnection> connection) { connection->close(); }
174 boost::shared_ptr<RUDICSConnection> new_connection =
175 RUDICSConnection::create(acceptor_.get_io_service());
176 acceptor_.async_accept(new_connection->socket(),
177 boost::bind(&RUDICSServer::handle_accept,
this, new_connection,
178 boost::asio::placeholders::error));
181 void handle_accept(boost::shared_ptr<RUDICSConnection> new_connection,
182 const boost::system::error_code& error)
189 connections_.insert(new_connection);
191 new_connection->disconnect_signal.connect(
192 boost::bind(&RUDICSServer::handle_disconnect,
this, _1));
193 connect_signal(new_connection);
194 new_connection->start();
195 glog.is(DEBUG1) &&
glog <<
"Received connection from: " 196 << new_connection->remote_endpoint_str() << std::endl;
202 void handle_disconnect(boost::shared_ptr<RUDICSConnection> connection)
205 using goby::common::logger::DEBUG1;
207 connections_.erase(connection);
210 glog <<
"Server removing connection: " << connection->remote_endpoint_str()
211 <<
". Remaining connection count: " << connections_.size() << std::endl;
214 std::set<boost::shared_ptr<RUDICSConnection> > connections_;
215 boost::asio::ip::tcp::acceptor acceptor_;
common::FlexOstream glog
Access the Goby logger through this object.
The global namespace for the Goby project.
void disconnect(Signal *signal, Slot slot)
disconnect a signal to a slot (e.g. function pointer)