]>
git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/ip++.h
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // ip++ - C++ layer for IP socket and address management
23 // HBO = host byte order, NBO = network byte order
25 // Rules for byte ordering: C++ objects store addresses and ports in NBO.
26 // Struct in_addr arguments are in NBO. Integer type arguments are in HBO.
27 // Stick with the conversion methods and you win. Cast around and you lose.
29 // @@@ Which namespace should we be in?
36 #include <sys/types.h>
37 #include <sys/ioctl.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
46 using namespace UnixPlusPlus
;
50 namespace IPPlusPlus
{
56 // For now, ports are simply a short unsigned integer type, in HBO.
58 typedef uint16 IPPort
;
62 // An IP host address.
64 class IPAddress
: public in_addr
{
66 IPAddress() { s_addr
= htonl(INADDR_ANY
); }
67 IPAddress(const struct in_addr
&addr
) { s_addr
= addr
.s_addr
; }
68 explicit IPAddress(uint32 addr
) { s_addr
= htonl(addr
); }
69 IPAddress(const char *s
); // ONLY dotted-quad form - use hosts.h for name resolution
71 operator uint32 () const { return ntohl(s_addr
); }
72 operator string () const; // "n.n.n.n" (no name resolution)
75 bool operator == (const IPAddress
&other
) const { return s_addr
== other
.s_addr
; }
76 bool operator != (const IPAddress
&other
) const { return s_addr
!= other
.s_addr
; }
77 bool operator < (const IPAddress
&other
) const { return s_addr
< other
.s_addr
; }
79 operator bool () const { return s_addr
!= htonl(INADDR_ANY
); }
80 bool operator ! () const { return s_addr
== htonl(INADDR_ANY
); }
83 static const IPAddress
&any
;
88 // An IP "socket address", i.e. a combined host address and port.
90 class IPSockAddress
: public sockaddr_in
{
93 IPSockAddress(const struct sockaddr_in
&sockaddr
) { *(sockaddr_in
*)this = sockaddr
; }
94 IPSockAddress(const IPAddress
&addr
, IPPort port
);
96 IPAddress
address() const { return sin_addr
; }
97 void address(IPAddress addr
) { sin_addr
= addr
; }
98 IPPort
port() const { return ntohs(sin_port
); }
99 void port(IPPort p
) { sin_port
= htons(p
); }
101 operator string () const; // "n.n.n.n:p" (no name resolution)
103 // automatically convert to struct sockaddr * for use in system calls
104 operator struct sockaddr
* ()
105 { return reinterpret_cast<struct sockaddr
*>(this); }
106 operator const struct sockaddr
* () const
107 { return reinterpret_cast<const struct sockaddr
*>(this); }
110 IPSockAddress
defaults(const IPSockAddress
&defaultAddr
) const;
111 IPSockAddress
defaults(const IPAddress
&defaultAddr
, IPPort defaultPort
= 0) const;
112 IPSockAddress
defaults(IPPort defaultPort
) const;
117 // UNIX Domain Socket addresses, for those who care.
118 // An "UNAddress", such as it were, is simply a string.
120 class UNSockAddress
: public sockaddr_un
{
123 UNSockAddress(const char *path
);
124 UNSockAddress(const std::string
&path
);
127 operator string () const { return path(); }
129 // automatically convert to struct sockaddr * for use in system calls
130 operator struct sockaddr
* ()
131 { return reinterpret_cast<struct sockaddr
*>(this); }
132 operator const struct sockaddr
* () const
133 { return reinterpret_cast<const struct sockaddr
*>(this); }
139 // This inherits all functionality of a FileDesc, so I/O is fun and easy.
140 // Socket is "passive"; it doesn't own any resources and does nothing on destruction.
141 // On the upside, you can assign Sockets freely.
142 // If you want self-managing sockets that clean up after themselves,
143 // use the subclasses below.
145 class Socket
: public FileDesc
{
148 explicit Socket(int domain
, int type
, int protocol
= 0);
149 explicit Socket(int type
);
151 Socket
&operator = (int fd
) { setFd(fd
); return *this; }
153 // basic open (socket system call)
154 void open(int domain
, int type
, int protocol
= 0);
155 void open(int type
) { open(AF_INET
, type
, 0); }
157 // standard socket operations
158 void bind(const IPSockAddress
&addr
); // to this socket address
159 void bind(const IPAddress
&addr
= IPAddress::any
, IPPort port
= 0);
160 void bind(const UNSockAddress
&addr
); // to this UNIX domain socket
161 void listen(int backlog
= 1);
162 void accept(Socket
&s
);
163 void accept(Socket
&s
, IPSockAddress
&peer
);
164 void accept(Socket
&s
, UNSockAddress
&peer
);
165 bool connect(const struct sockaddr
*peer
);
166 bool connect(const IPSockAddress
&peer
);
167 bool connect(const IPAddress
&addr
, IPPort port
);
168 bool connect(const UNSockAddress
&peer
);
169 void connect(const Host
&host
, IPPort port
); // any address of this host
170 void shutdown(int type
);
171 enum { shutdownRead
= 0, shutdownWrite
= 1, shutdownBoth
= 2 };
173 // get endpoint addresses
174 IPSockAddress
localAddress() const;
175 IPSockAddress
peerAddress() const;
178 void setOption(const void *value
, int length
, int name
, int level
= SOL_SOCKET
) const;
179 void getOption(void *value
, int &length
, int name
, int level
= SOL_SOCKET
) const;
181 template <class T
> void setOption(const T
&value
, int name
, int level
= SOL_SOCKET
) const
182 { setOption(&value
, sizeof(value
), name
, level
); }
184 template <class T
> T
getOption(int name
, int level
= SOL_SOCKET
) const
186 T value
; int length
= sizeof(value
);
187 getOption(&value
, length
, name
, level
);
188 assert(length
== sizeof(value
));
192 // some specific useful options
193 int type() const { return getOption
<int>(SO_TYPE
); }
194 int error() const { return getOption
<int>(SO_ERROR
); }
197 #if defined(SOMAXCONN)
198 static const int listenMaxQueue
= SOMAXCONN
;
200 static const int listenMaxQueue
= 5; // the traditional BSD UNIX value
204 void prepare(int fdFlags
, int domain
, int type
, int protocol
= 0);
209 // A TCPClientSocket is a self-connecting TCP socket that connects (actively) to a server.
210 // Since TCP, once established, is symmetric, it can also be used for the server side
211 // of a TCP pipe. You can think of it as the least complex embodiment of a TCP connection.
213 class TCPClientSocket
: public Socket
{
214 NOCOPY(TCPClientSocket
)
216 TCPClientSocket() { }
217 ~TCPClientSocket(); // closes connection
220 void open(int type
, int protocol
= 0) { Socket::open(type
, protocol
); }
225 void open(const IPSockAddress
&peer
, int fdFlags
= 0);
226 void open(const IPAddress
&addr
, IPPort port
, int fdFlags
= 0);
227 void open(const Host
&host
, IPPort port
, int fdFlags
= 0);
229 TCPClientSocket(const IPSockAddress
&peer
, int fdFlags
= 0)
230 { open(peer
, fdFlags
); }
231 TCPClientSocket(const IPAddress
&addr
, IPPort port
, int fdFlags
= 0)
232 { open(addr
, port
, fdFlags
); }
233 TCPClientSocket(const Host
&host
, IPPort port
, int fdFlags
= 0)
234 { open(host
, port
, fdFlags
); }
236 protected: // for serverSocket/clientSocket footsy play
237 void setFd(int fd
) { Socket::setFd(fd
); }
240 TCPClientSocket(int sockfd
);
245 // A TCPServerSocket is a self-initializing listener socket for incoming TCP requests
246 // (usually to a server). Its function operator yields the next incoming connection request
247 // as a TCPClientSocket (see above). For one-shot receivers, the receive() method will
248 // create the client and close the listener atomically (which is sometimes faster).
250 class TCPServerSocket
: public Socket
{
251 NOCOPY(TCPServerSocket
)
253 TCPServerSocket() { }
254 ~TCPServerSocket(); // closes listener; existing connections unaffected
256 void open(const IPSockAddress
&local
, int depth
= 1);
257 void open(IPPort port
= 0, int depth
= 1)
258 { open(IPSockAddress(IPAddress::any
, port
), depth
); }
260 TCPServerSocket(const IPSockAddress
&local
, int depth
= 1) { open(local
, depth
); }
261 TCPServerSocket(IPPort port
, int depth
= 1) { open(port
, depth
); }
263 void operator () (TCPClientSocket
&newClient
); // retrieve next connection
264 void receive(TCPClientSocket
&client
); // accept once, then close listener
268 } // end namespace IPPlusPlus
269 } // end namespace Security
272 #endif //_H_IPPLUSPLUS