Shadowrun: Awakened 29 September 2011 - Build 871
TCPClient.hpp
Go to the documentation of this file.
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 // TODO: Half-open connections can easily DoS the TCP server right now.
00030 // TODO: Port to Linux(eventfd) and BSD/MacOSX(kevent)
00031 
00032 #ifndef CAT_THREAD_POOL_SOCKETS_HPP
00033 #define CAT_THREAD_POOL_SOCKETS_HPP
00034 
00035 #include <cat/threads/ThreadPool.hpp>
00036 #include <cat/net/Sockets.hpp>
00037 
00038 #if defined(CAT_MS_SOCKET_API)
00039 # include <MSWSock.h>
00040 # include <cat/port/WindowsInclude.hpp>
00041 #endif
00042 
00043 namespace cat {
00044 
00045 
00046 /*
00047     Thread Pool Sockets library
00048 
00049     Provides a framework for rapidly developing TCP/UDP server and client objects
00050     that make use of high performance APIs under various server and desktop
00051     operating systems.
00052 
00053     All network events are processed by a thread pool managed by ThreadPool.
00054 */
00055 
00056 class TCPServer;
00057 class TCPConnection;
00058 class TCPClient;
00059 class UDPEndpoint;
00060 
00061 
00063 
00064 // Generate a buffer to pass to Post()
00065 u8 *GetPostBuffer(u32 bytes);
00066 
00067 void *ResizePostBuffer(void *buffer, u32 newBytes);
00068 
00069 // Release a buffer provided by GetPostBuffer()
00070 // Note: Once the buffer is submitted to Post() this is unnecessary
00071 void ReleasePostBuffer(void *buffer);
00072 
00073 
00075 
00076 // AcceptEx() OVERLAPPED structure
00077 struct AcceptExOverlapped
00078 {
00079     TypedOverlapped tov;
00080     Socket acceptSocket;
00081 
00082     // Space pre-allocated to receive addresses
00083     // NOTE: This is not necessarily how the addresses are organized in memory
00084     struct
00085     {
00086         // Not necessarily an IPv6 address either!
00087         sockaddr_in6 addr[2];
00088         u8 padding[2*16];
00089     } addresses;
00090 
00091     void Set(Socket s);
00092 };
00093 
00094 // WSARecvFrom() OVERLAPPED structure
00095 struct RecvFromOverlapped
00096 {
00097     TypedOverlapped tov;
00098 
00099     // Not necessarily and IPv6 address,
00100     // but we allocate enough space for one
00101     int addrLen;
00102     sockaddr_in6 addr;
00103 
00104     // data follows...
00105 
00106     void Reset();
00107 };
00108 
00109 
00110 /*
00111     class TCPServer
00112 
00113     Object that represents a TCP server bound to a single port
00114 
00115     Overload InstantiateServerConnection() to subclass connections with the server
00116 */
00117 class TCPServer : public ThreadRefObject
00118 {
00119     friend class TCPConnection;
00120     friend class ThreadPool;
00121 
00122 public:
00123     TCPServer();
00124     virtual ~TCPServer();
00125 
00126     bool ValidServer();
00127     Port GetPort();
00128 
00129     bool Bind(Port port = 0);
00130     void Close();
00131 
00132 protected:
00133     virtual TCPConnection *InstantiateServerConnection() = 0;
00134 
00135 private:
00136     Socket _socket;
00137     LPFN_ACCEPTEX _lpfnAcceptEx;
00138     LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
00139     LPFN_DISCONNECTEX _lpfnDisconnectEx;
00140     Port _port;
00141 
00142 private:
00143     bool QueueAcceptEx();
00144     bool QueueAccepts();
00145 
00146     void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
00147 };
00148 
00149 
00150 /*
00151     class TCPConnection
00152 
00153     Object that represents a TCPServer's connection from a TCPClient
00154 
00155     Object is instantiated just before accepting a connection
00156 
00157     DisconnectClient()      : Disconnect the client
00158     PostToClient()          : Send a message to the client
00159     ValidServerConnection() : Returns true iff the connection is valid
00160 
00161     OnConnectFromClient()   : Return false to deny this connection
00162     OnReadFromClient()      : Return false to disconnect the client in response to a message
00163     OnWriteToClient()       : Informs the derived class that data has been sent
00164     OnDisconectFromClient() : Informs the derived class that the client has disconnected
00165 */
00166 class TCPConnection : public ThreadRefObject
00167 {
00168     friend class TCPServer;
00169     friend class ThreadPool;
00170 
00171 public:
00172     TCPConnection();
00173     virtual ~TCPConnection();
00174 
00175     bool ValidServerConnection();
00176 
00177     void DisconnectClient();
00178     bool PostToClient(void *buffer, u32 bytes);
00179 
00180 protected:
00181     virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
00182     virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
00183     virtual void OnWriteToClient(u32 bytes) = 0;
00184     virtual void OnDisconnectFromClient() = 0;
00185 
00186 private:
00187     Socket _socket;
00188     LPFN_DISCONNECTEX _lpfnDisconnectEx;
00189     TypedOverlapped *_recvOv;
00190     volatile u32 _disconnecting;
00191 
00192 private:
00193     bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
00194                 LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
00195                 const NetAddr &remoteClientAddress);
00196 
00197     bool QueueWSARecv();
00198     void OnWSARecvComplete(int error, u32 bytes);
00199 
00200     bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
00201     void OnWSASendComplete(int error, u32 bytes);
00202 
00203     bool QueueDisconnectEx();
00204     void OnDisconnectExComplete(int error);
00205 };
00206 
00207 
00208 /*
00209     class TCPClient
00210 
00211     Object that represents a TCPClient bound to a single port
00212 
00213     ValidClient()      : Returns true iff the client socket is valid
00214 
00215     Connect()          : Connects to the given address
00216     DisconnectServer() : Disconnects from the server
00217     PostToServer()     : Send a message to the server (will fail if not connected)
00218 
00219     OnConnectToServer()      : Called when connection is accepted
00220     OnReadFromServer()       : Return false to disconnect the server in response to data
00221     OnWriteToServer()        : Informs the derived class that data has been sent
00222     OnDisconnectFromServer() : Informs the derived class that the server has disconnected
00223 */
00224 class TCPClient : public ThreadRefObject
00225 {
00226     friend class ThreadPool;
00227 
00228 public:
00229     TCPClient();
00230     virtual ~TCPClient();
00231 
00232     bool ValidClient();
00233 
00234     bool Connect(const NetAddr &remoteServerAddress);
00235     void DisconnectServer();
00236     bool PostToServer(void *buffer, u32 bytes);
00237 
00238 protected:
00239     virtual void OnConnectToServer() = 0;
00240     virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
00241     virtual void OnWriteToServer(u32 bytes) = 0;
00242     virtual void OnDisconnectFromServer() = 0;
00243 
00244 private:
00245     Socket _socket;
00246     TypedOverlapped *_recvOv;
00247     volatile u32 _disconnecting;
00248     bool _ipv6;
00249 
00250 private:
00251     bool QueueConnectEx(const NetAddr &remoteServerAddress);
00252     void OnConnectExComplete(int error);
00253 
00254     bool QueueWSARecv();
00255     void OnWSARecvComplete(int error, u32 bytes);
00256 
00257     bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
00258     void OnWSASendComplete(int error, u32 bytes);
00259 
00260     bool QueueDisconnectEx();
00261     void OnDisconnectExComplete(int error);
00262 };
00263 
00264 
00265 /*
00266     class TCPClientQueued
00267 
00268     Base class for a TCP client that needs to queue up data for sending before
00269     a connection has been established.  e.g. Uplink for a proxy server.
00270 
00271     PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
00272 */
00273 class TCPClientQueued : public TCPClient
00274 {
00275 private:
00276     volatile bool _queuing;
00277 
00278     Mutex _queueLock;
00279     void *_queueBuffer;
00280     u32 _queueBytes;
00281 
00282 protected:
00283     void PostQueuedToServer();
00284 
00285 public:
00286     TCPClientQueued();
00287     virtual ~TCPClientQueued();
00288 
00289     bool PostToServer(void *buffer, u32 bytes);
00290 };
00291 
00292 
00293 /*
00294     class UDPEndpoint
00295 
00296     Object that represents a UDP endpoint bound to a single port
00297 */
00298 class UDPEndpoint : public ThreadRefObject
00299 {
00300     friend class ThreadPool;
00301 
00302 public:
00303     UDPEndpoint();
00304     virtual ~UDPEndpoint();
00305 
00306     bool Valid();
00307     Port GetPort();
00308 
00309     // Is6() result is only valid AFTER Bind()
00310     CAT_INLINE bool Is6() { return _ipv6; }
00311 
00312     // For servers: Bind() with ignoreUnreachable = true ((default))
00313     // For clients: Bind() with ignoreUnreachable = false and call this
00314     //              after the first packet from the server is received.
00315     bool IgnoreUnreachable();
00316 
00317     void Close(); // Invalidates this object
00318     bool Bind(Port port = 0, bool ignoreUnreachable = true);
00319     bool QueueWSARecvFrom();
00320 
00321     // If Is6() == true, the address must be promoted to IPv6
00322     // before calling Post() with addr.PromoteTo6()
00323     bool Post(const NetAddr &addr, void *data, u32 bytes);
00324 
00325 protected:
00326     virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
00327     virtual void OnWrite(u32 bytes) = 0;
00328     virtual void OnClose() = 0;
00329     virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
00330 
00331 private:
00332     Socket _socket;
00333     Port _port;
00334     volatile u32 _closing;
00335     bool _ipv6;
00336 
00337 private:
00338     bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
00339     void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
00340 
00341     bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
00342     void OnWSASendToComplete(int error, u32 bytes);
00343 };
00344 
00345 
00346 } // namespace cat
00347 
00348 #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.

GNU Lesser General Public License 3 Sourceforge.net