Note: Goby version 1 (shown here) is now considered obsolete. Please use version 2 for new projects, and consider upgrading old projects.

Goby Underwater Autonomy Project  Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
util/liblinebasedcomms/client_base.h
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends