36 m_socket =
Descriptor( ::socket( domain , type , protocol ) ) ;
37 if( !m_socket.
valid() )
40 throw SocketError(
"cannot create socket" , m_reason_string ) ;
52 void GNet::Socket::prepare()
59 G_WARNING(
"GNet::Socket::open: cannot make socket non-blocking (" << m_reason_string <<
")" ) ;
75 void GNet::Socket::drop()
79 dropExceptionHandler() ;
82 void GNet::Socket::saveReason()
85 m_reason_string = reasonStringImp( m_reason ) ;
88 void GNet::Socket::saveReason()
const
95 G_DEBUG(
"Socket::bind: binding " << local_address.
displayString() <<
" on fd " << m_socket ) ;
97 if( local_address.
domain() != m_domain )
98 throw SocketBindError(
"address family does not match the socket domain" ) ;
102 setOptionPureV6( local_address.
family() == Address::Family::ipv6() ) ;
104 int rc = ::bind( m_socket.fd() , local_address.
address() , local_address.
length() ) ;
108 throw SocketBindError( local_address.
displayString() , m_reason_string ) ;
114 G_DEBUG(
"Socket::bind: binding " << local_address.
displayString() <<
" on fd " << m_socket ) ;
115 if( local_address.
domain() != m_domain )
return false ;
119 setOptionPureV6( local_address.
family() == Address::Family::ipv6() ) ;
121 int rc = ::bind( m_socket.fd() , local_address.
address() , local_address.
length() ) ;
127 G_DEBUG(
"GNet::Socket::connect: connecting to " << address.
displayString() ) ;
128 if( address.
domain() != m_domain )
130 G_WARNING(
"GNet::Socket::connect: cannot connect: address family does not match "
131 "the socket domain (" << address.
domain() <<
"," << m_domain <<
")" ) ;
135 setOptionPureV6( address.
family() == Address::Family::ipv6() ,
NoThrow() ) ;
137 int rc = ::connect( m_socket.fd() , address.
address() , address.
length() ) ;
147 G_DEBUG(
"GNet::Socket::connect: connection in progress" ) ;
148 if( done !=
nullptr ) *done = false ;
152 G_DEBUG(
"GNet::Socket::connect: synchronous connect failure: " << m_reason ) ;
156 if( done !=
nullptr ) *done = true ;
162 if( static_cast<ssize_type>(len) < 0 )
163 G_WARNING(
"GNet::Socket::write: too big" ) ;
165 ssize_type nsent = ::send( m_socket.fd() , buf , len , MSG_NOSIGNAL ) ;
166 if( sizeError(nsent) )
169 G_DEBUG(
"GNet::Socket::write: write error " << m_reason ) ;
172 else if( nsent < 0 || static_cast<size_type>(nsent) < len )
181 int rc = ::listen( m_socket.fd() , backlog ) ;
185 throw SocketError(
"cannot listen on socket" , m_reason_string ) ;
189 std::pair<bool,GNet::Address> GNet::Socket::getAddress(
bool local )
const
195 ::getsockname( m_socket.fd() , address_storage.
p1() , address_storage.
p2() ) :
196 ::getpeername( m_socket.fd() , address_storage.
p1() , address_storage.
p2() ) ;
204 return std::pair<bool,Address>( true , Address(address_storage) ) ;
209 return getAddress(
true ) ;
214 return getAddress(
false ) ;
219 return getPeerAddress().first ;
224 G_DEBUG(
"GNet::Socket::addReadHandler: fd " << m_socket ) ;
235 G_DEBUG(
"GNet::Socket::addWriteHandler: fd " << m_socket ) ;
241 G_DEBUG(
"GNet::Socket::addExceptionHandler: fd " << m_socket ) ;
257 std::ostringstream ss ;
264 std::ostringstream ss ;
271 ::shutdown( m_socket.fd() , for_writing ? 1 : 0 ) ;
276 return m_socket.fd() ;
282 Socket( address_domain , SOCK_STREAM , 0 )
284 setOptionNoLinger() ;
285 setOptionKeepAlive() ;
302 ssize_type nread =
G::Msg::recv( m_socket.fd() , buf , len , 0 ) ;
303 if( sizeError(nread) )
306 G_DEBUG(
"GNet::StreamSocket::read: cannot read from " << m_socket.fd() ) ;
320 Descriptor new_socket( ::accept(m_socket.fd(),addr.
p1(),addr.
p2()) ) ;
321 if( ! new_socket.
valid() )
324 throw SocketError(
"cannot accept on socket" , m_reason_string ) ;
328 throw SocketError(
"testing" ) ;
331 pair.second =
Address( addr.
p() , addr.
n() ) ;
332 G_DEBUG(
"GNet::StreamSocket::accept: accepted from socket " << m_socket.fd()
333 <<
" onto socket " << new_socket <<
" with address " << pair.second.
displayString() ) ;
335 pair.first.get()->setOptionNoLinger() ;
342 Socket( address_domain , SOCK_DGRAM , 0 )
352 int rc = ::connect( m_socket.fd() , 0 , 0 ) ;
359 if( len == 0 )
return 0 ;
361 socklen_t sender_len =
sizeof(sender) ;
362 ssize_type nread =
G::Msg::recvfrom( m_socket.fd() , buf , len , 0 , &sender , &sender_len ) ;
363 if( sizeError(nread) )
373 if( len == 0 )
return 0 ;
375 socklen_t sender_len =
sizeof(sender) ;
376 ssize_type nread =
G::Msg::recvfrom( m_socket.fd() , buf , len , 0 , &sender , &sender_len ) ;
377 if( sizeError(nread) )
382 src_address =
Address( &sender , sender_len ) ;
388 G_DEBUG(
"GNet::DatagramSocket::write: sending " << len <<
" bytes to " << dst.
displayString() ) ;
394 G_DEBUG(
"GNet::DatagramSocket::write: write error " << m_reason ) ;
405 void GNet::Socket::setOptionKeepAlive()
407 setOption( SOL_SOCKET ,
"so_keepalive" , SO_KEEPALIVE , 1 ) ;
410 void GNet::Socket::setOptionNoLinger()
412 struct linger options ;
413 options.l_onoff = 0 ;
414 options.l_linger = 0 ;
415 bool ok = setOptionImp( SOL_SOCKET , SO_LINGER , reinterpret_cast<char*>(&options) ,
sizeof(options) ) ;
419 throw SocketError(
"cannot set so_linger" , m_reason_string ) ;
423 bool GNet::Socket::setOption(
int level ,
const char * ,
int op ,
int arg , NoThrow )
425 const void *
const vp =
reinterpret_cast<const void*
>(&arg) ;
426 bool ok = setOptionImp( level , op , vp ,
sizeof(
int) ) ;
432 void GNet::Socket::setOption(
int level ,
const char * opp ,
int op ,
int arg )
434 if( !setOption( level , opp , op , arg , NoThrow() ) )
435 throw SocketError( opp , m_reason_string ) ;
Family family() const
Returns the address family.
virtual ssize_type read(char *buffer, size_type len)
Override from Socket::read().
std::pair< bool, Address > getLocalAddress() const
Retrieves local address of the socket.
void listen(int backlog=1)
Starts the socket listening on the bound address for incoming connections or incoming datagrams...
virtual void addWrite(Descriptor fd, EventHandler &handler)=0
Adds the given event source descriptor and associated handler to the write list.
bool connect(const Address &addr, bool *done=nullptr)
Initiates a connection to (or association with) the given address.
void dropReadHandler()
Reverses addReadHandler().
void addExceptionHandler(EventHandler &handler)
Adds this socket to the event source list so that the given handler receives exception events...
void addWriteHandler(EventHandler &handler)
Adds this socket to the event source list so that the given handler receives write events when flow c...
virtual ~DatagramSocket()
Destructor.
and hiding the definition of sockaddr_storage.
The GNet::Address class encapsulates a TCP/UDP transport address.
The Socket class encapsulates a non-blocking Unix socket file descriptor or a Windows 'SOCKET' handle...
socklen_t * p2()
Returns the length pointer for accept()/getsockname()/getpeername() to write into.
void addReadHandler(EventHandler &handler)
Adds this socket to the event source list so that the given handler receives read events...
sockaddr * p1()
Returns the sockaddr pointer for accept()/getsockname()/getpeername() to write into.
virtual void dropRead(Descriptor fd)=0
Removes the given event source descriptor from the list of read sources.
StreamSocket(int address_domain)
Constructor with a hint of the bind()/connect() address to be used later.
virtual SOCKET fd() const
Returns the socket descriptor. Override from G::ReadWrite.
virtual ~StreamSocket()
Destructor.
A class that encapsulates a network file descriptor and hides knowledge of its o/s-spefific error val...
const sockaddr * address() const
Returns the sockaddr address.
static ssize_t sendto(int, const void *, size_t, int, const sockaddr *, socklen_t, int fd_to_send=-1)
A sendto() replacement using sendmsg().
ssize_type writeto(const char *buffer, size_type len, const Address &dst)
Sends a datagram to the given address.
DatagramSocket(int address_domain)
Constructor with a hint of a local address.
void dropExceptionHandler()
Reverses addExceptionHandler().
virtual void dropException(Descriptor fd)=0
Removes the given event source descriptor from the list of exception sources.
void dropWriteHandler()
Reverses addWriteHandler().
void bind(const Address &)
Binds the socket with the given address.
const sockaddr * p() const
Returns the pointer.
std::string reasonString() const
Returns the failure reason as a string.
void disconnect()
Releases the association between two datagram endpoints reversing the effect of the previous Socket::...
std::pair< bool, Address > getPeerAddress() const
Retrieves address of socket's peer.
A derivation of GNet::Socket for a stream socket.
virtual void addRead(Descriptor fd, EventHandler &handler)=0
Adds the given event source descriptor and associated handler to the read list.
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
static bool enabled()
Returns true if test features are enabled.
socklen_t length() const
Returns the size of the sockaddr address. See address().
bool valid() const
Returns true if the descriptor is valid.
virtual ~Socket()
Destructor.
Socket(int domain, int type, int protocol)
Constructor used by derived classes.
virtual void addException(Descriptor fd, EventHandler &handler)=0
Adds the given event source descriptor and associated handler to the exception list.
A class which is used to return a new()ed socket to calling code, together with associated informatio...
static ssize_t recvfrom(int, void *, size_t, int, sockaddr *, socklen_t *, int *fd_received_p=nullptr)
A recvfrom() replacement using recvmsg().
int domain() const
Returns the address 'domain', eg. PF_INET.
A base class for classes that handle asynchronous events from the event loop.
virtual ssize_type write(const char *buf, size_type len) override=0
Writes to the socket.
bool hasPeer() const
Returns true if the socket has a valid peer.
virtual ssize_type read(char *buffer, size_type buffer_length)
Override from Socket::read().
virtual ssize_type write(const char *buf, size_type len)
Override from Socket::write().
static void init()
An optional early-initialisation function. May be called more than once.
void shutdown(bool for_writing=true)
Shuts the socket for writing (or reading).
AcceptPair accept()
Accepts an incoming connection, returning a new()ed socket and the peer address.
Overload discriminator class for GNet::Socket.
socklen_t n() const
Returns the length.
virtual ssize_type write(const char *buffer, size_type len)
Override from Socket::write().
virtual void dropWrite(Descriptor fd)=0
Removes the given event source descriptor from the list of write sources.
std::string displayString() const
Returns a string which represents the transport address for debugging and diagnostics purposes...
static EventLoop & instance()
Returns a reference to an instance of the class, if any.
ssize_type readfrom(char *buffer, size_type len, Address &src)
Reads a datagram and returns the sender's address by reference.
std::string asString() const
Returns the socket handle as a string.
static ssize_t recv(int, void *, size_t, int, int *fd_received_p=nullptr)
A recv() replacement using recvmsg().