Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
00001 // copyright 2010 t. schneider tes@mit.edu 00002 // 00003 // 00004 // This program is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // This software is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this software. If not, see <http://www.gnu.org/licenses/>. 00016 00017 00018 #ifndef TCPServer20100719H 00019 #define TCPServer20100719H 00020 00021 #include <iostream> 00022 #include <string> 00023 #include <set> 00024 #include <deque> 00025 00026 #include <boost/bind.hpp> 00027 #include <boost/shared_ptr.hpp> 00028 #include <boost/enable_shared_from_this.hpp> 00029 #include <boost/foreach.hpp> 00030 #include <boost/asio.hpp> 00031 00032 #include "goby/util/string.h" 00033 00034 #include "interface.h" 00035 #include "connection.h" 00036 00037 namespace goby 00038 { 00039 namespace util 00040 { 00041 class TCPConnection; 00042 00044 class TCPServer : public LineBasedInterface 00045 { 00046 public: 00051 TCPServer(unsigned port, 00052 const std::string& delimiter = "\r\n") 00053 : LineBasedInterface(delimiter), 00054 acceptor_(LineBasedInterface::io_service_, 00055 boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) 00056 { } 00057 00059 std::string local_endpoint() { return goby::util::as<std::string>(acceptor_.local_endpoint()); } 00060 00061 00062 00063 // for access to static members of LineBasedInterface 00064 friend class TCPConnection; 00065 friend class LineBasedConnection<boost::asio::ip::tcp::socket>; 00066 private: 00067 void do_start() 00068 { start_accept(); } 00069 00070 void do_write(const protobuf::Datagram& line); 00071 void do_close(const boost::system::error_code& error); 00072 00073 private: 00074 void start_accept(); 00075 void handle_accept(boost::shared_ptr<TCPConnection> new_connection, 00076 const boost::system::error_code& error); 00077 00078 private: 00079 static std::map<std::string, TCPServer*> inst_; 00080 std::string server_; 00081 boost::asio::ip::tcp::acceptor acceptor_; 00082 boost::shared_ptr<TCPConnection> new_connection_; 00083 std::set< boost::shared_ptr<TCPConnection> > connections_; 00084 }; 00085 00086 00087 class TCPConnection : public boost::enable_shared_from_this<TCPConnection>, 00088 public LineBasedConnection<boost::asio::ip::tcp::socket> 00089 { 00090 public: 00091 static boost::shared_ptr<TCPConnection> create(); 00092 00093 boost::asio::ip::tcp::socket& socket() 00094 { return socket_; } 00095 00096 void start() 00097 { socket_.get_io_service().post(boost::bind(&TCPConnection::read_start, this)); } 00098 00099 void write(const protobuf::Datagram& msg) 00100 { socket_.get_io_service().post(boost::bind(&TCPConnection::socket_write, this, msg)); } 00101 00102 void close(const boost::system::error_code& error) 00103 { socket_.get_io_service().post(boost::bind(&TCPConnection::socket_close, this, error)); } 00104 00105 std::string local_endpoint() { return goby::util::as<std::string>(socket_.local_endpoint()); } 00106 std::string remote_endpoint() { return goby::util::as<std::string>(socket_.remote_endpoint()); } 00107 00108 private: 00109 void socket_write(const protobuf::Datagram& line); 00110 void socket_close(const boost::system::error_code& error); 00111 00112 TCPConnection() 00113 : socket_(LineBasedInterface::io_service_) 00114 { } 00115 00116 00117 private: 00118 boost::asio::ip::tcp::socket socket_; 00119 }; 00120 } 00121 00122 } 00123 00124 #endif