Go to the documentation of this file.00001
00055 #pragma once
00056
00057 #include <cstdlib>
00058 #include <iostream>
00059 #include <boost/bind.hpp>
00060 #include <boost/asio.hpp>
00061 #include <boost/signals2/signal.hpp>
00062 #include <boost/thread/mutex.hpp>
00063
00064 #include <ros/console.h>
00065
00067 class Any_Session
00068 {
00069 public:
00071 typedef boost::signals2::signal<void (const char *data, const size_t size, Any_Session *writer)> SIG_ON_DATA;
00072
00074 Any_Session(SIG_ON_DATA &cb)
00075 : on_data_(cb)
00076 {
00077 }
00078
00079 virtual ~Any_Session() {}
00080
00082 virtual void write(const std::string &buffer)=0;
00083
00084 protected:
00085
00086 SIG_ON_DATA &on_data_;
00087 };
00088
00089
00091 class TCP_Session : public Any_Session
00092 {
00093 public:
00094
00095 TCP_Session(boost::asio::io_service& io_service, SIG_ON_DATA &cb)
00096 : Any_Session(cb), socket_(io_service)
00097 {
00098 }
00099
00100 virtual ~TCP_Session() {
00101 }
00102
00104 boost::asio::ip::tcp::socket& socket()
00105 {
00106 return socket_;
00107 }
00108
00109 virtual bool connect(const std::string &path, const std::string &service)
00110 {
00111 boost::asio::ip::tcp::resolver resolver(socket_.get_io_service());
00112 boost::asio::ip::tcp::resolver::query query(path, service);
00113 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
00114 boost::asio::ip::tcp::resolver::iterator end;
00115
00116 while (endpoint_iterator != end) {
00117 if(connect(*endpoint_iterator))
00118 return true;
00119 }
00120
00121 return false;
00122 }
00123
00124 virtual bool connect(const boost::asio::ip::tcp::resolver::endpoint_type &ep)
00125 {
00126 close();
00127
00128 boost::system::error_code error = boost::asio::error::host_not_found;
00129 socket_.connect(ep, error);
00130 if (error) {
00131 ROS_ERROR("connecting failed");
00132 return false;
00133 }
00134
00135 socket_.async_read_some(boost::asio::buffer(data_, max_length),
00136 boost::bind(&TCP_Session::handle_read, this,
00137 boost::asio::placeholders::error,
00138 boost::asio::placeholders::bytes_transferred));
00139 return true;
00140 }
00141
00142 virtual void close() {
00143 if(socket_.is_open()) socket_.close();
00144 boost::mutex::scoped_lock lock(mtx_);
00145 }
00146
00147 protected:
00148
00150 virtual void write(const std::string &buffer) {
00151 boost::asio::async_write(socket_,
00152 boost::asio::buffer( buffer ),
00153 boost::bind(&TCP_Session::handle_write, this,
00154 boost::asio::placeholders::error));
00155 }
00156 virtual void write(const std::vector<char> &buffer) {
00157 boost::asio::async_write(socket_,
00158 boost::asio::buffer( buffer ),
00159 boost::bind(&TCP_Session::handle_write, this,
00160 boost::asio::placeholders::error));
00161 }
00162
00164 virtual void write(const boost::asio::mutable_buffers_1 &buffer) {
00165 boost::asio::async_write(socket_,
00166 buffer,
00167 boost::bind(&TCP_Session::handle_write, this,
00168 boost::asio::placeholders::error));
00169 }
00170
00171 private:
00172
00174 void handle_read(const boost::system::error_code& error,
00175 size_t bytes_transferred)
00176 {
00177
00178
00179 if (!error)
00180 {
00181 on_data_(data_, bytes_transferred, this);
00182 }
00183 else
00184 {
00185 ROS_ERROR("error while reading from socket");
00186 delete this;
00187 }
00188
00189 if(socket_.is_open())
00190 socket_.async_read_some(boost::asio::buffer(data_, max_length),
00191 boost::bind(&TCP_Session::handle_read, this,
00192 boost::asio::placeholders::error,
00193 boost::asio::placeholders::bytes_transferred));
00194 }
00195
00197 void handle_write(const boost::system::error_code& error)
00198 {
00199
00200
00201 if (error)
00202 {
00203 ROS_ERROR("error while writing to socket");
00204 delete this;
00205 }
00206 }
00207
00208 protected:
00209 boost::asio::ip::tcp::socket socket_;
00210 enum { max_length = 4096 };
00211 char data_[max_length];
00212 boost::mutex mtx_;
00213 };