E-MailRelay
gsocket.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gsocket.cpp
19///
20
21#include "gdef.h"
22#include "gsocket.h"
23#include "gtest.h"
24#include "gsleep.h"
25#include "glimits.h"
26#include "gmsg.h"
27#include "gstr.h"
28#include "gassert.h"
29#include "glog.h"
30
31GNet::SocketBase::SocketBase( Address::Family family , int type , int protocol ) :
32 m_reason(0) ,
33 m_domain(Address::domain(family)) ,
34 m_family(family) ,
35 m_read_added(false) ,
36 m_write_added(false) ,
37 m_other_added(false) ,
38 m_accepted(false)
39{
40 if( !create(m_domain,type,protocol) )
41 throw SocketCreateError( "cannot create socket" , reason() ) ;
42
43 if( !prepare(false) )
44 {
45 destroy() ;
46 throw SocketError( "cannot prepare socket" , reason() ) ;
47 }
48}
49
50GNet::SocketBase::SocketBase( const SocketBase::Raw & , int domain , int type , int protocol ) :
51 m_reason(0) ,
52 m_domain(domain) ,
53 m_family(Address::Family::local) ,
54 m_read_added(false) ,
55 m_write_added(false) ,
56 m_other_added(false) ,
57 m_accepted(false)
58{
59 G_ASSERT( !Address::supports( Address::Domain() , domain ) ) ;
60
61 if( !create(domain,type,protocol) )
62 throw SocketCreateError( "cannot create socket" , reason() ) ;
63
64 if( !prepare(false) )
65 {
66 destroy() ;
67 throw SocketError( "cannot prepare socket" , reason() ) ;
68 }
69}
70
71GNet::SocketBase::SocketBase( Address::Family family , Descriptor fd ) :
72 m_reason(0) ,
73 m_domain(Address::domain(family)) ,
74 m_family(family) ,
75 m_fd(fd) ,
76 m_read_added(false) ,
77 m_write_added(false) ,
78 m_other_added(false) ,
79 m_accepted(false)
80{
81 if( !prepare(false) )
82 {
83 destroy() ;
84 throw SocketError( "cannot prepare socket" , reason() ) ;
85 }
86}
87
88GNet::SocketBase::SocketBase( Address::Family family , Descriptor fd , const Accepted & ) :
89 m_reason(0) ,
90 m_domain(Address::domain(family)) ,
91 m_family(family) ,
92 m_fd(fd) ,
93 m_read_added(false) ,
94 m_write_added(false) ,
95 m_other_added(false) ,
96 m_accepted(true)
97{
98 if( !prepare(true) )
99 {
100 destroy() ;
101 throw SocketError( "cannot prepare socket" , reason() ) ;
102 }
103}
104
106{
107 drop() ;
108 destroy() ;
109}
110
111bool GNet::SocketBase::isFamily( Address::Family family ) const
112{
113 // note that raw sockets to not have a family supported by
114 // GNet::Address and their m_address field is bogus
115 return Address::supports(Address::Domain(),m_domain) && family == m_family ;
116}
117
118void GNet::SocketBase::drop() noexcept
119{
120 static_assert( noexcept(dropReadHandler()) , "" ) ;
121 dropReadHandler() ;
122 dropWriteHandler() ;
123 dropOtherHandler() ;
124}
125
127{
128 m_reason = 0 ;
129}
130
132{
133 const_cast<GNet::SocketBase*>(this)->saveReason() ;
134}
135
136GNet::SocketBase::ssize_type GNet::SocketBase::writeImp( const char * buffer , size_type length )
137{
138 if( static_cast<ssize_type>(length) < 0 )
139 G_WARNING( "GNet::SocketBase::writeImp: too big" ) ; // should get EMSGSIZE from ::send()
140
141 ssize_type nsent = G::Msg::send( m_fd.fd() , buffer , length , MSG_NOSIGNAL ) ;
142 if( sizeError(nsent) ) // if -1
143 {
144 saveReason() ;
145 G_DEBUG( "GNet::SocketBase::writeImp: write error: " << reason() ) ;
146 return -1 ;
147 }
148 else if( nsent < 0 || static_cast<size_type>(nsent) < length )
149 {
150 saveReason() ;
151 }
152 return nsent;
153}
154
156{
157 G_DEBUG( "GNet::SocketBase::addReadHandler: fd " << m_fd ) ;
158 if( !m_read_added )
159 EventLoop::instance().addRead( m_fd , handler , es ) ;
160 m_read_added = true ;
161}
162
164{
165 G_DEBUG( "GNet::SocketBase::addWriteHandler: fd " << m_fd ) ;
166 if( !m_write_added )
167 EventLoop::instance().addWrite( m_fd , handler , es ) ;
168 m_write_added = true ;
169}
170
172{
173 G_DEBUG( "GNet::SocketBase::addOtherHandler: fd " << m_fd ) ;
174 if( !m_other_added )
175 EventLoop::instance().addOther( m_fd , handler , es ) ;
176 m_other_added = true ;
177}
178
180{
181 if( m_read_added && EventLoop::ptr() )
182 EventLoop::ptr()->dropRead( m_fd ) ;
183 m_read_added = false ;
184}
185
187{
188 if( m_write_added && EventLoop::ptr() )
189 EventLoop::ptr()->dropWrite( m_fd ) ;
190 m_write_added = false ;
191}
192
194{
195 if( m_other_added && EventLoop::ptr() )
196 EventLoop::ptr()->dropOther( m_fd ) ;
197 m_other_added = false ;
198}
199
200SOCKET GNet::SocketBase::fd() const noexcept
201{
202 return m_fd.fd() ;
203}
204
205#ifndef G_LIB_SMALL
207{
208 return m_fd ;
209}
210#endif
211
212std::string GNet::SocketBase::reason() const
213{
214 if( m_reason == 0 ) return {} ;
215 return reasonString( m_reason ) ;
216}
217
218std::string GNet::SocketBase::asString() const
219{
220 std::ostringstream ss ;
221 ss << m_fd ;
222 return ss.str() ;
223}
224
225// ==
226
227GNet::Socket::Config::Config()
228= default ;
229
230GNet::Socket::Socket( Address::Family af , int type , int protocol , const Config & config ) :
231 SocketBase(af,type,protocol) ,
232 m_config(config)
233{
234}
235
236GNet::Socket::Socket( Address::Family af , Descriptor s , const Accepted & a , const Config & config ) :
237 SocketBase(af,s,a) ,
238 m_config(config)
239{
240}
241
242GNet::Socket::Socket( Address::Family af , Descriptor s , const Adopted & , const Config & config ) :
243 SocketBase(af,s) ,
244 m_config(config)
245{
246}
247
248void GNet::Socket::bind( const Address & local_address )
249{
250 G_DEBUG( "Socket::bind: binding " << local_address.displayString() << " on fd " << fd() ) ;
251
252 if( !isFamily( local_address.family() ) )
253 throw SocketBindError( "address family does not match the socket domain" ) ;
254
255 setOptionsOnBind( local_address.family() ) ;
256
257 int rc = ::bind( fd() , local_address.address() , local_address.length() ) ;
258 if( error(rc) )
259 {
260 saveReason() ;
261 throw SocketBindError( local_address , reason() , eInUse() ) ;
262 }
263 m_bound_scope_id = local_address.scopeId() ;
264}
265
266bool GNet::Socket::bind( const Address & local_address , std::nothrow_t )
267{
268 G_DEBUG( "Socket::bind: binding " << local_address.displayString() << " on fd " << fd() ) ;
269 if( !isFamily( local_address.family() ) )
270 return false ;
271
272 setOptionsOnBind( local_address.family() ) ;
273
274 int rc = ::bind( fd() , local_address.address() , local_address.length() ) ;
275 if( error(rc) )
276 {
277 saveReason() ;
278 return false ;
279 }
280 m_bound_scope_id = local_address.scopeId() ;
281 return true ;
282}
283
284unsigned long GNet::Socket::getBoundScopeId() const
285{
286 return m_bound_scope_id ;
287}
288
289bool GNet::Socket::connect( const Address & address , bool * done )
290{
291 G_DEBUG( "GNet::Socket::connect: connecting to " << address.displayString() ) ;
292 if( !isFamily( address.family() ) )
293 {
294 G_WARNING( "GNet::Socket::connect: cannot connect: address family does not match the socket domain" ) ;
295 return false ;
296 }
297
298 setOptionsOnConnect( address.family() ) ;
299
300 int rc = ::connect( fd() , address.address() , address.length() ) ;
301 if( error(rc) )
302 {
303 saveReason() ;
304
305 if( eInProgress() )
306 {
307 G_DEBUG( "GNet::Socket::connect: connection in progress" ) ;
308 if( done != nullptr ) *done = false ;
309 return true ;
310 }
311
312 G_DEBUG( "GNet::Socket::connect: synchronous connect failure: " << reason() ) ;
313 return false;
314 }
315
316 if( done != nullptr ) *done = true ;
317 return true ;
318}
319
321{
322 int listen_queue = m_config.listen_queue ;
323 if( listen_queue <= 0 )
324 listen_queue = G::Limits<>::net_listen_queue ;
325
326 int rc = ::listen( fd() , std::max(1,listen_queue) ) ; // see also SOMAXCONN
327 if( error(rc) )
328 {
329 saveReason() ;
330 throw SocketError( "cannot listen on socket" , reason() ) ;
331 }
332}
333
335{
336 AddressStorage address_storage ;
337 int rc = ::getsockname( fd.fd() , address_storage.p1() , address_storage.p2() ) ;
338 if( error(rc) )
339 throw SocketError( std::string("no bound address on fd ").append(std::to_string(fd.fd())) ) ;
340 return Address( address_storage ) ;
341}
342
344{
345 AddressStorage address_storage ;
346 int rc = ::getsockname( fd() , address_storage.p1() , address_storage.p2() ) ;
347 if( error(rc) )
348 {
349 saveReason() ;
350 throw SocketError( "getsockname" , reason() ) ;
351 }
352 return Address( address_storage ) ;
353}
354
355std::pair<bool,GNet::Address> GNet::Socket::getPeerAddress() const
356{
357 AddressStorage address_storage ;
358 int rc = ::getpeername( fd() , address_storage.p1() , address_storage.p2() ) ;
359 if( error(rc) )
360 {
361 saveReason() ;
362 if( eNotConn() )
363 return { false , Address::defaultAddress() } ;
364 throw SocketError( "getpeername" , reason() ) ;
365 }
366 return { true , Address(address_storage) } ;
367}
368
370{
371 if( G::Test::enabled("socket-no-shutdown") ) return ;
372 ::shutdown( fd() , how ) ;
373}
374
375void GNet::Socket::setOptionsOnConnect( Address::Family af )
376{
377 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
378 {
379 if( af == Address::Family::ipv6 && m_config.connect_pureipv6 )
380 setOptionPureV6( std::nothrow ) ; // ignore errors - may fail if already bound
381 }
382}
383
384void GNet::Socket::setOptionsOnBind( Address::Family af )
385{
386 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
387 {
388 if( m_config.bind_reuse )
389 setOptionReuse() ;
390 if( m_config.bind_exclusive )
391 setOptionExclusive() ;
392 if( m_config.free_bind )
393 setOptionFreeBind() ;
394 if( af == Address::Family::ipv6 && m_config.bind_pureipv6 )
395 setOptionPureV6() ;
396 }
397}
398
399void GNet::Socket::setOptionKeepAlive()
400{
401 setOption( SOL_SOCKET , "so_keepalive" , SO_KEEPALIVE , 1 ) ;
402}
403
404void GNet::Socket::setOptionFreeBind()
405{
406 // not tested -- can also use /proc
407 //setOption( IPPROTO_IP , "so_freebind" , IP_FREEBIND , 1 ) ;
408}
409
410void GNet::Socket::setOptionLinger( int onoff , int time )
411{
412 struct linger linger_config {} ;
413 linger_config.l_onoff = static_cast<decltype(linger::l_onoff)>(onoff) ;
414 linger_config.l_linger = static_cast<decltype(linger::l_linger)>(time) ;
415 bool ok = setOptionImp( SOL_SOCKET , SO_LINGER , &linger_config , sizeof(linger_config) ) ;
416 if( !ok )
417 {
418 saveReason() ;
419 throw SocketError( "cannot set socket linger option" , reason() ) ;
420 }
421}
422
423bool GNet::Socket::setOption( int level , const char * , int op , int arg , std::nothrow_t )
424{
425 const void * const vp = static_cast<const void*>(&arg) ;
426 bool ok = setOptionImp( level , op , vp , sizeof(int) ) ;
427 if( !ok )
428 saveReason() ;
429 return ok ;
430}
431
432void GNet::Socket::setOption( int level , const char * opp , int op , int arg )
433{
434 if( !setOption( level , opp , op , arg , std::nothrow ) )
435 throw SocketError( opp , reason() ) ;
436}
437
438//==
439
440GNet::StreamSocket::Config::Config()
441= default ;
442
443GNet::StreamSocket::Config::Config( const Socket::Config & base ) :
444 Socket::Config(base)
445{
446}
447
448bool GNet::StreamSocket::supports( Address::Family af )
449{
450 if( af == Address::Family::ipv6 )
451 {
452 static bool first = true ;
453 static bool result = false ;
454 if( first )
455 {
456 first = false ;
457 if( !Address::supports(af) )
458 G_WARNING( "GNet::StreamSocket::supports: no ipv6 support built-in" ) ;
459 else if( !SocketBase::supports(af,SOCK_STREAM,0) )
460 G_WARNING( "GNet::StreamSocket::supports: no ipv6 support detected" ) ;
461 else
462 result = true ;
463 }
464 return result ;
465 }
466 else if( af == Address::Family::local )
467 {
468 return Address::supports( af ) ;
469 }
470 else
471 {
472 return true ; // ipv4 always supported
473 }
474}
475
476GNet::StreamSocket::StreamSocket( Address::Family af , const Config & config ) :
477 Socket(af,SOCK_STREAM,0,config) ,
478 m_config(config)
479{
480 setOptionsOnCreate( af , /*listener=*/false ) ;
481}
482
483GNet::StreamSocket::StreamSocket( Address::Family af , const Listener & , const Config & config ) :
484 Socket(af,SOCK_STREAM,0,config) ,
485 m_config(config)
486{
487 setOptionsOnCreate( af , /*listener=*/true ) ;
488}
489
491 Socket(family(fd),fd,Socket::Adopted(),config) ,
492 m_config(config)
493{
494}
495
496GNet::StreamSocket::StreamSocket( Address::Family af , Descriptor fd , const Accepted & accepted , const Config & config ) :
497 Socket(af,fd,accepted,config) ,
498 m_config(config)
499{
500 setOptionsOnAccept( af ) ;
501}
502
503GNet::Address::Family GNet::StreamSocket::family( Descriptor fd )
504{
505 return getLocalAddress(fd).family() ;
506}
507
508GNet::Socket::ssize_type GNet::StreamSocket::read( char * buffer , size_type length )
509{
510 if( length == 0 ) return 0 ;
511 clearReason() ;
512 ssize_type nread = G::Msg::recv( fd() , buffer , length , 0 ) ;
513 if( sizeError(nread) )
514 {
515 saveReason() ;
516 G_DEBUG( "GNet::StreamSocket::read: cannot read from " << fd() ) ;
517 return -1 ;
518 }
519 return nread ;
520}
521
522GNet::Socket::ssize_type GNet::StreamSocket::write( const char * buffer , size_type length )
523{
524 return writeImp( buffer , length ) ; // SocketBase
525}
526
528{
529 AddressStorage addr ;
530 Descriptor new_fd( ::accept(fd(),addr.p1(),addr.p2()) ) ;
531 if( !new_fd.validfd() )
532 {
533 saveReason() ;
534 if( eTooMany() )
535 throw SocketTooMany( "cannot accept on listening socket" , reason() ) ;
536 else
537 throw SocketError( "cannot accept on listening socket" , reason() ) ;
538 }
539
540 if( G::Test::enabled("socket-accept-throws") )
541 throw SocketError( "testing" ) ;
542
543 AcceptInfo info ;
544 info.address = Address( addr ) ;
545 info.socket_ptr.reset( new StreamSocket( info.address.family() , new_fd , SocketBase::Accepted() , m_config ) ) ; // 'new' sic
546
547 G_DEBUG( "GNet::StreamSocket::accept: accepted from " << fd()
548 << " to " << new_fd << " (" << info.address.displayString() << ")" ) ;
549
550 return info ;
551}
552
553void GNet::StreamSocket::setOptionsOnCreate( Address::Family af , bool /*listener*/ )
554{
555 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
556 {
557 if( m_config.create_linger_onoff == 1 )
558 setOptionLinger( 1 , m_config.create_linger_time ) ;
559 else if( m_config.create_linger_onoff == 0 )
560 setOptionLinger( 0 , 0 ) ;
561 if( m_config.create_keepalive )
562 setOptionKeepAlive() ;
563 }
564}
565
566void GNet::StreamSocket::setOptionsOnAccept( Address::Family af )
567{
568 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
569 {
570 if( m_config.accept_linger_onoff == 1 )
571 setOptionLinger( 1 , m_config.accept_linger_time ) ;
572 else if( m_config.accept_linger_onoff == 0 )
573 setOptionLinger( 0 , 0 ) ;
574 if( m_config.accept_keepalive )
575 setOptionKeepAlive() ;
576 }
577}
578
579//==
580
581GNet::DatagramSocket::Config::Config()
582= default ;
583
584GNet::DatagramSocket::Config::Config( const Socket::Config & base ) :
585 Socket::Config(base)
586{
587}
588
589GNet::DatagramSocket::DatagramSocket( Address::Family af , int protocol , const Config & config ) :
590 Socket(af,SOCK_DGRAM,protocol,config)
591{
592}
593
594#ifndef G_LIB_SMALL
596{
597 int rc = ::connect( fd() , nullptr , 0 ) ;
598 if( error(rc) )
599 saveReason() ;
600}
601#endif
602
603GNet::Socket::ssize_type GNet::DatagramSocket::read( char * buffer , size_type length )
604{
605 if( length == 0 ) return 0 ;
606 sockaddr sender {} ; // not used
607 socklen_t sender_len = sizeof(sender) ;
608 ssize_type nread = G::Msg::recvfrom( fd() , buffer , length , 0 , &sender , &sender_len ) ;
609 if( sizeError(nread) )
610 {
611 saveReason() ;
612 return -1 ;
613 }
614 return nread ;
615}
616
617GNet::Socket::ssize_type GNet::DatagramSocket::readfrom( char * buffer , size_type length , Address & src_address )
618{
619 if( length == 0 ) return 0 ;
620 sockaddr sender {} ;
621 socklen_t sender_len = sizeof(sender) ;
622 ssize_type nread = G::Msg::recvfrom( fd() , buffer , length , 0 , &sender , &sender_len ) ;
623 if( sizeError(nread) )
624 {
625 saveReason() ;
626 return -1 ;
627 }
628 src_address = Address( &sender , sender_len ) ;
629 return nread ;
630}
631
632GNet::Socket::ssize_type GNet::DatagramSocket::writeto( const char * buffer , size_type length , const Address & dst )
633{
634 ssize_type nsent = G::Msg::sendto( fd() , buffer , length , MSG_NOSIGNAL , dst.address() , dst.length() ) ;
635 if( nsent < 0 )
636 {
637 saveReason() ;
638 G_DEBUG( "GNet::DatagramSocket::write: write error: " << reason() ) ;
639 return -1 ;
640 }
641 return nsent ;
642}
643
644GNet::Socket::ssize_type GNet::DatagramSocket::write( const char * buffer , size_type length )
645{
646 return writeImp( buffer , length ) ; // SocketBase
647}
648
A move-only class which is used to return a new()ed socket to calling code, together with associated ...
Definition: gsocket.h:345
A helper class for calling accept(), getsockname() and getpeername() and hiding the definition of soc...
Definition: gaddress.h:310
sockaddr * p1()
Returns the sockaddr pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress.cpp:530
socklen_t * p2()
Returns the length pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress.cpp:535
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:63
socklen_t length() const
Returns the size of the sockaddr address. See address().
Definition: gaddress.cpp:426
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Definition: gaddress.cpp:203
static bool supports(Family) noexcept
Returns true if the implementation supports the given address family.
Definition: gaddress.cpp:33
std::string displayString(bool with_scope_id=false) const
Returns a printable string that represents the transport address.
Definition: gaddress.cpp:356
const sockaddr * address() const
Returns the sockaddr address.
Definition: gaddress.cpp:417
unsigned long scopeId(unsigned long default_=0UL) const
Returns the scope-id.
Definition: gaddress.cpp:444
Family family() const noexcept
Returns the address family enumeration.
Definition: gaddress.cpp:474
ssize_type writeto(const char *buffer, size_type len, const Address &dst)
Sends a datagram to the given address.
Definition: gsocket.cpp:632
ssize_type write(const char *buffer, size_type len) override
Override from Socket::write().
Definition: gsocket.cpp:644
ssize_type read(char *buffer, size_type len) override
Override from ReadWrite::read().
Definition: gsocket.cpp:603
void disconnect()
Releases the association between two datagram endpoints reversing the effect of the previous Socket::...
Definition: gsocket.cpp:595
DatagramSocket(Address::Family, int protocol, const Config &config)
Constructor.
Definition: gsocket.cpp:589
ssize_type readfrom(char *buffer, size_type len, Address &src)
Reads a datagram and returns the sender's address by reference.
Definition: gsocket.cpp:617
A class that encapsulates a network socket file descriptor and an associated windows event handle.
Definition: gdescriptor.h:37
bool validfd() const noexcept
Returns true if the socket part is valid, ignoring the handle.
A base class for classes that have a file descriptor and handle asynchronous events from the event lo...
Definition: geventhandler.h:48
virtual void dropWrite(Descriptor fd) noexcept=0
Removes the given event descriptor from the list of write sources.
virtual void dropRead(Descriptor fd) noexcept=0
Removes the given event descriptor from the list of read sources.
static EventLoop * ptr() noexcept
Returns a pointer to an instance of the class, if any.
Definition: geventloop.cpp:40
virtual void addWrite(Descriptor fd, EventHandler &, EventState)=0
Adds the given event source descriptor and associated handler to the write list.
static EventLoop & instance()
Returns a reference to an instance of the class, if any.
Definition: geventloop.cpp:45
virtual void dropOther(Descriptor fd) noexcept=0
Removes the given event descriptor from the list of other-event sources.
virtual void addRead(Descriptor fd, EventHandler &, EventState)=0
Adds the given event source descriptor and associated handler to the read list.
virtual void addOther(Descriptor fd, EventHandler &, EventState)=0
Adds the given event source descriptor and associated handler to the exception list.
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
A socket base class that holds a non-blocking socket file descriptor and interfaces to the event loop...
Definition: gsocket.h:53
~SocketBase() override
Destructor.
Definition: gsocket.cpp:105
std::string reason() const
Returns the reason for the previous error.
Definition: gsocket.cpp:212
void addOtherHandler(EventHandler &, EventState)
Adds this socket to the event source list so that the given handler receives exception events.
Definition: gsocket.cpp:171
SOCKET fd() const noexcept override
Returns the socket file descriptor.
Definition: gsocket.cpp:200
void clearReason()
Clears the saved errno.
Definition: gsocket.cpp:126
std::string asString() const
Returns the socket handle as a string.
Definition: gsocket.cpp:218
void dropReadHandler() noexcept
Reverses addReadHandler().
Definition: gsocket.cpp:179
void addWriteHandler(EventHandler &, EventState)
Adds this socket to the event source list so that the given handler receives write events when flow c...
Definition: gsocket.cpp:163
SocketBase(Address::Family, int type, int protocol)
Constructor used by derived classes.
Definition: gsocket.cpp:31
void addReadHandler(EventHandler &, EventState)
Adds this socket to the event source list so that the given handler receives read events.
Definition: gsocket.cpp:155
bool isFamily(Address::Family) const
Returns true if the socket family is as given.
Definition: gsocket.cpp:111
Descriptor fdd() const noexcept
Returns the socket descriptor.
Definition: gsocket.cpp:206
static bool supports(Address::Family, int type, int protocol)
Returns true if sockets can be created with the given parameters.
void dropOtherHandler() noexcept
Reverses addOtherHandler().
Definition: gsocket.cpp:193
void dropWriteHandler() noexcept
Reverses addWriteHandler().
Definition: gsocket.cpp:186
void saveReason()
Saves the current errno following error()/sizeError().
An internet-protocol socket class.
Definition: gsocket.h:227
bool connect(const Address &addr, bool *done=nullptr)
Initiates a connection to (or association with) the given address.
Definition: gsocket.cpp:289
void shutdown(int how=1)
Modifies the local socket state so that new sends (1 or 2) and/or receives (0 or 2) will fail.
Definition: gsocket.cpp:369
void bind(const Address &)
Binds the socket with the given address.
Definition: gsocket.cpp:248
unsigned long getBoundScopeId() const
Returns the scope-id of the address last successfully bind()ed.
Definition: gsocket.cpp:284
std::pair< bool, Address > getPeerAddress() const
Retrieves address of socket's peer.
Definition: gsocket.cpp:355
void listen()
Starts the socket listening on the bound address for incoming connections or incoming datagrams.
Definition: gsocket.cpp:320
Address getLocalAddress() const
Retrieves the local address of the socket.
Definition: gsocket.cpp:343
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:356
AcceptInfo accept()
Accepts an incoming connection, returning a new()ed socket and the peer address.
Definition: gsocket.cpp:527
ssize_type write(const char *buf, size_type len) override
Override from Socket::write().
Definition: gsocket.cpp:522
StreamSocket(Address::Family, const Config &config)
Constructor.
Definition: gsocket.cpp:476
ssize_type read(char *buffer, size_type buffer_length) override
Override from ReadWrite::read().
Definition: gsocket.cpp:508
static bool supports(Address::Family)
Returns true if stream sockets can be created with the given the address family.
Definition: gsocket.cpp:448
static ssize_t recv(SOCKET, void *, std::size_t, int flags) noexcept
A recv() wrapper.
Definition: gmsg_mac.cpp:39
static ssize_t send(SOCKET, const void *, std::size_t, int flags) noexcept
A send() wrapper.
Definition: gmsg_mac.cpp:27
static ssize_t sendto(SOCKET, const void *, std::size_t, int flags, const sockaddr *, socklen_t) noexcept
A sendto() wrapper.
Definition: gmsg_mac.cpp:32
static ssize_t recvfrom(SOCKET, void *, std::size_t, int, sockaddr *, socklen_t *) noexcept
A recvfrom() wrapper.
Definition: gmsg_mac.cpp:44
static bool enabled() noexcept
Returns true if test features are enabled.
Definition: gtest.cpp:79
Overload discriminator for Address::supports()
Definition: gaddress.h:72
A configuration structure for GNet::DatagramSocket.
Definition: gsocket.h:433
Overload discriminator class for GNet::SocketBase.
Definition: gsocket.h:70
Overload discriminator class for GNet::SocketBase.
Definition: gsocket.h:72
Exception class for GNet::SocketBase bind failures.
Definition: gsocket.h:60
Overload discriminator class for GNet::Socket.
Definition: gsocket.h:230
A configuration structure for GNet::StreamSocket.
Definition: gsocket.h:363
Overload discriminator class for GNet::StreamSocket.
Definition: gsocket.h:361
A set of compile-time buffer sizes.
Definition: glimits.h:48