Claw
1.7.0
|
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 this->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 this->setg( m_input_buffer, m_input_buffer, m_input_buffer + read_count); 00218 result = this->sgetc(); 00219 } 00220 else 00221 this->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 this->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()