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 // socks - socks version of IP sockets
22 // This Socks implementation replaces the TCP-functional layer of the socket interface
23 // (TCPClientSocket and TCPServerSocket), not the raw Socket layer. Remember what
24 // Socks was invented for -- it's NOT a generic socket abstraction layer, valiant efforts
25 // of the various -lsocks libraries nonwithstanding.
26 // Do note that these are not virtual overrides, but textual replacements.
28 // This implementation supports Socks versions 4 and 5, as well as direct (un-socksed) sockets.
29 // The choice is per socket object.
32 // SocksServer *server = SocksServer::make(version, IP-address);
33 // SocksServer::defaultServer(server); // for new sockets
34 // SocksClientSocket clientSocket(...);
35 // clientSocket.server(server); // for this socket
36 // SocksServerSocket serverSocket(...); // only supports .receive()
37 // Otherwise, Socks{Client,Server}Socket is functionally equivalent to {Client,Server}Socket.
38 // Sockets without a Server (explicit or by default) are direct.
40 // Minimum replacement strategy:
41 // #define TCPClientSocket SocksClientSocket
42 // #define TCPServerSocket SocksServerSocket
43 // SocksServer::defaultServer(SocksServer::make(...));
46 // There is no UDP Socks support.
47 // @@@ Nonblocking sockets may not work quite right.
49 #ifndef _H_SOCKSPLUSPLUS
50 #define _H_SOCKSPLUSPLUS
53 #include <Security/threading.h>
54 #include <Security/globalizer.h>
57 using namespace UnixPlusPlus
;
61 namespace IPPlusPlus
{
64 class SocksServerSocket
;
65 class SocksClientSocket
;
69 // A particular Socks server and version. Get one by calling SocksServer::make().
70 // You can express "no socks server" (direct connect) with a NULL pointer (or version==0).
73 class Support
; friend class Support
;
77 mutable Mutex lock
; // lock for mGlobalServerAddress
78 SocksServer
*mServer
; // global default server
79 ThreadNexus
<IPAddress
> lastConnected
; // last address connected to (for aux. bind)
81 Global() : mServer(NULL
) { }
83 void server(SocksServer
*srv
) { StLock
<Mutex
> _(lock
); mServer
= srv
; }
84 SocksServer
*server() const { StLock
<Mutex
> _(lock
); return mServer
; }
86 static ModuleNexus
<Global
> global
; // global state
89 typedef unsigned int Version
;
91 static SocksServer
*make(Version version
, const IPSockAddress
&addr
);
93 const IPSockAddress
&address() const { return mServerAddress
; }
94 Version
version() const { return mVersion
; }
97 static SocksServer
*defaultServer() { return global().server(); }
98 static void defaultServer(SocksServer
*server
) { global().server(server
); }
101 virtual void connect(SocksClientSocket
&me
, const IPSockAddress
&peer
) = 0;
102 virtual void connect(SocksClientSocket
&me
, const Host
&host
, IPPort port
) = 0;
103 virtual void bind(SocksServerSocket
&me
, const IPAddress
&peer
, IPPort port
) = 0;
104 virtual void receive(SocksServerSocket
&me
, SocksClientSocket
&receiver
) = 0;
106 SocksServer(Version v
, const IPSockAddress
&addr
) : mVersion(v
), mServerAddress(addr
) { }
110 IPSockAddress mServerAddress
;
115 SocksServer
*server() const { return mServer
; }
116 void server(SocksServer
*srv
) { mServer
= srv
; }
118 IPSockAddress
localAddress(const Socket
&me
) const;
119 IPSockAddress
peerAddress(const Socket
&me
) const;
122 Support() : mServer(defaultServer()) { }
124 void connect(SocksClientSocket
&me
, const IPSockAddress
&peer
)
125 { mServer
->connect(me
, peer
); }
126 void connect(SocksClientSocket
&me
, const Host
&host
, IPPort port
)
127 { mServer
->connect(me
, host
, port
); }
128 void bind(SocksServerSocket
&me
, const IPAddress
&peer
, IPPort port
)
129 { mServer
->bind(me
, peer
, port
); }
130 void receive(SocksServerSocket
&me
, SocksClientSocket
&receiver
)
131 { mServer
->receive(me
, receiver
); }
133 void lastConnected(IPAddress addr
) { global().lastConnected() = addr
; }
134 IPAddress
lastConnected() const { return global().lastConnected(); }
137 SocksServer
*mServer
; // server for this socket
138 IPSockAddress mLocalAddress
; // my own address, as reported by server
139 IPSockAddress mPeerAddress
; // peer address
145 // The Socks version of a TCPClientSocket
147 class SocksClientSocket
: public TCPClientSocket
, public SocksServer::Support
{
149 SocksClientSocket() { }
150 SocksClientSocket(const IPSockAddress
&peer
) { open(peer
); }
151 SocksClientSocket(const IPAddress
&addr
, IPPort port
) { open(addr
, port
); }
152 SocksClientSocket(const Host
&host
, IPPort port
) { open(host
, port
); }
154 void open(const IPSockAddress
&peer
);
155 void open(const IPAddress
&addr
, IPPort port
);
156 void open(const Host
&host
, IPPort port
);
158 IPSockAddress
localAddress() const { return Support::localAddress(*this); }
159 IPSockAddress
peerAddress() const { return Support::peerAddress(*this); }
162 void setFd(int fd
, const IPSockAddress
&local
, const IPSockAddress
&peer
);
167 // The Socks version of a TCPServerSocket.
168 // Note that this version only supports the receive() access method.
169 // By the nature of things, the queue-length argument is ignored (it's always 1).
171 // A note about setMainConnection: There is a structural problem
172 // with the Socks protocol. When a SocksServerSocket goes active,
173 // the protocol requires the IP address of the host the connection will be
174 // coming from. Typical Socks library layers simply assume that this will
175 // be the address of the last server connected to by another (TCP) socket.
176 // We do this heuristic too, but it's unreliable: it's a per-thread global, and will
177 // fail if you interleave multiple socks "sessions" in the same thread. For this
178 // case (or if you just want to be safe and explicit), you can call setMainConnection to
179 // explicitly link this socket to a TCPClientSocket whose peer we should use.
180 // Do note that this call does not exist in the plain (non-socks) socket layer.
182 class SocksServerSocket
: public TCPServerSocket
, public SocksServer::Support
{
184 SocksServerSocket() { }
185 SocksServerSocket(const IPSockAddress
&local
, int = 1) { open(local
); }
186 SocksServerSocket(IPPort port
, int = 1) { open(port
); }
188 void open(const IPSockAddress
&local
, int = 1);
189 void open(IPPort port
= 0, int = 1)
190 { open(IPSockAddress(IPAddress::any
, port
)); }
192 void receive(SocksClientSocket
&client
); // accept incoming and close listener
194 IPSockAddress
localAddress() const { return Support::localAddress(*this); }
195 IPSockAddress
peerAddress() const { return Support::peerAddress(*this); }
197 // this special call is not an overlay of TCPServerSocket - it exists only for Socks
198 void setMainConnection(TCPClientSocket
&main
)
199 { mConnectionPeer
= main
.peerAddress().address(); }
202 IPAddress mConnectionPeer
; // address to say we're peered with
205 void operator () (TCPClientSocket
&newClient
); // not supported by Socks
209 } // end namespace IPPlusPlus
210 } // end namespace Security
213 #endif //_H_IPPLUSPLUS