E-MailRelay
gsocket.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 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 dropReadHandler() ;
121 dropWriteHandler() ;
122 dropOtherHandler() ;
123}
124
126{
127 m_reason = 0 ;
128}
129
131{
132 const_cast<GNet::SocketBase*>(this)->saveReason() ;
133}
134
135GNet::SocketBase::ssize_type GNet::SocketBase::writeImp( const char * buffer , size_type length )
136{
137 if( static_cast<ssize_type>(length) < 0 )
138 G_WARNING( "GNet::SocketBase::writeImp: too big" ) ; // should get EMSGSIZE from ::send()
139
140 ssize_type nsent = G::Msg::send( m_fd.fd() , buffer , length , MSG_NOSIGNAL ) ;
141 if( sizeError(nsent) ) // if -1
142 {
143 saveReason() ;
144 G_DEBUG( "GNet::SocketBase::writeImp: write error: " << reason() ) ;
145 return -1 ;
146 }
147 else if( nsent < 0 || static_cast<size_type>(nsent) < length )
148 {
149 saveReason() ;
150 }
151 return nsent;
152}
153
155{
156 G_DEBUG( "GNet::SocketBase::addReadHandler: fd " << m_fd ) ;
157 if( !m_read_added )
158 EventLoop::instance().addRead( m_fd , handler , es ) ;
159 m_read_added = true ;
160}
161
163{
164 G_DEBUG( "GNet::SocketBase::addWriteHandler: fd " << m_fd ) ;
165 if( !m_write_added )
166 EventLoop::instance().addWrite( m_fd , handler , es ) ;
167 m_write_added = true ;
168}
169
171{
172 G_DEBUG( "GNet::SocketBase::addOtherHandler: fd " << m_fd ) ;
173 if( !m_other_added )
174 EventLoop::instance().addOther( m_fd , handler , es ) ;
175 m_other_added = true ;
176}
177
179{
180 if( m_read_added && EventLoop::ptr() )
181 EventLoop::ptr()->dropRead( m_fd ) ;
182 m_read_added = false ;
183}
184
186{
187 if( m_write_added && EventLoop::ptr() )
188 EventLoop::ptr()->dropWrite( m_fd ) ;
189 m_write_added = false ;
190}
191
193{
194 if( m_other_added && EventLoop::ptr() )
195 EventLoop::ptr()->dropOther( m_fd ) ;
196 m_other_added = false ;
197}
198
199SOCKET GNet::SocketBase::fd() const noexcept
200{
201 return m_fd.fd() ;
202}
203
204std::string GNet::SocketBase::reason() const
205{
206 if( m_reason == 0 ) return {} ;
207 return reasonString( m_reason ) ;
208}
209
210std::string GNet::SocketBase::asString() const
211{
212 std::ostringstream ss ;
213 ss << m_fd ;
214 return ss.str() ;
215}
216
217// ==
218
219GNet::Socket::Config::Config()
220= default ;
221
222GNet::Socket::Socket( Address::Family af , int type , int protocol , const Config & config ) :
223 SocketBase(af,type,protocol) ,
224 m_config(config)
225{
226}
227
228GNet::Socket::Socket( Address::Family af , Descriptor s , const Accepted & a , const Config & config ) :
229 SocketBase(af,s,a) ,
230 m_config(config)
231{
232}
233
234GNet::Socket::Socket( Address::Family af , Descriptor s , const Adopted & , const Config & config ) :
235 SocketBase(af,s) ,
236 m_config(config)
237{
238}
239
240void GNet::Socket::bind( const Address & local_address )
241{
242 G_DEBUG( "Socket::bind: binding " << local_address.displayString() << " on fd " << fd() ) ;
243
244 if( !isFamily( local_address.family() ) )
245 throw SocketBindError( "address family does not match the socket domain" ) ;
246
247 setOptionsOnBind( local_address.family() ) ;
248
249 int rc = ::bind( fd() , local_address.address() , local_address.length() ) ;
250 if( error(rc) )
251 {
252 saveReason() ;
253 throw SocketBindError( local_address.displayString() , reason() ) ;
254 }
255 m_bound_scope_id = local_address.scopeId() ;
256}
257
258bool GNet::Socket::bind( const Address & local_address , std::nothrow_t )
259{
260 G_DEBUG( "Socket::bind: binding " << local_address.displayString() << " on fd " << fd() ) ;
261 if( !isFamily( local_address.family() ) )
262 return false ;
263
264 setOptionsOnBind( local_address.family() ) ;
265
266 int rc = ::bind( fd() , local_address.address() , local_address.length() ) ;
267 if( error(rc) )
268 {
269 saveReason() ;
270 return false ;
271 }
272 m_bound_scope_id = local_address.scopeId() ;
273 return true ;
274}
275
276unsigned long GNet::Socket::getBoundScopeId() const
277{
278 return m_bound_scope_id ;
279}
280
281bool GNet::Socket::connect( const Address & address , bool * done )
282{
283 G_DEBUG( "GNet::Socket::connect: connecting to " << address.displayString() ) ;
284 if( !isFamily( address.family() ) )
285 {
286 G_WARNING( "GNet::Socket::connect: cannot connect: address family does not match the socket domain" ) ;
287 return false ;
288 }
289
290 setOptionsOnConnect( address.family() ) ;
291
292 int rc = ::connect( fd() , address.address() , address.length() ) ;
293 if( error(rc) )
294 {
295 saveReason() ;
296
297 if( eInProgress() )
298 {
299 G_DEBUG( "GNet::Socket::connect: connection in progress" ) ;
300 if( done != nullptr ) *done = false ;
301 return true ;
302 }
303
304 G_DEBUG( "GNet::Socket::connect: synchronous connect failure: " << reason() ) ;
305 return false;
306 }
307
308 if( done != nullptr ) *done = true ;
309 return true ;
310}
311
313{
314 int listen_queue = m_config.listen_queue ;
315 if( listen_queue <= 0 )
316 listen_queue = G::Limits<>::net_listen_queue ;
317
318 int rc = ::listen( fd() , std::max(1,listen_queue) ) ; // see also SOMAXCONN
319 if( error(rc) )
320 {
321 saveReason() ;
322 throw SocketError( "cannot listen on socket" , reason() ) ;
323 }
324}
325
327{
328 AddressStorage address_storage ;
329 int rc = ::getsockname( fd.fd() , address_storage.p1() , address_storage.p2() ) ;
330 if( error(rc) )
331 throw SocketError( std::string("no bound address on fd ").append(std::to_string(fd.fd())) ) ;
332 return Address( address_storage ) ;
333}
334
336{
337 AddressStorage address_storage ;
338 int rc = ::getsockname( fd() , address_storage.p1() , address_storage.p2() ) ;
339 if( error(rc) )
340 {
341 saveReason() ;
342 throw SocketError( "getsockname" , reason() ) ;
343 }
344 return Address( address_storage ) ;
345}
346
347std::pair<bool,GNet::Address> GNet::Socket::getPeerAddress() const
348{
349 AddressStorage address_storage ;
350 int rc = ::getpeername( fd() , address_storage.p1() , address_storage.p2() ) ;
351 if( error(rc) )
352 {
353 saveReason() ;
354 if( eNotConn() )
355 return { false , Address::defaultAddress() } ;
356 throw SocketError( "getpeername" , reason() ) ;
357 }
358 return { true , Address(address_storage) } ;
359}
360
362{
363 if( G::Test::enabled("socket-no-shutdown") ) return ;
364 ::shutdown( fd() , how ) ;
365}
366
367void GNet::Socket::setOptionsOnConnect( Address::Family af )
368{
369 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
370 {
371 if( af == Address::Family::ipv6 && m_config.connect_pureipv6 )
372 setOptionPureV6( std::nothrow ) ; // ignore errors - may fail if already bound
373 }
374}
375
376void GNet::Socket::setOptionsOnBind( Address::Family af )
377{
378 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
379 {
380 if( m_config.bind_reuse )
381 setOptionReuse() ;
382 if( m_config.bind_exclusive )
383 setOptionExclusive() ;
384 if( m_config.free_bind )
385 setOptionFreeBind() ;
386 if( af == Address::Family::ipv6 && m_config.bind_pureipv6 )
387 setOptionPureV6() ;
388 }
389}
390
391void GNet::Socket::setOptionKeepAlive()
392{
393 setOption( SOL_SOCKET , "so_keepalive" , SO_KEEPALIVE , 1 ) ;
394}
395
396void GNet::Socket::setOptionFreeBind()
397{
398 // not tested -- can also use /proc
399 //setOption( IPPROTO_IP , "so_freebind" , IP_FREEBIND , 1 ) ;
400}
401
402void GNet::Socket::setOptionLinger( int onoff , int time )
403{
404 struct linger linger_config {} ;
405 linger_config.l_onoff = static_cast<decltype(linger::l_onoff)>(onoff) ;
406 linger_config.l_linger = static_cast<decltype(linger::l_linger)>(time) ;
407 bool ok = setOptionImp( SOL_SOCKET , SO_LINGER , &linger_config , sizeof(linger_config) ) ;
408 if( !ok )
409 {
410 saveReason() ;
411 throw SocketError( "cannot set socket linger option" , reason() ) ;
412 }
413}
414
415bool GNet::Socket::setOption( int level , const char * , int op , int arg , std::nothrow_t )
416{
417 const void * const vp = static_cast<const void*>(&arg) ;
418 bool ok = setOptionImp( level , op , vp , sizeof(int) ) ;
419 if( !ok )
420 saveReason() ;
421 return ok ;
422}
423
424void GNet::Socket::setOption( int level , const char * opp , int op , int arg )
425{
426 if( !setOption( level , opp , op , arg , std::nothrow ) )
427 throw SocketError( opp , reason() ) ;
428}
429
430//==
431
432GNet::StreamSocket::Config::Config()
433= default ;
434
435GNet::StreamSocket::Config::Config( const Socket::Config & base ) :
436 Socket::Config(base)
437{
438}
439
440bool GNet::StreamSocket::supports( Address::Family af )
441{
442 if( af == Address::Family::ipv6 )
443 {
444 static bool first = true ;
445 static bool result = false ;
446 if( first )
447 {
448 first = false ;
449 if( !Address::supports(af) )
450 G_WARNING( "GNet::StreamSocket::supports: no ipv6 support built-in" ) ;
451 else if( !SocketBase::supports(af,SOCK_STREAM,0) )
452 G_WARNING( "GNet::StreamSocket::supports: no ipv6 support detected" ) ;
453 else
454 result = true ;
455 }
456 return result ;
457 }
458 else if( af == Address::Family::local )
459 {
460 return Address::supports( af ) ;
461 }
462 else
463 {
464 return true ; // ipv4 always supported
465 }
466}
467
468GNet::StreamSocket::StreamSocket( Address::Family af , const Config & config ) :
469 Socket(af,SOCK_STREAM,0,config) ,
470 m_config(config)
471{
472 setOptionsOnCreate( af , /*listener=*/false ) ;
473}
474
475GNet::StreamSocket::StreamSocket( Address::Family af , const Listener & , const Config & config ) :
476 Socket(af,SOCK_STREAM,0,config) ,
477 m_config(config)
478{
479 setOptionsOnCreate( af , /*listener=*/true ) ;
480}
481
483 Socket(family(fd),fd,Socket::Adopted(),config) ,
484 m_config(config)
485{
486}
487
488GNet::StreamSocket::StreamSocket( Address::Family af , Descriptor fd , const Accepted & accepted , const Config & config ) :
489 Socket(af,fd,accepted,config) ,
490 m_config(config)
491{
492 setOptionsOnAccept( af ) ;
493}
494
495GNet::Address::Family GNet::StreamSocket::family( Descriptor fd )
496{
497 return getLocalAddress(fd).family() ;
498}
499
500GNet::Socket::ssize_type GNet::StreamSocket::read( char * buffer , size_type length )
501{
502 if( length == 0 ) return 0 ;
503 clearReason() ;
504 ssize_type nread = G::Msg::recv( fd() , buffer , length , 0 ) ;
505 if( sizeError(nread) )
506 {
507 saveReason() ;
508 G_DEBUG( "GNet::StreamSocket::read: cannot read from " << fd() ) ;
509 return -1 ;
510 }
511 return nread ;
512}
513
514GNet::Socket::ssize_type GNet::StreamSocket::write( const char * buffer , size_type length )
515{
516 return writeImp( buffer , length ) ; // SocketBase
517}
518
520{
521 AddressStorage addr ;
522 Descriptor new_fd( ::accept(fd(),addr.p1(),addr.p2()) ) ;
523 if( ! new_fd.valid() )
524 {
525 saveReason() ;
526 if( eTooMany() )
527 throw SocketTooMany( "cannot accept on listening socket" , reason() ) ;
528 else
529 throw SocketError( "cannot accept on listening socket" , reason() ) ;
530 }
531
532 if( G::Test::enabled("socket-accept-throws") )
533 throw SocketError( "testing" ) ;
534
535 AcceptInfo info ;
536 info.address = Address( addr ) ;
537 info.socket_ptr.reset( new StreamSocket( info.address.family() , new_fd , SocketBase::Accepted() , m_config ) ) ; // 'new' sic
538
539 G_DEBUG( "GNet::StreamSocket::accept: accepted from " << fd()
540 << " to " << new_fd << " (" << info.address.displayString() << ")" ) ;
541
542 return info ;
543}
544
545void GNet::StreamSocket::setOptionsOnCreate( Address::Family af , bool /*listener*/ )
546{
547 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
548 {
549 if( m_config.create_linger_onoff == 1 )
550 setOptionLinger( 1 , m_config.create_linger_time ) ;
551 else if( m_config.create_linger_onoff == 0 )
552 setOptionLinger( 0 , 0 ) ;
553 if( m_config.create_keepalive )
554 setOptionKeepAlive() ;
555 }
556}
557
558void GNet::StreamSocket::setOptionsOnAccept( Address::Family af )
559{
560 if( af == Address::Family::ipv4 || af == Address::Family::ipv6 )
561 {
562 if( m_config.accept_linger_onoff == 1 )
563 setOptionLinger( 1 , m_config.accept_linger_time ) ;
564 else if( m_config.accept_linger_onoff == 0 )
565 setOptionLinger( 0 , 0 ) ;
566 if( m_config.accept_keepalive )
567 setOptionKeepAlive() ;
568 }
569}
570
571//==
572
573GNet::DatagramSocket::Config::Config()
574= default ;
575
576GNet::DatagramSocket::Config::Config( const Socket::Config & base ) :
577 Socket::Config(base)
578{
579}
580
581GNet::DatagramSocket::DatagramSocket( Address::Family af , int protocol , const Config & config ) :
582 Socket(af,SOCK_DGRAM,protocol,config)
583{
584}
585
586#ifndef G_LIB_SMALL
588{
589 int rc = ::connect( fd() , nullptr , 0 ) ;
590 if( error(rc) )
591 saveReason() ;
592}
593#endif
594
595GNet::Socket::ssize_type GNet::DatagramSocket::read( char * buffer , size_type length )
596{
597 if( length == 0 ) return 0 ;
598 sockaddr sender {} ; // not used
599 socklen_t sender_len = sizeof(sender) ;
600 ssize_type nread = G::Msg::recvfrom( fd() , buffer , length , 0 , &sender , &sender_len ) ;
601 if( sizeError(nread) )
602 {
603 saveReason() ;
604 return -1 ;
605 }
606 return nread ;
607}
608
609GNet::Socket::ssize_type GNet::DatagramSocket::readfrom( char * buffer , size_type length , Address & src_address )
610{
611 if( length == 0 ) return 0 ;
612 sockaddr sender {} ;
613 socklen_t sender_len = sizeof(sender) ;
614 ssize_type nread = G::Msg::recvfrom( fd() , buffer , length , 0 , &sender , &sender_len ) ;
615 if( sizeError(nread) )
616 {
617 saveReason() ;
618 return -1 ;
619 }
620 src_address = Address( &sender , sender_len ) ;
621 return nread ;
622}
623
624GNet::Socket::ssize_type GNet::DatagramSocket::writeto( const char * buffer , size_type length , const Address & dst )
625{
626 ssize_type nsent = G::Msg::sendto( fd() , buffer , length , MSG_NOSIGNAL , dst.address() , dst.length() ) ;
627 if( nsent < 0 )
628 {
629 saveReason() ;
630 G_DEBUG( "GNet::DatagramSocket::write: write error " << reason() ) ;
631 return -1 ;
632 }
633 return nsent ;
634}
635
636GNet::Socket::ssize_type GNet::DatagramSocket::write( const char * buffer , size_type length )
637{
638 return writeImp( buffer , length ) ; // SocketBase
639}
640
A move-only class which is used to return a new()ed socket to calling code, together with associated ...
Definition: gsocket.h:330
A helper class for calling accept(), getsockname() and getpeername() and hiding the definition of soc...
Definition: gaddress.h:309
sockaddr * p1()
Returns the sockaddr pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress.cpp:532
socklen_t * p2()
Returns the length pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress.cpp:537
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:62
socklen_t length() const
Returns the size of the sockaddr address. See address().
Definition: gaddress.cpp:428
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Definition: gaddress.cpp:205
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:358
const sockaddr * address() const
Returns the sockaddr address.
Definition: gaddress.cpp:419
unsigned long scopeId(unsigned long default_=0UL) const
Returns the scope-id.
Definition: gaddress.cpp:446
Family family() const noexcept
Returns the address family enumeration.
Definition: gaddress.cpp:476
ssize_type writeto(const char *buffer, size_type len, const Address &dst)
Sends a datagram to the given address.
Definition: gsocket.cpp:624
ssize_type write(const char *buffer, size_type len) override
Override from Socket::write().
Definition: gsocket.cpp:636
ssize_type read(char *buffer, size_type len) override
Override from ReadWrite::read().
Definition: gsocket.cpp:595
void disconnect()
Releases the association between two datagram endpoints reversing the effect of the previous Socket::...
Definition: gsocket.cpp:587
DatagramSocket(Address::Family, int protocol, const Config &config)
Constructor.
Definition: gsocket.cpp:581
ssize_type readfrom(char *buffer, size_type len, Address &src)
Reads a datagram and returns the sender's address by reference.
Definition: gsocket.cpp:609
A class that encapsulates a network socket file descriptor and an associated windows event handle.
Definition: gdescriptor.h:37
bool valid() 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 addOther(Descriptor fd, EventHandler &, ExceptionSink)=0
Adds the given event source descriptor and associated handler to the exception list.
virtual void addWrite(Descriptor fd, EventHandler &, ExceptionSink)=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 addRead(Descriptor fd, EventHandler &, ExceptionSink)=0
Adds the given event source descriptor and associated handler to the read list.
virtual void dropOther(Descriptor fd) noexcept=0
Removes the given event descriptor from the list of other-event sources.
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
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:204
SOCKET fd() const noexcept override
Returns the socket file descriptor.
Definition: gsocket.cpp:199
void clearReason()
Clears the saved errno.
Definition: gsocket.cpp:125
std::string asString() const
Returns the socket handle as a string.
Definition: gsocket.cpp:210
void dropReadHandler() noexcept
Reverses addReadHandler().
Definition: gsocket.cpp:178
void addOtherHandler(EventHandler &, ExceptionSink)
Adds this socket to the event source list so that the given handler receives exception events.
Definition: gsocket.cpp:170
SocketBase(Address::Family, int type, int protocol)
Constructor used by derived classes.
Definition: gsocket.cpp:31
bool isFamily(Address::Family) const
Returns true if the socket family is as given.
Definition: gsocket.cpp:111
void addReadHandler(EventHandler &, ExceptionSink)
Adds this socket to the event source list so that the given handler receives read events.
Definition: gsocket.cpp:154
static bool supports(Address::Family, int type, int protocol)
Returns true if sockets can be created with the given parameters.
void addWriteHandler(EventHandler &, ExceptionSink)
Adds this socket to the event source list so that the given handler receives write events when flow c...
Definition: gsocket.cpp:162
void dropOtherHandler() noexcept
Reverses addOtherHandler().
Definition: gsocket.cpp:192
void dropWriteHandler() noexcept
Reverses addWriteHandler().
Definition: gsocket.cpp:185
void saveReason()
Saves the current errno following error()/sizeError().
An internet-protocol socket class.
Definition: gsocket.h:212
bool connect(const Address &addr, bool *done=nullptr)
Initiates a connection to (or association with) the given address.
Definition: gsocket.cpp:281
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:361
void bind(const Address &)
Binds the socket with the given address.
Definition: gsocket.cpp:240
unsigned long getBoundScopeId() const
Returns the scope-id of the address last successfully bind()ed.
Definition: gsocket.cpp:276
std::pair< bool, Address > getPeerAddress() const
Retrieves address of socket's peer.
Definition: gsocket.cpp:347
void listen()
Starts the socket listening on the bound address for incoming connections or incoming datagrams.
Definition: gsocket.cpp:312
Address getLocalAddress() const
Retrieves the local address of the socket.
Definition: gsocket.cpp:335
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:341
AcceptInfo accept()
Accepts an incoming connection, returning a new()ed socket and the peer address.
Definition: gsocket.cpp:519
ssize_type write(const char *buf, size_type len) override
Override from Socket::write().
Definition: gsocket.cpp:514
StreamSocket(Address::Family, const Config &config)
Constructor.
Definition: gsocket.cpp:468
ssize_type read(char *buffer, size_type buffer_length) override
Override from ReadWrite::read().
Definition: gsocket.cpp:500
static bool supports(Address::Family)
Returns true if stream sockets can be created with the given the address family.
Definition: gsocket.cpp:440
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:71
A configuration structure for GNet::DatagramSocket.
Definition: gsocket.h:418
Overload discriminator class for GNet::SocketBase.
Definition: gsocket.h:62
Overload discriminator class for GNet::SocketBase.
Definition: gsocket.h:64
Overload discriminator class for GNet::Socket.
Definition: gsocket.h:215
A configuration structure for GNet::StreamSocket.
Definition: gsocket.h:348
Overload discriminator class for GNet::StreamSocket.
Definition: gsocket.h:346
A set of compile-time buffer sizes.
Definition: glimits.h:48