diff options
Diffstat (limited to 'src/net/tmwa/network.cpp')
-rw-r--r-- | src/net/tmwa/network.cpp | 302 |
1 files changed, 9 insertions, 293 deletions
diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp index 4f2f85a51..98f6485a7 100644 --- a/src/net/tmwa/network.cpp +++ b/src/net/tmwa/network.cpp @@ -90,112 +90,17 @@ short packet_lengths[] = -1, 122, 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<Network*>(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) @@ -256,49 +161,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<int>(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; @@ -308,11 +170,18 @@ bool Network::messageReady() { int msgId = readWord(0); 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 && mInSize > 4) len = readWord(2); @@ -356,162 +225,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<uint32_t>(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<uint16_t*>(mInBuffer + (pos))); -#endif -} - -void Network::fixSendBuffer() -{ - if (mOutSize > BUFFER_LIMIT) - { - if (mState != CONNECTED) - mOutSize = 0; - else - flush(); - } -} - } // namespace TmwAthena |