Shadowrun: Awakened 29 September 2011 - Build 871
TCPServer.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 #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.

GNU Lesser General Public License 3 Sourceforge.net