Goby3  3.1.5
2024.05.14
iridium_shore_sbd_directip.h
Go to the documentation of this file.
1 // Copyright 2015-2023:
2 // GobySoft, LLC (2013-)
3 // Community contributors (see AUTHORS file)
4 // File authors:
5 // Toby Schneider <toby@gobysoft.org>
6 //
7 //
8 // This file is part of the Goby Underwater Autonomy Project Libraries
9 // ("The Goby Libraries").
10 //
11 // The Goby Libraries are free software: you can redistribute them and/or modify
12 // them under the terms of the GNU Lesser General Public License as published by
13 // the Free Software Foundation, either version 2.1 of the License, or
14 // (at your option) any later version.
15 //
16 // The Goby Libraries are distributed in the hope that they will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
23 
24 #ifndef GOBY_ACOMMS_MODEMDRIVER_IRIDIUM_SHORE_SBD_DIRECTIP_H
25 #define GOBY_ACOMMS_MODEMDRIVER_IRIDIUM_SHORE_SBD_DIRECTIP_H
26 
27 #include <boost/asio.hpp>
28 #include <boost/bind/bind.hpp>
29 #include <boost/enable_shared_from_this.hpp>
30 
33 #include "goby/time.h"
34 #include "goby/util/asio_compat.h"
35 #include "goby/util/binary.h"
36 #include "goby/util/debug_logger.h"
37 
38 namespace goby
39 {
40 namespace acomms
41 {
42 namespace directip
43 {
44 
46 {
47  public:
48  SBDMessageReader(boost::asio::ip::tcp::socket& socket)
49  : socket_(socket), pos_(0), data_(1 << 16)
50  {
51  }
52 
53  virtual bool data_ready() const = 0;
54 
56  {
57  return pre_header_;
58  }
59  const goby::acomms::iridium::protobuf::DirectIPMOHeader& header() const { return header_; }
62  {
63  return confirm_;
64  }
65 
66  enum
67  {
70  };
71 
72  void pre_header_handler(const boost::system::error_code& error, std::size_t bytes_transferred)
73  {
74  if (error)
75  throw std::runtime_error("Error while reading: " + error.message());
76 
77  pre_header_.set_protocol_ver(read_byte());
78  pre_header_.set_overall_length(read_uint16());
79 
80  boost::asio::async_read(socket_, boost::asio::buffer(data_),
81  boost::asio::transfer_at_least(pre_header_.overall_length() +
82  PRE_HEADER_SIZE - bytes_transferred),
83  boost::bind(&SBDMessageReader::ie_handler, this,
84  boost::placeholders::_1, boost::placeholders::_2));
85  }
86 
87  std::vector<char>& data() { return data_; }
88 
89  private:
90  void ie_handler(const boost::system::error_code& error, std::size_t bytes_transferred)
91  {
92  if (error)
93  throw std::runtime_error("Error while reading: " + error.message());
94 
95  char iei = read_byte();
96  unsigned length = read_uint16();
97 
98  switch (iei)
99  {
100  case 0x01: // header
101  {
102  header_.set_iei(iei);
103  header_.set_length(length);
104  header_.set_cdr_reference(read_uint32()); // 4 bytes
105 
106  header_.set_imei(read_imei()); // 15 bytes
107 
108  header_.set_session_status(read_byte()); // 1 byte
109  header_.set_momsn(read_uint16()); // 2 bytes
110  header_.set_mtmsn(read_uint16()); // 2 bytes
111  header_.set_time_of_session(read_uint32()); // 4 bytes
112  }
113  break;
114 
115  case 0x02: // payload
116  body_.set_iei(iei);
117  body_.set_length(length);
118  body_.set_payload(std::string(data_.begin() + pos_, data_.begin() + pos_ + length));
119  pos_ += length;
120  break;
121 
122  case 0x44: // confirmation
123  confirm_.set_iei(iei);
124  confirm_.set_length(length);
125  confirm_.set_client_id(read_uint32());
126  confirm_.set_imei(read_imei());
127  confirm_.set_auto_ref_id(read_uint32());
128  confirm_.set_status(read_int16());
129 
130  default: // skip this IE
131  pos_ += length;
132  break;
133  }
134 
135  if (pos_ < pre_header_.overall_length() + PRE_HEADER_SIZE)
136  ie_handler(error, bytes_transferred);
137  }
138 
139  char read_byte() { return data_.at(pos_++) & 0xff; }
140 
141  unsigned read_uint16()
142  {
143  unsigned u = (data_.at(pos_++) & 0xff) << BITS_PER_BYTE;
144  u |= data_.at(pos_++) & 0xff;
145  return u;
146  }
147 
148  int read_int16()
149  {
150  int i = (data_.at(pos_++) & 0xff) << BITS_PER_BYTE;
151  i |= data_.at(pos_++) & 0xff;
152 
153  // sign extend
154  int sign_bit_mask = 0x8000;
155  if (i & sign_bit_mask)
156  i |= (-1 - 0xFFFF); // extend bits to fill int
157 
158  return i;
159  }
160 
161  unsigned read_uint32()
162  {
163  unsigned u = 0;
164  for (int i = 0; i < 4; ++i) u |= (data_.at(pos_++) & 0xff) << ((3 - i) * BITS_PER_BYTE);
165  return u;
166  }
167 
168  std::string read_imei()
169  {
170  const int imei_size = 15;
171  std::string imei = std::string(data_.begin() + pos_, data_.begin() + pos_ + imei_size);
172  pos_ += imei_size;
173  return imei;
174  }
175 
176  private:
181 
182  boost::asio::ip::tcp::socket& socket_;
183 
184  std::vector<char>::size_type pos_;
185  std::vector<char> data_;
186 };
187 
189 {
190  public:
191  SBDMOMessageReader(boost::asio::ip::tcp::socket& socket) : SBDMessageReader(socket) {}
192 
193  bool data_ready() const
194  {
196  }
197 };
198 
200 {
201  public:
202  SBDMTConfirmationMessageReader(boost::asio::ip::tcp::socket& socket) : SBDMessageReader(socket)
203  {
204  }
205 
206  bool data_ready() const { return pre_header().IsInitialized() && confirm().IsInitialized(); }
207 };
208 
209 class SBDConnection : public boost::enable_shared_from_this<SBDConnection>
210 {
211  public:
212  static std::shared_ptr<SBDConnection> create(
214  boost::asio::io_service& executor)
215 #else
216  const boost::asio::ip::tcp::socket::executor_type& executor)
217 #endif
218  {
219  return std::shared_ptr<SBDConnection>(new SBDConnection(executor));
220  }
221 
222  boost::asio::ip::tcp::socket& socket() { return socket_; }
223 
224  void start()
225  {
226  remote_endpoint_str_ = boost::lexical_cast<std::string>(socket_.remote_endpoint());
227 
228  connect_time_ = time::SystemClock::now().time_since_epoch() / std::chrono::seconds(1);
229  boost::asio::async_read(socket_, boost::asio::buffer(message_.data()),
230  boost::asio::transfer_at_least(SBDMessageReader::PRE_HEADER_SIZE),
232  boost::placeholders::_1, boost::placeholders::_2));
233  }
234 
236 
237  double connect_time() const { return connect_time_; }
238 
239  const SBDMOMessageReader& message() const { return message_; }
240  const std::string& remote_endpoint_str() { return remote_endpoint_str_; }
241 
242  private:
245  boost::asio::io_service& executor)
246 #else
247  const boost::asio::ip::tcp::socket::executor_type& executor)
248 #endif
249  : socket_(executor), connect_time_(-1), message_(socket_), remote_endpoint_str_("Unknown")
250  {
251  }
252 
253  boost::asio::ip::tcp::socket socket_;
254  double connect_time_;
255  SBDMOMessageReader message_;
256  std::string remote_endpoint_str_;
257 };
258 
260 {
261  public:
263  : acceptor_(io_context, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))
264  {
265  start_accept();
266  }
267 
268  std::set<std::shared_ptr<SBDConnection>>& connections() { return connections_; }
269 
270  private:
271  void start_accept()
272  {
273  std::shared_ptr<SBDConnection> new_connection =
274 #ifdef USE_BOOST_IO_SERVICE
275  SBDConnection::create(acceptor_.get_io_service());
276 #else
277  SBDConnection::create(acceptor_.get_executor());
278 #endif
279  connections_.insert(new_connection);
280 
281  acceptor_.async_accept(new_connection->socket(),
282  boost::bind(&SBDServer::handle_accept, this, new_connection,
283  boost::asio::placeholders::error));
284  }
285 
286  void handle_accept(std::shared_ptr<SBDConnection> new_connection,
287  const boost::system::error_code& error)
288  {
289  if (!error)
290  {
291  using namespace goby::util::logger;
292  using goby::glog;
293 
294  glog.is(DEBUG1) && glog << "Received SBD connection from: "
295  << new_connection->socket().remote_endpoint() << std::endl;
296 
297  new_connection->start();
298  }
299 
300  start_accept();
301  }
302 
303  std::set<std::shared_ptr<SBDConnection>> connections_;
304  boost::asio::ip::tcp::acceptor acceptor_;
305 };
306 
307 } // namespace directip
308 } // namespace acomms
309 } // namespace goby
310 
311 #endif
goby::time::SystemClock::now
static time_point now() noexcept
Returns the current system time unless SimulatorSettings::using_sim_time is set to true,...
Definition: system_clock.h:63
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_momsn
void set_momsn(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1288
goby::util::logger
Definition: flex_ncurses.h:42
goby::acomms::directip::SBDMTConfirmationMessageReader::data_ready
bool data_ready() const
Definition: iridium_shore_sbd_directip.h:206
goby::acomms::iridium::protobuf::DirectIPMOHeader::IsInitialized
bool IsInitialized() const final
goby::acomms::directip::SBDServer::connections
std::set< std::shared_ptr< SBDConnection > > & connections()
Definition: iridium_shore_sbd_directip.h:268
goby::acomms::iridium::protobuf::DirectIPMTConfirmation::set_iei
void set_iei(::google::protobuf::int32 value)
Definition: iridium_sbd_directip.pb.h:1766
goby::util::FlexOstream::is
bool is(goby::util::logger::Verbosity verbosity)
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_iei
void set_iei(::google::protobuf::int32 value)
Definition: iridium_sbd_directip.pb.h:1126
goby
The global namespace for the Goby project.
Definition: acomms_constants.h:33
goby::acomms::iridium::protobuf::DirectIPMTConfirmation::set_imei
void set_imei(const ::std::string &value)
Definition: iridium_sbd_directip.pb.h:1838
goby::acomms::directip::SBDMessageReader
Definition: iridium_shore_sbd_directip.h:45
goby::acomms::directip::SBDConnection::message
const SBDMOMessageReader & message() const
Definition: iridium_shore_sbd_directip.h:239
goby::acomms::directip::SBDMessageReader::header
const goby::acomms::iridium::protobuf::DirectIPMOHeader & header() const
Definition: iridium_shore_sbd_directip.h:59
goby::acomms::iridium::protobuf::DirectIPMOPayload::set_iei
void set_iei(::google::protobuf::int32 value)
Definition: iridium_sbd_directip.pb.h:1364
goby::acomms::directip::SBDConnection
Definition: iridium_shore_sbd_directip.h:209
goby::acomms::directip::SBDMOMessageReader::data_ready
bool data_ready() const
Definition: iridium_shore_sbd_directip.h:193
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_time_of_session
void set_time_of_session(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1336
boost
Definition: udp_driver.h:41
goby::acomms::directip::SBDServer
Definition: iridium_shore_sbd_directip.h:259
goby::acomms::iridium::protobuf::DirectIPMOPayload::set_length
void set_length(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1388
iridium_sbd_directip.pb.h
goby::acomms::directip::SBDMTConfirmationMessageReader
Definition: iridium_shore_sbd_directip.h:199
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_session_status
void set_session_status(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1264
goby::acomms::iridium::protobuf::DirectIPMOHeader
Definition: iridium_sbd_directip.pb.h:222
goby::acomms::directip::SBDMessageReader::pre_header
const goby::acomms::iridium::protobuf::DirectIPMOPreHeader & pre_header() const
Definition: iridium_shore_sbd_directip.h:55
goby::acomms::iridium::protobuf::DirectIPMOPayload::IsInitialized
bool IsInitialized() const final
goby::acomms::directip::SBDMessageReader::confirm
const goby::acomms::iridium::protobuf::DirectIPMTConfirmation & confirm() const
Definition: iridium_shore_sbd_directip.h:61
goby::acomms::directip::SBDMessageReader::data_ready
virtual bool data_ready() const =0
io_service
boost::asio::io_context
io_service io_context
Definition: asio_compat.h:44
goby::acomms::directip::SBDConnection::start
void start()
Definition: iridium_shore_sbd_directip.h:224
goby::acomms::iridium::protobuf::DirectIPMOPreHeader::IsInitialized
bool IsInitialized() const final
time.h
goby::acomms::iridium::protobuf::DirectIPMOPreHeader::set_overall_length
void set_overall_length(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1098
goby::acomms::directip::SBDMessageReader::SBDMessageReader
SBDMessageReader(boost::asio::ip::tcp::socket &socket)
Definition: iridium_shore_sbd_directip.h:48
goby::acomms::directip::SBDMessageReader::body
const goby::acomms::iridium::protobuf::DirectIPMOPayload & body() const
Definition: iridium_shore_sbd_directip.h:60
goby::acomms::directip::SBDMessageReader::data
std::vector< char > & data()
Definition: iridium_shore_sbd_directip.h:87
goby::acomms::iridium::protobuf::DirectIPMTConfirmation::set_length
void set_length(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1790
goby::acomms::directip::SBDMessageReader::PRE_HEADER_SIZE
@ PRE_HEADER_SIZE
Definition: iridium_shore_sbd_directip.h:68
goby::acomms::iridium::protobuf::DirectIPMOPreHeader
Definition: iridium_sbd_directip.pb.h:95
goby::acomms::directip::SBDServer::SBDServer
SBDServer(boost::asio::io_context &io_context, int port)
Definition: iridium_shore_sbd_directip.h:262
asio_compat.h
goby::acomms::directip::SBDMessageReader::BITS_PER_BYTE
@ BITS_PER_BYTE
Definition: iridium_shore_sbd_directip.h:69
goby::acomms::iridium::protobuf::DirectIPMOPayload::set_payload
void set_payload(const ::std::string &value)
Definition: iridium_sbd_directip.pb.h:1412
goby::acomms::bind
void bind(ModemDriverBase &driver, QueueManager &queue_manager)
binds the driver link-layer callbacks to the QueueManager
Definition: bind.h:45
binary.h
debug_logger.h
USE_BOOST_IO_SERVICE
#define USE_BOOST_IO_SERVICE
Definition: asio_compat.h:33
goby::acomms::iridium::protobuf::DirectIPMTConfirmation::set_auto_ref_id
void set_auto_ref_id(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1904
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_imei
void set_imei(const ::std::string &value)
Definition: iridium_sbd_directip.pb.h:1198
goby::acomms::directip::SBDConnection::connect_time
double connect_time() const
Definition: iridium_shore_sbd_directip.h:237
goby::acomms::directip::SBDConnection::create
static std::shared_ptr< SBDConnection > create(const boost::asio::ip::tcp::socket::executor_type &executor)
Definition: iridium_shore_sbd_directip.h:212
goby::acomms::directip::SBDConnection::socket
boost::asio::ip::tcp::socket & socket()
Definition: iridium_shore_sbd_directip.h:222
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_mtmsn
void set_mtmsn(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1312
goby::util::logger::DEBUG1
@ DEBUG1
Definition: flex_ostreambuf.h:77
goby::acomms::directip::SBDMessageReader::pre_header_handler
void pre_header_handler(const boost::system::error_code &error, std::size_t bytes_transferred)
Definition: iridium_shore_sbd_directip.h:72
goby::acomms::directip::SBDMOMessageReader::SBDMOMessageReader
SBDMOMessageReader(boost::asio::ip::tcp::socket &socket)
Definition: iridium_shore_sbd_directip.h:191
goby::glog
util::FlexOstream glog
Access the Goby logger through this object.
goby::acomms::iridium::protobuf::DirectIPMTConfirmation
Definition: iridium_sbd_directip.pb.h:872
goby::acomms::directip::SBDConnection::~SBDConnection
~SBDConnection()
Definition: iridium_shore_sbd_directip.h:235
goby::acomms::directip::SBDConnection::remote_endpoint_str
const std::string & remote_endpoint_str()
Definition: iridium_shore_sbd_directip.h:240
goby::acomms::iridium::protobuf::DirectIPMOPayload
Definition: iridium_sbd_directip.pb.h:417
goby::acomms::iridium::protobuf::DirectIPMTConfirmation::set_client_id
void set_client_id(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1814
goby::acomms::iridium::protobuf::DirectIPMTConfirmation::set_status
void set_status(::google::protobuf::int32 value)
Definition: iridium_sbd_directip.pb.h:1928
goby::acomms::directip::SBDMTConfirmationMessageReader::SBDMTConfirmationMessageReader
SBDMTConfirmationMessageReader(boost::asio::ip::tcp::socket &socket)
Definition: iridium_shore_sbd_directip.h:202
goby::acomms::iridium::protobuf::DirectIPMTConfirmation::IsInitialized
bool IsInitialized() const final
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_length
void set_length(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1150
rudics_shore.pb.h
goby::acomms::iridium::protobuf::DirectIPMOHeader::set_cdr_reference
void set_cdr_reference(::google::protobuf::uint32 value)
Definition: iridium_sbd_directip.pb.h:1174
goby::acomms::directip::SBDMOMessageReader
Definition: iridium_shore_sbd_directip.h:188
goby::acomms::iridium::protobuf::DirectIPMOPreHeader::overall_length
::google::protobuf::uint32 overall_length() const
Definition: iridium_sbd_directip.pb.h:1094
goby::acomms::iridium::protobuf::DirectIPMOPreHeader::set_protocol_ver
void set_protocol_ver(::google::protobuf::int32 value)
Definition: iridium_sbd_directip.pb.h:1074