TOBI Interface A  0.1
/home/breidi/Dropbox/libtia/src/tia/newtia/network_impl/boost_tcp_socket_impl.cpp
00001 /*
00002     This file is part of the TOBI Interface A (TiA) library.
00003 
00004     Commercial Usage
00005     Licensees holding valid Graz University of Technology Commercial
00006     licenses may use this file in accordance with the Graz University
00007     of Technology Commercial License Agreement provided with the
00008     Software or, alternatively, in accordance with the terms contained in
00009     a written agreement between you and Graz University of Technology.
00010 
00011     --------------------------------------------------
00012 
00013     GNU Lesser General Public License Usage
00014     Alternatively, this file may be used under the terms of the GNU Lesser
00015     General Public License version 3.0 as published by the Free Software
00016     Foundation and appearing in the file lgpl.txt included in the
00017     packaging of this file.  Please review the following information to
00018     ensure the GNU General Public License version 3.0 requirements will be
00019     met: http://www.gnu.org/copyleft/lgpl.html.
00020 
00021     In case of GNU Lesser General Public License Usage ,the TiA library
00022     is distributed in the hope that it will be useful,
00023     but WITHOUT ANY WARRANTY; without even the implied warranty of
00024     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025     GNU General Public License for more details.
00026 
00027     You should have received a copy of the GNU Lesser General Public License
00028     along with the TiA library. If not, see <http://www.gnu.org/licenses/>.
00029 
00030     Copyright 2010 Graz University of Technology
00031     Contact: TiA@tobi-project.org
00032 */
00033 
00034 #include "tia-private/newtia/network_impl/boost_tcp_socket_impl.h"
00035 #include "tia-private/newtia/messages/tia_control_message_tags_1_0.h"
00036 #include "tia-private/newtia/tia_exceptions.h"
00037 
00038 #include <boost/asio.hpp>
00039 #include <boost/lexical_cast.hpp>
00040 #include <iostream>
00041 
00042 using std::string;
00043 
00044 static const int RESERVED_STRING_LENGTH = 2048;
00045 static const int RESERVED_STREAM_BUFFER_SIZE = 2048;
00046 
00047 namespace tia
00048 {
00049 BoostTCPSocketImpl::BoostTCPSocketImpl (boost::asio::io_service& io_service,
00050                                         boost::asio::ip::tcp::endpoint const& endpoint, unsigned buffer_size)
00051   : socket_ (new boost::asio::ip::tcp::socket (io_service) ), input_stream_(&stream_buffer_)
00052 {
00053   socket_->connect (endpoint);
00054   boost::asio::socket_base::receive_buffer_size option (buffer_size);
00055   socket_->set_option (option);
00056 
00057   remote_endpoint_str_ = socket_->remote_endpoint().address().to_string() + ":"
00058       + boost::lexical_cast<std::string>( socket_->remote_endpoint().port() );
00059 
00060   local_endpoint_str_ = socket_->local_endpoint().address().to_string() + ":"
00061       + boost::lexical_cast<std::string>( socket_->local_endpoint().port() );
00062 
00063 
00064   stream_buffer_.prepare(RESERVED_STREAM_BUFFER_SIZE);
00065   str_buffer_.reserve(RESERVED_STRING_LENGTH);
00066 }
00067 
00068 //-----------------------------------------------------------------------------
00069 
00070 BoostTCPSocketImpl::BoostTCPSocketImpl (boost::shared_ptr<boost::asio::ip::tcp::socket> boost_socket)
00071     : socket_ (boost_socket), input_stream_(&stream_buffer_)
00072 {
00073   remote_endpoint_str_ = socket_->remote_endpoint().address().to_string() + ":"
00074       + boost::lexical_cast<std::string>( socket_->remote_endpoint().port() );
00075 
00076   local_endpoint_str_ = socket_->local_endpoint().address().to_string() + ":"
00077       + boost::lexical_cast<std::string>( socket_->local_endpoint().port() );
00078 
00079   stream_buffer_.prepare(RESERVED_STREAM_BUFFER_SIZE);
00080   str_buffer_.reserve(RESERVED_STRING_LENGTH);
00081 }
00082 
00083 //-----------------------------------------------------------------------------
00084 BoostTCPSocketImpl::~BoostTCPSocketImpl ()
00085 {
00086     if (socket_)
00087     {
00088         socket_->close ();
00089     }
00090     str_buffer_.clear ();
00091 }
00092 
00093 //-----------------------------------------------------------------------------
00094 void BoostTCPSocketImpl::setReceiveBufferSize (unsigned size)
00095 {
00096     boost::asio::socket_base::receive_buffer_size option(size);
00097     if (socket_)
00098         socket_->set_option (option);
00099 }
00100 
00101 //-----------------------------------------------------------------------------
00102 
00103 string BoostTCPSocketImpl::readUntil (char delimiter)
00104 {
00105   error_.clear();
00106   str_buffer_.clear();
00107   size_t transfered = boost::asio::read_until (*socket_, stream_buffer_, delimiter, error_ );
00108 
00109   if(error_)
00110     throw TiALostConnection ("InputStreamSocket::readUntil error_ read_until: "
00111                              + string (error_.category().name()) + error_.message());
00112   str_buffer_.resize(transfered -1);
00113 
00114   size_t n = 0;
00115   while(n != transfered-1)
00116   {
00117     str_buffer_[n] = input_stream_.peek();
00118     stream_buffer_.consume(1);
00119     n++;
00120   }
00121   input_stream_.get();
00122 
00123   return(str_buffer_);
00124 }
00125 
00126 //-----------------------------------------------------------------------------
00127 
00128 string BoostTCPSocketImpl::readUntil (std::string delimiter)
00129 {
00130   error_.clear();
00131   str_buffer_.clear();
00132   size_t transfered = boost::asio::read_until (*socket_, stream_buffer_, delimiter,error_ );
00133 
00134   if(error_)
00135     throw TiALostConnection ("InputStreamSocket::readUntil error_ read_until: "
00136                              + string (error_.category().name()) + error_.message());
00137   str_buffer_.resize(transfered -delimiter.size());
00138 
00139   size_t n = 0;
00140   while(n != transfered-delimiter.size())
00141   {
00142     str_buffer_[n] = input_stream_.peek();
00143     stream_buffer_.consume(1);
00144     n++;
00145   }
00146 
00147   for(unsigned int s = 0; s < delimiter.size(); s++)
00148     input_stream_.get();
00149 
00150   return(str_buffer_);
00151 }
00152 
00153 
00154 //-----------------------------------------------------------------------------
00155 string BoostTCPSocketImpl::readString (unsigned length)
00156 {
00157   str_buffer_.clear();
00158   if(stream_buffer_.size() < length)
00159   {
00160     error_.clear();
00161     boost::asio::read (*socket_, stream_buffer_,
00162                        boost::asio::transfer_at_least( length - stream_buffer_.size() ), error_ ) ;
00163     if (error_)
00164       throw TiALostConnection ("InputStreamSocket::readString error_ read: "
00165                                + string (error_.category().name()) + error_.message());
00166   }
00167 
00168   str_buffer_.clear();
00169   str_buffer_.resize(length);
00170 
00171   for(unsigned int n = 0; n < length; n++)
00172   {
00173     str_buffer_[n] = input_stream_.peek();
00174     stream_buffer_.consume(1);
00175   }
00176   return(str_buffer_);
00177 }
00178 
00179 //-----------------------------------------------------------------------------
00180 char BoostTCPSocketImpl::readCharacter ()
00181 {
00182   if(!stream_buffer_.size())
00183     waitForData();
00184 
00185   char c = input_stream_.peek();
00186   stream_buffer_.consume(1);
00187   return(c);
00188 
00189 }
00190 
00191 //-----------------------------------------------------------------------------
00192 void BoostTCPSocketImpl::waitForData ()
00193 {
00194   error_.clear();
00195   if (!stream_buffer_.size () )
00196     boost::asio::read (*socket_, stream_buffer_, boost::asio::transfer_at_least(1), error_) ;
00197 
00198   if (error_)
00199     throw TiALostConnection ("InputStreamSocket::readBytes error_ read: "
00200                              + string (error_.category().name()) + error_.message());
00201 }
00202 
00203 //-----------------------------------------------------------------------------
00204 void BoostTCPSocketImpl::sendString (string const& str) throw (TiALostConnection)
00205 {
00206     error_.clear();
00207     socket_->send (boost::asio::buffer (str), 0, error_);
00208     if (error_)
00209         throw TiALostConnection ("BoostTCPSocketImpl: sending string failed");
00210 }
00211 
00212 //-----------------------------------------------------------------------------
00213 
00214 size_t BoostTCPSocketImpl::readBytes (char* data, size_t bytes_to_read)
00215 {
00216 
00217   if(stream_buffer_.size () < bytes_to_read )
00218   {
00219     error_.clear();
00220     boost::asio::read (*socket_, stream_buffer_,
00221                        boost::asio::transfer_at_least(bytes_to_read-stream_buffer_.size ()),error_);
00222     if (error_)
00223       throw TiALostConnection ("InputStreamSocket::readBytes error_ read: "
00224                                + string (error_.category().name()) + error_.message());
00225 
00226     input_stream_.read(data, bytes_to_read);
00227     return bytes_to_read;
00228   }
00229   else
00230   {
00231     input_stream_.read( data, bytes_to_read);
00232     return bytes_to_read;
00233   }
00234 }
00235 
00236 //-----------------------------------------------------------------------------
00237 
00238 size_t BoostTCPSocketImpl::getAvailableData (char* data, size_t max_size)
00239 {
00240 
00241   size_t available_data = stream_buffer_.size ();
00242   if ( !available_data )
00243   {
00244     data = 0;
00245     return 0;
00246   }
00247   else
00248   {
00249     if(available_data > max_size)
00250     {
00251       input_stream_.read( data, max_size);
00252       return max_size;
00253     }
00254     else
00255     {
00256       input_stream_.read( data, available_data);
00257       return available_data;
00258     }
00259   }
00260 }
00261 
00262 //-----------------------------------------------------------------------------
00263 
00264 std::string BoostTCPSocketImpl::getRemoteEndPointAsString()
00265 {
00266   return(remote_endpoint_str_);
00267 }
00268 
00269 //-----------------------------------------------------------------------------
00270 
00271 std::string BoostTCPSocketImpl::getLocalEndPointAsString()
00272 {
00273   return(local_endpoint_str_);
00274 }
00275 
00276 //-----------------------------------------------------------------------------
00277 
00278 }
 All Data Structures Files Functions Variables Typedefs Enumerations