tcp_interface.cpp
Go to the documentation of this file.
00001 /*
00002 * Unpublished Copyright (c) 2009-2017 AutonomouStuff, LLC, All Rights Reserved.
00003 *
00004 * This file is part of the network_interface ROS 1.0 driver which is released under the MIT license.
00005 * See file LICENSE included with this software or go to https://opensource.org/licenses/MIT for full license details.
00006 */
00007 
00008 #include <network_interface.h>
00009 
00010 using namespace AS::Network;  // NOLINT
00011 using boost::asio::ip::tcp;
00012 
00013 // Default constructor.
00014 TCPInterface::TCPInterface() :
00015   socket_(io_service_)
00016 {
00017 }
00018 
00019 // Default destructor.
00020 TCPInterface::~TCPInterface()
00021 {
00022 }
00023 
00024 return_statuses TCPInterface::open(const char *ip_address, const int &port)
00025 {
00026   if (socket_.is_open())
00027     return OK;
00028 
00029   std::stringstream sPort;
00030   sPort << port;
00031   tcp::resolver res(io_service_);
00032   tcp::resolver::query query(tcp::v4(), ip_address, sPort.str());
00033   tcp::resolver::iterator it = res.resolve(query);
00034   boost::system::error_code ec;
00035 
00036   socket_.connect(*it, ec);
00037 
00038   if (ec.value() == boost::system::errc::success)
00039   {
00040     return OK;
00041   }
00042   else if (ec.value() == boost::asio::error::invalid_argument)
00043   {
00044     return BAD_PARAM;
00045   }
00046   else
00047   {
00048     close();
00049     return INIT_FAILED;
00050   }
00051 }
00052 
00053 return_statuses TCPInterface::close()
00054 {
00055   if (!socket_.is_open())
00056     return OK;
00057 
00058   boost::system::error_code ec;
00059   socket_.close(ec);
00060 
00061   if (ec.value() == boost::system::errc::success)
00062   {
00063     return OK;
00064   }
00065   else
00066   {
00067     return CLOSE_FAILED;
00068   }
00069 }
00070 
00071 bool TCPInterface::is_open()
00072 {
00073   return socket_.is_open();
00074 }
00075 
00076 void TCPInterface::timeout_handler(const boost::system::error_code& error)
00077 {
00078   // If the operation was not aborted, store the bytes that were read and set the read flag
00079   if (error != boost::asio::error::operation_aborted)
00080   {
00081     error_.assign(boost::system::errc::timed_out, boost::system::system_category());
00082   }
00083 }
00084 
00085 void TCPInterface::read_handler(const boost::system::error_code& error, size_t bytes_read)
00086 {
00087   bytes_read_ = bytes_read;
00088 }
00089 
00090 return_statuses TCPInterface::read(unsigned char *msg,
00091                                    const size_t &buf_size,
00092                                    size_t &bytes_read,
00093                                    int timeout_ms)
00094 {
00095   if (!socket_.is_open())
00096     return SOCKET_CLOSED;
00097 
00098   error_.assign(boost::system::errc::success, boost::system::system_category());
00099 
00100   boost::asio::deadline_timer timer(io_service_);
00101   // If requested timeout duration is set to 0 ms, don't set a deadline
00102   if (timeout_ms > 0)
00103   {
00104     timer.expires_from_now(boost::posix_time::milliseconds(timeout_ms));
00105     timer.async_wait(boost::bind(&TCPInterface::timeout_handler,
00106                                  this,
00107                                  boost::asio::placeholders::error));
00108   }
00109 
00110   boost::asio::async_read(socket_,
00111                           boost::asio::buffer(msg, buf_size),
00112                           boost::bind(&TCPInterface::read_handler,
00113                                       this,
00114                                       boost::asio::placeholders::error,
00115                                       boost::asio::placeholders::bytes_transferred));
00116   // Run until a handler is called
00117   while (io_service_.run_one())
00118   {
00119     if (error_.value() == boost::system::errc::success)
00120     {
00121       timer.cancel();
00122       bytes_read = bytes_read_;
00123     }
00124     else if (error_.value() == boost::system::errc::timed_out)
00125     {
00126       socket_.cancel();
00127     }
00128   }
00129   // Reset the io service so that it is available for the next call to TCPInterface::read
00130   io_service_.reset();
00131 
00132   if (error_.value() == boost::system::errc::success)
00133   {
00134     return OK;
00135   }
00136   else if (error_.value() == boost::system::errc::timed_out)
00137   {
00138     return SOCKET_TIMEOUT;
00139   }
00140   else
00141   {
00142     return READ_FAILED;
00143   }
00144 }
00145 
00146 return_statuses TCPInterface::read_exactly(unsigned char *msg,
00147     const size_t &buf_size,
00148     const size_t &bytes_to_read,
00149     int timeout_ms)
00150 {
00151   if (!socket_.is_open())
00152     return SOCKET_CLOSED;
00153 
00154   error_.assign(boost::system::errc::success, boost::system::system_category());
00155 
00156   boost::asio::deadline_timer timer(io_service_);
00157   // If requested timeout duration is set to 0 ms, don't set a deadline
00158   if (timeout_ms > 0)
00159   {
00160     timer.expires_from_now(boost::posix_time::milliseconds(timeout_ms));
00161     timer.async_wait(boost::bind(&TCPInterface::timeout_handler,
00162                                  this,
00163                                  boost::asio::placeholders::error));
00164   }
00165 
00166   boost::asio::async_read(socket_,
00167                           boost::asio::buffer(msg, buf_size),
00168                           boost::asio::transfer_exactly(bytes_to_read),
00169                           boost::bind(&TCPInterface::read_handler,
00170                                       this,
00171                                       boost::asio::placeholders::error,
00172                                       boost::asio::placeholders::bytes_transferred));
00173   // Run until a handler is called
00174   while (io_service_.run_one())
00175   {
00176     if (error_.value() == boost::system::errc::success)
00177     {
00178       timer.cancel();
00179     }
00180     else if (error_.value() == boost::system::errc::timed_out)
00181     {
00182       socket_.cancel();
00183     }
00184   }
00185   // Reset the io service so that it is available for the next call to TCPInterface::read_exactly
00186   io_service_.reset();
00187 
00188   if (error_.value() == boost::system::errc::success)
00189   {
00190     return OK;
00191   }
00192   else if (error_.value() == boost::system::errc::timed_out)
00193   {
00194     return SOCKET_TIMEOUT;
00195   }
00196   else
00197   {
00198     return READ_FAILED;
00199   }
00200 }
00201 
00202 return_statuses TCPInterface::write(unsigned char *msg, const size_t &msg_size)
00203 {
00204   if (!socket_.is_open())
00205     return SOCKET_CLOSED;
00206 
00207   boost::system::error_code ec;
00208   boost::asio::write(socket_, boost::asio::buffer(msg, msg_size), ec);
00209 
00210   if (ec.value() == boost::system::errc::success)
00211   {
00212     return OK;
00213   }
00214   else
00215   {
00216     return WRITE_FAILED;
00217   }
00218 }


network_interface
Author(s): Joshua Whitley , Daniel Stanek , Joe Kale
autogenerated on Thu Jun 6 2019 21:43:30