00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "net/ea/network.h"
00023
00024 #include "net/messagehandler.h"
00025 #include "net/messagein.h"
00026
00027 #include "log.h"
00028 #include "utils/stringutils.h"
00029
00030 #include <sstream>
00031
00035 short packet_lengths[] = {
00036 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00037 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00038 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00039 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00040
00041 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00042 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00043 0, 0, 0, -1, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2,
00044 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
00045
00046 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0,
00047 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
00048 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
00049 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
00050
00051 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
00052 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
00053 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
00054 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
00055
00056 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1,
00057 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16,
00058 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1,
00059 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26,
00060
00061 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6,
00062 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42,
00063 -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182,
00064 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1,
00065
00066 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6,
00067 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, 4, 6, 2, 6,
00068 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4,
00069 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3,
00070
00071 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28,
00072 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6,
00073 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
00074 -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
00075
00076 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
00077 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00078 };
00079
00080 const unsigned int BUFFER_SIZE = 65536;
00081
00082 int networkThread(void *data)
00083 {
00084 Network *network = static_cast<Network*>(data);
00085
00086 if (!network->realConnect())
00087 return -1;
00088
00089 network->receive();
00090
00091 return 0;
00092 }
00093
00094 Network *Network::mInstance = 0;
00095
00096 Network::Network():
00097 mSocket(0),
00098 mAddress(), mPort(0),
00099 mInBuffer(new char[BUFFER_SIZE]),
00100 mOutBuffer(new char[BUFFER_SIZE]),
00101 mInSize(0), mOutSize(0),
00102 mToSkip(0),
00103 mState(IDLE),
00104 mWorkerThread(0)
00105 {
00106 SDLNet_Init();
00107
00108 mMutex = SDL_CreateMutex();
00109 mInstance = this;
00110 }
00111
00112 Network::~Network()
00113 {
00114 clearHandlers();
00115
00116 if (mState != IDLE && mState != NET_ERROR)
00117 disconnect();
00118
00119 SDL_DestroyMutex(mMutex);
00120 mInstance = 0;
00121
00122 delete[] mInBuffer;
00123 delete[] mOutBuffer;
00124
00125 SDLNet_Quit();
00126 }
00127
00128 bool Network::connect(const std::string &address, short port)
00129 {
00130 if (mState != IDLE && mState != NET_ERROR)
00131 {
00132 logger->log("Tried to connect an already connected socket!");
00133 return false;
00134 }
00135
00136 if (address.empty())
00137 {
00138 setError("Empty address given to Network::connect()!");
00139 return false;
00140 }
00141
00142 logger->log("Network::Connecting to %s:%i", address.c_str(), port);
00143
00144 mAddress = address;
00145 mPort = port;
00146
00147
00148 mOutSize = 0;
00149 mInSize = 0;
00150 mToSkip = 0;
00151
00152 mState = CONNECTING;
00153 mWorkerThread = SDL_CreateThread(networkThread, this);
00154 if (!mWorkerThread)
00155 {
00156 setError("Unable to create network worker thread");
00157 return false;
00158 }
00159
00160 return true;
00161 }
00162
00163 void Network::disconnect()
00164 {
00165 mState = IDLE;
00166
00167 if (mWorkerThread)
00168 {
00169 SDL_WaitThread(mWorkerThread, NULL);
00170 mWorkerThread = NULL;
00171 }
00172
00173 if (mSocket)
00174 {
00175 SDLNet_TCP_Close(mSocket);
00176 mSocket = 0;
00177 }
00178 }
00179
00180 void Network::registerHandler(MessageHandler *handler)
00181 {
00182 for (const Uint16 *i = handler->handledMessages; *i; ++i)
00183 {
00184 mMessageHandlers[*i] = handler;
00185 }
00186
00187 handler->setNetwork(this);
00188 }
00189
00190 void Network::unregisterHandler(MessageHandler *handler)
00191 {
00192 for (const Uint16 *i = handler->handledMessages; *i; ++i)
00193 {
00194 mMessageHandlers.erase(*i);
00195 }
00196
00197 handler->setNetwork(0);
00198 }
00199
00200 void Network::clearHandlers()
00201 {
00202 MessageHandlerIterator i;
00203 for (i = mMessageHandlers.begin(); i != mMessageHandlers.end(); ++i)
00204 {
00205 i->second->setNetwork(0);
00206 }
00207 mMessageHandlers.clear();
00208 }
00209
00210 void Network::dispatchMessages()
00211 {
00212 while (messageReady())
00213 {
00214 MessageIn msg = getNextMessage();
00215
00216 MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
00217
00218 if (iter != mMessageHandlers.end())
00219 iter->second->handleMessage(msg);
00220 else
00221 logger->log("Unhandled packet: %x", msg.getId());
00222
00223 skip(msg.getLength());
00224 }
00225 }
00226
00227 void Network::flush()
00228 {
00229 if (!mOutSize || mState != CONNECTED)
00230 return;
00231
00232 int ret;
00233
00234
00235 SDL_mutexP(mMutex);
00236 ret = SDLNet_TCP_Send(mSocket, mOutBuffer, mOutSize);
00237 if (ret < (int)mOutSize)
00238 {
00239 setError("Error in SDLNet_TCP_Send(): " +
00240 std::string(SDLNet_GetError()));
00241 }
00242 mOutSize = 0;
00243 SDL_mutexV(mMutex);
00244 }
00245
00246 void Network::skip(int len)
00247 {
00248 SDL_mutexP(mMutex);
00249 mToSkip += len;
00250 if (!mInSize)
00251 {
00252 SDL_mutexV(mMutex);
00253 return;
00254 }
00255
00256 if (mInSize >= mToSkip)
00257 {
00258 mInSize -= mToSkip;
00259 memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
00260 mToSkip = 0;
00261 }
00262 else
00263 {
00264 mToSkip -= mInSize;
00265 mInSize = 0;
00266 }
00267 SDL_mutexV(mMutex);
00268 }
00269
00270 bool Network::messageReady()
00271 {
00272 int len = -1;
00273
00274 SDL_mutexP(mMutex);
00275 if (mInSize >= 2)
00276 {
00277 len = packet_lengths[readWord(0)];
00278
00279 if (len == -1 && mInSize > 4)
00280 len = readWord(2);
00281
00282 }
00283
00284 bool ret = (mInSize >= static_cast<unsigned int>(len));
00285 SDL_mutexV(mMutex);
00286
00287 return ret;
00288 }
00289
00290 MessageIn Network::getNextMessage()
00291 {
00292 while (!messageReady())
00293 {
00294 if (mState == NET_ERROR)
00295 break;
00296 }
00297
00298 SDL_mutexP(mMutex);
00299 int msgId = readWord(0);
00300 int len = packet_lengths[msgId];
00301
00302 if (len == -1)
00303 len = readWord(2);
00304
00305 #ifdef DEBUG
00306 logger->log("Received packet 0x%x of length %d", msgId, len);
00307 #endif
00308
00309 MessageIn msg(mInBuffer, len);
00310 SDL_mutexV(mMutex);
00311
00312 return msg;
00313 }
00314
00315 bool Network::realConnect()
00316 {
00317 IPaddress ipAddress;
00318
00319 if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
00320 {
00321 std::string error = "Unable to resolve host \"" + mAddress + "\"";
00322 setError(error);
00323 logger->log("SDLNet_ResolveHost: %s", error.c_str());
00324 return false;
00325 }
00326
00327 mState = CONNECTING;
00328
00329 mSocket = SDLNet_TCP_Open(&ipAddress);
00330 if (!mSocket)
00331 {
00332 logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
00333 setError(SDLNet_GetError());
00334 return false;
00335 }
00336
00337 logger->log("Network::Started session with %s:%i",
00338 ipToString(ipAddress.host), ipAddress.port);
00339
00340 mState = CONNECTED;
00341
00342 return true;
00343 }
00344
00345 void Network::receive()
00346 {
00347 SDLNet_SocketSet set;
00348
00349 if (!(set = SDLNet_AllocSocketSet(1)))
00350 {
00351 setError("Error in SDLNet_AllocSocketSet(): " +
00352 std::string(SDLNet_GetError()));
00353 return;
00354 }
00355
00356 if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
00357 {
00358 setError("Error in SDLNet_AddSocket(): " +
00359 std::string(SDLNet_GetError()));
00360 }
00361
00362 while (mState == CONNECTED)
00363 {
00364
00365
00366 int numReady = SDLNet_CheckSockets(set, ((Uint32)500));
00367 int ret;
00368 switch (numReady)
00369 {
00370 case -1:
00371 logger->log("Error: SDLNet_CheckSockets");
00372
00373 case 0:
00374 break;
00375
00376 case 1:
00377
00378 SDL_mutexP(mMutex);
00379 ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
00380
00381 if (!ret)
00382 {
00383
00384 mState = IDLE;
00385 logger->log("Disconnected.");
00386 }
00387 else if (ret < 0)
00388 {
00389 setError("Error in SDLNet_TCP_Recv(): " +
00390 std::string(SDLNet_GetError()));
00391 }
00392 else {
00393 mInSize += ret;
00394 if (mToSkip)
00395 {
00396 if (mInSize >= mToSkip)
00397 {
00398 mInSize -= mToSkip;
00399 memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
00400 mToSkip = 0;
00401 }
00402 else
00403 {
00404 mToSkip -= mInSize;
00405 mInSize = 0;
00406 }
00407 }
00408 }
00409 SDL_mutexV(mMutex);
00410 break;
00411
00412 default:
00413
00414
00415 std::stringstream errorStream;
00416 errorStream << "Error in SDLNet_TCP_Recv(), " << numReady
00417 << " sockets are ready: " << SDLNet_GetError();
00418 setError(errorStream.str());
00419 break;
00420 }
00421 }
00422
00423 if (SDLNet_TCP_DelSocket(set, mSocket) == -1)
00424 {
00425 logger->log("Error in SDLNet_DelSocket(): %s", SDLNet_GetError());
00426 }
00427
00428 SDLNet_FreeSocketSet(set);
00429 }
00430
00431 Network *Network::instance()
00432 {
00433 return mInstance;
00434 }
00435
00436 void Network::setError(const std::string &error)
00437 {
00438 logger->log("Network error: %s", error.c_str());
00439 mError = error;
00440 mState = NET_ERROR;
00441 }
00442
00443 Uint16 Network::readWord(int pos)
00444 {
00445 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00446 return SDL_Swap16((*(Uint16*)(mInBuffer+(pos))));
00447 #else
00448 return (*(Uint16*)(mInBuffer+(pos)));
00449 #endif
00450 }