E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gsocket_unix.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 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 // gsocket_unix.cpp
19 //
20
21 #include "gdef.h"
22 #include "gsocket.h"
23 #include "gprocess.h"
24 #include "gdebug.h"
25 #include "gstr.h"
26 #include "gcleanup.h"
27 #include "gassert.h"
28 #include "glog.h"
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33
34 bool GNet::Socket::create( int domain , int type , int protocol )
35 {
36 m_socket = Descriptor( ::socket(domain,type,protocol) ) ;
37 if( m_socket == Descriptor::invalid() )
38 {
39 saveReason() ;
40 return false ;
41 }
42 return true ;
43 }
44
45 bool GNet::Socket::prepare( bool accepted )
46 {
47 static bool first = true ;
48 if( first )
49 {
50 first = false ;
51 G::Cleanup::init() ; // ignore SIGPIPE
52 }
53
54 if( !setNonBlock() )
55 {
56 saveReason() ;
57 return false ;
58 }
59 return true ;
60 }
61
62 void GNet::Socket::destroy()
63 {
64 ::close( m_socket.fd() ) ;
65 }
66
67 bool GNet::Socket::error( int rc )
68 {
69 return rc < 0 ;
70 }
71
72 void GNet::Socket::saveReason()
73 {
74 m_reason = errno ;
75 m_reason_string = reasonString( m_reason ) ;
76 }
77
78 bool GNet::Socket::setNonBlock()
79 {
80 int mode = ::fcntl( m_socket.fd() , F_GETFL ) ;
81 if( mode < 0 )
82 return false ;
83
84 int rc = ::fcntl( m_socket.fd() , F_SETFL , mode | O_NONBLOCK ) ;
85 return rc >= 0 ;
86 }
87
88 bool GNet::Socket::sizeError( ssize_t size )
89 {
90 return size < 0 ;
91 }
92
93 bool GNet::Socket::eWouldBlock()
94 {
95 return m_reason == EWOULDBLOCK || m_reason == EAGAIN || m_reason == EINTR ;
96 }
97
98 bool GNet::Socket::eInProgress()
99 {
100 return m_reason == EINPROGRESS ;
101 }
102
103 bool GNet::Socket::eMsgSize()
104 {
105 return m_reason == EMSGSIZE ;
106 }
107
108 bool GNet::Socket::canBindHint( const Address & address )
109 {
110 return bind( address , NoThrow() ) ;
111 }
112
113 void GNet::Socket::setOptionReuse()
114 {
115 setOption( SOL_SOCKET , "so_reuseaddr" , SO_REUSEADDR , 1 ) ; // allow bind on TIME_WAIT address -- see also SO_REUSEPORT
116 }
117
118 void GNet::Socket::setOptionExclusive()
119 {
120 // no-op
121 }
122
123 void GNet::Socket::setOptionPureV6( bool active )
124 {
125 #if GCONFIG_HAVE_IPV6
126 if( active )
127 setOption( IPPROTO_IPV6 , "ipv6_v6only" , IPV6_V6ONLY , 1 ) ;
128 #else
129 if( active )
130 throw SocketError( "cannot set socket option for pure ipv6" ) ;
131 #endif
132 }
133
134 bool GNet::Socket::setOptionPureV6( bool active , NoThrow )
135 {
136 #if GCONFIG_HAVE_IPV6
137 return active ? setOption( IPPROTO_IPV6 , "ipv6_v6only" , IPV6_V6ONLY , 1 , NoThrow() ) : true ;
138 #else
139 return !active ;
140 #endif
141 }
142
143 bool GNet::Socket::setOptionImp( int level , int op , const void * arg , socklen_t n )
144 {
145 int rc = ::setsockopt( m_socket.fd() , level , op , arg , n ) ;
146 return ! error(rc) ;
147 }
148
149 std::string GNet::Socket::reasonString( int e )
150 {
151 return G::Str::lower(G::Process::strerror(e)) ;
152 }
153
154 /// \file gsocket_unix.cpp
GNet::Socket::canBindHint
bool canBindHint(const Address &address)
Returns true if the socket can probably be bound with the given address.
Definition: gsocket_unix.cpp:108
GNet::Descriptor::invalid
static Descriptor invalid()
Returns a descriptor with an invalid socket part and a zero handle.
Definition: gdescriptor.h:108
glog.h
GNet::Address
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:54
gcleanup.h
GNet::Socket::eMsgSize
bool eMsgSize()
Returns true if the previous socket operation failed with the EMSGSIZE error status.
Definition: gsocket_unix.cpp:103
G::Str::lower
static std::string lower(const std::string &s)
Returns a copy of 's' in which all Latin-1 uppercase characters have been replaced by lowercase chara...
Definition: gstr.cpp:599
gstr.h
gassert.h
gprocess.h
GNet::Socket::eInProgress
bool eInProgress()
Returns true if the previous socket operation failed with the EINPROGRESS error status.
Definition: gsocket_unix.cpp:98
gsocket.h
G::Cleanup::init
static void init()
An optional early-initialisation function. May be called more than once.
Definition: gcleanup_unix.cpp:98
GNet::Socket::eWouldBlock
virtual bool eWouldBlock() override
Returns true if the previous socket operation failed because the socket would have blocked...
Definition: gsocket_unix.cpp:93
GNet::Socket::NoThrow
Overload discriminator class for GNet::Socket.
Definition: gsocket.h:56
gdebug.h