Goby v2
client_base.h
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef ClientBase20100628H
24 #define ClientBase20100628H
25 
26 #include "connection.h"
27 #include "interface.h"
28 
29 namespace goby
30 {
31 namespace util
32 {
33 // template for type of client socket (asio::serial_port, asio::ip::tcp::socket)
34 // LineBasedInterface runs in a one thread (same as user program)
35 // LineBasedClient and LineBasedConnection run in another thread (spawned by LineBasedInterface's constructor)
36 template <typename ASIOAsyncReadStream>
37 class LineBasedClient : public LineBasedInterface, public LineBasedConnection<ASIOAsyncReadStream>
38 {
39  protected:
40  LineBasedClient(const std::string& delimiter, int retry_interval = 10)
42  retry_interval_(retry_interval)
43  {
44  }
45 
46  virtual ~LineBasedClient() {}
47 
48  virtual ASIOAsyncReadStream& socket() = 0;
49  virtual std::string local_endpoint() = 0;
50  virtual std::string remote_endpoint() = 0;
51 
52  // from LineBasedInterface
53  void do_start()
54  {
55  last_start_time_ = common::goby_time();
56 
57  set_active(start_specific());
58 
59  LineBasedInterface::io_service().post(
62  LineBasedInterface::io_service().post(
64  }
65 
66  virtual bool start_specific() = 0;
67 
68  // from LineBasedInterface
69  void do_write(const protobuf::Datagram& line)
70  {
71  bool write_in_progress = !LineBasedConnection<ASIOAsyncReadStream>::out().empty();
73  if (!write_in_progress)
74  LineBasedInterface::io_service().post(
76  }
77 
78  // from LineBasedInterface
79  void do_close(const boost::system::error_code& error)
80  {
81  if (error ==
82  boost::asio::error::operation_aborted) // if this call is the result of a timer cancel()
83  return; // ignore it because the connection cancelled the timer
84 
85  set_active(false);
86  socket().close();
87 
88  // try to restart if we had a real error
89  if (error != boost::system::error_code())
90  {
91  using namespace boost::posix_time;
92  ptime now = common::goby_time();
93  if (now - seconds(retry_interval_) < last_start_time_)
94  LineBasedInterface::sleep(retry_interval_ -
95  (now - last_start_time_).total_seconds());
96 
97  // add this to the io_service jobs
98  LineBasedInterface::start();
99  }
100  }
101 
102  // same as do_close in this case
103  void socket_close(const boost::system::error_code& error) { do_close(error); }
104 
105  private:
106  boost::posix_time::ptime last_start_time_;
107 
109  LineBasedClient& operator=(const LineBasedClient&);
110 
111  int retry_interval_;
112 };
113 
114 } // namespace util
115 } // namespace goby
116 
117 #endif
ReturnType goby_time()
Returns current UTC time as a boost::posix_time::ptime.
Definition: time.h:104
The global namespace for the Goby project.
basic interface class for all the derived serial (and networking mimics) line-based nodes (serial...
Definition: interface.h:44