![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright (c) 2009 Christopher A. Taylor. All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without 00005 modification, are permitted provided that the following conditions are met: 00006 00007 * Redistributions of source code must retain the above copyright notice, 00008 this list of conditions and the following disclaimer. 00009 * Redistributions in binary form must reproduce the above copyright notice, 00010 this list of conditions and the following disclaimer in the documentation 00011 and/or other materials provided with the distribution. 00012 * Neither the name of LibCat nor the names of its contributors may be used 00013 to endorse or promote products derived from this software without 00014 specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00019 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00020 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00021 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00022 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00023 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00024 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00025 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00026 POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00029 #ifndef CAT_THREAD_POOL_SOCKETS_HPP 00030 #define CAT_THREAD_POOL_SOCKETS_HPP 00031 00032 /* 00033 Windows version of thread pool sockets with IO Completion Ports 00034 00035 Included from <cat/net/ThreadPoolSockets.hpp> 00036 Do not include directly 00037 */ 00038 00039 #include <MSWSock.h> 00040 #include <cat/port/WindowsInclude.hpp> 00041 00042 namespace cat { 00043 00044 00045 /* 00046 Thread Pool Sockets library 00047 00048 Provides a framework for rapidly developing TCP/UDP server and client objects 00049 that make use of high performance APIs under various server and desktop 00050 operating systems. 00051 00052 All network events are processed by a thread pool managed by ThreadPool. 00053 */ 00054 00055 class TCPServer; 00056 class TCPConnection; 00057 class TCPClient; 00058 class UDPEndpoint; 00059 00060 00062 00063 // Generate a buffer to pass to Post() 00064 u8 *GetPostBuffer(u32 bytes); 00065 00066 void *ResizePostBuffer(void *buffer, u32 newBytes); 00067 00068 // Release a buffer provided by GetPostBuffer() 00069 // Note: Once the buffer is submitted to Post() this is unnecessary 00070 void ReleasePostBuffer(void *buffer); 00071 00072 00074 00075 // AcceptEx() OVERLAPPED structure 00076 struct AcceptExOverlapped 00077 { 00078 TypedOverlapped tov; 00079 Socket acceptSocket; 00080 00081 // Space pre-allocated to receive addresses 00082 // NOTE: This is not necessarily how the addresses are organized in memory 00083 struct 00084 { 00085 // Not necessarily an IPv6 address either! 00086 sockaddr_in6 addr[2]; 00087 u8 padding[2*16]; 00088 } addresses; 00089 00090 void Set(Socket s); 00091 }; 00092 00093 // WSARecvFrom() OVERLAPPED structure 00094 struct RecvFromOverlapped 00095 { 00096 TypedOverlapped tov; 00097 00098 // Not necessarily and IPv6 address, 00099 // but we allocate enough space for one 00100 int addrLen; 00101 sockaddr_in6 addr; 00102 00103 // data follows... 00104 00105 void Reset(); 00106 }; 00107 00108 00109 /* 00110 class TCPServer 00111 00112 Object that represents a TCP server bound to a single port 00113 00114 Overload InstantiateServerConnection() to subclass connections with the server 00115 */ 00116 class TCPServer : public ThreadRefObject 00117 { 00118 friend class TCPConnection; 00119 friend class ThreadPool; 00120 00121 public: 00122 TCPServer(); 00123 virtual ~TCPServer(); 00124 00125 bool ValidServer(); 00126 Port GetPort(); 00127 00128 bool Bind(Port port = 0); 00129 void Close(); 00130 00131 protected: 00132 virtual TCPConnection *InstantiateServerConnection() = 0; 00133 00134 private: 00135 Socket _socket; 00136 LPFN_ACCEPTEX _lpfnAcceptEx; 00137 LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs; 00138 LPFN_DISCONNECTEX _lpfnDisconnectEx; 00139 Port _port; 00140 00141 private: 00142 bool QueueAcceptEx(); 00143 bool QueueAccepts(); 00144 00145 void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped); 00146 }; 00147 00148 00149 /* 00150 class TCPConnection 00151 00152 Object that represents a TCPServer's connection from a TCPClient 00153 00154 Object is instantiated just before accepting a connection 00155 00156 DisconnectClient() : Disconnect the client 00157 PostToClient() : Send a message to the client 00158 ValidServerConnection() : Returns true iff the connection is valid 00159 00160 OnConnectFromClient() : Return false to deny this connection 00161 OnReadFromClient() : Return false to disconnect the client in response to a message 00162 OnWriteToClient() : Informs the derived class that data has been sent 00163 OnDisconectFromClient() : Informs the derived class that the client has disconnected 00164 */ 00165 class TCPConnection : public ThreadRefObject 00166 { 00167 friend class TCPServer; 00168 friend class ThreadPool; 00169 00170 public: 00171 TCPConnection(); 00172 virtual ~TCPConnection(); 00173 00174 bool ValidServerConnection(); 00175 00176 void DisconnectClient(); 00177 bool PostToClient(void *buffer, u32 bytes); 00178 00179 protected: 00180 virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect 00181 virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect 00182 virtual void OnWriteToClient(u32 bytes) = 0; 00183 virtual void OnDisconnectFromClient() = 0; 00184 00185 private: 00186 Socket _socket; 00187 LPFN_DISCONNECTEX _lpfnDisconnectEx; 00188 TypedOverlapped *_recvOv; 00189 volatile u32 _disconnecting; 00190 00191 private: 00192 bool AcceptConnection(Socket listenSocket, Socket acceptSocket, 00193 LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress, 00194 const NetAddr &remoteClientAddress); 00195 00196 bool QueueWSARecv(); 00197 void OnWSARecvComplete(int error, u32 bytes); 00198 00199 bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes); 00200 void OnWSASendComplete(int error, u32 bytes); 00201 00202 bool QueueDisconnectEx(); 00203 void OnDisconnectExComplete(int error); 00204 }; 00205 00206 00207 /* 00208 class TCPClient 00209 00210 Object that represents a TCPClient bound to a single port 00211 00212 ValidClient() : Returns true iff the client socket is valid 00213 00214 Connect() : Connects to the given address 00215 DisconnectServer() : Disconnects from the server 00216 PostToServer() : Send a message to the server (will fail if not connected) 00217 00218 OnConnectToServer() : Called when connection is accepted 00219 OnReadFromServer() : Return false to disconnect the server in response to data 00220 OnWriteToServer() : Informs the derived class that data has been sent 00221 OnDisconnectFromServer() : Informs the derived class that the server has disconnected 00222 */ 00223 class TCPClient : public ThreadRefObject 00224 { 00225 friend class ThreadPool; 00226 00227 public: 00228 TCPClient(); 00229 virtual ~TCPClient(); 00230 00231 bool ValidClient(); 00232 00233 bool Connect(const NetAddr &remoteServerAddress); 00234 void DisconnectServer(); 00235 bool PostToServer(void *buffer, u32 bytes); 00236 00237 protected: 00238 virtual void OnConnectToServer() = 0; 00239 virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect 00240 virtual void OnWriteToServer(u32 bytes) = 0; 00241 virtual void OnDisconnectFromServer() = 0; 00242 00243 private: 00244 Socket _socket; 00245 TypedOverlapped *_recvOv; 00246 volatile u32 _disconnecting; 00247 bool _ipv6; 00248 00249 private: 00250 bool QueueConnectEx(const NetAddr &remoteServerAddress); 00251 void OnConnectExComplete(int error); 00252 00253 bool QueueWSARecv(); 00254 void OnWSARecvComplete(int error, u32 bytes); 00255 00256 bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes); 00257 void OnWSASendComplete(int error, u32 bytes); 00258 00259 bool QueueDisconnectEx(); 00260 void OnDisconnectExComplete(int error); 00261 }; 00262 00263 00264 /* 00265 class TCPClientQueued 00266 00267 Base class for a TCP client that needs to queue up data for sending before 00268 a connection has been established. e.g. Uplink for a proxy server. 00269 00270 PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages. 00271 */ 00272 class TCPClientQueued : public TCPClient 00273 { 00274 private: 00275 volatile bool _queuing; 00276 00277 Mutex _queueLock; 00278 void *_queueBuffer; 00279 u32 _queueBytes; 00280 00281 protected: 00282 void PostQueuedToServer(); 00283 00284 public: 00285 TCPClientQueued(); 00286 virtual ~TCPClientQueued(); 00287 00288 bool PostToServer(void *buffer, u32 bytes); 00289 }; 00290 00291 00292 /* 00293 class UDPEndpoint 00294 00295 Object that represents a UDP endpoint bound to a single port 00296 */ 00297 class UDPEndpoint : public ThreadRefObject 00298 { 00299 friend class ThreadPool; 00300 00301 public: 00302 UDPEndpoint(); 00303 virtual ~UDPEndpoint(); 00304 00305 bool Valid(); 00306 Port GetPort(); 00307 00308 // Is6() result is only valid AFTER Bind() 00309 CAT_INLINE bool Is6() { return _ipv6; } 00310 00311 // For servers: Bind() with ignoreUnreachable = true ((default)) 00312 // For clients: Bind() with ignoreUnreachable = false and call this 00313 // after the first packet from the server is received. 00314 bool IgnoreUnreachable(); 00315 00316 void Close(); // Invalidates this object 00317 bool Bind(Port port = 0, bool ignoreUnreachable = true); 00318 bool QueueWSARecvFrom(); 00319 00320 // If Is6() == true, the address must be promoted to IPv6 00321 // before calling Post() with addr.PromoteTo6() 00322 bool Post(const NetAddr &addr, void *data, u32 bytes); 00323 00324 protected: 00325 virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close 00326 virtual void OnWrite(u32 bytes) = 0; 00327 virtual void OnClose() = 0; 00328 virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid 00329 00330 private: 00331 Socket _socket; 00332 Port _port; 00333 volatile u32 _closing; 00334 bool _ipv6; 00335 00336 private: 00337 bool QueueWSARecvFrom(RecvFromOverlapped *recvOv); 00338 void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes); 00339 00340 bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes); 00341 void OnWSASendToComplete(int error, u32 bytes); 00342 }; 00343 00344 00345 } // namespace cat 00346 00347 #endif // CAT_THREAD_POOL_SOCKETS_HPP
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.