Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
00001 // copyright 2009, 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 #ifndef ClientBase20100628H 00018 #define ClientBase20100628H 00019 00020 #include "interface.h" 00021 #include "connection.h" 00022 00023 namespace goby 00024 { 00025 namespace util 00026 { 00027 // template for type of client socket (asio::serial_port, asio::ip::tcp::socket) 00028 // LineBasedInterface runs in a one thread (same as user program) 00029 // LineBasedClient and LineBasedConnection run in another thread (spawned by LineBasedInterface's constructor) 00030 template<typename ASIOAsyncReadStream> 00031 class LineBasedClient : public LineBasedInterface, public LineBasedConnection<ASIOAsyncReadStream> 00032 { 00033 00034 protected: 00035 LineBasedClient(const std::string& delimiter) 00036 : LineBasedInterface(delimiter), 00037 LineBasedConnection<ASIOAsyncReadStream>() 00038 { } 00039 00040 enum { RETRY_INTERVAL = 10 }; 00041 00042 virtual ASIOAsyncReadStream& socket () = 0; 00043 virtual std::string local_endpoint() = 0; 00044 virtual std::string remote_endpoint() = 0; 00045 00046 // from LineBasedInterface 00047 void do_start() 00048 { 00049 last_start_time_ = goby_time(); 00050 00051 set_active(start_specific()); 00052 00053 LineBasedConnection<ASIOAsyncReadStream>::read_start(); 00054 if(!LineBasedConnection<ASIOAsyncReadStream>::out().empty()) 00055 LineBasedConnection<ASIOAsyncReadStream>::write_start(); 00056 } 00057 00058 virtual bool start_specific() = 0; 00059 00060 // from LineBasedInterface 00061 void do_write(const protobuf::Datagram& line) 00062 { 00063 bool write_in_progress = !LineBasedConnection<ASIOAsyncReadStream>::out().empty(); 00064 LineBasedConnection<ASIOAsyncReadStream>::out().push_back(line); 00065 if (!write_in_progress) LineBasedConnection<ASIOAsyncReadStream>::write_start(); 00066 } 00067 00068 // from LineBasedInterface 00069 void do_close(const boost::system::error_code& error) 00070 { 00071 if (error == boost::asio::error::operation_aborted) // if this call is the result of a timer cancel() 00072 return; // ignore it because the connection cancelled the timer 00073 00074 set_active(false); 00075 socket().close(); 00076 00077 using namespace boost::posix_time; 00078 ptime now = goby_time(); 00079 if(now - seconds(RETRY_INTERVAL) < last_start_time_) 00080 sleep(RETRY_INTERVAL - (now-last_start_time_).total_seconds()); 00081 00082 do_start(); 00083 } 00084 00085 // same as do_close in this case 00086 void socket_close(const boost::system::error_code& error) 00087 { do_close(error); } 00088 00089 //for static members of LineBasedInterface 00090 friend class LineBasedConnection<ASIOAsyncReadStream>; 00091 private: 00092 boost::posix_time::ptime last_start_time_; 00093 00094 LineBasedClient(const LineBasedClient&); 00095 LineBasedClient& operator= (const LineBasedClient&); 00096 00097 }; 00098 00099 } 00100 } 00101 00102 00103 #endif