2 CLAW - a C++ Library Absolutely Wonderful
4 CLAW is a free library without any particular aim but being useful to
7 Copyright (C) 2005-2011 Julien Jorge
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 contact: julien.jorge@gamned.org
26 * \file basic_socketbuf.tpp
27 * \brief Implantation of the claw::net::basic_socketbuf class.
28 * \author Julien Jorge
30 #include <claw/assert.hpp>
32 /*----------------------------------------------------------------------------*/
33 template<typename CharT, typename Traits>
34 const size_t claw::net::basic_socketbuf<CharT, Traits>::s_buffer_size = 256;
36 /*----------------------------------------------------------------------------*/
39 * \param read_limit Number of second to wait before considering nothing will
40 * come in the socket. Negative values mean infinity.
41 * \post is_open() == false;
43 template<typename CharT, typename Traits>
44 claw::net::basic_socketbuf<CharT, Traits>::basic_socketbuf( int read_limit )
45 : m_read_limit(read_limit), m_input_buffer(NULL), m_input_buffer_size(0),
46 m_output_buffer(NULL), m_output_buffer_size(0)
49 } // basic_socketbuf::basic_socketbuf()
51 /*----------------------------------------------------------------------------*/
55 template<typename CharT, typename Traits>
56 claw::net::basic_socketbuf<CharT, Traits>::~basic_socketbuf()
60 } // basic_socketbuf::basic_socketbuf()
62 /*----------------------------------------------------------------------------*/
64 * \brief Initialise the socket.
65 * \param address Address to open.
66 * \param port The port to connect to.
67 * \return this if everything works fine, NULL otherwise.
69 template<typename CharT, typename Traits>
70 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
71 claw::net::basic_socketbuf<CharT, Traits>::open
72 ( const std::string& address, int port )
74 self_type* result = NULL;
77 if ( basic_socket::open() )
79 if ( connect( address, port ) )
86 } // basic_socketbuf::open()
88 /*----------------------------------------------------------------------------*/
90 * \brief Link the socket to a file descriptor.
91 * \param d The file descriptor.
92 * \return this if everything works fine, NULL otherwise.
93 * \remark This method should be only called by claw::net::basic_*socket_stream.
94 * \remark If this socket was open and \a fd is valid, the socket will be closed
95 * before that \a d will be assigned.
97 template<typename CharT, typename Traits>
98 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
99 claw::net::basic_socketbuf<CharT, Traits>::open( socket_traits::descriptor d )
101 self_type* result = NULL;
103 if ( socket_traits::is_open(d) )
121 } // basic_socketbuf::open()
123 /*----------------------------------------------------------------------------*/
125 * \brief Close the socket.
126 * \post is_open() == false;
128 template<typename CharT, typename Traits>
129 typename claw::net::basic_socketbuf<CharT, Traits>::self_type*
130 claw::net::basic_socketbuf<CharT, Traits>::close()
132 if ( basic_socket::close() )
136 } // basic_socketbuf::close()
138 /*----------------------------------------------------------------------------*/
140 * \brief Tell if the socket is open.
142 template<typename CharT, typename Traits>
143 bool claw::net::basic_socketbuf<CharT, Traits>::is_open() const
145 return basic_socket::is_open();
146 } // // basic_socketbuf::is_open()
148 /*----------------------------------------------------------------------------*/
150 * \brief Set the number of second to wait before considering nothing will come
152 * \param read_limit The number of seconds. Negative values mean infinity.
154 template<typename CharT, typename Traits>
155 void claw::net::basic_socketbuf<CharT, Traits>::set_read_time_limit
158 m_read_limit = read_limit;
159 } // // basic_socketbuf::set_read_time_limit()
161 /*----------------------------------------------------------------------------*/
163 * \brief Write the buffered data in the socket.
166 template<typename CharT, typename Traits>
167 int claw::net::basic_socketbuf<CharT, Traits>::sync()
169 CLAW_PRECOND( is_open() );
170 CLAW_PRECOND( buffered() );
172 ssize_t write_count = 0;
173 ssize_t length = (this->pptr() - this->pbase()) * sizeof(char_type);
177 write_count = send(m_descriptor, static_cast<const char*>(this->pbase()),
180 if ( write_count >= 0 )
181 this->setp( m_output_buffer, m_output_buffer + m_output_buffer_size );
186 } // basic_socketbuf::sync()
188 /*----------------------------------------------------------------------------*/
190 * \brief Fill the input buffer.
191 * \pre is_open() && gptr() != NULL
192 * \return The next symbol to be read ( *gptr() ) if there is data coming from
193 * the socket, traits::eof() otherwise.
195 template<typename CharT, typename Traits>
196 typename claw::net::basic_socketbuf<CharT, Traits>::int_type
197 claw::net::basic_socketbuf<CharT, Traits>::underflow()
199 CLAW_PRECOND( buffered() );
200 CLAW_PRECOND( this->gptr() >= this->egptr() );
203 ssize_t length = m_input_buffer_size * sizeof(char_type);
204 int_type result = traits_type::eof();
209 if ( socket_traits::select_read(m_descriptor, m_read_limit) )
210 read_count = recv(m_descriptor, static_cast<char*>(m_input_buffer), length,
215 if ( read_count > 0 )
217 this->setg( m_input_buffer, m_input_buffer, m_input_buffer + read_count);
218 result = this->sgetc();
221 this->setg( m_input_buffer, m_input_buffer + m_input_buffer_size,
222 m_input_buffer + m_input_buffer_size );
225 } // basic_socketbuf::underflow()
227 /*----------------------------------------------------------------------------*/
229 * \brief Synchronize the output buffer (ie. write in the socket).
232 template<typename CharT, typename Traits>
233 typename claw::net::basic_socketbuf<CharT, Traits>::int_type
234 claw::net::basic_socketbuf<CharT, Traits>::overflow( int_type c )
236 CLAW_PRECOND( is_open() );
237 CLAW_PRECOND( buffered() );
239 int_type result = traits_type::eof();
243 result = traits_type::not_eof(c);
245 if ( !traits_type::eq_int_type(c, traits_type::eof()) )
250 } // basic_socketbuf::overflow()
252 /*----------------------------------------------------------------------------*/
254 * \brief Connect the socket to a port.
255 * \param addr The address to connect to.
256 * \param port The port to connect to.
257 * \return true if the connection is established.
258 * \pre m_fd is a valid socket descriptor.
260 template<typename CharT, typename Traits>
261 bool claw::net::basic_socketbuf<CharT, Traits>::connect
262 ( const std::string& addr, int port )
264 CLAW_PRECOND( socket_traits::valid_descriptor(m_descriptor) );
266 return socket_traits::connect(m_descriptor, addr, port);
267 } // basic_socketbuf::connect()
269 /*----------------------------------------------------------------------------*/
271 * \brief Create the buffers.
272 * \pre pbase() == eback() == NULL
274 template<typename CharT, typename Traits>
275 void claw::net::basic_socketbuf<CharT, Traits>::create_buffers()
277 CLAW_PRECOND( this->pbase() == NULL );
278 CLAW_PRECOND( this->eback() == NULL );
280 m_input_buffer_size = m_output_buffer_size = s_buffer_size;
282 m_input_buffer = new char_type[m_input_buffer_size];
283 m_output_buffer = new char_type[m_output_buffer_size];
285 this->setg( m_input_buffer, m_input_buffer + m_input_buffer_size,
286 m_input_buffer + m_input_buffer_size );
287 this->setp( m_output_buffer, m_output_buffer + m_output_buffer_size );
288 } // basic_socketbuf::create_buffers()
290 /*----------------------------------------------------------------------------*/
292 * \brief Destroy the buffers.
293 * \post pbase() == eback() == NULL
295 template<typename CharT, typename Traits>
296 void claw::net::basic_socketbuf<CharT, Traits>::destroy_buffers()
298 if ( m_input_buffer )
300 delete[] m_input_buffer;
301 m_input_buffer = NULL;
304 if ( m_output_buffer )
306 delete[] m_output_buffer;
307 m_output_buffer = NULL;
310 this->setg( NULL, NULL, NULL );
311 this->setp( NULL, NULL );
312 } // basic_socketbuf::destroy_buffers()
314 /*----------------------------------------------------------------------------*/
316 * \brief Tell if we use buffered input and output.
317 * \remark Should always be true !
319 template<typename CharT, typename Traits>
320 bool claw::net::basic_socketbuf<CharT, Traits>::buffered() const
322 return this->pbase() && this->pptr() && this->epptr()
323 && this->eback() && this->gptr() && this->egptr();
324 } // basic_socketbuf::buffered()