diff options
Diffstat (limited to '')
-rw-r--r-- | source/cSocketThreads.h | 348 |
1 files changed, 174 insertions, 174 deletions
diff --git a/source/cSocketThreads.h b/source/cSocketThreads.h index a8174a115..b13ecf02d 100644 --- a/source/cSocketThreads.h +++ b/source/cSocketThreads.h @@ -1,174 +1,174 @@ -
-// cSocketThreads.h
-
-// Interfaces to the cSocketThreads class representing the heart of MCS's client networking.
-// This object takes care of network communication, groups sockets into threads and uses as little threads as possible for full read / write support
-// For more detail, see http://forum.mc-server.org/showthread.php?tid=327
-
-/*
-Additional details:
-When a client is terminating a connection:
-- they call the StopReading() method to disable callbacks for the incoming data
-- they call the Write() method to queue any outstanding outgoing data
-- they call the QueueClose() method to queue the socket to close after outgoing data has been sent.
-When a socket slot is marked as having no callback, it is kept alive until its outgoing data queue is empty and its m_ShouldClose flag is set.
-This means that the socket can be written to several times before finally closing it via QueueClose()
-*/
-
-
-
-
-
-/// How many clients should one thread handle? (must be less than FD_SETSIZE - 1 for your platform)
-#define MAX_SLOTS 63
-
-
-
-
-
-#pragma once
-#ifndef CSOCKETTHREADS_H_INCLUDED
-#define CSOCKETTHREADS_H_INCLUDED
-
-#include "packets/cPacket.h"
-#include "cIsThread.h"
-
-
-
-
-// Check MAX_SLOTS:
-#if MAX_SLOTS >= FD_SETSIZE
- #error "MAX_SLOTS must be less than FD_SETSIZE - 1 for your platform! (otherwise select() won't work)"
-#endif
-
-
-
-
-
-// fwd:
-class cSocket;
-class cClientHandle;
-
-
-
-
-
-class cSocketThreads
-{
-public:
-
- // Clients of cSocketThreads must implement this interface to be able to communicate
- class cCallback
- {
- public:
- /// Called when data is received from the remote party
- virtual void DataReceived(const char * a_Data, int a_Size) = 0;
-
- /// Called when data can be sent to remote party; the function is supposed to append outgoing data to a_Data
- virtual void GetOutgoingData(AString & a_Data) = 0;
-
- /// Called when the socket has been closed for any reason
- virtual void SocketClosed(void) = 0;
- } ;
-
-
- cSocketThreads(void);
- ~cSocketThreads();
-
- /// Add a (socket, client) pair for processing, data from a_Socket is to be sent to a_Client; returns true if successful
- bool AddClient(cSocket * a_Socket, cCallback * a_Client);
-
- /// Remove the socket (and associated client) from processing
- void RemoveClient(const cSocket * a_Socket);
-
- /// Remove the associated socket and the client from processing
- void RemoveClient(const cCallback * a_Client);
-
- /// Notify the thread responsible for a_Client that the client has something to write
- void NotifyWrite(const cCallback * a_Client);
-
- /// Puts a_Data into outgoing data queue for a_Socket
- void Write(const cSocket * a_Socket, const AString & a_Data);
-
- /// Stops reading from the socket - when this call returns, no more calls to the callbacks are made
- void StopReading(const cCallback * a_Client);
-
- /// Queues the socket for closing, as soon as its outgoing data is sent
- void QueueClose(const cSocket * a_Socket);
-
-private:
-
- class cSocketThread :
- public cIsThread
- {
- typedef cIsThread super;
-
- public:
-
- cSocketThread(cSocketThreads * a_Parent);
- ~cSocketThread();
-
- // All these methods assume parent's m_CS is locked
- bool HasEmptySlot(void) const {return m_NumSlots < MAX_SLOTS; }
- bool IsEmpty (void) const {return m_NumSlots == 0; }
-
- void AddClient (cSocket * a_Socket, cCallback * a_Client);
- bool RemoveClient(const cCallback * a_Client); // Returns true if removed, false if not found
- bool RemoveSocket(const cSocket * a_Socket); // Returns true if removed, false if not found
- bool HasClient (const cCallback * a_Client) const;
- bool HasSocket (const cSocket * a_Socket) const;
- bool NotifyWrite (const cCallback * a_Client); // Returns true if client handled by this thread
- bool Write (const cSocket * a_Socket, const AString & a_Data); // Returns true if socket handled by this thread
- bool StopReading (const cCallback * a_Client); // Returns true if client handled by this thread
- bool QueueClose (const cSocket * a_Socket); // Returns true if socket handled by this thread
-
- bool Start(void); // Hide the cIsThread's Start method, we need to provide our own startup to create the control socket
-
- bool IsValid(void) const {return m_ControlSocket2.IsValid(); } // If the Control socket dies, the thread is not valid anymore
-
- private:
-
- cSocketThreads * m_Parent;
-
- // Two ends of the control socket, the first is select()-ed, the second is written to for notifications
- cSocket m_ControlSocket1;
- cSocket m_ControlSocket2;
-
- // Socket-client-packetqueues triplets.
- // Manipulation with these assumes that the parent's m_CS is locked
- struct sSlot
- {
- cSocket * m_Socket;
- cCallback * m_Client;
- AString m_Outgoing; // If sending writes only partial data, the rest is stored here for another send
- bool m_ShouldClose; // If true, the socket is to be closed after sending all outgoing data
- } ;
- sSlot m_Slots[MAX_SLOTS];
- int m_NumSlots; // Number of slots actually used
-
- virtual void Execute(void) override;
-
- void AddOrUpdatePacket(int a_Slot, cPacket * a_Packet); // Adds the packet to the specified slot, or updates an existing packet in that queue (EntityMoveLook filtering)
-
- void PrepareSet (fd_set * a_Set, cSocket::xSocket & a_Highest); // Puts all sockets into the set, along with m_ControlSocket1
- void ReadFromSockets(fd_set * a_Read); // Reads from sockets indicated in a_Read
- void WriteToSockets (fd_set * a_Write); // Writes to sockets indicated in a_Write
- void RemoveClosedSockets(void); // Removes sockets that have closed from m_Slots[]
- } ;
-
- typedef std::list<cSocketThread *> cSocketThreadList;
-
-
- cCriticalSection m_CS;
- cSocketThreadList m_Threads;
-} ;
-
-
-
-
-
-#endif // CSOCKETTHREADS_H_INCLUDED
-
-
-
-
+ +// cSocketThreads.h + +// Interfaces to the cSocketThreads class representing the heart of MCS's client networking. +// This object takes care of network communication, groups sockets into threads and uses as little threads as possible for full read / write support +// For more detail, see http://forum.mc-server.org/showthread.php?tid=327 + +/* +Additional details: +When a client is terminating a connection: +- they call the StopReading() method to disable callbacks for the incoming data +- they call the Write() method to queue any outstanding outgoing data +- they call the QueueClose() method to queue the socket to close after outgoing data has been sent. +When a socket slot is marked as having no callback, it is kept alive until its outgoing data queue is empty and its m_ShouldClose flag is set. +This means that the socket can be written to several times before finally closing it via QueueClose() +*/ + + + + + +/// How many clients should one thread handle? (must be less than FD_SETSIZE - 1 for your platform) +#define MAX_SLOTS 63 + + + + + +#pragma once +#ifndef CSOCKETTHREADS_H_INCLUDED +#define CSOCKETTHREADS_H_INCLUDED + +#include "packets/cPacket.h" +#include "cIsThread.h" + + + + +// Check MAX_SLOTS: +#if MAX_SLOTS >= FD_SETSIZE + #error "MAX_SLOTS must be less than FD_SETSIZE - 1 for your platform! (otherwise select() won't work)" +#endif + + + + + +// fwd: +class cSocket; +class cClientHandle; + + + + + +class cSocketThreads +{ +public: + + // Clients of cSocketThreads must implement this interface to be able to communicate + class cCallback + { + public: + /// Called when data is received from the remote party + virtual void DataReceived(const char * a_Data, int a_Size) = 0; + + /// Called when data can be sent to remote party; the function is supposed to append outgoing data to a_Data + virtual void GetOutgoingData(AString & a_Data) = 0; + + /// Called when the socket has been closed for any reason + virtual void SocketClosed(void) = 0; + } ; + + + cSocketThreads(void); + ~cSocketThreads(); + + /// Add a (socket, client) pair for processing, data from a_Socket is to be sent to a_Client; returns true if successful + bool AddClient(cSocket * a_Socket, cCallback * a_Client); + + /// Remove the socket (and associated client) from processing + void RemoveClient(const cSocket * a_Socket); + + /// Remove the associated socket and the client from processing + void RemoveClient(const cCallback * a_Client); + + /// Notify the thread responsible for a_Client that the client has something to write + void NotifyWrite(const cCallback * a_Client); + + /// Puts a_Data into outgoing data queue for a_Socket + void Write(const cSocket * a_Socket, const AString & a_Data); + + /// Stops reading from the socket - when this call returns, no more calls to the callbacks are made + void StopReading(const cCallback * a_Client); + + /// Queues the socket for closing, as soon as its outgoing data is sent + void QueueClose(const cSocket * a_Socket); + +private: + + class cSocketThread : + public cIsThread + { + typedef cIsThread super; + + public: + + cSocketThread(cSocketThreads * a_Parent); + ~cSocketThread(); + + // All these methods assume parent's m_CS is locked + bool HasEmptySlot(void) const {return m_NumSlots < MAX_SLOTS; } + bool IsEmpty (void) const {return m_NumSlots == 0; } + + void AddClient (cSocket * a_Socket, cCallback * a_Client); + bool RemoveClient(const cCallback * a_Client); // Returns true if removed, false if not found + bool RemoveSocket(const cSocket * a_Socket); // Returns true if removed, false if not found + bool HasClient (const cCallback * a_Client) const; + bool HasSocket (const cSocket * a_Socket) const; + bool NotifyWrite (const cCallback * a_Client); // Returns true if client handled by this thread + bool Write (const cSocket * a_Socket, const AString & a_Data); // Returns true if socket handled by this thread + bool StopReading (const cCallback * a_Client); // Returns true if client handled by this thread + bool QueueClose (const cSocket * a_Socket); // Returns true if socket handled by this thread + + bool Start(void); // Hide the cIsThread's Start method, we need to provide our own startup to create the control socket + + bool IsValid(void) const {return m_ControlSocket2.IsValid(); } // If the Control socket dies, the thread is not valid anymore + + private: + + cSocketThreads * m_Parent; + + // Two ends of the control socket, the first is select()-ed, the second is written to for notifications + cSocket m_ControlSocket1; + cSocket m_ControlSocket2; + + // Socket-client-packetqueues triplets. + // Manipulation with these assumes that the parent's m_CS is locked + struct sSlot + { + cSocket * m_Socket; + cCallback * m_Client; + AString m_Outgoing; // If sending writes only partial data, the rest is stored here for another send + bool m_ShouldClose; // If true, the socket is to be closed after sending all outgoing data + } ; + sSlot m_Slots[MAX_SLOTS]; + int m_NumSlots; // Number of slots actually used + + virtual void Execute(void) override; + + void AddOrUpdatePacket(int a_Slot, cPacket * a_Packet); // Adds the packet to the specified slot, or updates an existing packet in that queue (EntityMoveLook filtering) + + void PrepareSet (fd_set * a_Set, cSocket::xSocket & a_Highest); // Puts all sockets into the set, along with m_ControlSocket1 + void ReadFromSockets(fd_set * a_Read); // Reads from sockets indicated in a_Read + void WriteToSockets (fd_set * a_Write); // Writes to sockets indicated in a_Write + void RemoveClosedSockets(void); // Removes sockets that have closed from m_Slots[] + } ; + + typedef std::list<cSocketThread *> cSocketThreadList; + + + cCriticalSection m_CS; + cSocketThreadList m_Threads; +} ; + + + + + +#endif // CSOCKETTHREADS_H_INCLUDED + + + + |