]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/ip++.h
2 * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // ip++ - C++ layer for IP socket and address management
29 // HBO = host byte order, NBO = network byte order
31 // Rules for byte ordering: C++ objects store addresses and ports in NBO.
32 // Struct in_addr arguments are in NBO. Integer type arguments are in HBO.
33 // Stick with the conversion methods and you win. Cast around and you lose.
35 // @@@ Which namespace should we be in?
42 #include <sys/types.h>
43 #include <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
52 using namespace UnixPlusPlus
;
56 namespace IPPlusPlus
{
62 // For now, ports are simply a short unsigned integer type, in HBO.
64 typedef UInt16 IPPort
;
68 // An IP host address.
70 class IPAddress
: public in_addr
{
72 IPAddress() { s_addr
= htonl(INADDR_ANY
); }
73 IPAddress(const struct in_addr
&addr
) { s_addr
= addr
.s_addr
; }
74 explicit IPAddress(UInt32 addr
) { s_addr
= htonl(addr
); }
75 IPAddress(const char *s
); // ONLY dotted-quad form - use hosts.h for name resolution
77 operator UInt32 () const { return ntohl(s_addr
); }
78 operator string () const; // "n.n.n.n" (no name resolution)
81 bool operator == (const IPAddress
&other
) const { return s_addr
== other
.s_addr
; }
82 bool operator != (const IPAddress
&other
) const { return s_addr
!= other
.s_addr
; }
83 bool operator < (const IPAddress
&other
) const { return s_addr
< other
.s_addr
; }
85 operator bool () const { return s_addr
!= htonl(INADDR_ANY
); }
86 bool operator ! () const { return s_addr
== htonl(INADDR_ANY
); }
89 static const IPAddress
&any
;
94 // An IP "socket address", i.e. a combined host address and port.
96 class IPSockAddress
: public sockaddr_in
{
99 IPSockAddress(const struct sockaddr_in
&sockaddr
) { *(sockaddr_in
*)this = sockaddr
; }
100 IPSockAddress(const IPAddress
&addr
, IPPort port
);
102 IPAddress
address() const { return sin_addr
; }
103 void address(IPAddress addr
) { sin_addr
= addr
; }
104 IPPort
port() const { return ntohs(sin_port
); }
105 void port(IPPort p
) { sin_port
= htons(p
); }
107 operator string () const; // "n.n.n.n:p" (no name resolution)
109 // automatically convert to struct sockaddr * for use in system calls
110 operator struct sockaddr
* ()
111 { return reinterpret_cast<struct sockaddr
*>(this); }
112 operator const struct sockaddr
* () const
113 { return reinterpret_cast<const struct sockaddr
*>(this); }
116 IPSockAddress
defaults(const IPSockAddress
&defaultAddr
) const;
117 IPSockAddress
defaults(const IPAddress
&defaultAddr
, IPPort defaultPort
= 0) const;
118 IPSockAddress
defaults(IPPort defaultPort
) const;
123 // UNIX Domain Socket addresses, for those who care.
124 // An "UNAddress", such as it were, is simply a string.
126 class UNSockAddress
: public sockaddr_un
{
129 UNSockAddress(const char *path
);
130 UNSockAddress(const std::string
&path
);
133 operator string () const { return path(); }
135 // automatically convert to struct sockaddr * for use in system calls
136 operator struct sockaddr
* ()
137 { return reinterpret_cast<struct sockaddr
*>(this); }
138 operator const struct sockaddr
* () const
139 { return reinterpret_cast<const struct sockaddr
*>(this); }
145 // This inherits all functionality of a FileDesc, so I/O is fun and easy.
146 // Socket is "passive"; it doesn't own any resources and does nothing on destruction.
147 // On the upside, you can assign Sockets freely.
148 // If you want self-managing sockets that clean up after themselves,
149 // use the subclasses below.
151 class Socket
: public FileDesc
{
154 explicit Socket(int domain
, int type
, int protocol
= 0);
155 explicit Socket(int type
);
157 Socket
&operator = (int fd
) { setFd(fd
); return *this; }
159 // basic open (socket system call)
160 void open(int domain
, int type
, int protocol
= 0);
161 void open(int type
) { open(AF_INET
, type
, 0); }
163 // standard socket operations
164 void bind(const IPSockAddress
&addr
); // to this socket address
165 void bind(const IPAddress
&addr
= IPAddress::any
, IPPort port
= 0);
166 void bind(const UNSockAddress
&addr
); // to this UNIX domain socket
167 void listen(int backlog
= 1);
168 void accept(Socket
&s
);
169 void accept(Socket
&s
, IPSockAddress
&peer
);
170 void accept(Socket
&s
, UNSockAddress
&peer
);
171 bool connect(const struct sockaddr
*peer
);
172 bool connect(const IPSockAddress
&peer
);
173 bool connect(const IPAddress
&addr
, IPPort port
);
174 bool connect(const UNSockAddress
&peer
);
175 void connect(const Host
&host
, IPPort port
); // any address of this host
176 void shutdown(int type
);
177 enum { shutdownRead
= 0, shutdownWrite
= 1, shutdownBoth
= 2 };
179 // get endpoint addresses
180 IPSockAddress
localAddress() const;
181 IPSockAddress
peerAddress() const;
184 void setOption(const void *value
, int length
, int name
, int level
= SOL_SOCKET
) const;
185 void getOption(void *value
, socklen_t
&length
, int name
, int level
= SOL_SOCKET
) const;
187 template <class T
> void setOption(const T
&value
, int name
, int level
= SOL_SOCKET
) const
188 { setOption(&value
, sizeof(value
), name
, level
); }
190 template <class T
> T
getOption(int name
, int level
= SOL_SOCKET
) const
192 T value
; socklen_t length
= sizeof(value
);
193 getOption(&value
, length
, name
, level
);
194 assert(length
== sizeof(value
));
198 // some specific useful options
199 int type() const { return getOption
<int>(SO_TYPE
); }
200 int error() const { return getOption
<int>(SO_ERROR
); }
203 #if defined(SOMAXCONN)
204 static const int listenMaxQueue
= SOMAXCONN
;
206 static const int listenMaxQueue
= 5; // the traditional BSD UNIX value
210 void prepare(int fdFlags
, int domain
, int type
, int protocol
= 0);
215 // A TCPClientSocket is a self-connecting TCP socket that connects (actively) to a server.
216 // Since TCP, once established, is symmetric, it can also be used for the server side
217 // of a TCP pipe. You can think of it as the least complex embodiment of a TCP connection.
219 class TCPClientSocket
: public Socket
{
220 NOCOPY(TCPClientSocket
)
222 TCPClientSocket() { }
223 ~TCPClientSocket(); // closes connection
226 void open(int type
, int protocol
= 0) { Socket::open(type
, protocol
); }
231 void open(const IPSockAddress
&peer
, int fdFlags
= 0);
232 void open(const IPAddress
&addr
, IPPort port
, int fdFlags
= 0);
233 void open(const Host
&host
, IPPort port
, int fdFlags
= 0);
235 TCPClientSocket(const IPSockAddress
&peer
, int fdFlags
= 0)
236 { open(peer
, fdFlags
); }
237 TCPClientSocket(const IPAddress
&addr
, IPPort port
, int fdFlags
= 0)
238 { open(addr
, port
, fdFlags
); }
239 TCPClientSocket(const Host
&host
, IPPort port
, int fdFlags
= 0)
240 { open(host
, port
, fdFlags
); }
242 protected: // for serverSocket/clientSocket footsy play
243 void setFd(int fd
) { Socket::setFd(fd
); }
246 TCPClientSocket(int sockfd
);
251 // A TCPServerSocket is a self-initializing listener socket for incoming TCP requests
252 // (usually to a server). Its function operator yields the next incoming connection request
253 // as a TCPClientSocket (see above). For one-shot receivers, the receive() method will
254 // create the client and close the listener atomically (which is sometimes faster).
256 class TCPServerSocket
: public Socket
{
257 NOCOPY(TCPServerSocket
)
259 TCPServerSocket() { }
260 ~TCPServerSocket(); // closes listener; existing connections unaffected
262 void open(const IPSockAddress
&local
, int depth
= 1);
263 void open(IPPort port
= 0, int depth
= 1)
264 { open(IPSockAddress(IPAddress::any
, port
), depth
); }
266 TCPServerSocket(const IPSockAddress
&local
, int depth
= 1) { open(local
, depth
); }
267 TCPServerSocket(IPPort port
, int depth
= 1) { open(port
, depth
); }
269 void operator () (TCPClientSocket
&newClient
); // retrieve next connection
270 void receive(TCPClientSocket
&client
); // accept once, then close listener
274 } // end namespace IPPlusPlus
275 } // end namespace Security
278 #endif //_H_IPPLUSPLUS