TrinityCore
Loading...
Searching...
No Matches
SocketMgr.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITYCORE_SOCKET_MGR_H
19#define TRINITYCORE_SOCKET_MGR_H
20
21#include "AsyncAcceptor.h"
22#include "Errors.h"
23#include "NetworkThread.h"
24#include "Socket.h"
25#include <boost/asio/ip/tcp.hpp>
26#include <memory>
27
28namespace Trinity::Net
29{
30template <typename Traits>
32{
33public:
34 using Self = typename Traits::Self;
35 using SocketType = typename Traits::SocketType;
36 using ThreadType = typename Traits::ThreadType;
37
38 SocketMgr(SocketMgr const&) = delete;
39 SocketMgr(SocketMgr&&) = delete;
40 SocketMgr& operator=(SocketMgr const&) = delete;
42
43 virtual ~SocketMgr()
44 {
45 ASSERT(!_threads && !_acceptor && !_threadCount, "StopNetwork must be called prior to SocketMgr destruction");
46 }
47
48 virtual bool StartNetwork(Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int threadCount)
49 {
50 ASSERT(threadCount > 0);
51
52 std::unique_ptr<AsyncAcceptor> acceptor = nullptr;
53 try
54 {
55 acceptor = std::make_unique<AsyncAcceptor>(ioContext, bindIp, port);
56 }
57 catch (boost::system::system_error const& err)
58 {
59 TC_LOG_ERROR("network", "Exception caught in SocketMgr.StartNetwork ({}:{}): {}", bindIp, port, err.what());
60 return false;
61 }
62
63 if (!acceptor->Bind())
64 {
65 TC_LOG_ERROR("network", "StartNetwork failed to bind socket acceptor");
66 return false;
67 }
68
69 _acceptor = std::move(acceptor);
70 _threadCount = threadCount;
71 _threads = static_cast<Self*>(this)->CreateThreads();
72
74
75 for (int32 i = 0; i < _threadCount; ++i)
76 _threads[i].Start();
77
78 _acceptor->AsyncAccept(
79 [this]{ return SelectThreadWithMinConnections(); },
80 [this](IoContextTcpSocket&& sock) { static_cast<Self*>(this)->OnSocketOpen(std::move(sock)); });
81
82 return true;
83 }
84
85 virtual void StopNetwork()
86 {
87 _acceptor->Close();
88
89 for (int32 i = 0; i < _threadCount; ++i)
90 _threads[i].Stop();
91
92 Wait();
93
94 _acceptor = nullptr;
95 _threads = nullptr;
96 _threadCount = 0;
97 }
98
99 void Wait()
100 {
101 for (int32 i = 0; i < _threadCount; ++i)
102 _threads[i].Wait();
103 }
104
105 virtual void OnSocketOpen(IoContextTcpSocket&& sock)
106 {
107 try
108 {
109 int32 threadIndex = 0;
110 for (; threadIndex < _threadCount; ++threadIndex)
111 if (_threads[threadIndex].GetIoContext()->get_executor() == sock.get_executor())
112 break;
113
114 std::shared_ptr<SocketType> newSocket = std::make_shared<SocketType>(std::move(sock));
115 newSocket->Start();
116
117 _threads[threadIndex].AddSocket(std::move(newSocket));
118 }
119 catch (boost::system::system_error const& err)
120 {
121 TC_LOG_WARN("network", "Failed to retrieve client's remote address {}", err.what());
122 }
123 }
124
126
128 {
129 ThreadType* min = &_threads[0];
130
131 for (ThreadType* i = min + 1; i != _threads.get() + _threadCount; ++i)
132 if (i->GetConnectionCount() < min->GetConnectionCount())
133 min = i;
134
135 return min->GetIoContext();
136 }
137
138protected:
140 {
141 }
142
143 virtual std::unique_ptr<ThreadType[]> CreateThreads() const
144 {
145 return std::make_unique<ThreadType[]>(GetNetworkThreadCount());
146 }
147
148 std::unique_ptr<AsyncAcceptor> _acceptor;
149 std::unique_ptr<ThreadType[]> _threads;
151};
152}
153
154#endif // TRINITYCORE_SOCKET_MGR_H
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
#define ASSERT
Definition Errors.h:80
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_WARN(filterType__, message__,...)
Definition Log.h:187
int32 GetNetworkThreadCount() const
Definition SocketMgr.h:125
SocketMgr & operator=(SocketMgr &&)=delete
virtual bool StartNetwork(Asio::IoContext &ioContext, std::string const &bindIp, uint16 port, int threadCount)
Definition SocketMgr.h:48
typename Traits::SocketType SocketType
Definition SocketMgr.h:35
virtual std::unique_ptr< ThreadType[]> CreateThreads() const
Definition SocketMgr.h:143
typename Traits::ThreadType ThreadType
Definition SocketMgr.h:36
virtual void StopNetwork()
Definition SocketMgr.h:85
virtual void OnSocketOpen(IoContextTcpSocket &&sock)
Definition SocketMgr.h:105
Asio::IoContext * SelectThreadWithMinConnections() const
Definition SocketMgr.h:127
std::unique_ptr< ThreadType[]> _threads
Definition SocketMgr.h:149
typename Traits::Self Self
Definition SocketMgr.h:34
std::unique_ptr< AsyncAcceptor > _acceptor
Definition SocketMgr.h:148
SocketMgr & operator=(SocketMgr const &)=delete
SocketMgr(SocketMgr &&)=delete
SocketMgr(SocketMgr const &)=delete
boost::asio::basic_stream_socket< boost::asio::ip::tcp, boost::asio::io_context::executor_type > IoContextTcpSocket
Definition Socket.h:40