[complement-svn] SF.net SVN: complement: [1892] branches/complement-sockios/explore
Status: Pre-Alpha
Brought to you by:
complement
From: <com...@us...> - 2008-06-09 18:32:08
|
Revision: 1892 http://complement.svn.sourceforge.net/complement/?rev=1892&view=rev Author: complement Date: 2008-06-09 11:31:16 -0700 (Mon, 09 Jun 2008) Log Message: ----------- sockstream2 family renamed to sockstream; basic_sockbuf become proxy, real implementation is basic_sockbuf_aux and should be controlled from sockmgr; just compile, not really work Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sp.cc branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/ut/Makefile.inc branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc branches/complement-sockios/explore/lib/sockios/ut/sockios_test.cc branches/complement-sockios/explore/lib/sockios/ut/sockios_test.h branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc Added Paths: ----------- branches/complement-sockios/explore/include/sockios/sockstream branches/complement-sockios/explore/include/sockios/sockstream.cc Removed Paths: ------------- branches/complement-sockios/explore/include/sockios/sockstream branches/complement-sockios/explore/include/sockios/sockstream.cc branches/complement-sockios/explore/include/sockios/sockstream2 branches/complement-sockios/explore/include/sockios/sockstream2.cc Deleted: branches/complement-sockios/explore/include/sockios/sockstream =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream 2008-06-07 17:06:27 UTC (rev 1891) +++ branches/complement-sockios/explore/include/sockios/sockstream 2008-06-09 18:31:16 UTC (rev 1892) @@ -1,623 +0,0 @@ -// -*- C++ -*- Time-stamp: <07/09/06 23:42:19 ptr> - -/* - * Copyright (c) 1997-1999, 2002, 2003, 2005-2007 - * Petr Ovtchenkov - * - * Portion Copyright (c) 1999-2001 - * Parallel Graphics Ltd. - * - * Licensed under the Academic Free License version 3.0 - * - */ - -#ifndef __SOCKSTREAM__ -#define __SOCKSTREAM__ - -#ifndef __config_feature_h -#include <config/feature.h> -#endif - -#if !defined(__sun) && !defined(_WIN32) // i.e. __linux and __hpux -#include <sys/poll.h> // pollfd -#endif - -#ifndef __XMT_H -#include <mt/xmt.h> -#endif - -#include <netdb.h> -#include <netinet/in.h> - -#include <iosfwd> -#include <ios> -#include <streambuf> -#include <iostream> -#include <string> -#include <stdexcept> - -#ifdef WIN32 -# include <winsock2.h> -#else // WIN32 -# include <unistd.h> -# include <sys/types.h> -# if defined(__hpux) && !defined(_INCLUDE_XOPEN_SOURCE_EXTENDED) -# define _INCLUDE_XOPEN_SOURCE_EXTENDED -# endif -# include <sys/socket.h> -# if !defined(__UCLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -# include <stropts.h> -# endif -# ifdef __sun -# include <sys/conf.h> -# endif -# include <netinet/in.h> -# include <arpa/inet.h> -# include <netdb.h> -# ifdef __hpux -// # ifndef socklen_t // HP-UX 10.01 -// typedef int socklen_t; -// # endif -# endif -# include <cerrno> -#endif // !WIN32 - -#include <sockios/netinfo.h> - -#ifdef STLPORT -_STLP_BEGIN_NAMESPACE -#else -namespace std { -#endif - -class sock_base -{ - public: - typedef unsigned long shutdownflg; -#ifdef __unix - typedef int socket_type; -#endif -#ifdef WIN32 - typedef SOCKET socket_type; -#endif - - enum stype { - sock_stream = SOCK_STREAM, // stream socket - sock_dgram = SOCK_DGRAM, // datagram socket - sock_raw = SOCK_RAW, // raw-protocol interface - sock_rdm = SOCK_RDM, // reliably-delivered message - sock_seqpacket = SOCK_SEQPACKET // sequenced packet stream - }; - - enum protocol { - local, // local to host (pipes, portals) - inet // internetwork: UDP, TCP, etc. - }; - - // Option flags per-socket. - enum so_t { - so_debug = SO_DEBUG, // turn on debugging info recording -#ifndef __linux - so_acceptconn = SO_ACCEPTCONN, // socket has had listen() -#endif - so_reuseaddr = SO_REUSEADDR, // allow local address reuse - so_keepalive = SO_KEEPALIVE, // keep connections alive - so_dontroute = SO_DONTROUTE, // just use interface addresses - so_broadcast = SO_BROADCAST, // permit sending of broadcast msgs -#ifndef __linux - so_useloopback = SO_USELOOPBACK, // bypass hardware when possible -#endif - so_linger = SO_LINGER, // linger on close if data present - so_oobinline = SO_OOBINLINE, // leave received OOB data in line - // Additional options, not kept in so_options. - so_sndbuf = SO_SNDBUF, // send buffer size - so_rcvbuf = SO_RCVBUF, // receive buffer size - so_sndlowat = SO_SNDLOWAT, // send low-water mark - so_rcvlowat = SO_RCVLOWAT, // receive low-water mark - so_sndtimeo = SO_SNDTIMEO, // send timeout - so_rcvtimeo = SO_RCVTIMEO, // receive timeout - so_error = SO_ERROR, // get error status and clear - so_type = SO_TYPE // get socket type -#ifdef __sun // indeed HP-UX 11.00 also has it, but 10.01 not - , - so_prototype = SO_PROTOTYPE // get/set protocol type -#endif - }; - - // Level number for (get/set)sockopt() to apply to socket itself. -// enum _level { -// sol_socket = SOL_SOCKET -// }; - - enum shutdownflags { - stop_in = 0x1, - stop_out = 0x2 - }; - -#ifdef WIN32 - class Init - { - // sometimes I need Init outside sock_base... - // private: - public: - __FIT_DECLSPEC Init(); - __FIT_DECLSPEC ~Init(); - - friend class sock_base; - }; - - protected: - __FIT_DECLSPEC sock_base(); - __FIT_DECLSPEC ~sock_base(); -#endif -}; - -template<class charT, class traits, class _Alloc> -class basic_sockbuf : - public basic_streambuf<charT, traits> -{ - public: - typedef basic_ios<charT, traits> ios_type; - typedef basic_sockbuf<charT, traits, _Alloc> sockbuf_type; - typedef typename traits::state_type state_t; -#ifdef WIN32 - typedef u_short family_type; -#else -# ifdef sa_family_t - typedef sa_family_t family_type; -# else // HP-UX 10.01 - typedef unsigned short family_type; -# endif -#endif - - public: - /* Inherited from basic_streambuf : */ - typedef charT char_type; - typedef typename traits::int_type int_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - typedef traits traits_type; - /* */ - - basic_sockbuf() : - _fd( -1 ), -#if !defined(STLPORT) && defined(__GNUC__) -#if ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4))) // hmm, 3.3.6 - _mode( ios_base::openmode(__ios_flags::_S_in | __ios_flags::_S_out) ), -#else // 4.1.1 - _mode( _S_in | _S_out ), -#endif // __GNUC__ -#else // STLPORT - _mode( 0 ), -#endif // STLPORT - _bbuf(0), _ebuf(0), _allocated( true ) - // , _doclose( true ) - { -#ifdef __FIT_POLL - _timeout = -1; -#endif -#ifdef __FIT_SELECT - _timeout_ref = 0; -#endif - } - basic_sockbuf( const char *hostname, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol prot = sock_base::inet, - const timespec *timeout = 0 ) : - _fd( -1 ), -#if !defined(STLPORT) && defined(__GNUC__) -#if ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4))) - _mode( ios_base::openmode(__ios_flags::_S_in | __ios_flags::_S_out) ), -#else // 4.1.1 - _mode( _S_in | _S_out ), -#endif // __GNUC__ -#else // STLPORT - _mode( 0 ), -#endif // STLPORT - _bbuf(0), _ebuf(0), _allocated( true ) - // , _doclose( true ) - { - open( hostname, port, type, prot, timeout ); - } - basic_sockbuf( const in_addr& addr, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol prot = sock_base::inet, - const timespec *timeout = 0 ) : - _fd( -1 ), -#if !defined(STLPORT) && defined(__GNUC__) -#if ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4))) - _mode( ios_base::openmode(__ios_flags::_S_in | __ios_flags::_S_out) ), -#else // 4.1.1 - _mode( _S_in | _S_out ), -#endif // __GNUC__ -#else // STLPORT - _mode( 0 ), -#endif // STLPORT - _bbuf(0), _ebuf(0), _allocated( true ) - // , _doclose( true ) - { - open( addr, type, prot, timeout ); - } - virtual ~basic_sockbuf() - { - close(); - _M_deallocate_block(); - } - - bool is_open() const - { return _fd != -1; } - - sockbuf_type *open( const char *hostname, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol prot = sock_base::inet, - const timespec *timeout = 0 ); - - sockbuf_type *open( const in_addr& addr, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol prot = sock_base::inet, - const timespec *timeout = 0 ); - - sockbuf_type *open( sock_base::socket_type s, - sock_base::stype t = sock_base::sock_stream, - const timespec *timeout = 0 ); - - sockbuf_type *open( sock_base::socket_type s, const sockaddr& addr, - sock_base::stype t = sock_base::sock_stream, - const timespec *timeout = 0 ); - - sockbuf_type *attach( sock_base::socket_type s, - sock_base::stype t = sock_base::sock_stream, - const timespec *timeout = 0 ); - - sockbuf_type *attach( sock_base::socket_type s, const sockaddr& addr, - sock_base::stype t = sock_base::sock_stream, - const timespec *timeout = 0 ); - - sockbuf_type *close(); - void shutdown( sock_base::shutdownflg dir ); - - sock_base::socket_type fd() const { return _fd;} - - family_type family() const - { return /* is_open() ? */ _address.any.sa_family /* : 0 */; } - - int port() const - { return /* is_open() && */ _address.any.sa_family == AF_INET ? - _address.inet.sin_port : 0; } - - unsigned long inet_addr() const - { return /* is_open() && */ _address.any.sa_family == AF_INET ? - _address.inet.sin_addr.s_addr : 0; } - - const sockaddr_in& inet_sockaddr() const throw( std::domain_error ) - { - if ( _address.any.sa_family != AF_INET ) { - throw domain_error( "socket not belongs to inet type" ); - } - return /* is_open() && */ _address.inet; - } - - sock_base::stype stype() const - { return _type; } - - // const string& hostname() const - // { return _hostname; } - - protected: - // bool findhost( const char *hostname ); - - virtual streamsize showmanyc() - { return this->egptr() - this->gptr(); } - - virtual int_type underflow(); - virtual int_type overflow( int_type c = traits::eof() ); - virtual int_type pbackfail( int_type c = traits::eof() ) - { - if ( !is_open() ) - return traits::eof(); - - if ( this->gptr() <= this->eback() ) { - return traits::eof(); - } - - this->gbump(-1); - if ( !traits::eq_int_type(c,traits::eof()) ) { - *this->gptr() = traits::to_char_type(c); - return c; - } - - return traits::not_eof(c); - } - - // Buffer managment and positioning: - virtual basic_streambuf<charT, traits> *setbuf(char_type *s, streamsize n ) - { - if ( s != 0 && n != 0 ) { - _M_deallocate_block(); - _allocated = false; - _bbuf = s; - _ebuf = s + n; - } - return this; - } - - virtual int sync(); - virtual streamsize xsputn(const char_type *s, streamsize n); - - public: - xmt::mutex _M_lock_w; // lock for writing - - private: // Helper functions - charT* _bbuf; - charT* _ebuf; - bool _allocated; // true, if _bbuf should be deallocated -#ifdef __FIT_POLL - pollfd pfd; - int _timeout; // milliseconds -#endif -#ifdef __FIT_SELECT - fd_set pfd; - struct timeval _timeout; - struct timeval *_timeout_ref; -#endif - - // Precondition: 0 < __n <= max_size(). - charT* _M_allocate( size_t __n ) { return _M_data_allocator.allocate(__n); } - void _M_deallocate( charT* __p, size_t __n ) - { if (__p) _M_data_allocator.deallocate(__p, __n); } - - void _M_allocate_block(size_t __n) - { - if ( _allocated ) { - if ( __n <= max_size() ) { - _bbuf = _M_allocate(__n); - _ebuf = _bbuf + __n; - // _STLP_ASSERT( __n > 0 ? _bbuf != 0 : _bbuf == 0 ); - } else - this->_M_throw_length_error(); - } - } - - void _M_deallocate_block() - { if ( _allocated ) _M_deallocate(_bbuf, _ebuf - _bbuf); } - - size_t max_size() const { return (size_t(-1) / sizeof(charT)) - 1; } - -#ifdef STLPORT - void _M_throw_length_error() const - { _STLP_THROW(length_error("basic_sockbuf")); } -#else - void _M_throw_length_error() const - { throw length_error("basic_sockbuf"); } -#endif - -#ifdef STLPORT - typedef typename _Alloc_traits<charT, _Alloc>::allocator_type allocator_type; -#else - typedef _Alloc allocator_type; -#endif - /* typedef __allocator<charT, _Alloc> _Alloc_type; */ - - /* _Alloc_type */ allocator_type _M_data_allocator; - - private: - typedef basic_sockbuf<charT,traits,_Alloc> _Self_type; - int (basic_sockbuf<charT,traits,_Alloc>::*_xwrite)( const void *, size_t ); - int (basic_sockbuf<charT,traits,_Alloc>::*_xread)( void *, size_t ); - int write( const void *buf, size_t n ) -#ifndef WIN32 - { return ::write( _fd, buf, n ); } -#else - { return ::send( _fd, (const char *)buf, n, 0 ); } -#endif - int send( const void *buf, size_t n ) -#ifdef WIN32 - { return ::send( _fd, (const char *)buf, n, 0 ); } -#else - { return ::send( _fd, buf, n, 0 ); } -#endif - int sendto( const void *buf, size_t n ) -#ifdef WIN32 - { return ::sendto( _fd, (const char *)buf, n, 0, &_address.any, sizeof( sockaddr_in ) ); } -#else - { return ::sendto( _fd, buf, n, 0, &_address.any, sizeof( sockaddr_in ) ); } -#endif - - int read( void *buf, size_t n ) -#ifdef WIN32 - { return ::recv( _fd, (char *)buf, n, 0 ); } -#else - { return ::read( _fd, buf, n ); } -#endif - int recv( void *buf, size_t n ) -#ifdef WIN32 - { return ::recv( _fd, (char *)buf, n, 0 ); } -#else - { return ::recv( _fd, buf, n, 0 ); } -#endif - int recvfrom( void *buf, size_t n ); - void __hostname(); - - sock_base::socket_type _fd; - union sockaddr_t { - sockaddr_in inet; - sockaddr any; - } _address; - - ios_base::openmode _mode; - int _errno; - sock_base::stype _type; - // bool _doclose; -}; - -template <class charT, class traits, class _Alloc> -class basic_sockstream : - public sock_base, - public basic_iostream<charT,traits> -{ - public: - /* Inherited from basic_iostream - typedef charT char_type; - typedef typename traits::int_type int_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - */ - basic_sockstream() : - sock_base(), - basic_iostream<charT,traits>( 0 ) - { basic_ios<charT,traits>::init(&_sb); } - basic_sockstream( const char *hostname, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol pro = sock_base::inet, - const timespec *timeout = 0 ) : - sock_base(), - basic_iostream<charT,traits>( 0 ) - { - basic_ios<charT,traits>::init(&_sb); - basic_iostream<charT,traits>::clear(); - if ( _sb.open( hostname, port, type, pro, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - basic_sockstream( const in_addr& addr, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol pro = sock_base::inet, - const timespec *timeout = 0 ) : - sock_base(), - basic_iostream<charT,traits>( 0 ) - { - basic_ios<charT,traits>::init(&_sb); - basic_iostream<charT,traits>::clear(); - if ( _sb.open( addr, port, type, pro, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - basic_sockstream( sock_base::socket_type s, const sockaddr& addr, - sock_base::stype type = sock_base::sock_stream, - const timespec *timeout = 0 ) : - sock_base(), - basic_iostream<charT,traits>( 0 ) - { - basic_ios<charT,traits>::init(&_sb); - basic_iostream<charT,traits>::clear(); - if ( _sb.open( s, addr, type, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - basic_sockstream( sock_base::socket_type s, - sock_base::stype type = sock_base::sock_stream, - const timespec *timeout = 0 ) : - sock_base(), - basic_iostream<charT,traits>( 0 ) - { - basic_ios<charT,traits>::init(&_sb); - basic_iostream<charT,traits>::clear(); - if ( _sb.open( s, type, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - basic_sockbuf<charT,traits,_Alloc>* rdbuf() const - { return const_cast<basic_sockbuf<charT,traits,_Alloc>*>(&_sb); } - bool is_open() const - { return _sb.is_open(); } - void open( const char *hostname, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol pro = sock_base::inet, - const timespec *timeout = 0 ) - { - basic_iostream<charT,traits>::clear(); - if ( _sb.open( hostname, port, type, pro, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - void open( const in_addr& addr, int port, - sock_base::stype type = sock_base::sock_stream, - sock_base::protocol pro = sock_base::inet, - const timespec *timeout = 0 ) - { - basic_iostream<charT,traits>::clear(); - if ( _sb.open( addr, port, type, pro, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - // only for sock_stream : inet now! - void open( sock_base::socket_type s, const sockaddr& addr, - sock_base::stype type = sock_base::sock_stream, - const timespec *timeout = 0 ) - { - basic_iostream<charT,traits>::clear(); - if ( _sb.open( s, addr, type, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - void open( sock_base::socket_type s, - sock_base::stype type = sock_base::sock_stream, - const timespec *timeout = 0 ) - { - basic_iostream<charT,traits>::clear(); - if ( _sb.open( s, type, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - void attach( sock_base::socket_type s, const sockaddr& addr, - sock_base::stype type = sock_base::sock_stream, - const timespec *timeout = 0 ) - { - basic_iostream<charT,traits>::clear(); - if ( _sb.attach( s, addr, type, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - void attach( sock_base::socket_type s, - sock_base::stype type = sock_base::sock_stream, - const timespec *timeout = 0 ) - { - basic_iostream<charT,traits>::clear(); - if ( _sb.attach( s, type, timeout ) == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); - } - } - - void close() - { - if ( _sb.is_open() ) { - if ( _sb.close() == 0 ) { - basic_ios<charT,traits>::setstate( ios_base::failbit ); - } else { - basic_iostream<charT,traits>::clear(); - } - } - } - - void setoptions( sock_base::so_t optname, bool on_off = true, - int __v = 0 ); - - private: - basic_sockbuf<charT,traits,_Alloc> _sb; -}; - -typedef basic_sockbuf<char,char_traits<char>,allocator<char> > sockbuf; -typedef basic_sockbuf<wchar_t,char_traits<wchar_t>,allocator<wchar_t> > wsockbuf; -typedef basic_sockstream<char,char_traits<char>,allocator<char> > sockstream; -typedef basic_sockstream<wchar_t,char_traits<wchar_t>,allocator<wchar_t> > wsockstream; - -#ifdef STLPORT -_STLP_END_NAMESPACE -#else -} // namespace std -#endif - -#ifndef __STL_LINK_TIME_INSTANTIATION -#include <sockios/sockstream.cc> -#endif - -#endif // __SOCKSTREAM__ Copied: branches/complement-sockios/explore/include/sockios/sockstream (from rev 1886, branches/complement-sockios/explore/include/sockios/sockstream2) =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream (rev 0) +++ branches/complement-sockios/explore/include/sockios/sockstream 2008-06-09 18:31:16 UTC (rev 1892) @@ -0,0 +1,661 @@ +// -*- C++ -*- Time-stamp: <08/06/09 22:22:05 yeti> + +/* + * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#ifndef __SOCKIOS_SOCKSTREAM +#define __SOCKIOS_SOCKSTREAM + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#if !defined(__sun) && !defined(_WIN32) // i.e. __linux and __hpux +#include <sys/poll.h> // pollfd +#endif + +#include <mt/mutex> +#include <mt/condition_variable> +#include <mt/date_time> +#include <mt/thread> + +#include <netdb.h> +#include <netinet/in.h> + +#include <iosfwd> +#include <ios> +#include <streambuf> +#include <iostream> +#include <string> +#include <stdexcept> + +#ifdef WIN32 +# include <winsock2.h> +#else // WIN32 +# include <unistd.h> +# include <sys/types.h> +# if defined(__hpux) && !defined(_INCLUDE_XOPEN_SOURCE_EXTENDED) +# define _INCLUDE_XOPEN_SOURCE_EXTENDED +# endif +# include <sys/socket.h> +# if !defined(__UCLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +# include <stropts.h> +# endif +# ifdef __sun +# include <sys/conf.h> +# endif +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +# ifdef __hpux +// # ifndef socklen_t // HP-UX 10.01 +// typedef int socklen_t; +// # endif +# endif +# include <cerrno> +#endif // !WIN32 + +#include <sockios/netinfo.h> + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +class sock_base +{ + public: + typedef unsigned long shutdownflg; +#ifdef __unix + typedef int socket_type; +#endif +#ifdef WIN32 + typedef SOCKET socket_type; +#endif + + enum stype { + sock_stream = SOCK_STREAM, // stream socket + sock_dgram = SOCK_DGRAM, // datagram socket + sock_raw = SOCK_RAW, // raw-protocol interface + sock_rdm = SOCK_RDM, // reliably-delivered message + sock_seqpacket = SOCK_SEQPACKET // sequenced packet stream + }; + + enum protocol { + local, // local to host (pipes, portals) + inet // internetwork: UDP, TCP, etc. + }; + + // Option flags per-socket. + enum so_t { + so_debug = SO_DEBUG, // turn on debugging info recording +#ifndef __linux + so_acceptconn = SO_ACCEPTCONN, // socket has had listen() +#endif + so_reuseaddr = SO_REUSEADDR, // allow local address reuse + so_keepalive = SO_KEEPALIVE, // keep connections alive + so_dontroute = SO_DONTROUTE, // just use interface addresses + so_broadcast = SO_BROADCAST, // permit sending of broadcast msgs +#ifndef __linux + so_useloopback = SO_USELOOPBACK, // bypass hardware when possible +#endif + so_linger = SO_LINGER, // linger on close if data present + so_oobinline = SO_OOBINLINE, // leave received OOB data in line + // Additional options, not kept in so_options. + so_sndbuf = SO_SNDBUF, // send buffer size + so_rcvbuf = SO_RCVBUF, // receive buffer size + so_sndlowat = SO_SNDLOWAT, // send low-water mark + so_rcvlowat = SO_RCVLOWAT, // receive low-water mark + so_sndtimeo = SO_SNDTIMEO, // send timeout + so_rcvtimeo = SO_RCVTIMEO, // receive timeout + so_error = SO_ERROR, // get error status and clear + so_type = SO_TYPE // get socket type +#ifdef __sun // indeed HP-UX 11.00 also has it, but 10.01 not + , + so_prototype = SO_PROTOTYPE // get/set protocol type +#endif + }; + + // Level number for (get/set)sockopt() to apply to socket itself. +// enum _level { +// sol_socket = SOL_SOCKET +// }; + + enum shutdownflags { + stop_in = 0x1, + stop_out = 0x2 + }; + +#ifdef WIN32 + class Init + { + // sometimes I need Init outside sock_base... + // private: + public: + __FIT_DECLSPEC Init(); + __FIT_DECLSPEC ~Init(); + + friend class sock_base; + }; + + protected: + __FIT_DECLSPEC sock_base(); + __FIT_DECLSPEC ~sock_base(); +#endif +}; + +class socket_timeout : + public std::exception +{ + public: + socket_timeout() + { } + + virtual char const *what() throw() + { return "socket timeout"; } +}; + +class socket_read_timeout : + public socket_timeout +{ + public: + socket_read_timeout() + { } + + virtual char const *what() throw() + { return "socket read timeout"; } +}; + +class socket_write_timeout : + public socket_timeout +{ + public: + socket_write_timeout() + { } + + virtual char const *what() throw() + { return "socket write timeout"; } +}; + +namespace detail { +template <class charT, class traits, class _Alloc> class sockmgr; +} // namespace detail + +template <class charT, class traits, class _Alloc> +class sock_processor_base; + +template<class charT, class traits, class _Alloc> +class basic_socket +{ + protected: + basic_socket() : + _fd( -1 ), + _use_rdtimeout( false ), + _use_wrtimeout( false ), + _notify_close( false ) + { new( Init_buf ) Init(); } + + ~basic_socket() + { ((Init *)Init_buf)->~Init(); } + + bool is_open_unsafe() const + { return _fd != -1; } + sock_base::socket_type fd_unsafe() const + { return _fd; } + + class Init + { + public: + Init() + { _guard( 1 ); } + ~Init() + { _guard( 0 ); } + + private: + static void _guard( int direction ); + static void __at_fork_prepare(); + static void __at_fork_child(); + static void __at_fork_parent(); + static int _count; + static bool _at_fork; + }; + + static char Init_buf[]; + + public: +#ifdef WIN32 + typedef u_short family_type; +#else +# ifdef sa_family_t + typedef sa_family_t family_type; +# else // HP-UX 10.01 + typedef unsigned short family_type; +# endif +#endif + + template <class Duration> + void rdtimeout( const Duration& ); + void rdtimeout() // infinite + { _use_rdtimeout = false; } + + template <class Duration> + void wrtimeout( const Duration& ); + void wrtimeout() // infinite + { _use_wrtimeout = false; } + + sock_base::socket_type fd() const { return _fd;} + bool is_open() const + { return _fd != -1; } + + family_type family() const + { return /* is_open() ? */ _address.any.sa_family /* : 0 */; } + + int port() const + { return /* is_open() && */ _address.any.sa_family == AF_INET ? _address.inet.sin_port : 0; } + + unsigned long inet_addr() const + { return /* is_open() && */ _address.any.sa_family == AF_INET ? _address.inet.sin_addr.s_addr : 0; } + + const sockaddr_in& inet_sockaddr() const throw( std::domain_error ) + { + if ( _address.any.sa_family != AF_INET ) { + throw domain_error( "socket not belongs to inet type" ); + } + return /* is_open() && */ _address.inet; + } + + protected: + sock_base::socket_type _fd; + + union sockaddr_t { + sockaddr_in inet; + sockaddr any; + } _address; + + std::tr2::milliseconds _rdtimeout; + std::tr2::milliseconds _wrtimeout; + bool _use_rdtimeout; + bool _use_wrtimeout; + bool _notify_close; + + static detail::sockmgr<charT,traits,_Alloc>* mgr; + friend class Init; +}; + +template<class charT, class traits, class _Alloc> +int basic_socket<charT,traits,_Alloc>::Init::_count = 0; + +template<class charT, class traits, class _Alloc> +bool basic_socket<charT,traits,_Alloc>::Init::_at_fork = false; + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::_guard( int direction ) +{ + static std::tr2::mutex _init_lock; + + if ( direction ) { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( _count++ == 0 ) { + basic_socket<charT,traits,_Alloc>::mgr = new detail::sockmgr<charT,traits,_Alloc>(); +#ifdef __FIT_PTHREADS + if ( !_at_fork ) { // call only once + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + // throw system_error; + } + _at_fork = true; + } +#endif +// _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); + std::cerr << __FILE__ << ":" << __LINE__ << " new mgr " << std::tr2::getpid() << std::endl; + } + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( --_count == 0 ) { + if ( basic_socket<charT,traits,_Alloc>::mgr == 0 ) { + std::cerr << __FILE__ << ":" << __LINE__ << " shit happens\n"; + } + std::cerr << __FILE__ << ":" << __LINE__ << " mgr destroyed " << std::tr2::getpid() << std::endl; + delete basic_socket<charT,traits,_Alloc>::mgr; + basic_socket<charT,traits,_Alloc>::mgr = 0; + } + } +} + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::__at_fork_prepare() +{ +} + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::__at_fork_child() +{ + if ( _count != 0 ) { + // stop mgr + _count = 1; + delete basic_socket<charT,traits,_Alloc>::mgr; + basic_socket<charT,traits,_Alloc>::mgr = new detail::sockmgr<charT,traits,_Alloc>(); + } + // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); +} + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::__at_fork_parent() +{ } + +template<class charT, class traits, class _Alloc> +char basic_socket<charT,traits,_Alloc>::Init_buf[128]; + +template <class charT, class traits, class _Alloc> +detail::sockmgr<charT,traits,_Alloc>* basic_socket<charT,traits,_Alloc>::mgr = 0; + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif + +#include <sockios/sp.h> + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +template<class charT, class traits, class _Alloc> +class basic_sockbuf : + public basic_streambuf<charT, traits> + // public basic_socket<charT,traits,_Alloc> +{ + private: + typedef basic_socket<charT,traits,_Alloc> basic_socket_t; + + public: + typedef basic_ios<charT, traits> ios_type; + typedef basic_sockbuf<charT, traits, _Alloc> sockbuf_type; + typedef typename traits::state_type state_t; + typedef typename basic_socket_t::family_type family_type; + + public: + /* Inherited from basic_streambuf : */ + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef traits traits_type; + /* */ + + basic_sockbuf() : + impl( 0 ) + { } + + basic_sockbuf( const char *hostname, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol prot = sock_base::inet ) : + impl( 0 ) + { open( hostname, port, type, prot ); } + + basic_sockbuf( const in_addr& addr, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol prot = sock_base::inet ) : + impl( 0 ) + { open( addr, type, prot ); } + + virtual ~basic_sockbuf() + { close(); } + + sockbuf_type *open( const char *hostname, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol prot = sock_base::inet ); + + sockbuf_type *open( const in_addr& addr, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol prot = sock_base::inet ) + { return impl->open( addr, port, type, prot ) ? this : 0; } + + sockbuf_type *open( sock_base::socket_type s, + sock_base::stype t = sock_base::sock_stream ); + + sockbuf_type *open( sock_base::socket_type s, const sockaddr& addr, + sock_base::stype t = sock_base::sock_stream ) + { return impl->open( s, addr, t ) ? this : 0; } + + sockbuf_type *attach( sock_base::socket_type s, + sock_base::stype t = sock_base::sock_stream ); + + sockbuf_type *attach( sock_base::socket_type s, const sockaddr& addr, + sock_base::stype t = sock_base::sock_stream ); + + sockbuf_type *close() + { return impl->close() ? this : 0; } + + void shutdown( sock_base::shutdownflg dir ) + { impl->shutdown( dir ); } + + sock_base::stype stype() const + { return impl->stype(); } + + template <class Duration> + void rdtimeout( const Duration& d ) + { impl->rdtimeout( d ); } + void rdtimeout() // infinite + { impl->rdtimeout(); } + + template <class Duration> + void wrtimeout( const Duration& d ) + { impl->wrtimeout( d ); } + void wrtimeout() // infinite + { impl->wrtimeout(); } + + sock_base::socket_type fd() const { return impl->fd();} + bool is_open() const + { return impl->is_open(); } + + family_type family() const + { return impl->family(); } + + int port() const + { return impl->port(); } + + unsigned long inet_addr() const + { return impl->inet_addr(); } + + const sockaddr_in& inet_sockaddr() const throw( std::domain_error ) + { return impl->inet_sockaddr(); } + + + protected: + virtual streamsize showmanyc() + { return impl->showmanyc(); } + + virtual int_type underflow() + { return impl->underflow(); } + virtual int_type overflow( int_type c = traits::eof() ) + { return impl->overflow(c); } + virtual int_type pbackfail( int_type c = traits::eof() ) + { return impl->pbackfail( c ); } + // Buffer managment and positioning: + virtual basic_streambuf<charT, traits> *setbuf(char_type *s, streamsize n ) + { impl->setbuf( s, n ); return this; } + + virtual int sync() + { return impl->sync(); } + virtual streamsize xsputn(const char_type *s, streamsize n) + { return impl->xsputn( s, n ); } + + private: + detail::basic_sockbuf_aux<charT,traits,_Alloc> *impl; +}; + +template <class charT, class traits, class _Alloc> +class basic_sockstream : + public sock_base, + public basic_iostream<charT,traits> +{ + public: + /* Inherited from basic_iostream + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + */ + basic_sockstream() : + sock_base(), + basic_iostream<charT,traits>( 0 ) + { basic_ios<charT,traits>::init(&_sb); } + basic_sockstream( const char *hostname, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol pro = sock_base::inet ) : + sock_base(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( hostname, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockstream( const in_addr& addr, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol pro = sock_base::inet ) : + sock_base(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( addr, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockstream( sock_base::socket_type s, const sockaddr& addr, + sock_base::stype type = sock_base::sock_stream ) : + sock_base(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, addr, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockstream( sock_base::socket_type s, + sock_base::stype type = sock_base::sock_stream ) : + sock_base(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockbuf<charT,traits,_Alloc>* rdbuf() const + { return const_cast<basic_sockbuf<charT,traits,_Alloc>*>(&_sb); } + + bool is_open() const + { return _sb.is_open(); } + + void open( const char *hostname, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol pro = sock_base::inet ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( hostname, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void open( const in_addr& addr, int port, + sock_base::stype type = sock_base::sock_stream, + sock_base::protocol pro = sock_base::inet ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( addr, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + // only for sock_stream : inet now! + void open( sock_base::socket_type s, const sockaddr& addr, + sock_base::stype type = sock_base::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, addr, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void open( sock_base::socket_type s, + sock_base::stype type = sock_base::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void attach( sock_base::socket_type s, const sockaddr& addr, + sock_base::stype type = sock_base::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.attach( s, addr, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void attach( sock_base::socket_type s, + sock_base::stype type = sock_base::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.attach( s, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void close() + { + if ( _sb.is_open() ) { + if ( _sb.close() == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit ); + } else { + basic_iostream<charT,traits>::clear(); + } + } + } + + void setoptions( sock_base::so_t optname, bool on_off = true, + int __v = 0 ); + + private: + basic_sockbuf<charT,traits,_Alloc> _sb; +}; + +typedef basic_sockbuf<char,char_traits<char>,allocator<char> > sockbuf; +// typedef basic_sockbuf<wchar_t,char_traits<wchar_t>,allocator<wchar_t> > wsockbuf; +typedef basic_sockstream<char,std::char_traits<char>,std::allocator<char> > sockstream; +// typedef basic_sockstream<wchar_t,char_traits<wchar_t>,allocator<wchar_t> > wsockstream; + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif + +#ifndef __STL_LINK_TIME_INSTANTIATION +#include <sockios/sockstream.cc> +#endif + +#endif // __SOCKIOS_SOCKSTREAM Deleted: branches/complement-sockios/explore/include/sockios/sockstream.cc =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream.cc 2008-06-07 17:06:27 UTC (rev 1891) +++ branches/complement-sockios/explore/include/sockios/sockstream.cc 2008-06-09 18:31:16 UTC (rev 1892) @@ -1,777 +0,0 @@ -// -*- C++ -*- Time-stamp: <07/09/06 23:48:33 ptr> - -/* - * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 - * Petr Ovtchenkov - * - * Portion Copyright (c) 1999-2001 - * Parallel Graphics Ltd. - * - * Licensed under the Academic Free License version 3.0 - * - */ - -#include <sockios/netinfo.h> - -#ifdef __unix -extern "C" int nanosleep(const struct timespec *, struct timespec *); -#endif - -#if defined(__unix) && !defined(__UCLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -# include <stropts.h> // for ioctl() call -#endif - -#ifdef __FIT_NONBLOCK_SOCKETS -# include <fcntl.h> -#endif - -#ifdef STLPORT -_STLP_BEGIN_NAMESPACE -#else -namespace std { -#endif - -template<class charT, class traits, class _Alloc> -basic_sockbuf<charT, traits, _Alloc> * -basic_sockbuf<charT, traits, _Alloc>::open( const char *name, int port, - sock_base::stype type, - sock_base::protocol prot, - const timespec *timeout ) -{ - if ( is_open() ) { - return 0; - } - try { - _mode = ios_base::in | ios_base::out; - _errno = 0; - _type = type; -#ifdef WIN32 - WSASetLastError( 0 ); -#endif -#ifdef __FIT_POLL - if ( timeout != 0 ) { - _timeout = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000; - } else { - _timeout = -1; - } -#endif -#ifdef __FIT_SELECT - if ( timeout != 0 ) { - _timeout.tv_sec = timeout->tv_sec; - _timeout.tv_usec = timeout->tv_nsec / 1000; - _timeout_ref = &_timeout; - } else { - _timeout_ref = 0; - } -#endif - if ( prot == sock_base::inet ) { - _fd = socket( PF_INET, type, 0 ); - if ( _fd == -1 ) { - throw std::runtime_error( "can't open socket" ); - } - _address.inet.sin_family = AF_INET; - // htons is a define at least in Linux 2.2.5-15, and it's expantion fail - // for gcc 2.95.3 -#if defined(linux) && defined(htons) && defined(__bswap_16) - _address.inet.sin_port = ((((port) >> 8) & 0xff) | (((port) & 0xff) << 8)); -#else - _address.inet.sin_port = htons( port ); -#endif // linux && htons - _address.inet.sin_addr = std::findhost( name ); - - // Generally, stream sockets may successfully connect() only once - if ( connect( _fd, &_address.any, sizeof( _address ) ) == -1 ) { - throw std::domain_error( "connect fail" ); - } - if ( type == sock_base::sock_stream ) { - _xwrite = &_Self_type::write; - _xread = &_Self_type::read; - } else if ( type == sock_base::sock_dgram ) { - _xwrite = &_Self_type::send; - _xread = &_Self_type::recv; - } - } else if ( prot == sock_base::local ) { - _fd = socket( PF_UNIX, type, 0 ); - if ( _fd == -1 ) { - throw std::runtime_error( "can't open socket" ); - } - } else { // other protocols not implemented yet - throw std::invalid_argument( "protocol not implemented" ); - } - if ( _bbuf == 0 ) - _M_allocate_block( type == sock_base::sock_stream ? 0xb00 : 0xffff ); // max 1460 (dec) [0x5b4] --- single segment - if ( _bbuf == 0 ) { - throw std::length_error( "can't allocate block" ); - } - -#ifdef __FIT_NONBLOCK_SOCKETS - if ( fcntl( _fd, F_SETFL, fcntl( _fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - throw std::runtime_error( "can't establish nonblock mode" ); - } -#endif -#ifdef __FIT_POLL - pfd.fd = _fd; - pfd.events = POLLIN | POLLHUP | POLLRDNORM; -#endif - setp( _bbuf, _bbuf + ((_ebuf - _bbuf)>>1) ); - setg( this->epptr(), this->epptr(), this->epptr() ); - - _errno = 0; // if any - } - catch ( std::domain_error& ) { -#ifdef WIN32 - _errno = WSAGetLastError(); - ::closesocket( _fd ); -#else - _errno = errno; - ::close( _fd ); -#endif - _fd = -1; - return 0; - } - catch ( std::length_error& ) { -#ifdef WIN32 - ::closesocket( _fd ); -#else - ::close( _fd ); -#endif - _fd = -1; - return 0; - } - catch ( std::runtime_error& ) { -#ifdef WIN32 - _errno = WSAGetLastError(); -#else - _errno = errno; -#endif - return 0; - } - catch ( std::invalid_argument& ) { - return 0; - } - - return this; -} - -// -- -template<class charT, class traits, class _Alloc> -basic_sockbuf<charT, traits, _Alloc> * -basic_sockbuf<charT, traits, _Alloc>::open( const in_addr& addr, int port, - sock_base::stype type, - sock_base::protocol prot, - const timespec *timeout ) -{ - if ( is_open() ) { - return 0; - } - try { - _mode = ios_base::in | ios_base::out; - _errno = 0; - _type = type; -#ifdef WIN32 - WSASetLastError( 0 ); -#endif -#ifdef __FIT_POLL - if ( timeout != 0 ) { - _timeout = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000; - } else { - _timeout = -1; - } -#endif -#ifdef __FIT_SELECT - if ( timeout != 0 ) { - _timeout.tv_sec = timeout->tv_sec; - _timeout.tv_usec = timeout->tv_nsec / 1000; - _timeout_ref = &_timeout; - } else { - _timeout_ref = 0; - } -#endif - if ( prot == sock_base::inet ) { - _fd = socket( PF_INET, type, 0 ); - if ( _fd == -1 ) { - throw std::runtime_error( "can't open socket" ); - } - _address.inet.sin_family = AF_INET; - // htons is a define at least in Linux 2.2.5-15, and it's expantion fail - // for gcc 2.95.3 -#if defined(linux) && defined(htons) && defined(__bswap_16) - _address.inet.sin_port = ((((port) >> 8) & 0xff) | (((port) & 0xff) << 8)); -#else - _address.inet.sin_port = htons( port ); -#endif // linux && htons - _address.inet.sin_addr = addr; - - // Generally, stream sockets may successfully connect() only once - if ( connect( _fd, &_address.any, sizeof( _address ) ) == -1 ) { - throw std::domain_error( "connect fail" ); - } - if ( type == sock_base::sock_stream ) { - _xwrite = &_Self_type::write; - _xread = &_Self_type::read; - } else if ( type == sock_base::sock_dgram ) { - _xwrite = &_Self_type::send; - _xread = &_Self_type::recv; - } - } else if ( prot == sock_base::local ) { - _fd = socket( PF_UNIX, type, 0 ); - if ( _fd == -1 ) { - throw std::runtime_error( "can't open socket" ); - } - } else { // other protocols not implemented yet - throw std::invalid_argument( "protocol not implemented" ); - } - if ( _bbuf == 0 ) - _M_allocate_block( type == sock_base::sock_stream ? 0xb00 : 0xffff ); // max 1460 (dec) [0x5b4] --- single segment - if ( _bbuf == 0 ) { - throw std::length_error( "can't allocate block" ); - } - -#ifdef __FIT_NONBLOCK_SOCKETS - if ( fcntl( _fd, F_SETFL, fcntl( _fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - throw std::runtime_error( "can't establish nonblock mode" ); - } -#endif -#ifdef __FIT_POLL - pfd.fd = _fd; - pfd.events = POLLIN | POLLHUP | POLLRDNORM; -#endif - setp( _bbuf, _bbuf + ((_ebuf - _bbuf)>>1) ); - setg( this->epptr(), this->epptr(), this->epptr() ); - - _errno = 0; // if any - } - catch ( std::domain_error& ) { -#ifdef WIN32 - _errno = WSAGetLastError(); - ::closesocket( _fd ); -#else - _errno = errno; - ::close( _fd ); -#endif - _fd = -1; - return 0; - } - catch ( std::length_error& ) { -#ifdef WIN32 - ::closesocket( _fd ); -#else - ::close( _fd ); -#endif - _fd = -1; - return 0; - } - catch ( std::runtime_error& ) { -#ifdef WIN32 - _errno = WSAGetLastError(); -#else - _errno = errno; -#endif - return 0; - } - catch ( std::invalid_argument& ) { - return 0; - } - - return this; -} -// -- - -template<class charT, class traits, class _Alloc> -basic_sockbuf<charT, traits, _Alloc> * -basic_sockbuf<charT, traits, _Alloc>::open( sock_base::socket_type s, - sock_base::stype t, - const timespec *timeout ) -{ - if ( is_open() || s == -1 ) { - return 0; - } - - sockaddr sa; - socklen_t sl = sizeof(sa); - getsockname( s, &sa, &sl ); - - return basic_sockbuf<charT, traits, _Alloc>::open( s, sa, t, timeout ); -} - -template<class charT, class traits, class _Alloc> -basic_sockbuf<charT, traits, _Alloc> * -basic_sockbuf<charT, traits, _Alloc>::open( sock_base::socket_type s, - const sockaddr& addr, - sock_base::stype t, - const timespec *timeout ) -{ - if ( is_open() || s == -1 ) { - return 0; - } - _fd = s; - memcpy( (void *)&_address.any, (const void *)&addr, sizeof(sockaddr) ); - _mode = ios_base::in | ios_base::out; - _errno = 0; - _type = t; -#ifdef WIN32 - WSASetLastError( 0 ); -#endif -#ifdef __FIT_POLL - if ( timeout != 0 ) { - _timeout = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000; - } else { - _timeout = -1; - } -#endif -#ifdef __FIT_SELECT - if ( timeout != 0 ) { - _timeout.tv_sec = timeout->tv_sec; - _timeout.tv_usec = timeout->tv_nsec / 1000; - _timeout_ref = &_timeout; - } else { - _timeout_ref = 0; - } -#endif - if ( t == sock_base::sock_stream ) { - _xwrite = &_Self_type::write; - _xread = &_Self_type::read; - } else if ( t == sock_base::sock_dgram ) { - _xwrite = &_Self_type::sendto; - _xread = &_Self_type::recvfrom; - } else { - _fd = -1; - return 0; // unsupported type - } - - if ( _bbuf == 0 ) { - _M_allocate_block( t == sock_base::sock_stream ? 0xb00 : 0x1ffff ); - } - - if ( _bbuf == 0 ) { -#ifdef WIN32 - ::closesocket( _fd ); -#else - ::close( _fd ); -#endif - _fd = -1; - return 0; - } - -#ifdef __FIT_NONBLOCK_SOCKETS - if ( fcntl( _fd, F_SETFL, fcntl( _fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - throw std::runtime_error( "can't establish nonblock mode" ); - } -#endif -#ifdef __FIT_POLL - pfd.fd = _fd; - pfd.events = POLLIN | POLLHUP | POLLRDNORM; -#endif - setp( _bbuf, _bbuf + ((_ebuf - _bbuf)>>1) ); - setg( this->epptr(), this->epptr(), this->epptr() ); - - _errno = 0; // if any - - return this; -} - -template<class charT, class traits, class _Alloc> -basic_sockbuf<charT, traits, _Alloc> * -basic_sockbuf<charT, traits, _Alloc>::attach( sock_base::socket_type s, - sock_base::stype t, - const timespec *timeout ) -{ - if ( is_open() || s == -1 ) { - return 0; - } - - sockaddr sa; - socklen_t sl = sizeof(sa); - getsockname( s, &sa, &sl ); - - return basic_sockbuf<charT, traits, _Alloc>::attach( s, sa, t, timeout ); -} - -template<class charT, class traits, class _Alloc> -basic_sockbuf<charT, traits, _Alloc> * -basic_sockbuf<charT, traits, _Alloc>::attach( sock_base::socket_type s, - const sockaddr& addr, - sock_base::stype t, - const timespec *timeout ) -{ - if ( is_open() || s == -1 ) { - return 0; - } - - // _doclose = false; - return basic_sockbuf<charT, traits, _Alloc>::open( dup(s), addr, t, timeout ); -} - -template<class charT, class traits, class _Alloc> -basic_sockbuf<charT, traits, _Alloc> * -basic_sockbuf<charT, traits, _Alloc>::close() -{ - if ( !is_open() ) - return 0; - - // if ( _doclose ) { -#ifdef WIN32 - ::closesocket( _fd ); -#else - ::close( _fd ); -#endif - // } - - // _STLP_ASSERT( _bbuf != 0 ); - // put area before get area - setp( _bbuf, _bbuf + ((_ebuf - _bbuf)>>1) ); - setg( this->epptr(), this->epptr(), this->epptr() ); - - _fd = -1; - - return this; -} - -template<class charT, class traits, class _Alloc> -void basic_sockbuf<charT, traits, _Alloc>::shutdown( sock_base::shutdownflg dir ) -{ - if ( is_open() ) { - if ( (dir & (sock_base::stop_in | sock_base::stop_out)) == - (sock_base::stop_in | sock_base::stop_out) ) { - ::shutdown( _fd, 2 ); - } else if ( dir & sock_base::stop_in ) { - ::shutdown( _fd, 0 ); - } else if ( dir & sock_base::stop_out ) { - ::shutdown( _fd, 1 ); - } - } -} - -template<class charT, class traits, class _Alloc> -__FIT_TYPENAME basic_sockbuf<charT, traits, _Alloc>::int_type -basic_sockbuf<charT, traits, _Alloc>::underflow() -{ - if( !is_open() ) - return traits::eof(); - - if ( this->gptr() < this->egptr() ) - return traits::to_int_type(*this->gptr()); - -#ifndef __FIT_NONBLOCK_SOCKETS -# ifdef __FIT_SELECT - FD_ZERO( &pfd ); - FD_SET( fd(), &pfd ); - - while ( select( fd() + 1, &pfd, 0, 0, _timeout_ref ) <= 0 ) { - if ( errno == EINTR ) { // may be interrupted, check and ignore - errno = 0; - continue; - } - return traits::eof(); - } -# endif // __FIT_SELECT -# ifdef __FIT_POLL - pfd.revents = 0; - - while ( poll( &pfd, 1, _timeout ) <= 0 ) { // wait infinite - if ( errno == EINTR ) { // may be interrupted, check and ignore - errno = 0; - continue; - } - return traits::eof(); - } - if ( (pfd.revents & POLLERR) != 0 ) { - // _state |= ios_base::failbit; - return traits::eof(); - } -# endif // __FIT_POLL -#endif // !__FIT_NONBLOCK_SOCKETS - long offset = (this->*_xread)( this->eback(), sizeof(char_type) * (_ebuf - this->eback()) ); -#ifdef __FIT_NONBLOCK_SOCKETS - if ( offset < 0 && errno == EAGAIN ) { - errno = 0; -# ifdef __FIT_SELECT - FD_ZERO( &pfd ); - FD_SET( fd(), &pfd ); - - while ( select( fd() + 1, &pfd, 0, 0, _timeout_ref ) <= 0 ) { - if ( errno == EINTR ) { // may be interrupted, check and ignore - errno = 0; - continue; - } - return traits::eof(); - } -# endif // __FIT_SELECT -# ifdef __FIT_POLL - pfd.revents = 0; - - while ( poll( &pfd, 1, _timeout ) <= 0 ) { // wait infinite - if ( errno == EINTR ) { // may be interrupted, check and ignore - errno = 0; - continue; - } - return traits::eof(); - } - if ( (pfd.revents & POLLERR) != 0 ) { - // _state |= ios_base::failbit; - return traits::eof(); - } -# endif // __FIT_POLL - offset = (this->*_xread)( this->eback(), sizeof(char_type) * (_ebuf - this->eback()) ); - } -#endif // __FIT_NONBLOCK_SOCKETS - // Without __FIT_NONBLOCK_SOCKETS: - // don't allow message of zero length: - // in conjunction with POLLIN in revent of poll above this designate that - // we receive FIN packet. - // With __FIT_NONBLOCK_SOCKETS: - // 0 is eof, < 0 --- second read also return < 0, but shouldn't - if ( offset <= 0 ) { - return traits::eof(); - } - - offset /= sizeof(charT); - - setg( this->eback(), this->eback(), this->eback() + offset ); - - return traits::to_int_type(*this->gptr()); -} - -template<class charT, class traits, class _Alloc> -__FIT_TYPENAME basic_sockbuf<charT, traits, _Alloc>::int_type -basic_sockbuf<charT, traits, _Alloc>::overflow( int_type c ) -{ - if ( !is_open() ) - return traits::eof(); - - if ( !traits::eq_int_type( c, traits::eof() ) && this->pptr() < this->epptr() ) { - sputc( traits::to_char_type(c) ); - return c; - } - - long count = this->pptr() - this->pbase(); - - if ( count ) { - count *= sizeof(charT); -#ifndef __FIT_NONBLOCK_SOCKETS - if ( (this->*_xwrite)( this->pbase(), count ) != count ) { - return traits::eof(); - } -#else - long offset = (this->*_xwrite)( this->pbase(), count ); - if ( offset < 0 ) { - if ( errno == EAGAIN ) { - pollfd wpfd; - wpfd.fd = _fd; - wpfd.events = POLLOUT | POLLHUP | POLLWRNORM; - wpfd.revents = 0; - while ( poll( &wpfd, 1, _timeout ) <= 0 ) { // wait infinite - if ( errno == EINTR ) { // may be interrupted, check and ignore - errno = 0; - continue; - } - return traits::eof(); - } - if ( (wpfd.revents & POLLERR) != 0 ) { - return traits::eof(); - } - offset = (this->*_xwrite)( this->pbase(), count ); - if ( offset < 0 ) { - return traits::eof(); - } - } else { - return traits::eof(); - } - } - if ( offset < count ) { - // MUST BE: (offset % sizeof(char_traits)) == 0 ! - offset /= sizeof(charT); - count /= sizeof(charT); - traits::move( this->pbase(), this->pbase() + offset, count - offset ); - // std::copy_backword( this->pbase() + offset, this->pbase() + count, this->pbase() ); - setp( this->pbase(), this->epptr() ); // require: set pptr - this->pbump( count - offset ); - if( !traits::eq_int_type(c,traits::eof()) ) { - sputc( traits::to_char_type(c) ); - } - - return traits::not_eof(c); - } -#endif - } - - setp( this->pbase(), this->epptr() ); // require: set pptr - if( !traits::eq_int_type(c,traits::eof()) ) { - sputc( traits::to_char_type(c) ); - } - - return traits::not_eof(c); -} - -template<class charT, class traits, class _Alloc> -int basic_sockbuf<charT, traits, _Alloc>::sync() -{ - if ( !is_open() ) { - return -1; - } - - long count = this->pptr() - this->pbase(); - if ( count ) { - // _STLP_ASSERT( this->pbase() != 0 ); - count *= sizeof(charT); -#ifndef __FIT_NONBLOCK_SOCKETS - if ( (this->*_xwrite)( this->pbase(), count ) != count ) { - return -1; - } -#else - long start = 0; - while ( count > 0 ) { - long offset = (this->*_xwrite)( this->pbase() + start, count ); - if ( offset < 0 ) { - ... [truncated message content] |