diff --git a/CMakeLists.txt b/CMakeLists.txt index aadf06dc..b5ad4d10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,9 @@ SET(SOURCES src/menustate.cpp src/teststate.cpp +# game net + src/net/protocoltibia87.cpp + # framework sources src/framework/dispatcher.cpp src/framework/framebuffer.cpp @@ -79,7 +82,9 @@ SET(SOURCES # network src/framework/net/connection.cpp - src/framework/net/connections.cpp) + src/framework/net/connections.cpp + src/framework/net/protocol.cpp + src/framework/net/networkmessage.cpp) IF(WIN32) SET(SOURCES ${SOURCES} src/framework/win32platform.cpp) diff --git a/src/framework/net/connection.cpp b/src/framework/net/connection.cpp index 44c26305..65da5ff5 100644 --- a/src/framework/net/connection.cpp +++ b/src/framework/net/connection.cpp @@ -43,13 +43,19 @@ void Connection::stop() } } -void Connection::connect(const std::string& ip, uint16 port) +bool Connection::connect(const std::string& ip, uint16 port, ConnectionCallback onConnect) { if(m_connecting){ logError("Already is connecting."); - return; + return false; + } + + if(m_connected){ + logError("Already is connected."); + return false; } + m_connectCallback = onConnect; m_connecting = true; m_ip = ip; m_port = port; @@ -57,14 +63,15 @@ void Connection::connect(const std::string& ip, uint16 port) //first resolve dns boost::asio::ip::tcp::resolver::query query(ip, convertType(port)); m_resolver.async_resolve(query, boost::bind(&Connection::onResolveDns, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); + + return true; } void Connection::onResolveDns(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator endpointIt) { - m_lastError = error; - if(error){ m_connecting = false; + m_connectCallback(error); return; } @@ -74,19 +81,75 @@ void Connection::onResolveDns(const boost::system::error_code& error, boost::asi void Connection::onConnect(const boost::system::error_code& error) { - m_lastError = error; + if(!error){ + m_connected = true; + } + + m_connecting = false; + + m_connectCallback(error); +} + +void Connection::handleError(const boost::system::error_code& error) +{ + if(isConnected()){ + closeSocket(); + } + + stop(); +} + +void Connection::closeSocket() +{ + boost::system::error_code error; + m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error); + + if(error) { + logError("Connection::closeSocket(): %s", error.message().c_str()); + } + + m_socket.close(error); + + if(error) { + logError("Connection::closeSocket(): %s", error.message().c_str()); + } +} + +void Connection::send(NetworkMessagePtr networkMessage, ConnectionCallback onSend) +{ + m_socket.async_send( + boost::asio::buffer(networkMessage->getBuffer(), NetworkMessage::header_length), + boost::bind(&Connection::onSendHeader, shared_from_this(), networkMessage, onSend, boost::asio::placeholders::error) + ); +} + +void Connection::onSendHeader(ConnectionPtr connection, NetworkMessagePtr networkMessage, ConnectionCallback onSend, const boost::system::error_code& error) +{ + if(!connection->isConnected()){ + return; + } if(error){ - m_connecting = false; + connection->handleError(error); + onSend(error); return; - } - - m_connected = true; + } + + connection->getSocket().async_send( + boost::asio::buffer(networkMessage->getBodyBuffer(), networkMessage->getMessageLength()), + boost::bind(&Connection::onSendBody, connection, networkMessage, onSend, boost::asio::placeholders::error) + ); +} - if(!m_callback){ - logError("onConnect::m_callback not set."); +void Connection::onSendBody(ConnectionPtr connection, NetworkMessagePtr networkMessage, ConnectionCallback onSend, const boost::system::error_code& error) +{ + if(!connection->isConnected()){ return; } - m_callback(); + if(error){ + connection->handleError(error); + } + + onSend(error); } diff --git a/src/framework/net/connection.h b/src/framework/net/connection.h index beecc409..a31c4d87 100644 --- a/src/framework/net/connection.h +++ b/src/framework/net/connection.h @@ -28,33 +28,46 @@ #include +#include "networkmessage.h" + class TestState; +class Protocol; +class Connections; -class Connection +class Connection : public std::enable_shared_from_this { public: + typedef std::function ConnectionCallback; + typedef std::shared_ptr ConnectionPtr; + +private: Connection(boost::asio::io_service& ioService); - void connect(const std::string& ip, uint16 port); + bool connect(const std::string& ip, uint16 port, ConnectionCallback onConnect); void stop(); + void send(NetworkMessagePtr networkMessage, ConnectionCallback onSend); - bool isConnecting() const { return m_connecting; } - bool isConnected() const { return m_connected; } + bool isConnecting() const { return m_connecting; } + bool isConnected() const { return m_connected; } - const boost::system::error_code& getLastError() const { return m_lastError; } + boost::asio::ip::tcp::socket& getSocket() { return m_socket; } - void resetLastError() { m_lastError = boost::system::error_code(); } - - void setCallback(std::function f) { m_callback = f; } +private: + static void onSendHeader(ConnectionPtr connection, NetworkMessagePtr networkMessage, ConnectionCallback onSend, const boost::system::error_code& error); + static void onSendBody(ConnectionPtr connection, NetworkMessagePtr networkMessage, ConnectionCallback onSend, const boost::system::error_code& error); private: void onResolveDns(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator endpointIt); void onConnect(const boost::system::error_code& error); private: + void closeSocket(); + +private: + void handleError(const boost::system::error_code& error); + boost::asio::ip::tcp::socket m_socket; boost::asio::ip::tcp::resolver m_resolver; - boost::system::error_code m_lastError; bool m_connecting; bool m_connected; @@ -62,10 +75,12 @@ private: std::string m_ip; uint16_t m_port; - std::function m_callback; + ConnectionCallback m_connectCallback; + + friend class Protocol; + friend class Connections; }; typedef std::shared_ptr ConnectionPtr; - #endif //CONNECTION_h diff --git a/src/framework/net/connections.cpp b/src/framework/net/connections.cpp index 59be8619..75e1b17d 100644 --- a/src/framework/net/connections.cpp +++ b/src/framework/net/connections.cpp @@ -34,6 +34,6 @@ ConnectionPtr Connections::createConnection() { ConnectionPtr connection(new Connection(m_ioService)); m_connections.push_back(connection); - + return connection; } diff --git a/src/framework/prerequisites.h b/src/framework/prerequisites.h index 0e4d2753..866fb5a3 100644 --- a/src/framework/prerequisites.h +++ b/src/framework/prerequisites.h @@ -31,6 +31,7 @@ typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; +typedef uint64_t uint64; typedef uint32_t uint32; typedef uint16_t uint16; typedef uint8_t uint8; diff --git a/src/teststate.cpp b/src/teststate.cpp index f704a2eb..32115185 100644 --- a/src/teststate.cpp +++ b/src/teststate.cpp @@ -30,24 +30,12 @@ #include "framework/net/connections.h" -void TestState::onEnter() -{ - m_connection = g_connections.createConnection(); - m_connection->setCallback([this]() { - this->onConnect(); - }); +#include "net/protocoltibia87.h" - m_connection->connect("www.google.com.br", 80); -} - -void TestState::onConnect() +void TestState::onEnter() { - if(m_connection->isConnected()){ - logInfo("Connected."); - } - else{ - logError("Not connected: %d", m_connection->getLastError().message().c_str()); - } + m_protocol = ProtocolTibia87Ptr(new ProtocolTibia87); + m_protocol->begin(); } void TestState::onLeave() diff --git a/src/teststate.h b/src/teststate.h index accedd2e..989929a5 100644 --- a/src/teststate.h +++ b/src/teststate.h @@ -26,8 +26,7 @@ #define TESTSTATE_H #include "framework/gamestate.h" - -#include "framework/net/connection.h" +#include "net/protocoltibia87.h" class TestState : public GameState { @@ -44,10 +43,7 @@ public: virtual void update(int ticks, int elapsedTicks); private: - void onConnect(); - -private: - ConnectionPtr m_connection; + ProtocolTibia87Ptr m_protocol; }; #endif // TESTSTATE_H