summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugenio Favalli <elvenprogrammer@gmail.com>2006-04-28 12:08:06 +0000
committerEugenio Favalli <elvenprogrammer@gmail.com>2006-04-28 12:08:06 +0000
commit184aae8cb1fb072b40d63f69c569d92ad7ed2eef (patch)
treeaf33d3deaf9bfe3d932a508c8d6cd7e43ba59596
parent0adc743277b82b21c16b08a4722f5f4ab2096a59 (diff)
downloadmanaserv-184aae8cb1fb072b40d63f69c569d92ad7ed2eef.tar.gz
manaserv-184aae8cb1fb072b40d63f69c569d92ad7ed2eef.tar.bz2
manaserv-184aae8cb1fb072b40d63f69c569d92ad7ed2eef.tar.xz
manaserv-184aae8cb1fb072b40d63f69c569d92ad7ed2eef.zip
Merged enet_switch changes r2268:2309 into the trunk.
-rw-r--r--ChangeLog24
-rw-r--r--src/client.cpp1164
-rw-r--r--src/connectionhandler.cpp110
-rw-r--r--src/connectionhandler.h3
-rw-r--r--src/main.cpp79
-rw-r--r--src/messagein.cpp15
-rw-r--r--src/messageout.cpp20
-rw-r--r--src/messageout.h10
-rw-r--r--src/netcomputer.cpp12
-rw-r--r--src/netcomputer.h11
-rw-r--r--src/netsession.cpp86
-rw-r--r--src/netsession.h7
-rw-r--r--src/utils/logger.cpp3
-rw-r--r--tmwserv.dev2
14 files changed, 914 insertions, 632 deletions
diff --git a/ChangeLog b/ChangeLog
index cfde9af0..bca4bb63 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2006-04-11 Eugenio Favalli <elvenprogrammer@gmail.com>
+
+ * src/client.cpp, src/connectionhandler.cpp, tmwserv.dev: Updated some
+ code to latest enet version, and fixed a linking issue in windows.
+
+2006-03-26 Eugenio Favalli <elvenprogrammer@gmail.com>
+
+ * src/messagein.cpp, src/messageout.cpp: Got rid of SDL_net endianess
+ code.
+ * src/messagein.cpp: Fixed a mistake.
+
+2006-03-20 Eugenio Favalli <elvenprogrammer@gmail.com>
+
+ * src/client.cpp, src/connectionhandler.cpp, src/connectionhandler.h,
+ src/main.cpp, src/messagein.cpp, src/messageout.cpp,
+ src/netcomputer.cpp, src/netcomputer.h, src/netsession.cpp,
+ src/netsession.h, src/utils/logger.cpp, tmwserv.dev: Got rid of
+ SDL_net, now both server and test client use enet.
+
+2006-03-18 Eugenio Favalli <elvenprogrammer@gmail.com>
+
+ * src/client.cpp, src/messageout.cpp, src/messageout.h: Converted the
+ test client to use enet.
+
2006-03-14 Eugenio Favalli <elvenprogrammer@gmail.com>
* tmwserv.dev: Updated project file.
diff --git a/src/client.cpp b/src/client.cpp
index 87646f10..81f023c7 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -21,7 +21,7 @@
*/
#include <iostream>
-#include <SDL_net.h>
+#include <enet/enet.h>
#include "defines.h"
#include "messageout.h"
@@ -33,6 +33,8 @@
#define PACKAGE_VERSION PRODUCT_VERSION
#endif
+void parsePacket(char *data, int recvLength);
+
int main(int argc, char *argv[])
{
@@ -40,639 +42,665 @@ int main(int argc, char *argv[])
#include "../config.h"
#endif
std::cout << "The Mana World Test Client v" << PACKAGE_VERSION << std::endl;
-
- // Initialize SDL
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) {
- std::cout << "SDL_Init: " << SDL_GetError() << std::endl;
- exit(1);
+
+ if (enet_initialize () != 0)
+ {
+ printf("An error occurred while initializing ENet.\n");
+ return EXIT_FAILURE;
}
- // Set SDL to quit on exit
- atexit(SDL_Quit);
+ atexit(enet_deinitialize);
- // Initialize SDL_net
- if (SDLNet_Init() == -1) {
- std::cout << "SDLNet_Init: " << SDLNet_GetError() << std::endl;
- exit(2);
- }
+ ENetHost *client;
- // Try to connect to server
- IPaddress ip;
- TCPsocket tcpsock;
+ client = enet_host_create(NULL /* create a client host */,
+ 1 /* only allow 1 outgoing connection */,
+ 57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
+ 14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
- if (SDLNet_ResolveHost(&ip, "localhost", 9601) == -1) {
- std::cout << "SDLNet_ResolveHost: " << SDLNet_GetError() << std::endl;
- exit(1);
+ if (client == NULL)
+ {
+ printf("An error occurred while trying to create an ENet client host.\n");
+ exit (EXIT_FAILURE);
}
- tcpsock = SDLNet_TCP_Open(&ip);
- if (!tcpsock) {
- std::cout << "SDLNet_TCP_Open: " << SDLNet_GetError() << std::endl;
- exit(2);
- }
+ ENetAddress address;
+ ENetPeer *peer;
- std::cout << "Successfully connected!" << std::endl;
+ /* Connect to localhost:9601. */
+ enet_address_set_host(&address, "localhost");
+ address.port = 9601;
- int answer = 1;
- char line[256] = "";
+ /* Initiate the connection, allocating one channel. */
+ peer = enet_host_connect(client, &address, 1);
- while (answer != 0)
+ if (peer == NULL)
{
- bool responseRequired = true;
- MessageOut msg;
-
- std::cout << "0) Quit 9) Character selection" << std::endl;
- std::cout << "1) Register 10) Delete Character" << std::endl;
- std::cout << "2) Unregister 11) List Characters" << std::endl;
- std::cout << "3) Login 12) Move Character" << std::endl;
- std::cout << "4) Logout 13) Chat" << std::endl;
- std::cout << "5) Change Password 14) Equip Item" << std::endl;
- std::cout << "6) Change Email 15) Ruby Expression" << std::endl;
- std::cout << "7) Get Email" << std::endl;
- std::cout << "8) Create character" << std::endl;
- std::cout << "Choose your option: ";
- std::cin >> answer;
-
- switch (answer) {
- case 1:
- // Register
- msg.writeShort(CMSG_REGISTER);
- // We send the client version
- msg.writeString(PACKAGE_VERSION);
- std::cout << "Account name: ";
- std::cin >> line;
- msg.writeString(line);
- std::cout <<"Password: ";
- std::cin >> line;
- msg.writeString(line);
- std::cout << "Email address: ";
- std::cin >> line;
- msg.writeString(line);
- break;
-
- case 2:
- // Unregister (deleting an account)
- msg.writeShort(CMSG_UNREGISTER);
- std::cout << "Account name: ";
- std::cin >> line;
- msg.writeString(line);
- std::cout << "Password: ";
- std::cin >> line;
- msg.writeString(line);
- break;
+ printf("No available peers for initiating an ENet connection.\n");
+ exit (EXIT_FAILURE);
+ }
- case 3:
- // Login
- msg.writeShort(CMSG_LOGIN);
- // We send the client version
- msg.writeString(PACKAGE_VERSION);
- std::cout << "Account name: ";
- std::cin >> line;
- msg.writeString(line);
- std::cout << "Password: ";
- std::cin >> line;
- msg.writeString(line);
- break;
+ ENetEvent event;
+ bool exit = false;
+ bool connected = false;
+ int answer = 0;
+ char line[256] = "";
+ bool responseRequired = false;
- case 4:
- // Logout
- msg.writeShort(CMSG_LOGOUT);
- std::cout << "Logout" << std::endl;
- break;
+ printf("Starting client...\n");
- case 5:
- // Change Password
- msg.writeShort(CMSG_PASSWORD_CHANGE);
- std::cout << "Old Password: ";
- std::cin >> line;
- msg.writeString(line);
- std::cout << "New Password: ";
- std::cin >> line;
- msg.writeString(line);
- std::cout << "Retype new Password: ";
- std::cin >> line;
- msg.writeString(line);
- break;
+ /* Wait up to 1000 milliseconds for an event. */
+ while (!exit) {
+ if (connected) {
+ std::cout << std::endl;
+ std::cout << "0) Quit 9) Character selection" << std::endl;
+ std::cout << "1) Register 10) Delete Character" << std::endl;
+ std::cout << "2) Unregister 11) List Characters" << std::endl;
+ std::cout << "3) Login 12) Move Character" << std::endl;
+ std::cout << "4) Logout 13) Chat" << std::endl;
+ std::cout << "5) Change Password 14) Equip Item" << std::endl;
+ std::cout << "6) Change Email 15) Ruby Expression" << std::endl;
+ std::cout << "7) Get Email" << std::endl;
+ std::cout << "8) Create character" << std::endl;
+ std::cout << "Choose your option: ";
+ std::cin >> answer;
+
+ MessageOut msg;
+
+ switch (answer) {
+ case 0:
+ // Disconnection
+ if (connected) {
+ enet_peer_disconnect(&client->peers[0], 0);
+ }
+ exit = true;
+ break;
+
+ case 1:
+ // Register
+ msg.writeShort(CMSG_REGISTER);
+ // We send the client version
+ msg.writeString(PACKAGE_VERSION);
+ std::cout << "Account name: ";
+ std::cin >> line;
+ msg.writeString(line);
+ std::cout <<"Password: ";
+ std::cin >> line;
+ msg.writeString(line);
+ std::cout << "Email address: ";
+ std::cin >> line;
+ msg.writeString(line);
+ break;
- case 6:
- // Change Email
- msg.writeShort(CMSG_EMAIL_CHANGE);
- std::cout << "New Email: ";
- std::cin >> line;
- msg.writeString(line);
- break;
+ case 2:
+ // Unregister (deleting an account)
+ msg.writeShort(CMSG_UNREGISTER);
+ std::cout << "Account name: ";
+ std::cin >> line;
+ msg.writeString(line);
+ std::cout << "Password: ";
+ std::cin >> line;
+ msg.writeString(line);
+ break;
- case 7:
- // Get current Account's Email value
- msg.writeShort(CMSG_EMAIL_GET);
- break;
+ case 3:
+ // Login
+ msg.writeShort(CMSG_LOGIN);
+ // We send the client version
+ msg.writeString(PACKAGE_VERSION);
+ std::cout << "Account name: ";
+ std::cin >> line;
+ msg.writeString(line);
+ std::cout << "Password: ";
+ std::cin >> line;
+ msg.writeString(line);
+ break;
- case 8:
- {
- // Create character
- msg.writeShort(CMSG_CHAR_CREATE);
- std::cout << "Name: ";
- std::cin >> line;
- msg.writeString(line);
-
- std::cout << "Hair Style ID (0 - " << MAX_HAIRSTYLE_VALUE << "): ";
- std::cin >> line;
- msg.writeByte(atoi(line));
-
- std::cout << "Hair Color ID (0 - " << MAX_HAIRCOLOR_VALUE << "): ";
- std::cin >> line;
- msg.writeByte(atoi(line));
-
- std::cout << "Gender ID (0 - " << MAX_GENDER_VALUE << "): ";
- std::cin >> line;
- msg.writeByte(atoi(line));
-
- std::cout << "Strength: ";
- std::cin >> line;
- msg.writeShort(atoi(line));
-
- std::cout << "Agility: ";
- std::cin >> line;
- msg.writeShort(atoi(line));
-
- std::cout << "Vitality: ";
- std::cin >> line;
- msg.writeShort(atoi(line));
-
- std::cout << "Intelligence: ";
- std::cin >> line;
- msg.writeShort(atoi(line));
-
- std::cout << "Dexterity: ";
- std::cin >> line;
- msg.writeShort(atoi(line));
-
- std::cout << "Luck: ";
- std::cin >> line;
- msg.writeShort(atoi(line));
- } break;
+ case 4:
+ // Logout
+ msg.writeShort(CMSG_LOGOUT);
+ std::cout << "Logout" << std::endl;
+ break;
- case 9:
- {
- // Select character
- msg.writeShort(CMSG_CHAR_SELECT);
- std::cout << "Character ID: ";
- std::cin >> line;
- msg.writeByte(atoi(line));
- } break;
+ case 5:
+ // Change Password
+ msg.writeShort(CMSG_PASSWORD_CHANGE);
+ std::cout << "Old Password: ";
+ std::cin >> line;
+ msg.writeString(line);
+ std::cout << "New Password: ";
+ std::cin >> line;
+ msg.writeString(line);
+ std::cout << "Retype new Password: ";
+ std::cin >> line;
+ msg.writeString(line);
+ break;
- case 10:
- {
- // Delete character
- msg.writeShort(CMSG_CHAR_DELETE);
- std::cout << "Character ID: ";
- std::cin >> line;
- msg.writeByte(atoi(line));
- } break;
+ case 6:
+ // Change Email
+ msg.writeShort(CMSG_EMAIL_CHANGE);
+ std::cout << "New Email: ";
+ std::cin >> line;
+ msg.writeString(line);
+ break;
- case 11:
- {
- // List characters
- msg.writeShort(CMSG_CHAR_LIST);
- } break;
+ case 7:
+ // Get current Account's Email value
+ msg.writeShort(CMSG_EMAIL_GET);
+ break;
- case 12:
- {
- // Move character
- long x, y;
- std::cout << "X: ";
- std::cin >> x;
- std::cout << "Y: ";
- std::cin >> y;
-
- msg.writeShort(CMSG_WALK);
- msg.writeLong(x);
- msg.writeLong(y);
-
- responseRequired = false;
- } break;
+ case 8:
+ {
+ // Create character
+ msg.writeShort(CMSG_CHAR_CREATE);
+ std::cout << "Name: ";
+ std::cin >> line;
+ msg.writeString(line);
+
+ std::cout << "Hair Style ID (0 - " << MAX_HAIRSTYLE_VALUE << "): ";
+ std::cin >> line;
+ msg.writeByte(atoi(line));
+
+ std::cout << "Hair Color ID (0 - " << MAX_HAIRCOLOR_VALUE << "): ";
+ std::cin >> line;
+ msg.writeByte(atoi(line));
+
+ std::cout << "Gender ID (0 - " << MAX_GENDER_VALUE << "): ";
+ std::cin >> line;
+ msg.writeByte(atoi(line));
+
+ std::cout << "Strength: ";
+ std::cin >> line;
+ msg.writeShort(atoi(line));
+
+ std::cout << "Agility: ";
+ std::cin >> line;
+ msg.writeShort(atoi(line));
+
+ std::cout << "Vitality: ";
+ std::cin >> line;
+ msg.writeShort(atoi(line));
+
+ std::cout << "Intelligence: ";
+ std::cin >> line;
+ msg.writeShort(atoi(line));
+
+ std::cout << "Dexterity: ";
+ std::cin >> line;
+ msg.writeShort(atoi(line));
+
+ std::cout << "Luck: ";
+ std::cin >> line;
+ msg.writeShort(atoi(line));
+ } break;
+
+ case 9:
+ {
+ // Select character
+ msg.writeShort(CMSG_CHAR_SELECT);
+ std::cout << "Character ID: ";
+ std::cin >> line;
+ msg.writeByte(atoi(line));
+ } break;
+
+ case 10:
+ {
+ // Delete character
+ msg.writeShort(CMSG_CHAR_DELETE);
+ std::cout << "Character ID: ";
+ std::cin >> line;
+ msg.writeByte(atoi(line));
+ } break;
+
+ case 11:
+ {
+ // List characters
+ msg.writeShort(CMSG_CHAR_LIST);
+ } break;
+
+ case 12:
+ {
+ // Move character
+ long x, y;
+ std::cout << "X: ";
+ std::cin >> x;
+ std::cout << "Y: ";
+ std::cin >> y;
+
+ msg.writeShort(CMSG_WALK);
+ msg.writeLong(x);
+ msg.writeLong(y);
+
+ responseRequired = false;
+ } break;
+
+ case 13:
+ // Chat
+ msg.writeShort(CMSG_SAY);
+ std::cout << "Chat: ";
+ std::cin >> line;
+ msg.writeString(line);
+ msg.writeShort(0);
+ responseRequired = false;
+ break;
- case 13:
- // Chat
- msg.writeShort(CMSG_SAY);
- std::cout << "Chat: ";
- std::cin >> line;
- msg.writeString(line);
- msg.writeShort(0);
- responseRequired = false;
- break;
+ case 14:
+ {
+ // Equip
+ unsigned int itemId;
+ unsigned int slot;
+ std::cout << "Item ID: ";
+ std::cin >> itemId;
+ std::cout << "Slot: ";
+ std::cin >> slot;
+ msg.writeShort(CMSG_EQUIP);
+ msg.writeLong(itemId);
+ msg.writeByte(slot);
+ } break;
+
+ case 15:
+ {
+ std::cout << "Expr: ";
+ std::cin >> line;
+ msg.writeShort(0x800);
+ msg.writeString(line);
+
+ responseRequired = false;
+ } break;
- case 14:
- {
- // Equip
- unsigned int itemId;
- unsigned int slot;
- std::cout << "Item ID: ";
- std::cin >> itemId;
- std::cout << "Slot: ";
- std::cin >> slot;
- msg.writeShort(CMSG_EQUIP);
- msg.writeLong(itemId);
- msg.writeByte(slot);
- } break;
+ default:
+ continue;
+ break;
+ } // end switch
+
+ // Send prepared message
+ if (!exit && connected) {
+ ENetPacket *packet = enet_packet_create(
+ msg.getData(),
+ msg.getDataSize() + 1,
+ ENET_PACKET_FLAG_RELIABLE);
+ // Send the packet to the peer over channel id 0.
+ enet_peer_send(peer, 0, packet);
+ } // end if
+
+ } // end if
+
+ while (enet_host_service(client, &event, 1000)) {
+ switch (event.type) {
+ case ENET_EVENT_TYPE_CONNECT:
+ printf("Connected to server\n");
+ connected = true;
+ break;
- case 15:
- {
- std::cout << "Expr: ";
- std::cin >> line;
- msg.writeShort(0x800);
- msg.writeString(line);
+ case ENET_EVENT_TYPE_RECEIVE:
+ std::cout << "A packet of length "
+ << event.packet->dataLength
+ << " was received from "
+ << event.peer->address.host
+ << std::endl;
+
+ parsePacket((char *)event.packet->data,
+ event.packet->dataLength);
+
+ // Clean up the packet now that we're done using it.
+ enet_packet_destroy(event.packet);
+ break;
- responseRequired = false;
- } break;
+ case ENET_EVENT_TYPE_DISCONNECT:
+ printf("Disconected.\n");
+ connected = false;
+ break;
- default:
- continue;
- }
- std::cout << "Sent: " << std::endl;
+ default:
+ //printf("Unhandled enet event.\n");
+ break;
+ } // end switch
+ } // end while
- // Message hex
- for (unsigned int i = 0; i < msg.getPacket()->length; i++) {
- std::cout << int(msg.getPacket()->data[i]) << " ";
+ if (!connected) {
+ exit = true;
}
- std::cout << std::endl;
-
- SDLNet_TCP_Send(tcpsock, msg.getPacket()->data,
- msg.getPacket()->length);
+ } // end while
- // Raw Datas
- char data[1024];
- int recvLength = SDLNet_TCP_Recv(tcpsock, data, 1024);
+ if (connected) {
+ // The disconnection attempt didn't succeed yet. Force disconnection.
+ enet_peer_reset(&client->peers[0]);
+ }
+
+ enet_host_destroy(client);
- if (responseRequired) {
- std::cout << "Received: ";
- if (recvLength != -1) {
- for (unsigned int i = 0; i < recvLength; i++) {
- std::cout << int(data[i]) << " ";
- }
- } else {
- std::cout << "ERROR!" << std::endl;
- }
- std::cout << std::endl;
- }
+ return 0;
+}
- // Response handling
- // Transforming it into a MessageIn object
- if (recvLength >= 2)
- {
- Packet *packet = new Packet(data, recvLength);
- MessageIn msg(packet); // (MessageIn frees packet)
+void parsePacket(char *data, int recvLength) {
+ // Response handling
+ // Transforming it into a MessageIn object
+ if (recvLength >= 2) {
+ Packet *packet = new Packet(data, recvLength);
+ MessageIn msg(packet); // (MessageIn frees packet)
- switch (msg.getId()) {
- case SMSG_REGISTER_RESPONSE:
- // Register
- switch (msg.readByte())
- {
- case REGISTER_OK:
- std::cout << "Account registered." << std::endl;
+ switch (msg.getId()) {
+ case SMSG_REGISTER_RESPONSE:
+ // Register
+ switch (msg.readByte()) {
+ case REGISTER_OK:
+ std::cout << "Account registered." << std::endl;
break;
- case REGISTER_INVALID_USERNAME:
- std::cout << "Account registering: Invalid username." << std::endl;
+ case REGISTER_INVALID_USERNAME:
+ std::cout << "Account registering: Invalid username." << std::endl;
break;
- case REGISTER_INVALID_PASSWORD:
- std::cout << "Account registering: Invalid password." << std::endl;
+ case REGISTER_INVALID_PASSWORD:
+ std::cout << "Account registering: Invalid password." << std::endl;
break;
- case REGISTER_INVALID_EMAIL:
- std::cout << "Account registering: Invalid Email." << std::endl;
+ case REGISTER_INVALID_EMAIL:
+ std::cout << "Account registering: Invalid Email." << std::endl;
break;
- case REGISTER_INVALID_VERSION:
- std::cout << "Account registering: Invalid version." << std::endl;
+ case REGISTER_INVALID_VERSION:
+ std::cout << "Account registering: Invalid version." << std::endl;
break;
- case REGISTER_EXISTS_USERNAME:
- std::cout << "Account registering: Username already exists." << std::endl;
+ case REGISTER_EXISTS_USERNAME:
+ std::cout << "Account registering: Username already exists." << std::endl;
break;
- case REGISTER_EXISTS_EMAIL:
- std::cout << "Account registering: Email already exists." << std::endl;
+ case REGISTER_EXISTS_EMAIL:
+ std::cout << "Account registering: Email already exists." << std::endl;
break;
- default:
- case REGISTER_UNKNOWN:
- std::cout << "Account registering: Unknown error." << std::endl;
+ default:
+ case REGISTER_UNKNOWN:
+ std::cout << "Account registering: Unknown error." << std::endl;
break;
- }
- break;
+ }
+ break;
- case SMSG_UNREGISTER_RESPONSE:
- // Register
- switch (msg.readByte())
- {
- case UNREGISTER_OK:
- std::cout << "Account unregistered." << std::endl;
+ case SMSG_UNREGISTER_RESPONSE:
+ // Register
+ switch (msg.readByte()) {
+ case UNREGISTER_OK:
+ std::cout << "Account unregistered." << std::endl;
break;
- case UNREGISTER_INVALID_PASSWORD:
- std::cout << "Account unregistering: Invalid password." << std::endl;
+ case UNREGISTER_INVALID_PASSWORD:
+ std::cout << "Account unregistering: Invalid password." << std::endl;
break;
- case UNREGISTER_INVALID_USERNAME:
- std::cout << "Account unregistering: Invalid username." << std::endl;
+ case UNREGISTER_INVALID_USERNAME:
+ std::cout << "Account unregistering: Invalid username." << std::endl;
break;
- case UNREGISTER_INVALID_UNSUFFICIENT_RIGHTS:
- std::cout << "Account unregistering: unsufficient rights." << std::endl;
+ case UNREGISTER_INVALID_UNSUFFICIENT_RIGHTS:
+ std::cout << "Account unregistering: unsufficient rights." << std::endl;
break;
- default:
- case UNREGISTER_UNKNOWN:
- std::cout << "Account unregistering: Unknown error." << std::endl;
+ default:
+ case UNREGISTER_UNKNOWN:
+ std::cout << "Account unregistering: Unknown error." << std::endl;
break;
- }
- break;
+ }
+ break;
- case SMSG_LOGIN_RESPONSE:
- // Register
- switch (msg.readByte())
- {
- case LOGIN_OK:
- char charNumber;
- charNumber = msg.readByte();
- std::cout << "Account has " << int(charNumber) << " characters." << std::endl;
- for (unsigned int i = 0; i < charNumber; i++)
- {
- if (i >0) std::cout << ", ";
- std::cout << msg.readString();
- }
- std::cout << "." << std::endl;
+ case SMSG_LOGIN_RESPONSE:
+ // Register
+ switch (msg.readByte()) {
+ case LOGIN_OK:
+ char charNumber;
+ charNumber = msg.readByte();
+ std::cout << "Account has " << int(charNumber) << " characters." << std::endl;
+ for (unsigned int i = 0; i < charNumber; i++) {
+ if (i >0) std::cout << ", ";
+ std::cout << msg.readString();
+ }
+ std::cout << "." << std::endl;
break;
- case LOGIN_INVALID_USERNAME:
- std::cout << "Login: Invalid Username." << std::endl;
+ case LOGIN_INVALID_USERNAME:
+ std::cout << "Login: Invalid Username." << std::endl;
break;
- case LOGIN_INVALID_PASSWORD:
- std::cout << "Login: Invalid Password." << std::endl;
+ case LOGIN_INVALID_PASSWORD:
+ std::cout << "Login: Invalid Password." << std::endl;
break;
- case LOGIN_INVALID_VERSION:
- std::cout << "Login: Invalid Version." << std::endl;
+ case LOGIN_INVALID_VERSION:
+ std::cout << "Login: Invalid Version." << std::endl;
break;
- case LOGIN_ALREADY_LOGGED:
- std::cout << "Login: Already logged with another account." << std::endl;
+ case LOGIN_ALREADY_LOGGED:
+ std::cout << "Login: Already logged with another account." << std::endl;
break;
- case LOGIN_SERVER_FULL:
- std::cout << "Login: Server has reached maximum of clients." << std::endl;
+ case LOGIN_SERVER_FULL:
+ std::cout << "Login: Server has reached maximum of clients." << std::endl;
break;
- case LOGIN_ACCOUNT_BANNED:
- std::cout << "Login: Your account has been banned." << std::endl;
+ case LOGIN_ACCOUNT_BANNED:
+ std::cout << "Login: Your account has been banned." << std::endl;
break;
- case LOGIN_ACCOUNT_REVIEW:
- std::cout << "TODO:Login: Your account is being reviewed." << std::endl;
+ case LOGIN_ACCOUNT_REVIEW:
+ std::cout << "TODO:Login: Your account is being reviewed." << std::endl;
break;
- default:
- case LOGIN_UNKNOWN:
- std::cout << "Login: Unknown error." << std::endl;
+ default:
+ case LOGIN_UNKNOWN:
+ std::cout << "Login: Unknown error." << std::endl;
break;
- }
- break;
-
- case SMSG_LOGOUT_RESPONSE:
- {
- switch (msg.readByte())
- {
- case LOGOUT_OK:
- std::cout << "Logout..." << std::endl;
- break;
- default:
- case LOGOUT_UNSUCCESSFULL:
- std::cout << "Logout: unsuccessfull." << std::endl;
- break;
- }
- }
- break;
-
- case SMSG_PASSWORD_CHANGE_RESPONSE:
- {
- switch (msg.readByte())
- {
- case PASSCHG_OK:
- std::cout << "Password correctly changed." << std::endl;
- break;
- case PASSCHG_NOLOGIN:
- std::cout << "Password change: Not logged in." << std::endl;
- break;
- case PASSCHG_MISMATCH:
- std::cout << "Password change: Passwords mismatch." << std::endl;
- break;
- case PASSCHG_INVALID:
- std::cout << "Password change: New password is invalid." << std::endl;
- break;
- default:
- case PASSCHG_UNKNOWN:
- std::cout << "Password change: Unknown error." << std::endl;
- break;
- }
- }
- break;
+ }
+ break;
- case SMSG_EMAIL_CHANGE_RESPONSE:
- {
- switch (msg.readByte())
- {
- case EMAILCHG_OK:
- std::cout << "Email correctly changed." << std::endl;
- break;
- case EMAILCHG_NOLOGIN:
- std::cout << "Email change: Not logged in." << std::endl;
- break;
- case EMAILCHG_EXISTS_EMAIL:
- std::cout << "Email change: Email already exists." << std::endl;
- break;
- case EMAILCHG_INVALID:
- std::cout << "Email change: New Email is invalid." << std::endl;
- break;
- default:
- case EMAILCHG_UNKNOWN:
- std::cout << "Email change: Unknown error." << std::endl;
- break;
- }
- }
- break;
+ case SMSG_LOGOUT_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case LOGOUT_OK:
+ std::cout << "Logout..." << std::endl;
+ break;
+ default:
+ case LOGOUT_UNSUCCESSFULL:
+ std::cout << "Logout: unsuccessfull." << std::endl;
+ break;
+ }
+ } break;
- case SMSG_EMAIL_GET_RESPONSE:
- {
- switch (msg.readByte())
- {
- case EMAILGET_OK:
- std::cout << "Current Email: " << msg.readString() << std::endl;
- break;
- case EMAILGET_NOLOGIN:
- std::cout << "Get Email: Not logged in." << std::endl;
- break;
- default:
- case EMAILGET_UNKNOWN:
- std::cout << "Get Email: Unknown error." << std::endl;
- break;
- }
- }
- break;
+ case SMSG_PASSWORD_CHANGE_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case PASSCHG_OK:
+ std::cout << "Password correctly changed." << std::endl;
+ break;
+ case PASSCHG_NOLOGIN:
+ std::cout << "Password change: Not logged in." << std::endl;
+ break;
+ case PASSCHG_MISMATCH:
+ std::cout << "Password change: Passwords mismatch." << std::endl;
+ break;
+ case PASSCHG_INVALID:
+ std::cout << "Password change: New password is invalid." << std::endl;
+ break;
+ default:
+ case PASSCHG_UNKNOWN:
+ std::cout << "Password change: Unknown error." << std::endl;
+ break;
+ }
+ } break;
- case SMSG_CHAR_CREATE_RESPONSE:
- {
- switch (msg.readByte())
- {
- case CREATE_OK:
- std::cout << "Character Created successfully." << std::endl;
- break;
- case CREATE_EXISTS_NAME:
- std::cout << "Character Creation: Character's name already exists."
- << std::endl;
- break;
- case CREATE_NOLOGIN:
- std::cout << "Character Creation: Not logged in." << std::endl;
- break;
- case CREATE_TOO_MUCH_CHARACTERS:
- std::cout << "Character Creation: Too much characters." << std::endl;
- break;
- case CREATE_INVALID_HAIRSTYLE:
- std::cout << "Character Creation: Invalid Hair Style Value." << std::endl;
- break;
- case CREATE_INVALID_HAIRCOLOR:
- std::cout << "Character Creation: Invalid Hair Color Value." << std::endl;
- break;
- case CREATE_INVALID_GENDER:
- std::cout << "Character Creation: Invalid Gender Value." << std::endl;
- break;
- case CREATE_INVALID_NAME:
- std::cout << "Character Creation: Invalid Name." << std::endl;
- break;
- case CREATE_RAW_STATS_EQUAL_TO_ZERO:
- std::cout << "Character Creation: a Statistic is equal to zero." << std::endl;
- break;
- case CREATE_RAW_STATS_INVALID_DIFF:
- std::cout << "Character Creation: Statistics disproportionned." << std::endl;
- break;
- case CREATE_RAW_STATS_TOO_HIGH:
- std::cout << "Character Creation: Statistics too high for level 1." << std::endl;
- break;
- case CREATE_RAW_STATS_TOO_LOW:
- std::cout << "Character Creation: Statistics too low for level 1." << std::endl;
- break;
- default:
- case CREATE_UNKNOWN:
- std::cout << "Character Creation: Unknown error." << std::endl;
- break;
- }
- }
- break;
+ case SMSG_EMAIL_CHANGE_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case EMAILCHG_OK:
+ std::cout << "Email correctly changed." << std::endl;
+ break;
+ case EMAILCHG_NOLOGIN:
+ std::cout << "Email change: Not logged in." << std::endl;
+ break;
+ case EMAILCHG_EXISTS_EMAIL:
+ std::cout << "Email change: Email already exists." << std::endl;
+ break;
+ case EMAILCHG_INVALID:
+ std::cout << "Email change: New Email is invalid." << std::endl;
+ break;
+ default:
+ case EMAILCHG_UNKNOWN:
+ std::cout << "Email change: Unknown error." << std::endl;
+ break;
+ }
+ } break;
+
+ case SMSG_EMAIL_GET_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case EMAILGET_OK:
+ std::cout << "Current Email: " << msg.readString() << std::endl;
+ break;
+ case EMAILGET_NOLOGIN:
+ std::cout << "Get Email: Not logged in." << std::endl;
+ break;
+ default:
+ case EMAILGET_UNKNOWN:
+ std::cout << "Get Email: Unknown error." << std::endl;
+ break;
+ }
+ } break;
- case SMSG_CHAR_DELETE_RESPONSE:
- {
- switch (msg.readByte())
- {
- case DELETE_OK:
- std::cout << "Character deleted." << std::endl;
- break;
- case DELETE_INVALID_ID:
- std::cout << "Character Deletion: Character's ID doesn't exist."
- << std::endl;
- break;
- case DELETE_NOLOGIN:
- std::cout << "Character Deletion: Not logged in." << std::endl;
- break;
- case DELETE_NO_MORE_CHARACTERS:
- std::cout << "Character Deletion: No more characters." << std::endl;
- break;
- default:
- case DELETE_UNKNOWN:
- std::cout << "Character Deletion: Unknown error." << std::endl;
- break;
- }
- }
- break;
+ case SMSG_CHAR_CREATE_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case CREATE_OK:
+ std::cout << "Character Created successfully." << std::endl;
+ break;
+ case CREATE_EXISTS_NAME:
+ std::cout << "Character Creation: Character's name already exists."
+ << std::endl;
+ break;
+ case CREATE_NOLOGIN:
+ std::cout << "Character Creation: Not logged in." << std::endl;
+ break;
+ case CREATE_TOO_MUCH_CHARACTERS:
+ std::cout << "Character Creation: Too much characters." << std::endl;
+ break;
+ case CREATE_INVALID_HAIRSTYLE:
+ std::cout << "Character Creation: Invalid Hair Style Value." << std::endl;
+ break;
+ case CREATE_INVALID_HAIRCOLOR:
+ std::cout << "Character Creation: Invalid Hair Color Value." << std::endl;
+ break;
+ case CREATE_INVALID_GENDER:
+ std::cout << "Character Creation: Invalid Gender Value." << std::endl;
+ break;
+ case CREATE_INVALID_NAME:
+ std::cout << "Character Creation: Invalid Name." << std::endl;
+ break;
+ case CREATE_RAW_STATS_EQUAL_TO_ZERO:
+ std::cout << "Character Creation: a Statistic is equal to zero." << std::endl;
+ break;
+ case CREATE_RAW_STATS_INVALID_DIFF:
+ std::cout << "Character Creation: Statistics disproportionned." << std::endl;
+ break;
+ case CREATE_RAW_STATS_TOO_HIGH:
+ std::cout << "Character Creation: Statistics too high for level 1." << std::endl;
+ break;
+ case CREATE_RAW_STATS_TOO_LOW:
+ std::cout << "Character Creation: Statistics too low for level 1." << std::endl;
+ break;
+ default:
+ case CREATE_UNKNOWN:
+ std::cout << "Character Creation: Unknown error." << std::endl;
+ break;
+ }
+ } break;
- case SMSG_CHAR_SELECT_RESPONSE:
- {
- switch (msg.readByte())
- {
- case SELECT_OK:
- {
- std::cout << "Character selected successfully.";
- std::cout << std::endl;
- std::cout << "Current Map: ";
- std::cout << msg.readString() << " (X:";
- std::cout << (int)msg.readShort() << ", Y:";
- std::cout << (int)msg.readShort() << ")" << std::endl;
- }
- break;
- case SELECT_INVALID:
- std::cout << "Character Selection: invalid ID."
- << std::endl;
- break;
- case SELECT_NOLOGIN:
- std::cout << "Character Selection: Not logged in." << std::endl;
- break;
- case SELECT_NO_CHARACTERS:
- std::cout << "Character Selection: No character to select." << std::endl;
- break;
- case SELECT_NO_MAPS:
- std::cout << "Character Selection: Can't load default map for character."
- << std::endl;
- break;
- default:
- case SELECT_UNKNOWN:
- std::cout << "Character Selection: Unknown error." << std::endl;
- break;
- }
- }
- break;
+ case SMSG_CHAR_DELETE_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case DELETE_OK:
+ std::cout << "Character deleted." << std::endl;
+ break;
+ case DELETE_INVALID_ID:
+ std::cout << "Character Deletion: Character's ID doesn't exist."
+ << std::endl;
+ break;
+ case DELETE_NOLOGIN:
+ std::cout << "Character Deletion: Not logged in." << std::endl;
+ break;
+ case DELETE_NO_MORE_CHARACTERS:
+ std::cout << "Character Deletion: No more characters." << std::endl;
+ break;
+ default:
+ case DELETE_UNKNOWN:
+ std::cout << "Character Deletion: Unknown error." << std::endl;
+ break;
+ }
+ } break;
- case SMSG_CHAR_LIST_RESPONSE:
+ case SMSG_CHAR_SELECT_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case SELECT_OK:
{
- switch (msg.readByte())
- {
- case CHAR_LIST_OK:
- char charNumber;
- charNumber = msg.readByte();
- std::cout << "Character List:" << std::endl
- << "---------------" << std::endl;
- std::cout << int(charNumber) << " character(s) in the account."
- << std::endl;
- char charID;
- for (unsigned int i = 0; i < charNumber; i++)
- {
- charID = msg.readByte();
- std::cout << int(charID) << ". "
- << msg.readString() << ":" << std::endl;
- std::cout << "Gender: " << int(msg.readByte()) << ", ";
- std::cout << "Hair Style: " << int(msg.readByte()) << ", ";
- std::cout << "Hair Color: " << int(msg.readByte()) << ", "
- << std::endl;
- std::cout << "Level: " << int(msg.readByte()) << ", ";
- std::cout << "Money: " << int(msg.readShort()) << ", "
- << std::endl;
- std::cout << "Strength: " << int(msg.readShort()) << ", ";
- std::cout << "Agility: " << int(msg.readShort()) << ", ";
- std::cout << "Vitality: " << int(msg.readShort()) << ", "
- << std::endl;
- std::cout << "Intelligence: " << int(msg.readShort()) << ", ";
- std::cout << "Dexterity: " << int(msg.readShort()) << ", ";
- std::cout << "Luck: " << int(msg.readShort()) << ". "
- << std::endl;
- std::cout << "Current Map: " << msg.readString() << " (X:";
- std::cout << int(msg.readShort()) << ", Y:" << int(msg.readShort()) << ")."
- << std::endl << std::endl;
- }
- break;
- case CHAR_LIST_NOLOGIN:
- std::cout << "Character List: Not logged in."
- << std::endl;
- break;
- default:
- case CHAR_LIST_UNKNOWN:
- std::cout << "Character List: Unknown error." << std::endl;
- break;
- }
- }
- break;
-
-
- default:
- continue;
- } // End switch MessageId
+ std::cout << "Character selected successfully.";
+ std::cout << std::endl;
+ std::cout << "Current Map: ";
+ std::cout << msg.readString() << " (X:";
+ std::cout << (int)msg.readShort() << ", Y:";
+ std::cout << (int)msg.readShort() << ")" << std::endl;
+ } break;
+ case SELECT_INVALID:
+ std::cout << "Character Selection: invalid ID."
+ << std::endl;
+ break;
+ case SELECT_NOLOGIN:
+ std::cout << "Character Selection: Not logged in." << std::endl;
+ break;
+ case SELECT_NO_CHARACTERS:
+ std::cout << "Character Selection: No character to select." << std::endl;
+ break;
+ case SELECT_NO_MAPS:
+ std::cout << "Character Selection: Can't load default map for character."
+ << std::endl;
+ break;
+ default:
+ case SELECT_UNKNOWN:
+ std::cout << "Character Selection: Unknown error." << std::endl;
+ break;
+ }
+ } break;
- } // end if recLength > 2 (MessageLength > 2)
+ case SMSG_CHAR_LIST_RESPONSE:
+ {
+ switch (msg.readByte()) {
+ case CHAR_LIST_OK:
+ char charNumber;
+ charNumber = msg.readByte();
+ std::cout << "Character List:" << std::endl
+ << "---------------" << std::endl;
+ std::cout << int(charNumber) << " character(s) in the account."
+ << std::endl;
+ char charID;
+ for (unsigned int i = 0; i < charNumber; i++) {
+ charID = msg.readByte();
+ std::cout << int(charID) << ". "
+ << msg.readString() << ":" << std::endl;
+ std::cout << "Gender: " << int(msg.readByte()) << ", ";
+ std::cout << "Hair Style: " << int(msg.readByte()) << ", ";
+ std::cout << "Hair Color: " << int(msg.readByte()) << ", "
+ << std::endl;
+ std::cout << "Level: " << int(msg.readByte()) << ", ";
+ std::cout << "Money: " << int(msg.readShort()) << ", "
+ << std::endl;
+ std::cout << "Strength: " << int(msg.readShort()) << ", ";
+ std::cout << "Agility: " << int(msg.readShort()) << ", ";
+ std::cout << "Vitality: " << int(msg.readShort()) << ", "
+ << std::endl;
+ std::cout << "Intelligence: " << int(msg.readShort()) << ", ";
+ std::cout << "Dexterity: " << int(msg.readShort()) << ", ";
+ std::cout << "Luck: " << int(msg.readShort()) << ". "
+ << std::endl;
+ std::cout << "Current Map: " << msg.readString() << " (X:";
+ std::cout << int(msg.readShort()) << ", Y:" << int(msg.readShort()) << ")."
+ << std::endl << std::endl;
+ } break;
+ case CHAR_LIST_NOLOGIN:
+ std::cout << "Character List: Not logged in."
+ << std::endl;
+ break;
+ default:
+ case CHAR_LIST_UNKNOWN:
+ std::cout << "Character List: Unknown error." << std::endl;
+ break;
+ }
+ } break;
- } // End running loop
+ default:
+ break;
+ } // end switch MessageId
- SDLNet_TCP_Close(tcpsock);
+ } // end if recLength > 2 (MessageLength > 2)
- return 0;
}
+
diff --git a/src/connectionhandler.cpp b/src/connectionhandler.cpp
index e3b30dde..c70f34e4 100644
--- a/src/connectionhandler.cpp
+++ b/src/connectionhandler.cpp
@@ -100,6 +100,7 @@ ConnectionHandler::ConnectionHandler()
void
ConnectionHandler::startListen(ListenThreadData *ltd)
{
+ /*
// Allocate a socket set
SDLNet_SocketSet set = SDLNet_AllocSocketSet(MAX_CLIENTS);
if (!set) {
@@ -226,7 +227,114 @@ ConnectionHandler::startListen(ListenThreadData *ltd)
// - Disconnect all clients (close sockets)
- SDLNet_FreeSocketSet(set);
+ SDLNet_FreeSocketSet(set);*/
+
+ while (ltd->running)
+ {
+ ENetEvent event;
+
+ // Wait up to 1000 milliseconds for an event.
+ while (enet_host_service(ltd->host, &event, 1000) > 0)
+ {
+ switch (event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ {
+ LOG_INFO("A new client connected from " <<
+ ip4ToString(event.peer->address.host) << ":" <<
+ event.peer->address.port, 0);
+ NetComputer *comp = new NetComputer(this, event.peer);
+ clients.push_back(comp);
+ computerConnected(comp);
+ /*LOG_INFO(ltd->host->peerCount <<
+ " client(s) connected", 0);*/
+
+ // Store any relevant client information here.
+ event.peer->data = (void *)comp;
+ } break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ {
+ LOG_INFO("A packet of length " << event.packet->dataLength
+ << " was received from " << event.peer->address.host,
+ 2);
+
+ NetComputer *comp = (NetComputer *)event.peer->data;
+
+#ifdef SCRIPT_SUPPORT
+ // This could be good if you wanted to extend the
+ // server protocol using a scripting language. This
+ // could be attained by using allowing scripts to
+ // "hook" certain messages.
+
+ //script->message(buffer);
+#endif
+
+ // If the scripting subsystem didn't hook the message
+ // it will be handled by the default message handler.
+
+ // Convert the client IP address to string
+ // representation
+ std::string ipaddr = ip4ToString(event.peer->address.host);
+
+ // Make sure that the packet is big enough (> short)
+ if (event.packet->dataLength >= 2)
+ {
+ Packet *packet = new Packet((char *)event.packet->data,
+ event.packet->dataLength);
+ MessageIn msg(packet); // (MessageIn frees packet)
+
+ short messageId = msg.getId();
+
+ if (handlers.find(messageId) != handlers.end())
+ {
+ // send message to appropriate handler
+ handlers[messageId]->receiveMessage(*comp, msg);
+ }
+ else {
+ // bad message (no registered handler)
+ LOG_ERROR("Unhandled message (" << messageId
+ << ") received from " << ipaddr, 0);
+ }
+ }
+ else {
+ LOG_ERROR("Message too short from " << ipaddr, 0);
+ }
+
+ /* Clean up the packet now that we're done using it. */
+ enet_packet_destroy(event.packet);
+ } break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ {
+ NetComputer *comp = (NetComputer *)event.peer->data;
+ /*LOG_INFO(event.peer->address.host
+ << " disconected.", 0);*/
+ // Reset the peer's client information.
+ computerDisconnected(comp);
+ delete comp;
+ event.peer->data = NULL;
+ } break;
+ }
+ }
+ }
+
+ // - Disconnect all clients (close sockets)
+
+ // TODO: probably there's a better way.
+ ENetPeer *currentPeer;
+
+ for (currentPeer = ltd->host->peers;
+ currentPeer < &ltd->host->peers[ltd->host->peerCount];
+ ++currentPeer)
+ {
+ if (currentPeer->state == ENET_PEER_STATE_CONNECTED)
+ {
+ enet_peer_disconnect(currentPeer, 0);
+ enet_host_flush(ltd->host);
+ enet_peer_reset(currentPeer);
+ }
+ }
}
void ConnectionHandler::computerConnected(NetComputer *comp)
diff --git a/src/connectionhandler.h b/src/connectionhandler.h
index 3eb4ac2c..dd6cf207 100644
--- a/src/connectionhandler.h
+++ b/src/connectionhandler.h
@@ -26,7 +26,6 @@
#include <list>
#include <map>
-#include <SDL_net.h>
#include "being.h"
@@ -48,7 +47,7 @@ class ClientData
public:
ClientData();
- TCPsocket sock; /**< The socket used for communication */
+ //TCPsocket sock; /**< The socket used for communication */
int inp; /**< The amount of data in the in buffer */
char in[IN_BUFFER_SIZE]; /**< The in buffer for incoming messages */
diff --git a/src/main.cpp b/src/main.cpp
index 833492b2..679408fb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -26,7 +26,7 @@
#include <iostream>
#include <physfs.h>
#include <SDL.h>
-#include <SDL_net.h>
+#include <enet/enet.h>
#if (defined __USE_UNIX98 || defined __FreeBSD__)
#include "../config.h"
@@ -41,6 +41,7 @@
#include "configuration.h"
#include "connectionhandler.h"
#include "gamehandler.h"
+#include "messageout.h"
#include "netsession.h"
#include "resourcemanager.h"
#include "skill.h"
@@ -184,7 +185,7 @@ void initialize()
accountHandler = new AccountHandler();
gameHandler = new GameHandler();
connectionHandler = new ConnectionHandler();
-
+
// Make SDL use a dummy videodriver so that it doesn't require an X server
putenv("SDL_VIDEODRIVER=dummy");
@@ -196,13 +197,16 @@ void initialize()
// Reset to default segmentation fault handling for debugging purposes
signal(SIGSEGV, SIG_DFL);
-
+
// set SDL to quit on exit.
atexit(SDL_Quit);
- // initialize SDL_net.
- if (SDLNet_Init() == -1) {
- LOG_FATAL("SDLNet_Init: " << SDLNet_GetError(), 0)
+ // set enet to quit on exit.
+ atexit(enet_deinitialize);
+
+ // initialize enet.
+ if (enet_initialize() != 0) {
+ LOG_FATAL("An error occurred while initializing ENet", 0)
exit(2);
}
@@ -259,9 +263,12 @@ void deinitialize()
// Stop world timer
SDL_RemoveTimer(worldTimerID);
+
+ // Quit SDL
+ SDL_Quit();
- // Quit SDL_net
- SDLNet_Quit();
+ // Quit ENet
+ enet_deinitialize();
#ifdef RUBY_SUPPORT
// Finish up ruby
@@ -390,8 +397,10 @@ int main(int argc, char *argv[])
connectionHandler->registerHandler(CMSG_REQ_TRADE, gameHandler);
connectionHandler->registerHandler(CMSG_EQUIP, gameHandler);
- session->startListen(connectionHandler, int(config.getValue("ListenOnPort", DEFAULT_SERVER_PORT)));
- LOG_INFO("Listening on port " << config.getValue("ListenOnPort", DEFAULT_SERVER_PORT) << "...", 0)
+ session->startListen(connectionHandler, int(config.getValue("ListenOnPort",
+ DEFAULT_SERVER_PORT)));
+ LOG_INFO("Listening on port " <<
+ config.getValue("ListenOnPort", DEFAULT_SERVER_PORT) << "...", 0)
using namespace tmwserv;
@@ -428,6 +437,53 @@ int main(int argc, char *argv[])
running = false;
}
}
+
+ /*ENetEvent netEvent;
+
+ while (enet_host_service(server, &netEvent, 3000) > 0)
+ {
+ switch (netEvent.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ printf("A new client connected from %x:%u.\n",
+ netEvent.peer->address.host,
+ netEvent.peer->address.port);
+
+ netEvent.peer->data = (void *)"Client information";
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ {
+ printf("A packet of length %u containing %s was received from %s on channel %u.\n",
+ netEvent.packet->dataLength,
+ netEvent.packet->data,
+ netEvent.peer->data,
+ netEvent.channelID);
+
+ MessageOut msg;
+ msg.writeShort(SMSG_REGISTER_RESPONSE);
+ msg.writeByte(REGISTER_OK);
+ ENetPacket *packet = enet_packet_create(msg.getData(),
+ msg.getDataSize() + 1,
+ ENET_PACKET_FLAG_RELIABLE);
+ // Send the packet to the peer over channel id 0.
+ enet_peer_send(netEvent.peer, 0, packet);
+ // Clean up the packet now that we're done using it.
+ enet_packet_destroy(netEvent.packet);
+ }
+ break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ printf("%s disconected.\n", netEvent.peer->data);
+
+ netEvent.peer->data = NULL;
+ break;
+
+ default:
+ printf("Unhandled enet event\n");
+ break;
+ }
+ }*/
// We know only about 10 events will happen per second,
// so give the CPU a break for a while.
@@ -435,7 +491,8 @@ int main(int argc, char *argv[])
}
LOG_INFO("Received: Quit signal, closing down...", 0)
- session->stopListen(int(config.getValue("ListenOnPort", DEFAULT_SERVER_PORT)));
+ session->stopListen(int(config.getValue("ListenOnPort",
+ DEFAULT_SERVER_PORT)));
deinitialize();
}
diff --git a/src/messagein.cpp b/src/messagein.cpp
index 88e673d7..c1736bbd 100644
--- a/src/messagein.cpp
+++ b/src/messagein.cpp
@@ -23,9 +23,10 @@
#include "messagein.h"
-#include <SDL_net.h>
#include <string>
+#include <enet/enet.h>
+
#include "packet.h"
MessageIn::MessageIn(Packet *packet):
@@ -60,12 +61,14 @@ char MessageIn::readByte()
short MessageIn::readShort()
{
+ short value = -1;
+
if (mPacket)
{
if ( (mPos + sizeof(short)) <= mPacket->length )
{
+ value = ENET_NET_TO_HOST_16(*(short *)(mPacket->data + mPos));
mPos += sizeof(short);
- return (short) SDLNet_Read16(&(mPacket->data[mPos - sizeof(short)]));
}
else
{
@@ -73,17 +76,19 @@ short MessageIn::readShort()
// that requires less length.
}
}
- return -1;
+ return value;
}
long MessageIn::readLong()
{
+ long value = -1;
+
if (mPacket)
{
if ( (mPos + sizeof(long)) <= mPacket->length )
{
+ value = ENET_NET_TO_HOST_32(*(long *)(mPacket->data + mPos));
mPos += sizeof(long);
- return (long) SDLNet_Read32(&(mPacket->data[mPos - sizeof(long)]));
}
else
{
@@ -91,7 +96,7 @@ long MessageIn::readLong()
// that requires less length.
}
}
- return -1;
+ return value;
}
std::string MessageIn::readString(int length)
diff --git a/src/messageout.cpp b/src/messageout.cpp
index e5400e64..7fa6e1fd 100644
--- a/src/messageout.cpp
+++ b/src/messageout.cpp
@@ -23,10 +23,10 @@
#include "messageout.h"
-#include <cstdlib>
-#include <SDL_net.h>
#include <string>
+#include <enet/enet.h>
+
#include "packet.h"
MessageOut::MessageOut():
@@ -66,7 +66,7 @@ MessageOut::writeByte(char value)
void MessageOut::writeShort(short value)
{
expand(mPos + sizeof(short));
- SDLNet_Write16(value, &mData[mPos]);
+ (*(short *)&mData[mPos]) = ENET_HOST_TO_NET_16(value);
mPos += sizeof(short);
}
@@ -74,7 +74,7 @@ void
MessageOut::writeLong(long value)
{
expand(mPos + sizeof(long));
- SDLNet_Write32(value, &mData[mPos]);
+ (*(long *)&mData[mPos]) = ENET_HOST_TO_NET_32(value);
mPos += sizeof(long);
}
@@ -119,3 +119,15 @@ MessageOut::getPacket()
return mPacket;
}
+
+char*
+MessageOut::getData()
+{
+ return mData;
+}
+
+unsigned int
+MessageOut::getDataSize()
+{
+ return mDataSize;
+}
diff --git a/src/messageout.h b/src/messageout.h
index f13695ab..245c3dca 100644
--- a/src/messageout.h
+++ b/src/messageout.h
@@ -60,6 +60,16 @@ class MessageOut
* a call to this method.
*/
const Packet *getPacket();
+
+ /**
+ * Returns the content of the message.
+ */
+ char *getData();
+
+ /**
+ * Returns the length of the data.
+ */
+ unsigned int getDataSize();
private:
/**
diff --git a/src/netcomputer.cpp b/src/netcomputer.cpp
index f3f1aeb7..1c736f47 100644
--- a/src/netcomputer.cpp
+++ b/src/netcomputer.cpp
@@ -27,9 +27,9 @@
#include "packet.h"
#include "state.h"
-NetComputer::NetComputer(ConnectionHandler *handler, TCPsocket sock):
+NetComputer::NetComputer(ConnectionHandler *handler, ENetPeer *peer):
handler(handler),
- socket(sock),
+ peer(peer),
mAccountPtr(NULL),
mCharacterPtr(NULL)
{
@@ -48,7 +48,13 @@ void NetComputer::disconnect(const std::string &reason)
void NetComputer::send(const Packet *p)
{
- SDLNet_TCP_Send(socket, p->data, p->length);
+ // Create a reliable packet.
+ ENetPacket *packet = enet_packet_create(p->data,
+ p->length + 1,
+ ENET_PACKET_FLAG_RELIABLE);
+
+ // Send the packet to the peer over channel id 0.
+ enet_peer_send(peer, 0, packet);
}
void NetComputer::setAccount(tmwserv::AccountPtr acc)
diff --git a/src/netcomputer.h b/src/netcomputer.h
index 89ad6ba7..2e74c960 100644
--- a/src/netcomputer.h
+++ b/src/netcomputer.h
@@ -25,9 +25,10 @@
#define _TMWSERV_NETCOMPUTER_H_
#include <iosfwd>
-#include <SDL_net.h>
#include <queue>
+#include <enet/enet.h>
+
#include "account.h"
#include "being.h"
@@ -45,7 +46,7 @@ class NetComputer
/**
* Constructor.
*/
- NetComputer(ConnectionHandler *handler, TCPsocket sock);
+ NetComputer(ConnectionHandler *handler, ENetPeer *peer);
/**
* Destructor
@@ -73,9 +74,9 @@ class NetComputer
//void send(Packet *p, bool reliable = true);
/**
- * Return the socket
+ * Return the peer
*/
- TCPsocket getSocket() { return socket; }
+ ENetPeer *getPeer() { return peer; }
/**
* Set the account associated with the connection
@@ -112,7 +113,7 @@ class NetComputer
ConnectionHandler *handler;
std::queue<Packet*> queue; /**< Message Queue (FIFO) */
- TCPsocket socket; /**< Client socket */
+ ENetPeer *peer; /**< Client peer */
tmwserv::AccountPtr mAccountPtr; /**< Account associated with connection */
tmwserv::BeingPtr mCharacterPtr; /**< Selected character */
diff --git a/src/netsession.cpp b/src/netsession.cpp
index 23476f6d..0a56d7c0 100644
--- a/src/netsession.cpp
+++ b/src/netsession.cpp
@@ -23,8 +23,12 @@
#include "netsession.h"
+#include <SDL.h>
+
#include "connectionhandler.h"
+#include "utils/logger.h"
+
/**
* This function is the new thread created to listen to a server socket. It
* immediately passes control over to the connection handler instance that will
@@ -58,28 +62,32 @@ void NetSession::startListen(ConnectionHandler *handler, Uint16 port)
data->handler = handler;
data->running = true;
- // Fill in IPaddress for opening local server socket
- if (SDLNet_ResolveHost(&data->address, NULL, port) == -1) {
- printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
- exit(6);
- }
+ ENetHost *server;
- // Attempt to open the local server socket
- data->socket = SDLNet_TCP_Open(&data->address);
+ // Bind the server to the default localhost.
+ data->address.host = ENET_HOST_ANY;
+ data->address.port = port;
- if (!data->socket) {
- printf("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
+ server = enet_host_create(&data->address /* the address to bind the server host to */,
+ MAX_CLIENTS /* allow up to MAX_CLIENTS clients and/or outgoing connections */,
+ 0 /* assume any amount of incoming bandwidth */,
+ 0 /* assume any amount of outgoing bandwidth */);
+ if (server == NULL)
+ {
+ LOG_ERROR("Unable to create an ENet server host.", 0);
exit(3);
}
-
+
+ data->host = server;
+
// Start the listening thread
data->thread = SDL_CreateThread(startListenThread, data);
if (data->thread == NULL) {
- printf("SDL_CreateThread: %s\n", SDL_GetError());
- exit(5);
+ LOG_ERROR("SDL_CreateThread: " << SDL_GetError(), 0);
+ exit(4);
}
-
+
listeners[port] = data;
}
@@ -99,13 +107,13 @@ void NetSession::stopListen(Uint16 port)
// Note: Somewhere in this process the ConnectionHandler should receive
// disconnect notifications about all the connected clients.
SDL_WaitThread(data->thread, NULL);
- SDLNet_TCP_Close(data->socket);
+ enet_host_destroy(data->host);
delete data;
listeners.erase(threadDataI);
}
else
{
- printf("NetSession::stopListen() not listening to port %d!\n", port);
+ LOG_WARN("NetSession::stopListen() not listening to port %d!\n", port);
}
}
@@ -115,22 +123,48 @@ NetComputer *NetSession::connect(const std::string &host, Uint16 port)
// can be used to send messages that way, or NULL when failing to connect.
//
// An asynchroneous wrapper could be created around this method.
+
+ ENetHost *client;
+
+ client = enet_host_create(NULL, 1, 0, 0);
+
+ if (client == NULL)
+ {
+ LOG_ERROR("Unable to create an ENet client host.", 0);
+ exit(3);
+ }
+
+ ENetAddress address;
+ ENetEvent event;
+ ENetPeer *peer;
- IPaddress address;
+ // Connect to host:port.
+ enet_address_set_host(&address, host.c_str());
+ address.port = port;
- if (!SDLNet_ResolveHost(&address, host.c_str(), port))
+ // Initiate the connection, allocating the channel 0.
+ peer = enet_host_connect(client, &address, 1);
+
+ if (peer == NULL)
{
- TCPsocket tcpsock = SDLNet_TCP_Open(&address);
- if (!tcpsock) {
- printf("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
- exit(3);
- }
+ LOG_ERROR("No available peer for initiating an ENet connection.", 0);
+ exit(4);
+ }
- // return computer;
+ // Wait up to 5 seconds for the connection attempt to succeed.
+ if (enet_host_service (client, &event, 5000) > 0 &&
+ event.type == ENET_EVENT_TYPE_CONNECT)
+ {
+ LOG_INFO("Connection succeeded.", 0);
}
- else {
- printf("SDLNet_ResolveHost: Could not resolve %s\n", host.c_str());
- exit(4);
+ else
+ {
+ /* Either the 5 seconds are up or a disconnect event was */
+ /* received. Reset the peer in the event the 5 seconds */
+ /* had run out without any significant event. */
+ enet_peer_reset(peer);
+ LOG_ERROR("Connection failed.", 0);
+ exit(5);
}
return NULL;
diff --git a/src/netsession.h b/src/netsession.h
index b02b9ede..e50cc6e7 100644
--- a/src/netsession.h
+++ b/src/netsession.h
@@ -25,9 +25,10 @@
#define _TMWSERV_NETSESSION_H_
#include <map>
-#include <SDL_net.h>
#include <SDL_thread.h>
+#include <enet/enet.h>
+
class ConnectionHandler;
class NetComputer;
@@ -37,8 +38,8 @@ class NetComputer;
*/
struct ListenThreadData
{
- IPaddress address; /**< Includes the port to listen to. */
- TCPsocket socket; /**< The socket that's been opened. */
+ ENetAddress address; /**< Includes the port to listen to. */
+ ENetHost *host; /**< The host that listen for connections. */
SDL_Thread *thread; /**< The thread, ignored by thread itself. */
ConnectionHandler *handler; /**< Handler for events. */
bool running; /**< Wether to keep listening. */
diff --git a/src/utils/logger.cpp b/src/utils/logger.cpp
index cd620f69..93dd289b 100644
--- a/src/utils/logger.cpp
+++ b/src/utils/logger.cpp
@@ -238,9 +238,6 @@ Logger::fatal(const std::string& msg, unsigned short atVerbosity)
else {
log((mLogFile.is_open() ? mLogFile : std::cerr), msg, "[FTL]");
}
-#ifdef WIN32
- MessageBox(NULL, msg.c_str(), "Fatal error", MB_ICONERROR | MB_OK);
-#endif
}
diff --git a/tmwserv.dev b/tmwserv.dev
index a325e6b6..931d73cc 100644
--- a/tmwserv.dev
+++ b/tmwserv.dev
@@ -12,7 +12,7 @@ ResourceIncludes=
MakeIncludes=
Compiler=_@@_
CppCompiler=-DSQLITE_SUPPORT_@@_
-Linker=-lmingw32_@@_-lSDL_@@_-lSDL_net_@@_-lsqlite3_@@_-lxml2_@@_-lphysfs_@@_-lz_@@_-mconsole_@@_-mwindows_@@_
+Linker=-lmingw32_@@_-lSDL_@@_-lenet_@@_-lws2_32_@@_-lsqlite3_@@_-lxml2_@@_-lphysfs_@@_-lz_@@_-mconsole_@@_-mwindows_@@_-lwinmm_@@_
IsCpp=1
Icon=
ExeOutput=