00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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 }
00050
00051
00055 template<typename CharT, typename Traits>
00056 claw::net::basic_socketbuf<CharT, Traits>::~basic_socketbuf()
00057 {
00058 close();
00059 destroy_buffers();
00060 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }