From 30d18cb5d0834132853fb14d45828582b42a8f6e Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sun, 19 Aug 2012 17:29:50 +0300 Subject: Move some code from network to base classes. --- src/net/eathena/network.cpp | 302 ++------------------------------------------ src/net/eathena/network.h | 63 +-------- 2 files changed, 12 insertions(+), 353 deletions(-) (limited to 'src/net/eathena') diff --git a/src/net/eathena/network.cpp b/src/net/eathena/network.cpp index d01613075..5cfe0af1a 100644 --- a/src/net/eathena/network.cpp +++ b/src/net/eathena/network.cpp @@ -112,112 +112,17 @@ short packet_lengths[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -const unsigned int BUFFER_SIZE = 1000000; -const unsigned int BUFFER_LIMIT = 930000; - -int networkThread(void *data) -{ - Network *network = static_cast(data); - - if (!network || !network->realConnect()) - return -1; - - network->receive(); - - return 0; -} - Network *Network::mInstance = nullptr; -Network::Network() : - mSocket(nullptr), - mInBuffer(new char[BUFFER_SIZE]), - mOutBuffer(new char[BUFFER_SIZE]), - mInSize(0), - mOutSize(0), - mToSkip(0), - mState(IDLE), - mWorkerThread(nullptr) +Network::Network() { - SDLNet_Init(); - - mMutex = SDL_CreateMutex(); mInstance = this; } Network::~Network() { clearHandlers(); - - if (mState != IDLE && mState != NET_ERROR) - disconnect(); - - SDL_DestroyMutex(mMutex); - mMutex = nullptr; mInstance = nullptr; - - delete []mInBuffer; - delete []mOutBuffer; - - SDLNet_Quit(); -} - -bool Network::connect(ServerInfo server) -{ - if (mState != IDLE && mState != NET_ERROR) - { - logger->log1("Tried to connect an already connected socket!"); - assert(false); - return false; - } - - if (server.hostname.empty()) - { - setError(_("Empty address given to Network::connect()!")); - return false; - } - - logger->log("Network::Connecting to %s:%i", - server.hostname.c_str(), server.port); - - mServer.hostname = server.hostname; - mServer.port = server.port; - - // Reset to sane values - mOutSize = 0; - mInSize = 0; - mToSkip = 0; - - mState = CONNECTING; - mWorkerThread = SDL_CreateThread(networkThread, this); - if (!mWorkerThread) - { - setError("Unable to create network worker thread"); - return false; - } - - return true; -} - -void Network::disconnect() -{ - mState = IDLE; - - if (mWorkerThread && SDL_GetThreadID(mWorkerThread)) - { - SDL_WaitThread(mWorkerThread, nullptr); - mWorkerThread = nullptr; - } - - if (mSocket) - { - // need call SDLNet_TCP_DelSocket? - SDLNet_TCP_Close(mSocket); - mSocket = nullptr; - int sleep = config.getIntValue("networksleep"); - if (sleep > 0) - SDL_Delay(sleep); - } } void Network::registerHandler(MessageHandler *handler) @@ -278,49 +183,6 @@ void Network::dispatchMessages() } } -void Network::flush() -{ - if (!mOutSize || mState != CONNECTED) - return; - - int ret; - - SDL_mutexP(mMutex); - ret = SDLNet_TCP_Send(mSocket, mOutBuffer, mOutSize); - DEBUGLOG("Send " + toString(mOutSize) + " bytes"); - if (ret < static_cast(mOutSize)) - { - setError("Error in SDLNet_TCP_Send(): " + - std::string(SDLNet_GetError())); - } - mOutSize = 0; - SDL_mutexV(mMutex); -} - -void Network::skip(int len) -{ - SDL_mutexP(mMutex); - mToSkip += len; - if (!mInSize) - { - SDL_mutexV(mMutex); - return; - } - - if (mInSize >= mToSkip) - { - mInSize -= mToSkip; - memmove(mInBuffer, mInBuffer + mToSkip, mInSize); - mToSkip = 0; - } - else - { - mToSkip -= mInSize; - mInSize = 0; - } - SDL_mutexV(mMutex); -} - bool Network::messageReady() { int len = -1; @@ -358,11 +220,18 @@ MessageIn Network::getNextMessage() int msgId = readWord(0); int len; if (msgId == SMSG_SERVER_VERSION_RESPONSE) + { len = 10; + } else if (msgId == SMSG_UPDATE_HOST2) + { len = -1; + } else - len = packet_lengths[msgId]; + { + if (msgId >= 0 && msgId < sizeof(packet_lengths) / sizeof (short)) + len = packet_lengths[msgId]; + } if (len == -1) len = readWord(2); @@ -378,162 +247,9 @@ MessageIn Network::getNextMessage() return msg; } -bool Network::realConnect() -{ - IPaddress ipAddress; - - if (SDLNet_ResolveHost(&ipAddress, mServer.hostname.c_str(), - mServer.port) == -1) - { - std::string errorMessage = _("Unable to resolve host \"") + - mServer.hostname + "\""; - setError(errorMessage); - logger->log("SDLNet_ResolveHost: %s", errorMessage.c_str()); - return false; - } - - mState = CONNECTING; - - mSocket = SDLNet_TCP_Open(&ipAddress); - if (!mSocket) - { - logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError()); - setError(SDLNet_GetError()); - return false; - } - - logger->log("Network::Started session with %s:%i", - ipToString(ipAddress.host), ipAddress.port); - - mState = CONNECTED; - - return true; -} - -void Network::receive() -{ - SDLNet_SocketSet set; - - if (!(set = SDLNet_AllocSocketSet(1))) - { - setError("Error in SDLNet_AllocSocketSet(): " + - std::string(SDLNet_GetError())); - return; - } - - if (SDLNet_TCP_AddSocket(set, mSocket) == -1) - { - setError("Error in SDLNet_AddSocket(): " + - std::string(SDLNet_GetError())); - } - - while (mState == CONNECTED) - { - // TODO Try to get this to block all the time while still being able - // to escape the loop - int numReady = SDLNet_CheckSockets(set, (static_cast(500))); - int ret; - switch (numReady) - { - case -1: - logger->log1("Error: SDLNet_CheckSockets"); - // FALLTHROUGH - case 0: - break; - - case 1: - // Receive data from the socket - SDL_mutexP(mMutex); - if (mInSize > BUFFER_LIMIT) - { - SDL_mutexV(mMutex); - SDL_Delay(100); - continue; - } - - ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, - BUFFER_SIZE - mInSize); - - if (!ret) - { - // We got disconnected - mState = IDLE; - logger->log1("Disconnected."); - } - else if (ret < 0) - { - setError(_("Connection to server terminated. ") + - std::string(SDLNet_GetError())); - } - else - { -// DEBUGLOG("Receive " + toString(ret) + " bytes"); - mInSize += ret; - if (mToSkip) - { - if (mInSize >= mToSkip) - { - mInSize -= mToSkip; - memmove(mInBuffer, mInBuffer + mToSkip, mInSize); - mToSkip = 0; - } - else - { - mToSkip -= mInSize; - mInSize = 0; - } - } - } - SDL_mutexV(mMutex); - break; - - default: - // more than one socket is ready.. - // this should not happen since we only listen once socket. - std::stringstream errorStream; - errorStream << "Error in SDLNet_TCP_Recv(), " << numReady - << " sockets are ready: " << SDLNet_GetError(); - setError(errorStream.str()); - break; - } - } - - if (SDLNet_TCP_DelSocket(set, mSocket) == -1) - logger->log("Error in SDLNet_DelSocket(): %s", SDLNet_GetError()); - - SDLNet_FreeSocketSet(set); -} - Network *Network::instance() { return mInstance; } -void Network::setError(const std::string &error) -{ - logger->log("Network error: %s", error.c_str()); - mError = error; - mState = NET_ERROR; -} - -uint16_t Network::readWord(int pos) -{ -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - return SDL_Swap16((*(uint16_t*)(mInBuffer + (pos)))); -#else - return (*reinterpret_cast(mInBuffer + (pos))); -#endif -} - -void Network::fixSendBuffer() -{ - if (mOutSize > BUFFER_LIMIT) - { - if (mState != CONNECTED) - mOutSize = 0; - else - flush(); - } -} - } // namespace EAthena diff --git a/src/net/eathena/network.h b/src/net/eathena/network.h index 1fdcf7c6e..0ce8591ff 100644 --- a/src/net/eathena/network.h +++ b/src/net/eathena/network.h @@ -23,6 +23,8 @@ #ifndef NET_EATHENA_NETWORK_H #define NET_EATHENA_NETWORK_H +#include "net/ea/network.h" + #include "net/serverinfo.h" #include "net/eathena/messagehandler.h" @@ -44,89 +46,30 @@ namespace EAthena { -class Network +class Network : public Ea::Network { public: Network(); ~Network(); - bool connect(ServerInfo server); - - void disconnect(); - - ServerInfo getServer() const - { return mServer; } - void registerHandler(MessageHandler *handler); void unregisterHandler(MessageHandler *handler); void clearHandlers(); - int getState() const - { return mState; } - - const std::string &getError() const - { return mError; } - - bool isConnected() const - { return mState == CONNECTED; } - - int getInSize() const - { return mInSize; } - - void skip(int len); - bool messageReady(); MessageIn getNextMessage(); void dispatchMessages(); - void flush(); - - void fixSendBuffer(); - - // ERROR replaced by NET_ERROR because already defined in Windows - enum - { - IDLE = 0, - CONNECTED, - CONNECTING, - DATA, - NET_ERROR - }; - protected: - friend int networkThread(void *data); friend class MessageOut; static Network *instance(); - void setError(const std::string &error); - - uint16_t readWord(int pos); - - bool realConnect(); - - void receive(); - - TCPsocket mSocket; - - ServerInfo mServer; - - char *mInBuffer, *mOutBuffer; - unsigned int mInSize, mOutSize; - - unsigned int mToSkip; - - int mState; - std::string mError; - - SDL_Thread *mWorkerThread; - SDL_mutex *mMutex; - typedef std::map MessageHandlers; typedef MessageHandlers::iterator MessageHandlerIterator; MessageHandlers mMessageHandlers; -- cgit v1.2.3-70-g09d2