Claw  1.7.0
basic_socketbuf.tpp
Go to the documentation of this file.
00001 /*
00002   CLAW - a C++ Library Absolutely Wonderful
00003 
00004   CLAW is a free library without any particular aim but being useful to 
00005   anyone.
00006 
00007   Copyright (C) 2005-2011 Julien Jorge
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Lesser General Public
00011   License as published by the Free Software Foundation; either
00012   version 2.1 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Lesser General Public License for more details.
00018 
00019   You should have received a copy of the GNU Lesser General Public
00020   License along with this library; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023   contact: julien.jorge@gamned.org
00024 */
00030 #include <claw/assert.hpp>
00031 
00032 /*----------------------------------------------------------------------------*/
00033 template<typename CharT, typename Traits>
00034 const size_t claw::net::basic_socketbuf<CharT, Traits>::s_buffer_size = 256;
00035 
00036 /*----------------------------------------------------------------------------*/
00043 template<typename CharT, typename Traits>
00044 claw::net::basic_socketbuf<CharT, Traits>::basic_socketbuf( int read_limit )
00045   : m_read_limit(read_limit), m_input_buffer(NULL), m_input_buffer_size(0),
00046     m_output_buffer(NULL), m_output_buffer_size(0)
00047 {
00048   create_buffers();
00049 } // basic_socketbuf::basic_socketbuf()
00050 
00051 /*----------------------------------------------------------------------------*/
00055 template<typename CharT, typename Traits>
00056 claw::net::basic_socketbuf<CharT, Traits>::~basic_socketbuf()
00057 {
00058   close();
00059   destroy_buffers();
00060 } // basic_socketbuf::basic_socketbuf()
00061 
00062 /*----------------------------------------------------------------------------*/
00069 template<typename CharT, typename Traits>
00070 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
00071 claw::net::basic_socketbuf<CharT, Traits>::open
00072 ( const std::string& address, int port )
00073 {
00074   self_type* result = NULL;
00075 
00076   if (!this->is_open())
00077     if ( basic_socket::open() )
00078       {
00079         if ( connect( address, port ) )
00080           result = this;
00081         else
00082     close();
00083       }
00084 
00085   return result;
00086 } // basic_socketbuf::open()
00087 
00088 /*----------------------------------------------------------------------------*/
00097 template<typename CharT, typename Traits>
00098 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
00099 claw::net::basic_socketbuf<CharT, Traits>::open( socket_traits::descriptor d )
00100 {
00101   self_type* result = NULL;
00102 
00103   if ( socket_traits::is_open(d) )
00104     {
00105       if (this->is_open())
00106         {
00107           if ( close() )
00108             {
00109               result = this;
00110               m_descriptor = d;
00111             }
00112         }
00113       else
00114         {
00115           result = this;
00116           m_descriptor = d;
00117         }
00118     }
00119 
00120   return result;
00121 } // basic_socketbuf::open()
00122 
00123 /*----------------------------------------------------------------------------*/
00128 template<typename CharT, typename Traits>
00129 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
00130 claw::net::basic_socketbuf<CharT, Traits>::close()
00131 {
00132   if ( basic_socket::close() )
00133     return this;
00134   else
00135     return NULL;
00136 } // basic_socketbuf::close()
00137 
00138 /*----------------------------------------------------------------------------*/
00142 template<typename CharT, typename Traits>
00143 bool claw::net::basic_socketbuf<CharT, Traits>::is_open() const
00144 {
00145   return basic_socket::is_open();
00146 } // // basic_socketbuf::is_open()
00147 
00148 /*----------------------------------------------------------------------------*/
00154 template<typename CharT, typename Traits>
00155 void claw::net::basic_socketbuf<CharT, Traits>::set_read_time_limit
00156 ( int read_limit )
00157 {
00158   m_read_limit = read_limit;
00159 } // // basic_socketbuf::set_read_time_limit()
00160 
00161 /*----------------------------------------------------------------------------*/
00166 template<typename CharT, typename Traits>
00167 int claw::net::basic_socketbuf<CharT, Traits>::sync()
00168 {
00169   CLAW_PRECOND( is_open() );
00170   CLAW_PRECOND( buffered() );
00171 
00172   ssize_t write_count = 0;
00173   ssize_t length = (this->pptr() - this->pbase()) * sizeof(char_type);
00174   int_type result = 0;
00175 
00176   if ( length > 0 )
00177     write_count = send(m_descriptor, static_cast<const char*>(this->pbase()),
00178            length, 0 );
00179 
00180   if ( write_count >= 0 )
00181     setp( m_output_buffer, m_output_buffer + m_output_buffer_size );
00182   else
00183     result = -1;
00184 
00185   return result;
00186 } // basic_socketbuf::sync()
00187 
00188 /*----------------------------------------------------------------------------*/
00195 template<typename CharT, typename Traits>
00196 typename claw::net::basic_socketbuf<CharT, Traits>::int_type
00197 claw::net::basic_socketbuf<CharT, Traits>::underflow()
00198 {
00199   CLAW_PRECOND( buffered() );
00200   CLAW_PRECOND( this->gptr() >= this->egptr() );
00201 
00202   ssize_t read_count;
00203   ssize_t length = m_input_buffer_size * sizeof(char_type);
00204   int_type result = traits_type::eof();
00205 
00206   if( !is_open() )
00207     return result;
00208 
00209   if ( socket_traits::select_read(m_descriptor, m_read_limit) )
00210     read_count = recv(m_descriptor, static_cast<char*>(m_input_buffer), length,
00211           0);
00212   else
00213     read_count = -1;
00214 
00215   if ( read_count > 0 )
00216     {
00217       setg( m_input_buffer, m_input_buffer, m_input_buffer + read_count);
00218       result = this->sgetc();
00219     }
00220   else
00221     setg( m_input_buffer, m_input_buffer + m_input_buffer_size,
00222           m_input_buffer + m_input_buffer_size );
00223 
00224   return result;
00225 } // basic_socketbuf::underflow()
00226 
00227 /*----------------------------------------------------------------------------*/
00232 template<typename CharT, typename Traits>
00233 typename claw::net::basic_socketbuf<CharT, Traits>::int_type
00234 claw::net::basic_socketbuf<CharT, Traits>::overflow( int_type c )
00235 {
00236   CLAW_PRECOND( is_open() );
00237   CLAW_PRECOND( buffered() );
00238 
00239   int_type result = traits_type::eof();
00240 
00241   if ( sync() == 0 )
00242     {
00243       result = traits_type::not_eof(c);
00244 
00245       if ( !traits_type::eq_int_type(c, traits_type::eof()) )
00246         sputc(c);
00247     }
00248 
00249   return result;
00250 } // basic_socketbuf::overflow()
00251 
00252 /*----------------------------------------------------------------------------*/
00260 template<typename CharT, typename Traits>
00261 bool claw::net::basic_socketbuf<CharT, Traits>::connect
00262 ( const std::string& addr, int port )
00263 {
00264   CLAW_PRECOND( socket_traits::valid_descriptor(m_descriptor) );
00265 
00266   return socket_traits::connect(m_descriptor, addr, port);
00267 } // basic_socketbuf::connect()
00268 
00269 /*----------------------------------------------------------------------------*/
00274 template<typename CharT, typename Traits>
00275 void claw::net::basic_socketbuf<CharT, Traits>::create_buffers()
00276 {
00277   CLAW_PRECOND( this->pbase() == NULL );
00278   CLAW_PRECOND( this->eback() == NULL );
00279 
00280   m_input_buffer_size = m_output_buffer_size = s_buffer_size;
00281 
00282   m_input_buffer  = new char_type[m_input_buffer_size];
00283   m_output_buffer = new char_type[m_output_buffer_size];
00284 
00285   this->setg( m_input_buffer, m_input_buffer + m_input_buffer_size, 
00286               m_input_buffer + m_input_buffer_size );
00287   this->setp( m_output_buffer, m_output_buffer + m_output_buffer_size );
00288 } // basic_socketbuf::create_buffers()
00289 
00290 /*----------------------------------------------------------------------------*/
00295 template<typename CharT, typename Traits>
00296 void claw::net::basic_socketbuf<CharT, Traits>::destroy_buffers()
00297 {
00298   if ( m_input_buffer )
00299     {
00300       delete[] m_input_buffer;
00301       m_input_buffer = NULL;
00302     }
00303 
00304   if ( m_output_buffer )
00305     {
00306       delete[] m_output_buffer;
00307       m_output_buffer = NULL;
00308     }
00309 
00310   this->setg( NULL, NULL, NULL );
00311   this->setp( NULL, NULL );
00312 } // basic_socketbuf::destroy_buffers()
00313 
00314 /*----------------------------------------------------------------------------*/
00319 template<typename CharT, typename Traits>
00320 bool claw::net::basic_socketbuf<CharT, Traits>::buffered() const
00321 {
00322   return this->pbase() && this->pptr() && this->epptr() 
00323     && this->eback() && this->gptr() && this->egptr();
00324 } // basic_socketbuf::buffered()