summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2012-08-19 17:29:50 +0300
committerAndrei Karas <akaras@inbox.ru>2012-08-19 18:22:41 +0300
commit30d18cb5d0834132853fb14d45828582b42a8f6e (patch)
treeaa1cc9fa09e3ae5601d412772856514874c573a6 /src/net
parent94d65b487d458341e3626bcfa41fa09c1c240d89 (diff)
downloadmv-30d18cb5d0834132853fb14d45828582b42a8f6e.tar.gz
mv-30d18cb5d0834132853fb14d45828582b42a8f6e.tar.bz2
mv-30d18cb5d0834132853fb14d45828582b42a8f6e.tar.xz
mv-30d18cb5d0834132853fb14d45828582b42a8f6e.zip
Move some code from network to base classes.
Diffstat (limited to 'src/net')
-rw-r--r--src/net/ea/network.cpp342
-rw-r--r--src/net/ea/network.h111
-rw-r--r--src/net/eathena/network.cpp302
-rw-r--r--src/net/eathena/network.h63
-rw-r--r--src/net/tmwa/network.cpp302
-rw-r--r--src/net/tmwa/network.h63
6 files changed, 477 insertions, 706 deletions
diff --git a/src/net/ea/network.cpp b/src/net/ea/network.cpp
new file mode 100644
index 000000000..ccf126a22
--- /dev/null
+++ b/src/net/ea/network.cpp
@@ -0,0 +1,342 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/ea/network.h"
+
+#include "configuration.h"
+#include "logger.h"
+
+#include "net/messagehandler.h"
+#include "net/messagein.h"
+
+#include "net/eathena/protocol.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <assert.h>
+#include <sstream>
+
+#include "debug.h"
+
+namespace Ea
+{
+
+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() :
+ mSocket(nullptr),
+ mInBuffer(new char[BUFFER_SIZE]),
+ mOutBuffer(new char[BUFFER_SIZE]),
+ mInSize(0),
+ mOutSize(0),
+ mToSkip(0),
+ mState(IDLE),
+ mWorkerThread(nullptr)
+{
+ SDLNet_Init();
+
+ mMutex = SDL_CreateMutex();
+}
+
+Network::~Network()
+{
+ if (mState != IDLE && mState != NET_ERROR)
+ disconnect();
+
+ SDL_DestroyMutex(mMutex);
+ mMutex = 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::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::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);
+}
+
+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 EAthena
diff --git a/src/net/ea/network.h b/src/net/ea/network.h
new file mode 100644
index 000000000..2fe2037a9
--- /dev/null
+++ b/src/net/ea/network.h
@@ -0,0 +1,111 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NET_EA_NETWORK_H
+#define NET_EA_NETWORK_H
+
+#include "net/serverinfo.h"
+
+#include "net/messagein.h"
+#include "net/messageout.h"
+
+#include <SDL_net.h>
+#include <SDL_thread.h>
+
+#include <map>
+#include <string>
+
+namespace Ea
+{
+
+class Network
+{
+ public:
+ Network();
+
+ ~Network();
+
+ bool connect(ServerInfo server);
+
+ void disconnect();
+
+ ServerInfo getServer() const
+ { return mServer; }
+
+ 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);
+
+ 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);
+
+ 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;
+};
+
+} // namespace Ea
+
+#endif // NET_EA_NETWORK_H
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<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)
@@ -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<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;
@@ -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<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 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<uint16_t, MessageHandler*> MessageHandlers;
typedef MessageHandlers::iterator MessageHandlerIterator;
MessageHandlers mMessageHandlers;
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
diff --git a/src/net/tmwa/network.h b/src/net/tmwa/network.h
index cc7ae129b..b110b7fb9 100644
--- a/src/net/tmwa/network.h
+++ b/src/net/tmwa/network.h
@@ -23,6 +23,8 @@
#ifndef NET_TA_NETWORK_H
#define NET_TA_NETWORK_H
+#include "net/ea/network.h"
+
#include "net/serverinfo.h"
#include "net/tmwa/messagehandler.h"
@@ -45,89 +47,30 @@
namespace TmwAthena
{
-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<uint16_t, MessageHandler*> MessageHandlers;
typedef MessageHandlers::iterator MessageHandlerIterator;
MessageHandlers mMessageHandlers;