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
00041 template<typename CharT, typename Traits>
00042 claw::net::basic_socketbuf<CharT, Traits>::basic_socketbuf()
00043 : m_input_buffer(NULL), m_input_buffer_size(0),
00044 m_output_buffer(NULL), m_output_buffer_size(0)
00045 {
00046 create_buffers();
00047 }
00048
00049
00053 template<typename CharT, typename Traits>
00054 claw::net::basic_socketbuf<CharT, Traits>::~basic_socketbuf()
00055 {
00056 close();
00057 destroy_buffers();
00058 }
00059
00060
00067 template<typename CharT, typename Traits>
00068 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
00069 claw::net::basic_socketbuf<CharT, Traits>::open
00070 ( const std::string& address, int port )
00071 {
00072 self_type* result = NULL;
00073
00074 if (!this->is_open())
00075 if ( basic_socket::open() )
00076 {
00077 if ( connect( address, port ) )
00078 result = this;
00079 else
00080 close();
00081 }
00082
00083 return result;
00084 }
00085
00086
00095 template<typename CharT, typename Traits>
00096 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
00097 claw::net::basic_socketbuf<CharT, Traits>::open( socket_traits::descriptor d )
00098 {
00099 self_type* result = NULL;
00100
00101 if ( socket_traits::is_open(d) )
00102 {
00103 if (this->is_open())
00104 {
00105 if ( close() )
00106 {
00107 result = this;
00108 m_descriptor = d;
00109 }
00110 }
00111 else
00112 {
00113 result = this;
00114 m_descriptor = d;
00115 }
00116 }
00117
00118 return result;
00119 }
00120
00121
00126 template<typename CharT, typename Traits>
00127 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
00128 claw::net::basic_socketbuf<CharT, Traits>::close()
00129 {
00130 if ( basic_socket::close() )
00131 return this;
00132 else
00133 return NULL;
00134 }
00135
00136
00140 template<typename CharT, typename Traits>
00141 bool claw::net::basic_socketbuf<CharT, Traits>::is_open() const
00142 {
00143 return basic_socket::is_open();
00144 }
00145
00146
00151 template<typename CharT, typename Traits>
00152 int claw::net::basic_socketbuf<CharT, Traits>::sync()
00153 {
00154 CLAW_PRECOND( is_open() );
00155 CLAW_PRECOND( buffered() );
00156
00157 ssize_t write_count = 0;
00158 ssize_t length = (this->pptr() - this->pbase()) * sizeof(char_type);
00159 int_type result = 0;
00160
00161 if ( length > 0 )
00162 write_count = send(m_descriptor, static_cast<const char*>(this->pbase()),
00163 length, 0 );
00164
00165 if ( write_count >= 0 )
00166 setp( m_output_buffer, m_output_buffer + m_output_buffer_size );
00167 else
00168 result = -1;
00169
00170 return result;
00171 }
00172
00173
00180 template<typename CharT, typename Traits>
00181 typename claw::net::basic_socketbuf<CharT, Traits>::int_type
00182 claw::net::basic_socketbuf<CharT, Traits>::underflow()
00183 {
00184 CLAW_PRECOND( is_open() );
00185 CLAW_PRECOND( buffered() );
00186 CLAW_PRECOND( this->gptr() >= this->egptr() );
00187
00188 ssize_t read_count;
00189 ssize_t length = m_input_buffer_size * sizeof(char_type);
00190 int_type result = traits_type::eof();
00191
00192 if ( socket_traits::select_read(m_descriptor) )
00193 read_count = recv(m_descriptor, static_cast<char*>(m_input_buffer), length,
00194 0);
00195 else
00196 read_count = -1;
00197
00198 if ( read_count > 0 )
00199 {
00200 setg( m_input_buffer, m_input_buffer, m_input_buffer + read_count);
00201 result = this->sgetc();
00202 }
00203 else
00204 setg( m_input_buffer, m_input_buffer + m_input_buffer_size,
00205 m_input_buffer + m_input_buffer_size );
00206
00207 return result;
00208 }
00209
00210
00215 template<typename CharT, typename Traits>
00216 typename claw::net::basic_socketbuf<CharT, Traits>::int_type
00217 claw::net::basic_socketbuf<CharT, Traits>::overflow( int_type c )
00218 {
00219 CLAW_PRECOND( is_open() );
00220 CLAW_PRECOND( buffered() );
00221
00222 int_type result = traits_type::eof();
00223
00224 if ( sync() == 0 )
00225 {
00226 result = traits_type::not_eof(c);
00227
00228 if ( !traits_type::eq_int_type(c, traits_type::eof()) )
00229 sputc(c);
00230 }
00231
00232 return result;
00233 }
00234
00235
00243 template<typename CharT, typename Traits>
00244 bool claw::net::basic_socketbuf<CharT, Traits>::connect
00245 ( const std::string& addr, int port )
00246 {
00247 CLAW_PRECOND( socket_traits::valid_descriptor(m_descriptor) );
00248
00249 return socket_traits::connect(m_descriptor, addr, port);
00250 }
00251
00252
00257 template<typename CharT, typename Traits>
00258 void claw::net::basic_socketbuf<CharT, Traits>::create_buffers()
00259 {
00260 CLAW_PRECOND( this->pbase() == NULL );
00261 CLAW_PRECOND( this->eback() == NULL );
00262
00263 m_input_buffer_size = m_output_buffer_size = s_buffer_size;
00264
00265 m_input_buffer = new char_type[m_input_buffer_size];
00266 m_output_buffer = new char_type[m_output_buffer_size];
00267
00268 this->setg( m_input_buffer, m_input_buffer + m_input_buffer_size,
00269 m_input_buffer + m_input_buffer_size );
00270 this->setp( m_output_buffer, m_output_buffer + m_output_buffer_size );
00271 }
00272
00273
00278 template<typename CharT, typename Traits>
00279 void claw::net::basic_socketbuf<CharT, Traits>::destroy_buffers()
00280 {
00281 if ( m_input_buffer )
00282 {
00283 delete[] m_input_buffer;
00284 m_input_buffer = NULL;
00285 }
00286
00287 if ( m_output_buffer )
00288 {
00289 delete[] m_output_buffer;
00290 m_output_buffer = NULL;
00291 }
00292
00293 this->setg( NULL, NULL, NULL );
00294 this->setp( NULL, NULL );
00295 }
00296
00297
00302 template<typename CharT, typename Traits>
00303 bool claw::net::basic_socketbuf<CharT, Traits>::buffered() const
00304 {
00305 return this->pbase() && this->pptr() && this->epptr()
00306 && this->eback() && this->gptr() && this->egptr();
00307 }