diff options
Diffstat (limited to 'src/network/NetworkClient.cpp')
-rw-r--r-- | src/network/NetworkClient.cpp | 175 |
1 files changed, 81 insertions, 94 deletions
diff --git a/src/network/NetworkClient.cpp b/src/network/NetworkClient.cpp index fd957a5..b8d880d 100644 --- a/src/network/NetworkClient.cpp +++ b/src/network/NetworkClient.cpp @@ -1,107 +1,94 @@ #include "NetworkClient.hpp" +#include "Packet.hpp" -ServerInfo NetworkClient::ServerPing(std::string address, unsigned short port) { - ServerInfo info; - Network network(address, port); - Packet packet_handshake = PacketBuilder::CHandshaking0x00(316, address, port, 1); - network.SendPacket(packet_handshake); - Packet packet_request(0); - network.SendPacket(packet_request); - Packet packet_response = network.ReceivePacket(); - PacketParser::Parse(packet_response, Login); - //std::string json = static_cast<FieldString *>(packet_response_parsed.GetFieldById(0))->GetValue(); - std::string json = packet_response.GetField(0).GetString(); - try { - nlohmann::json j = nlohmann::json::parse(json); - info.protocol = j["version"]["protocol"].get<int>(); - info.version = j["version"]["name"].get<std::string>(); - info.players_max = j["players"]["max"].get<int>(); - info.players_online = j["players"]["online"].get<int>(); - info.description = j["description"]["text"].get<std::string>(); - for (auto t:j["description"]["extra"]) { - info.description += t["text"].get<std::string>(); - } - if (!j["favicon"].is_null()) - info.favicon = j["favicon"].get<std::string>(); - info.json = json; - for (auto t:j["players"]["sample"]) { - std::pair<std::string, std::string> player; - player.first = t["id"].get<std::string>(); - player.second = t["name"].get<std::string>(); - info.players.push_back(player); - } - } catch (const nlohmann::detail::exception e) { - std::cerr << "Parsed json is not valid (" << e.id << "): " << e.what() << std::endl; - } - //Ping - Packet packet_ping(0x01); - Field payload; - payload.SetLong(771235); - packet_ping.AddField(payload); - std::chrono::high_resolution_clock clock; - auto t1 = clock.now(); - network.SendPacket(packet_ping); - Packet pong = network.ReceivePacket(); - auto t2 = clock.now(); - pong.ParseField(Long); - if (pong.GetField(0).GetLong() == 771235) { - std::chrono::duration<double, std::milli> pingTime = t2 - t1; - info.ping = pingTime.count(); - } - return info; -} +NetworkClient::NetworkClient(std::string address, unsigned short port, std::string username, bool &quit) + : network(address, port), isRunning(quit) { + state = Handshaking; -NetworkClient::NetworkClient(std::string address, unsigned short port, std::string username) : m_network(address, - port) { - m_network.SendHandshake(username); - Update(); - m_networkThread = std::thread(&NetworkClient::MainLoop, this); -} + PacketHandshake handshake; + handshake.protocolVersion = 335; + handshake.serverAddress = "127.0.0.1"; + handshake.serverPort = 25565; + handshake.nextState = 2; + network.SendPacket(handshake); + state = Login; -NetworkClient::~NetworkClient() { - LOG(INFO)<<"NC stopping..."; - isContinue=false; - m_networkThread.join(); - LOG(INFO)<<"NC is stopped"; -} + PacketLoginStart loginStart; + loginStart.Username = "HelloOne"; + network.SendPacket(loginStart); -Packet * NetworkClient::GetPacket() { - if (m_received.size() < 1) - return nullptr; - Packet packet = m_received.front(); - m_received.pop(); - return new Packet(packet); + auto response = std::static_pointer_cast<PacketLoginSuccess>(network.ReceivePacket(Login)); + if (response->Username != username) { + throw std::logic_error("Received username is not sended username"); + } + + state = Play; + + isActive = true; + std::thread thread(&NetworkClient::NetworkLoop, this); + std::swap(networkThread, thread); } -void NetworkClient::AddPacketToQueue(Packet packet) { - m_toSend.push(packet); +NetworkClient::~NetworkClient() { + isActive = false; + networkThread.join(); } -void NetworkClient::Update() { - if (m_toSend.size() > 0) { - m_network.SendPacket(m_toSend.front()); - m_toSend.pop(); - } - Packet received = m_network.ReceivePacket(); - if (received.GetId() == 0x1F) { - PacketParser::Parse(received); - Packet response = PacketBuilder::CPlay0x0B(received.GetField(0).GetVarInt()); - m_network.SendPacket(response); - return; - } - m_updateMutex.lock(); - m_received.push(received); - m_updateMutex.unlock(); +std::shared_ptr<Packet> NetworkClient::ReceivePacket() { + if (toReceive.empty()) + return std::shared_ptr<Packet>(nullptr); + toReceiveMutex.lock(); + auto ret = toReceive.front(); + toReceive.pop(); + toReceiveMutex.unlock(); + return ret; } -void NetworkClient::MainLoop() { - el::Helpers::setThreadName("Network"); - try { - while (isContinue) { - Update(); - } - } catch (int e){ - LOG(ERROR)<<"Catched exception in NC: "<<e; - } +void NetworkClient::SendPacket(std::shared_ptr<Packet> packet) { + toSendMutex.lock(); + toSend.push(packet); + toSendMutex.unlock(); +} +void NetworkClient::NetworkLoop() { + auto timeOfLastKeepAlivePacket = std::chrono::steady_clock::now(); + el::Helpers::setThreadName("Network"); + LOG(INFO) << "Network thread is started"; + try { + while (isActive) { + toSendMutex.lock(); + while (!toSend.empty()) { + if (toSend.front()!=nullptr) + network.SendPacket(*toSend.front()); + toSend.pop(); + } + toSendMutex.unlock(); + auto packet = network.ReceivePacket(state); + if (packet.get() != nullptr) { + if (packet->GetPacketId() != PacketNamePlayCB::KeepAliveCB) { + toReceiveMutex.lock(); + toReceive.push(packet); + toReceiveMutex.unlock(); + } else { + timeOfLastKeepAlivePacket = std::chrono::steady_clock::now(); + auto packetKeepAlive = std::static_pointer_cast<PacketKeepAliveCB>(packet); + auto packetKeepAliveSB = std::make_shared<PacketKeepAliveSB>(packetKeepAlive->KeepAliveId); + network.SendPacket(*packetKeepAliveSB); + } + } + using namespace std::chrono_literals; + if (std::chrono::steady_clock::now() - timeOfLastKeepAlivePacket > 20s) { + auto disconnectPacket = std::make_shared<PacketDisconnectPlay>(); + disconnectPacket->Reason = "Timeout"; + toReceiveMutex.lock(); + toReceive.push(disconnectPacket); + toReceiveMutex.unlock(); + break; + } + } + } catch (std::exception &e) { + LOG(ERROR) << "Exception catched in NetworkLoop: " << e.what(); + isRunning = false; + } + LOG(INFO) << "Network thread is stopped"; } |