NetworkServer.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* Copyright The kNet Project.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License. */
  11. #pragma once
  12. /** @file NetworkServer.h
  13. @brief The NetworkServer class. The main class for hosting a kNet server. */
  14. #include <list>
  15. #include "kNetBuildConfig.h"
  16. #include "SharedPtr.h"
  17. #include "Socket.h"
  18. #include "MessageConnection.h"
  19. #include "Datagram.h"
  20. #include "INetworkServerListener.h"
  21. #include "Lockable.h"
  22. namespace kNet
  23. {
  24. class Network;
  25. /// Manages all low-level networking required in maintaining a network server and keeps
  26. /// track of all currently established connections.
  27. /// NetworkServer has the
  28. class NetworkServer : public RefCountable
  29. {
  30. public:
  31. /// When destroyed, the NetworkServer closes all the server connections it has.
  32. ~NetworkServer();
  33. /// Enters a stand-alone processing loop that manages incoming connections until server is shut down.
  34. void RunModalServer();
  35. /// Enables or disables whether new connection attempts are allowed.
  36. void SetAcceptNewConnections(bool acceptNewConnections);
  37. // Returns whether this server is handling new connection attempts.
  38. bool AcceptsNewConnections() const { return acceptNewConnections; }
  39. /// Enables or disables whether rejected connection attempts are messaged back to the client (UDP only).
  40. /// i.e. whether to message "Connection rejected" back to the peer.
  41. void SetStealthMode(bool stealthModeEnabled);
  42. /// Handles all new connection attempts and pulls in new messages from all existing connections.
  43. /// Periodically call this function to update the NetworkServer object.
  44. void Process();
  45. /// Broadcasts the given message to all currently active connections, except for the single 'exclude' connection.
  46. /// If exclude is 0, all clients will receive the message.
  47. /// @param msg The message to send.
  48. /// @param exclude The network connection to exclude from the recipient list. All other clients connected to this
  49. /// server will get the message. This parameter is useful when you are implementing a server that relays messages
  50. /// between clients and want to avoid "echoing" the original message back to the client who sent it.
  51. void BroadcastMessage(const NetworkMessage &msg, MessageConnection *exclude = 0);
  52. /// Creates a NetworkMessage structure with the given data and broadcasts it to all currently active connections,
  53. /// except to the given excluded connection.
  54. void BroadcastMessage(unsigned long id, bool reliable, bool inOrder, unsigned long priority,
  55. unsigned long contentID, const char *data, size_t numBytes,
  56. MessageConnection *exclude = 0);
  57. template<typename SerializableData>
  58. void BroadcastStruct(const SerializableData &data, unsigned long id, bool inOrder,
  59. bool reliable, unsigned long priority, unsigned long contentID = 0, MessageConnection *exclude = 0);
  60. template<typename SerializableMessage>
  61. void Broadcast(const SerializableMessage &data, unsigned long contentID = 0, MessageConnection *exclude = 0);
  62. /// Sends the given message to the given destination.
  63. void SendMessage(const NetworkMessage &msg, MessageConnection &destination);
  64. /// Starts a benign disconnection procedure for all clients (write-closes each connection).
  65. /// Also calls SetAcceptNewConnections(false), since this function is intended to be used when the server is going down.
  66. /// It can take an indefinite time for the connections to bidirectionally close, since it is up to the individual
  67. /// clients to write-close their end of the connections. This function returns immediately.
  68. void DisconnectAllClients();
  69. /// Forcibly closes down the server. Calls SetAcceptNewConnections(false) so that no new connections are accepted.
  70. /// @param disconnectWaitMilliseconds If >0, this function calls DisconnectAllClients() and waits for the given amount
  71. /// of time until calling Close() on each client connection. If 0, MessageConnection::Close(0) will be immediately
  72. /// called on each client. In that case, this function returns immediately and all active clients will be left
  73. /// to time out at their end. Calling this function does not guarantee that all outbound data will be received
  74. /// by the peers.
  75. void Close(int disconnectWaitMilliseconds);
  76. /// Forcibly erases the given connection from the active connection list. The client will be left to time out.
  77. void ConnectionClosed(MessageConnection *connection);
  78. /// Returns all the sockets this server is listening on.
  79. std::vector<Socket *> &ListenSockets();
  80. typedef std::map<EndPoint, Ptr(MessageConnection)> ConnectionMap;
  81. /// Returns all the currently tracked connections.
  82. ConnectionMap GetConnections();
  83. /// Returns the number of currently active connections. A connection is active if it is at least read- or write-open.
  84. int NumConnections() const;
  85. /// Returns a one-liner textual summary of this server.
  86. std::string ToString() const;
  87. private:
  88. /// Private ctor - NetworkServer instances are created by the Network class.
  89. NetworkServer(Network *owner, std::vector<Socket *> listenSockets);
  90. /// We store possibly multiple listening sockets so that the server
  91. /// can listen on several sockets (UDP or TCP) at once, making it
  92. /// possible for clients to bypass firewalls and/or mix UDP and TCP use.
  93. std::vector<Socket *> listenSockets;
  94. /// The list of active client connections.
  95. Lockable<ConnectionMap> clients;
  96. /// The Network object this NetworkServer was spawned from.
  97. Network *owner;
  98. /// Stores the thread that manages the background processing of this server. The same thread can manage multiple
  99. /// connections and servers, and not just this one.
  100. NetworkWorkerThread *workerThread; // [set and read only by worker thread]
  101. #ifdef KNET_THREAD_CHECKING_ENABLED
  102. /// In debug mode, we track and enforce thread safety constraints through this ID.
  103. ThreadId workerThreadId; // [set by worker thread on thread startup, read by both main and worker thread]
  104. #endif
  105. /// If true, new connection attempts are processed. Otherwise, just discard all connection packets.
  106. bool acceptNewConnections;
  107. INetworkServerListener *networkServerListener;
  108. /// Sets the worker thread object that will handle this server.
  109. void SetWorkerThread(NetworkWorkerThread *thread); // [main thread]
  110. NetworkWorkerThread *WorkerThread() const { return workerThread; }
  111. /// If the server is running in UDP mode, the listenSocket is the socket that receives all application data.
  112. /// This function pulls all new data from the socket and sends it to MessageConnection instances for deserialization and processing.
  113. void ReadUDPSocketData(Socket *listenSocket); // [worker thread]
  114. void RegisterServerListener(INetworkServerListener *listener);
  115. /// Shuts down all listen sockets used by this server.
  116. /// This function is to be called only at destruction time when no network communication is being performed anymore.
  117. void CloseSockets();
  118. void CleanupDeadConnections();
  119. Socket *AcceptConnections(Socket *listenSocket);
  120. struct ConnectionAttemptDescriptor
  121. {
  122. Socket *listenSocket;
  123. EndPoint peer;
  124. Datagram data;
  125. };
  126. WaitFreeQueue<ConnectionAttemptDescriptor> udpConnectionAttempts;
  127. /// Called from the network worker thread.
  128. void EnqueueNewUDPConnectionAttempt(Socket *listenSocket, const EndPoint &endPoint, const char *data, size_t numBytes);
  129. bool ProcessNewUDPConnectionAttempt(Socket *listenSocket, const EndPoint &endPoint, const char *data, size_t numBytes);
  130. friend class Network;
  131. friend class NetworkWorkerThread;
  132. };
  133. template<typename SerializableData>
  134. void NetworkServer::BroadcastStruct(const SerializableData &data, unsigned long id, bool inOrder,
  135. bool reliable, unsigned long priority, unsigned long contentID, MessageConnection *exclude)
  136. {
  137. PolledTimer timer;
  138. Lockable<ConnectionMap>::LockType clientsLock = clients.Acquire();
  139. if (timer.MSecsElapsed() >= 50.f)
  140. {
  141. KNET_LOG(LogWaits, "NetworkServer::BroadcastMessage: Accessing the connection list took %f msecs.",
  142. timer.MSecsElapsed());
  143. }
  144. const size_t dataSize = data.Size();
  145. for(ConnectionMap::iterator iter = clientsLock->begin(); iter != clientsLock->end(); ++iter)
  146. {
  147. MessageConnection *connection = iter->second;
  148. assert(connection);
  149. if (connection == exclude || !connection->IsWriteOpen())
  150. continue;
  151. NetworkMessage *msg = connection->StartNewMessage(id, dataSize);
  152. if (dataSize > 0)
  153. {
  154. DataSerializer mb(msg->data, dataSize);
  155. data.SerializeTo(mb);
  156. assert(mb.BytesFilled() == dataSize); // The SerializableData::Size() estimate must be exact!
  157. }
  158. msg->id = id;
  159. msg->reliable = reliable;
  160. msg->inOrder = inOrder;
  161. msg->priority = priority;
  162. msg->contentID = contentID;
  163. #ifdef KNET_NETWORK_PROFILING
  164. char str[512];
  165. sprintf(str, "%s (%u)", SerializableData::Name(), (unsigned int)id);
  166. msg->profilerName = str;
  167. #endif
  168. connection->EndAndQueueMessage(msg);
  169. }
  170. }
  171. template<typename SerializableMessage>
  172. void NetworkServer::Broadcast(const SerializableMessage &data, unsigned long contentID, MessageConnection *exclude)
  173. {
  174. BroadcastStruct(data, SerializableMessage::messageID, data.inOrder, data.reliable, data.priority, contentID, exclude);
  175. }
  176. } // ~kNet