From 01591924a4f33d5a5e4a86db6c256c8ce797a820 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 20 Aug 2006 00:56:23 +0000 Subject: The Network can now connect to the three servers and affected methods now take the server type as a parameter. The MessageOut gained a convenience constructor (same as was added server side). The game states during login sequence have been renamed and redone in order to ensure no communication is attempted to unconnected servers. This allowed the removal of the outgoing message queue. Connecting to the account server has been moved before the login/register phase (dialogs will still need to be updated). Quite a few things are expected to be broken since I'm rather tired at the moment. I've left many TODO entries in the code. --- ChangeLog | 19 +++++ src/gui/char_select.cpp | 8 +- src/gui/connection.cpp | 4 +- src/gui/gui.cpp | 2 +- src/gui/login.cpp | 7 +- src/gui/register.cpp | 4 +- src/gui/updatewindow.cpp | 6 +- src/main.cpp | 189 +++++++++++++++++++++++------------------- src/main.h | 30 +++---- src/net/charserverhandler.cpp | 22 +++-- src/net/loginhandler.cpp | 8 +- src/net/maploginhandler.cpp | 4 +- src/net/messageout.cpp | 8 ++ src/net/messageout.h | 5 ++ src/net/network.cpp | 153 ++++++++++++++++++++++------------ src/net/network.h | 59 +++++++------ 16 files changed, 323 insertions(+), 205 deletions(-) diff --git a/ChangeLog b/ChangeLog index a9596e29..c4cb401c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-08-20 Bjørn Lindeijer + + * src/gui/connection.cpp, src/gui/login.cpp, src/gui/gui.cpp, + src/gui/updatewindow.cpp, src/gui/char_select.cpp, + src/gui/register.cpp, src/main.cpp, src/net/loginhandler.cpp, + src/net/messageout.cpp, src/net/network.h, + src/net/charserverhandler.cpp, src/net/maploginhandler.cpp, + src/net/messageout.h, src/net/network.cpp, src/main.h: The Network + can now connect to the three servers and affected methods now take the + server type as a parameter. The MessageOut gained a convenience + constructor (same as was added server side). The game states during + login sequence have been renamed and redone in order to ensure no + communication is attempted to unconnected servers. This allowed the + removal of the outgoing message queue. Connecting to the account + server has been moved before the login/register phase (dialogs will + still need to be updated). Quite a few things are expected to be + broken since I'm rather tired at the moment. I've left many TODO + entries in the code. + 2006-08-19 Bjørn Lindeijer * src/game.cpp, src/net/network.h, src/net/network.cpp: Removed diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 775ecc6f..2fa6c68e 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -139,7 +139,7 @@ void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget) } else if (eventId == "cancel") { - state = EXIT_STATE; + state = STATE_EXIT; } else if (eventId == "new") { @@ -208,7 +208,7 @@ void CharSelectDialog::attemptCharDelete() msg.writeShort(PAMSG_CHAR_DELETE); // TODO: Send the selected slot msg.writeByte(0); - network->send(msg); + network->send(Network::ACCOUNT, msg); mCharInfo->lock(); } @@ -218,7 +218,7 @@ void CharSelectDialog::attemptCharSelect() MessageOut msg; msg.writeShort(PAMSG_CHAR_SELECT); msg.writeByte(mCharInfo->getPos()); - network->send(msg); + network->send(Network::ACCOUNT, msg); mCharInfo->lock(); } @@ -337,5 +337,5 @@ void CharCreateDialog::attemptCharCreate() outMsg.writeShort(10); // INT outMsg.writeShort(10); // DEX outMsg.writeShort(10); // LUK - network->send(outMsg); + network->send(Network::ACCOUNT, outMsg); } diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp index f7fdaca6..a29008c3 100644 --- a/src/gui/connection.cpp +++ b/src/gui/connection.cpp @@ -35,7 +35,9 @@ namespace { struct ConnectionActionListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { state = EXIT_STATE; } + void action(const std::string &eventId, gcn::Widget *widget) { + state = STATE_EXIT; + } } listener; } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 026f24bd..0e200db3 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -234,7 +234,7 @@ Gui::mousePress(int mx, int my, int button) // Mouse pressed on window container (basically, the map) // Are we in-game yet? - if (state != GAME_STATE) + if (state != STATE_GAME) return; // Check if we are alive and kickin' diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 2f646bd1..cb16dcb4 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -147,18 +147,17 @@ LoginDialog::action(const std::string &eventId, gcn::Widget *widget) mLoginData->remember = mKeepCheck->isMarked(); mOkButton->setEnabled(false); - //mCancelButton->setEnabled(false); mRegisterButton->setEnabled(false); - state = ACCOUNT_STATE; + state = STATE_LOGIN_ATTEMPT; } } else if (eventId == "cancel") { - state = EXIT_STATE; + state = STATE_EXIT; } else if (eventId == "register") { - state = REGISTER_STATE; + state = STATE_REGISTER; } } diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 49da10b6..52833aea 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -119,7 +119,7 @@ RegisterDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "cancel") { - state = EXIT_STATE; + state = STATE_EXIT; } else if (eventId == "register") { @@ -205,7 +205,7 @@ RegisterDialog::action(const std::string &eventId, gcn::Widget *widget) mLoginData->password = mPasswordField->getText(); mLoginData->email = mEmailField->getText(); - state = REGISTER_ACCOUNT_STATE; + state = STATE_REGISTER_ATTEMPT; } } } diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 8c69d3ef..77a026fe 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -136,7 +136,7 @@ void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) // Skip the updating process if (mDownloadStatus == UPDATE_COMPLETE) { - state = EXIT_STATE; + state = STATE_EXIT; } else { @@ -145,7 +145,7 @@ void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) } else if (eventId == "play") { - state = LOGIN_STATE; + state = STATE_LOGIN; } } @@ -198,7 +198,7 @@ int UpdaterWindow::updateProgress(void *ptr, uw->mCurrentFile + " (" + toString((int)progress * 100) + "%)"); uw->setProgress(progress); - if (state != UPDATE_STATE || uw->mDownloadStatus == UPDATE_ERROR) + if (state != STATE_UPDATE || uw->mDownloadStatus == UPDATE_ERROR) { // If the action was canceled return an error code to stop the mThread return -1; diff --git a/src/main.cpp b/src/main.cpp index dc76846e..d62594c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,7 +99,9 @@ Logger *logger; /**< Log object */ namespace { struct ErrorListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { state = LOGIN_STATE; } + void action(const std::string &eventId, gcn::Widget *widget) { + state = STATE_CHOOSE_SERVER; + } } errorListener; } @@ -267,7 +269,7 @@ void init_engine() } gui = new Gui(graphics); - state = UPDATE_STATE; /**< Initial game state */ + state = STATE_CHOOSE_SERVER; /**< Initial game state */ // Initialize sound engine try { @@ -278,7 +280,7 @@ void init_engine() sound.setMusicVolume((int)config.getValue("musicVolume", 60)); } catch (const char *err) { - state = ERROR_STATE; + state = STATE_ERROR; errorMessage = err; logger->log("Warning: %s", err); } @@ -409,9 +411,7 @@ MapLoginHandler mapLoginHandler; // TODO Find some nice place for these functions void accountLogin(LoginData *loginData) { - logger->log("Trying to connect to account server..."); logger->log("Username is %s", loginData->username.c_str()); - network->connect(loginData->hostname, loginData->port); network->registerHandler(&loginHandler); network->registerHandler(&charServerHandler); loginHandler.setLoginData(loginData); @@ -419,12 +419,11 @@ void accountLogin(LoginData *loginData) charServerHandler.setCharInfo(&charInfo); // Send login infos - MessageOut msg; - msg.writeShort(PAMSG_LOGIN); + MessageOut msg(PAMSG_LOGIN); msg.writeLong(0); // client version msg.writeString(loginData->username); msg.writeString(loginData->password); - network->send(msg); + network->send(Network::ACCOUNT, msg); // Clear the password, avoids auto login when returning to login loginData->password = ""; @@ -440,40 +439,37 @@ void accountLogin(LoginData *loginData) void accountRegister(LoginData *loginData) { - logger->log("Trying to connect to account server..."); logger->log("Username is %s", loginData->username.c_str()); - network->connect(loginData->hostname, loginData->port); network->registerHandler(&loginHandler); loginHandler.setLoginData(loginData); charServerHandler.setLoginData(loginData); charServerHandler.setCharInfo(&charInfo); // Send login infos - MessageOut msg; - msg.writeShort(PAMSG_REGISTER); + MessageOut msg(PAMSG_REGISTER); msg.writeLong(0); // client version msg.writeString(loginData->username); msg.writeString(loginData->password); msg.writeString(loginData->email); - network->send(msg); + network->send(Network::ACCOUNT, msg); } void mapLogin(Network *network, LoginData *loginData) { - MessageOut outMsg; - - logger->log("Trying to connect to map server..."); + // TODO: Before the client has been identified using the magic token, the + // map path is not known yet. logger->log("Map: %s", map_path.c_str()); - network->connect(loginData->hostname, loginData->port); network->registerHandler(&mapLoginHandler); // Send login infos - outMsg.writeShort(0x0072); - outMsg.writeLong(loginData->account_ID); - outMsg.writeLong(player_node->mCharId); - outMsg.writeLong(loginData->session_ID1); - outMsg.writeLong(loginData->session_ID2); + // TODO: The token would need to be sent to complete client identification + // for the game server + //MessageOut outMsg(0x0072); + //outMsg.writeLong(loginData->account_ID); + //outMsg.writeLong(player_node->mCharId); + //outMsg.writeLong(loginData->session_ID1); + //outMsg.writeLong(loginData->session_ID2); } /** Main */ @@ -515,13 +511,6 @@ int main(int argc, char *argv[]) init_engine(); - if (options.skipUpdate && state != ERROR_STATE) { - state = LOGIN_STATE; - } - else { - state = UPDATE_STATE; - } - unsigned int oldstate = !state; // We start with a status change. Window *currentDialog = NULL; @@ -549,20 +538,21 @@ int main(int argc, char *argv[]) } network = new Network(); + SDL_Event event; - while (state != EXIT_STATE) + while (state != STATE_EXIT) { // Handle SDL events while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: - state = EXIT_STATE; + state = STATE_EXIT; break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) - state = EXIT_STATE; + state = STATE_EXIT; break; } @@ -574,7 +564,7 @@ int main(int argc, char *argv[]) if (network->getState() == Network::NET_ERROR) { - state = ERROR_STATE; + state = STATE_ERROR; errorMessage = "Got disconnected from server!"; } @@ -596,48 +586,89 @@ int main(int argc, char *argv[]) gui->draw(); graphics->updateScreen(); + // TODO: Add connect timeout to go back to choose server + if (state == STATE_CONNECT_ACCOUNT && + network->isConnected(Network::ACCOUNT)) + { + if (options.skipUpdate) { + state = STATE_LOGIN; + } else { + state = STATE_UPDATE; + } + } + else if (state == STATE_CONNECT_GAME && + network->isConnected(Network::GAME) && + network->isConnected(Network::CHAT)) + { + // TODO: Somehow send the token + state = STATE_GAME; + } + if (state != oldstate) { - switch (oldstate) + // Load updates after exiting the update state + if (oldstate == STATE_UPDATE) { - case UPDATE_STATE: - loadUpdates(); - break; - - // Those states don't cause a network disconnect - case ACCOUNT_STATE: - case CONNECTING_STATE: - break; + loadUpdates(); + } - default: - network->disconnect(); - network->clearHandlers(); - break; + // Disconnect from account server once connected to game server + if (oldstate == STATE_CONNECT_GAME && state == STATE_GAME) + { + network->disconnect(Network::ACCOUNT); } oldstate = state; - if (currentDialog && state != ACCOUNT_STATE && - state != CHAR_CONNECT_STATE) { + // Get rid of the dialog of the previous state + if (currentDialog) { delete currentDialog; currentDialog = NULL; } switch (state) { - case LOGIN_STATE: + case STATE_CHOOSE_SERVER: + logger->log("State: CHOOSE_SERVER"); + // TODO: Allow changing this using a server choice dialog + logger->log("Trying to connect to account server..."); + network->connect(Network::ACCOUNT, + loginData.hostname, loginData.port); + state = STATE_CONNECT_ACCOUNT; + break; + + case STATE_CONNECT_ACCOUNT: + logger->log("State: CONNECT_ACCOUNT"); + break; + + case STATE_UPDATE: + logger->log("State: UPDATE"); + // TODO: Revive later + //currentDialog = new UpdaterWindow(); + state = STATE_LOGIN; + break; + + case STATE_LOGIN: logger->log("State: LOGIN"); - if (!loginData.password.empty()) { - state = ACCOUNT_STATE; - } else { - currentDialog = new LoginDialog(&loginData); - } + currentDialog = new LoginDialog(&loginData); + // TODO: Restore autologin + //if (!loginData.password.empty()) { + // accountLogin(&loginData); + //} + break; + + case STATE_LOGIN_ATTEMPT: + accountLogin(&loginData); break; - case REGISTER_STATE: + case STATE_REGISTER: logger->log("State: REGISTER"); currentDialog = new RegisterDialog(&loginData); break; - case CHAR_SELECT_STATE: + case STATE_REGISTER_ATTEMPT: + accountRegister(&loginData); + break; + + case STATE_CHAR_SELECT: logger->log("State: CHAR_SELECT"); currentDialog = new CharSelectDialog(network, &charInfo); if (options.chooseDefault) { @@ -646,50 +677,38 @@ int main(int argc, char *argv[]) } break; - case GAME_STATE: - sound.fadeOutMusic(1000); - - currentDialog = NULL; - login_wallpaper->decRef(); - login_wallpaper = NULL; - - logger->log("State: GAME"); - game = new Game(network); - game->logic(); - delete game; - state = EXIT_STATE; - break; - - case UPDATE_STATE: - logger->log("State: UPDATE"); - currentDialog = new UpdaterWindow(); - break; - - case ERROR_STATE: + case STATE_ERROR: logger->log("State: ERROR"); currentDialog = new OkDialog("Error", errorMessage); currentDialog->addActionListener(&errorListener); currentDialog = NULL; // OkDialog deletes itself - network->disconnect(); + network->disconnect(Network::GAME); + network->disconnect(Network::CHAT); network->clearHandlers(); break; - case CONNECTING_STATE: - logger->log("State: CONNECTING"); + case STATE_CONNECT_GAME: + logger->log("State: CONNECT_GAME"); mapLogin(network, &loginData); currentDialog = new ConnectionDialog(); break; - case ACCOUNT_STATE: - accountLogin(&loginData); - break; + case STATE_GAME: + sound.fadeOutMusic(1000); - case REGISTER_ACCOUNT_STATE: - accountRegister(&loginData); + currentDialog = NULL; + login_wallpaper->decRef(); + login_wallpaper = NULL; + + logger->log("State: GAME"); + game = new Game(network); + game->logic(); + delete game; + state = STATE_EXIT; break; default: - state = EXIT_STATE; + state = STATE_EXIT; break; } } diff --git a/src/main.h b/src/main.h index 035b0ec7..47c650af 100644 --- a/src/main.h +++ b/src/main.h @@ -39,20 +39,20 @@ enum { - EXIT_STATE, - LOGIN_STATE, - ACCOUNT_STATE, - REGISTER_STATE, - REGISTER_ACCOUNT_STATE, - CHAR_CONNECT_STATE, - CHAR_SERVER_STATE, - CHAR_SELECT_STATE, - CHAR_NEW_STATE, - CHAR_DEL_STATE, - GAME_STATE, - ERROR_STATE, - UPDATE_STATE, - CONNECTING_STATE + STATE_CHOOSE_SERVER, + STATE_CONNECT_ACCOUNT, + STATE_UPDATE, + STATE_LOGIN, + STATE_LOGIN_ATTEMPT, + STATE_REGISTER, + STATE_REGISTER_ATTEMPT, + STATE_CHAR_SELECT, + STATE_CHAR_NEW, + STATE_CHAR_DELETE, + STATE_ERROR, + STATE_CONNECT_GAME, + STATE_GAME, + STATE_EXIT }; /* length definitions for several char[]s in order @@ -66,7 +66,7 @@ enum { LEN_MIN_PASSWORD = 4 }; -extern char n_server, n_character; +extern char n_character; extern unsigned char state; extern std::string errorMessage; diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp index b8cc710e..ea9b3196 100644 --- a/src/net/charserverhandler.cpp +++ b/src/net/charserverhandler.cpp @@ -165,14 +165,20 @@ CharServerHandler::handleCharSelectResponse(MessageIn &msg) if (errMsg == 0) { - //std::string token = msg.readString(32); - //std::string gameServer = msg.readString(); - //unsigned short gameServerPort = msg.readShort(); - //std::string chatServer = msg.readString(); - //unsigned short chatServerPort = msg.readShort(); - - // TODO: Connect to game and chat servers, and login using the given - // TODO: token. + // TODO: Somehow be able to send this token once connected + std::string token = msg.readString(32); + std::string gameServer = msg.readString(); + unsigned short gameServerPort = msg.readShort(); + std::string chatServer = msg.readString(); + unsigned short chatServerPort = msg.readShort(); + + logger->log("Game server: %s:%d", gameServer.c_str(), gameServerPort); + logger->log("Chat server: %s:%d", chatServer.c_str(), chatServerPort); + + network->connect(Network::GAME, gameServer, gameServerPort); + network->connect(Network::CHAT, chatServer, chatServerPort); + + state = STATE_CONNECT_GAME; } } diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp index 27d8eed5..4790d7d1 100644 --- a/src/net/loginhandler.cpp +++ b/src/net/loginhandler.cpp @@ -51,7 +51,7 @@ void LoginHandler::handleMessage(MessageIn *msg) // Successful login if (errMsg == ERRMSG_OK) { - state = CHAR_SELECT_STATE; + state = STATE_CHAR_SELECT; } // Login failed else @@ -73,7 +73,7 @@ void LoginHandler::handleMessage(MessageIn *msg) errorMessage = "Unknown error"; break; } - state = ERROR_STATE; + state = STATE_ERROR; } } break; @@ -83,7 +83,7 @@ void LoginHandler::handleMessage(MessageIn *msg) // Successful registration if (errMsg == ERRMSG_OK) { - state = ACCOUNT_STATE; + state = STATE_CHAR_SELECT; } // Registration failed else @@ -105,7 +105,7 @@ void LoginHandler::handleMessage(MessageIn *msg) errorMessage = "Unknown error"; break; } - state = ERROR_STATE; + state = STATE_ERROR; } } break; diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp index 38ed2203..579e8542 100644 --- a/src/net/maploginhandler.cpp +++ b/src/net/maploginhandler.cpp @@ -50,12 +50,12 @@ void MapLoginHandler::handleMessage(MessageIn *msg) msg->readLong(); // server tick //logger->log("Protocol: Player start position: (%d, %d), Direction: %d", // player_node->mX, player_node->mY, direction); - state = GAME_STATE; + state = STATE_GAME; break; case 0x0081: logger->log("Warning: Map server D/C"); - state = ERROR_STATE; + state = STATE_ERROR; break; } } diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp index 7f5fadcb..426a1c0d 100644 --- a/src/net/messageout.cpp +++ b/src/net/messageout.cpp @@ -36,6 +36,14 @@ MessageOut::MessageOut(): { } +MessageOut::MessageOut(short id): + mData(0), + mDataSize(0), + mPos(0) +{ + writeShort(id); +} + MessageOut::~MessageOut() { if (mData) { diff --git a/src/net/messageout.h b/src/net/messageout.h index 22754f60..81369c0e 100644 --- a/src/net/messageout.h +++ b/src/net/messageout.h @@ -37,6 +37,11 @@ class MessageOut */ MessageOut(); + /** + * Constructor. + */ + MessageOut(short id); + /** * Destructor. */ diff --git a/src/net/network.cpp b/src/net/network.cpp index f543bfb1..23d9e291 100644 --- a/src/net/network.cpp +++ b/src/net/network.cpp @@ -32,47 +32,55 @@ Network *network; Network::Network(): - mClient(0), mServer(0), - mAddress(), mPort(0), - mState(IDLE) + mAccountServer(NULL), + mGameServer(NULL), + mChatServer(NULL), + mState(NET_OK) { + mClient = enet_host_create(NULL, 3, 0, 0); + + if (!mClient) + { + logger->error( + "An error occurred while trying to create an ENet client."); + mState = NET_ERROR; + } } Network::~Network() { clearHandlers(); - if (mState != IDLE && mState != NET_ERROR) - disconnect(); + disconnect(ACCOUNT); + disconnect(GAME); + disconnect(CHAT); } -bool Network::connect(const std::string &address, short port) +bool +Network::connect(Server server, const std::string &address, short port) { - if (mState != IDLE && mState != NET_ERROR) - { - logger->log("Tried to connect an already connected socket!"); - return false; - } + logger->log("Network::connect(%d, %s, %i)", server, address.c_str(), port); if (address.empty()) { - logger->log("Empty address given to Network::connect()!"); + logger->log("Network::connect() got empty address!"); mState = NET_ERROR; return false; } - logger->log("Network::Connecting to %s:%i", address.c_str(), port); - - mAddress = address; - mPort = port; + ENetPeer *peer = NULL; - mState = CONNECTING; - - mClient = enet_host_create(NULL, 1, 0, 0); + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } - if (!mClient) + if (peer != NULL) { - logger->error("An error occurred while trying to create an ENet client."); + logger->log("Network::connect() already connected (or connecting) to " + "this server!"); + return false; } ENetAddress enetAddress; @@ -81,32 +89,51 @@ bool Network::connect(const std::string &address, short port) enetAddress.port = port; // Initiate the connection, allocating channel 0. - mServer = enet_host_connect(mClient, &enetAddress, 1); + peer = enet_host_connect(mClient, &enetAddress, 1); - if (mServer == 0) + if (peer == NULL) { logger->log("Unable to initiate connection to the server."); mState = NET_ERROR; return false; } + switch (server) { + case ACCOUNT: mAccountServer = peer; break; + case GAME: mGameServer = peer; break; + case CHAT: mChatServer = peer; break; + } + return true; } -void Network::disconnect() +void +Network::disconnect(Server server) { - mState = IDLE; + ENetPeer *peer = NULL; - if (mServer) + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } + + if (peer) { - enet_peer_disconnect(mServer, 0); + enet_peer_disconnect(peer, 0); enet_host_flush(mClient); - enet_peer_reset(mServer); - mServer = 0; + enet_peer_reset(peer); + + switch (server) { + case ACCOUNT: mAccountServer = NULL; break; + case GAME: mGameServer = NULL; break; + case CHAT: mChatServer = NULL; break; + } } } -void Network::registerHandler(MessageHandler *handler) +void +Network::registerHandler(MessageHandler *handler) { const Uint16 *i = handler->handledMessages; @@ -119,7 +146,8 @@ void Network::registerHandler(MessageHandler *handler) handler->setNetwork(this); } -void Network::unregisterHandler(MessageHandler *handler) +void +Network::unregisterHandler(MessageHandler *handler) { for (const Uint16 *i = handler->handledMessages; *i; i++) { @@ -129,7 +157,8 @@ void Network::unregisterHandler(MessageHandler *handler) handler->setNetwork(0); } -void Network::clearHandlers() +void +Network::clearHandlers() { MessageHandlerIterator i; for (i = mMessageHandlers.begin(); i != mMessageHandlers.end(); i++) @@ -139,6 +168,20 @@ void Network::clearHandlers() mMessageHandlers.clear(); } +bool +Network::isConnected(Server server) const +{ + ENetPeer *peer = NULL; + + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } + + return peer->state == ENET_PEER_STATE_CONNECTED; +} + void Network::dispatchMessage(ENetPacket *packet) { @@ -162,7 +205,7 @@ Network::dispatchMessage(ENetPacket *packet) void Network::flush() { - if (mState == IDLE || mState == NET_ERROR) + if (mState == NET_ERROR) { return; } @@ -176,7 +219,6 @@ void Network::flush() { case ENET_EVENT_TYPE_CONNECT: logger->log("Connected."); - mState = CONNECTED; // Store any relevant server information here. event.peer->data = 0; break; @@ -185,46 +227,53 @@ void Network::flush() logger->log("Incoming data..."); dispatchMessage(event.packet); break; + case ENET_EVENT_TYPE_DISCONNECT: - mState = IDLE; logger->log("Disconnected."); // Reset the server information. event.peer->data = 0; break; + case ENET_EVENT_TYPE_NONE: logger->log("No event during 10 milliseconds."); break; + default: logger->log("Unhandled enet event."); break; } } - - // If connected, manage incoming and outcoming packets - if (isConnected()) - { - while (isConnected() && !mOutgoingPackets.empty()) - { - ENetPacket *packet = mOutgoingPackets.front(); - enet_peer_send(mServer, 0, packet); - mOutgoingPackets.pop(); - } - } } -void Network::send(const MessageOut &msg) +void Network::send(Server server, const MessageOut &msg) { - if (mState == IDLE || mState == NET_ERROR) + if (mState == NET_ERROR) { logger->log("Warning: attempt to send a message while network not " "ready."); return; } - ENetPacket *packet = enet_packet_create(msg.getData(), - msg.getDataSize(), - ENET_PACKET_FLAG_RELIABLE); - mOutgoingPackets.push(packet); + ENetPeer *peer = NULL; + + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } + + if (peer) + { + logger->log("Sending message of size %d to server %d...", + msg.getDataSize(), server); + + // Directly send away the packet (TODO: check what ENet does in case + // this is done before connection is ready) + ENetPacket *packet = enet_packet_create(msg.getData(), + msg.getDataSize(), + ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(peer, 0, packet); + } } char *iptostring(int address) diff --git a/src/net/network.h b/src/net/network.h index eb2ce8ab..49583b9d 100644 --- a/src/net/network.h +++ b/src/net/network.h @@ -36,8 +36,6 @@ class MessageHandler; class MessageIn; class MessageOut; -class Network; - class Network { public: @@ -46,35 +44,53 @@ class Network Network(); ~Network(); - bool connect(const std::string &address, short port); - void disconnect(); + typedef enum { + ACCOUNT, + GAME, + CHAT + } Server; + + bool + connect(Server server, const std::string &address, short port); + + void + disconnect(Server server); + + void + registerHandler(MessageHandler *handler); + + void + unregisterHandler(MessageHandler *handler); - void registerHandler(MessageHandler *handler); - void unregisterHandler(MessageHandler *handler); - void clearHandlers(); + void + clearHandlers(); - int getState() const { return mState; } - bool isConnected() const { return mState == CONNECTED; } + int + getState() const { return mState; } - void dispatchMessage(ENetPacket *packet); - void flush(); + bool + isConnected(Server server) const; - void send(const MessageOut &msg); + void + dispatchMessage(ENetPacket *packet); + + void + flush(); + + void + send(Server server, const MessageOut &msg); enum State { - IDLE, - CONNECTED, - CONNECTING, - DATA, + NET_OK, NET_ERROR }; private: ENetHost *mClient; - ENetPeer *mServer; - std::string mAddress; - short mPort; + ENetPeer *mAccountServer; + ENetPeer *mGameServer; + ENetPeer *mChatServer; unsigned int mToSkip; @@ -83,11 +99,6 @@ class Network typedef std::map MessageHandlers; typedef MessageHandlers::iterator MessageHandlerIterator; MessageHandlers mMessageHandlers; - - std::queue mOutgoingPackets; - - bool realConnect(); - void receive(); }; /** Convert an address from int format to string */ -- cgit v1.2.3-70-g09d2