summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-04-18 08:38:18 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-04-18 08:38:18 -0700
commitb0d3b261f454e921f90a3a2c748731d3379e2db7 (patch)
treeb557ba4767fe7b00465f451b3be057721baf1156
parentae7b06ff8ad775a945bd677effd72b7fafa13d8d (diff)
downloadtmwa-b0d3b261f454e921f90a3a2c748731d3379e2db7.tar.gz
tmwa-b0d3b261f454e921f90a3a2c748731d3379e2db7.tar.bz2
tmwa-b0d3b261f454e921f90a3a2c748731d3379e2db7.tar.xz
tmwa-b0d3b261f454e921f90a3a2c748731d3379e2db7.zip
Die sensibly, take 2
-rw-r--r--src/admin/ladmin.cpp7
-rw-r--r--src/char/char.cpp63
-rw-r--r--src/login/login.cpp39
-rw-r--r--src/map/chrif.cpp13
-rw-r--r--src/map/clif.cpp36
-rw-r--r--src/mmo/socket.cpp80
-rw-r--r--src/mmo/socket.hpp43
7 files changed, 140 insertions, 141 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index 0d53ff4..9bbd710 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -286,7 +286,7 @@ void ladmin_log(XString line)
}
static
-void on_delete(Session *)
+void delete_fromlogin(Session *)
{
{
PRINTF("Impossible to have a connection with the login-server [%s:%d] !\n",
@@ -2785,7 +2785,8 @@ int Connect_login_server(void)
Iprintf("Attempt to connect to login-server...\n");
LADMIN_LOG("Attempt to connect to login-server...\n");
- login_session = make_connection(login_ip, login_port);
+ login_session = make_connection(login_ip, login_port, SessionParsers{func_parse: parse_fromlogin, func_delete: delete_fromlogin});
+
if (!login_session)
return 0;
@@ -2904,8 +2905,6 @@ int do_init(Slice<ZString> argv)
LADMIN_LOG("");
LADMIN_LOG("Configuration file readed.\n");
- set_defaultparse(parse_fromlogin, on_delete);
-
Iprintf("EAthena login-server administration tool.\n");
Version version = CURRENT_LOGIN_SERVER_VERSION;
Iprintf("for tmwA version %hhu.%hhu.%hhu (dev? %hhu) (flags %hhx) (which %hhx) (vend %hu)\n",
diff --git a/src/char/char.cpp b/src/char/char.cpp
index 7eb446a..8a3397d 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -189,34 +189,32 @@ static
void create_online_files(void);
static
-void on_delete(Session *sess)
+void delete_tologin(Session *sess)
{
- if (sess == login_session)
- {
- PRINTF("Char-server can't connect to login-server (connection #%d).\n",
- sess);
- login_session = nullptr;
- }
- else
- {
- auto it = std::find(server_session.begin(), server_session.end(), sess);
- if (it != server_session.end())
- {
- int id = it - server_session.begin();
- PRINTF("Map-server %d (session #%d) has disconnected.\n", id,
- sess);
- server[id] = mmo_map_server{};
- server_session[id] = nullptr;
- for (Session *& oci : online_chars)
- if (oci == sess)
- oci = nullptr;
- create_online_files(); // update online players files (to remove all online players of this server)
- }
- else
- {
- // normal player session
- }
- }
+ assert (sess == login_session);
+ PRINTF("Char-server can't connect to login-server (connection #%d).\n",
+ sess);
+ login_session = nullptr;
+}
+static
+void delete_char(Session *sess)
+{
+ (void)sess;
+}
+static
+void delete_frommap(Session *sess)
+{
+ auto it = std::find(server_session.begin(), server_session.end(), sess);
+ assert (it != server_session.end());
+ int id = it - server_session.begin();
+ PRINTF("Map-server %d (session #%d) has disconnected.\n", id,
+ sess);
+ server[id] = mmo_map_server{};
+ server_session[id] = nullptr;
+ for (Session *& oci : online_chars)
+ if (oci == sess)
+ oci = nullptr;
+ create_online_files(); // update online players files (to remove all online players of this server)
}
//------------------------------
@@ -2468,7 +2466,7 @@ void parse_char(Session *s)
{
int len;
WFIFOB(s, 2) = 0;
- s->func_parse = parse_frommap;
+ s->set_parsers(SessionParsers{func_parse: parse_frommap, func_delete: delete_frommap});
server_session[i] = s;
if (anti_freeze_enable)
server_freezeflag[i] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed
@@ -2605,10 +2603,10 @@ void check_connect_login_server(TimerData *, tick_t)
if (!login_session)
{
PRINTF("Attempt to connect to login-server...\n");
- login_session = make_connection(login_ip, login_port);
+ login_session = make_connection(login_ip, login_port,
+ SessionParsers{func_parse: parse_tologin, func_delete: delete_tologin});
if (!login_session)
return;
- login_session->func_parse = parse_tologin;
realloc_fifo(login_session, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
WFIFOW(login_session, 0) = 0x2710;
WFIFO_ZERO(login_session, 2, 24);
@@ -2924,10 +2922,7 @@ int do_init(Slice<ZString> argv)
update_online = TimeT::now();
create_online_files(); // update online players files at start of the server
-// set_termfunc (do_final);
- set_defaultparse(parse_char, on_delete);
-
- char_session = make_listen_port(char_port);
+ char_session = make_listen_port(char_port, SessionParsers{parse_char, delete_char});
Timer(gettick() + std::chrono::seconds(1),
check_connect_login_server,
diff --git a/src/login/login.cpp b/src/login/login.cpp
index 966d7dc..a60b34e 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -257,28 +257,27 @@ void login_log(XString line)
}
static
-void on_delete(Session *sess)
+void delete_login(Session *sess)
+{
+ (void)sess;
+}
+
+static
+void delete_fromchar(Session *sess)
{
auto it = std::find(server_session.begin(), server_session.end(), sess);
+ assert (it != server_session.end());
+ int id = it - server_session.begin();
IP4Address ip = sess->client_ip;
- if (it != server_session.end())
- {
- int id = it - server_session.begin();
- PRINTF("Char-server '%s' has disconnected.\n", server[id].name);
- LOGIN_LOG("Char-server '%s' has disconnected (ip: %s).\n",
- server[id].name, ip);
- server_session[id] = nullptr;
- server[id] = mmo_char_server{};
- }
- else
- {
- // player session
- ;
- }
+ PRINTF("Char-server '%s' has disconnected.\n", server[id].name);
+ LOGIN_LOG("Char-server '%s' has disconnected (ip: %s).\n",
+ server[id].name, ip);
+ server_session[id] = nullptr;
+ server[id] = mmo_char_server{};
}
static
-void on_delete_admin(Session *s)
+void delete_admin(Session *s)
{
PRINTF("Remote administration has disconnected (session #%d).\n",
s);
@@ -3015,7 +3014,7 @@ void parse_login(Session *s)
WFIFOW(s, 0) = 0x2711;
WFIFOB(s, 2) = 0;
WFIFOSET(s, 3);
- s->func_parse = parse_fromchar;
+ s->set_parsers(SessionParsers{func_parse: parse_fromchar, func_delete: delete_fromchar});
realloc_fifo(s, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
// send GM account to char-server
len = 4;
@@ -3089,8 +3088,7 @@ void parse_login(Session *s)
password, ip);
PRINTF("Connection of a remote administration accepted (non encrypted password).\n");
WFIFOB(s, 2) = 0;
- s->func_parse = parse_admin;
- s->func_delete = on_delete_admin;
+ s->set_parsers(SessionParsers{func_parse: parse_admin, func_delete: delete_admin});
}
else if (admin_state != 1)
LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n",
@@ -3912,8 +3910,7 @@ int do_init(Slice<ZString> argv)
read_gm_account();
mmo_auth_init();
// set_termfunc (mmo_auth_sync);
- set_defaultparse(parse_login, on_delete);
- login_session = make_listen_port(login_port);
+ login_session = make_listen_port(login_port, SessionParsers{func_parse: parse_login, func_delete: delete_login});
Timer(gettick() + std::chrono::minutes(5),
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index 86506b0..fa95be7 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -1037,6 +1037,15 @@ void ladmin_itemfrob(Session *s)
}
}
+static
+void chrif_delete(Session *s)
+{
+ assert (s == char_session);
+ PRINTF("Map-server can't connect to char-server (connection #%d).\n",
+ s);
+ char_session = nullptr;
+}
+
/*==========================================
*
*------------------------------------------
@@ -1207,10 +1216,10 @@ void check_connect_char_server(TimerData *, tick_t)
{
PRINTF("Attempt to connect to char-server...\n");
chrif_state = 0;
- char_session = make_connection(char_ip, char_port);
+ char_session = make_connection(char_ip, char_port,
+ SessionParsers{func_parse: chrif_parse, func_delete: chrif_delete});
if (!char_session)
return;
- char_session->func_parse = chrif_parse;
realloc_fifo(char_session, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
chrif_connect(char_session);
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 8f9565e..eb008e4 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -149,29 +149,22 @@ static
void clif_quitsave(Session *, dumb_ptr<map_session_data> sd);
static
-void on_delete(Session *s)
+void clif_delete(Session *s)
{
- if (s == char_session)
- {
- PRINTF("Map-server can't connect to char-server (connection #%d).\n",
- s);
- char_session = nullptr;
- }
- else
+ assert (s != char_session);
+
+ dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
+ if (sd && sd->state.auth)
{
- dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
- if (sd && sd->state.auth)
- {
- pc_logout(sd);
- clif_quitsave(s, sd);
+ pc_logout(sd);
+ clif_quitsave(s, sd);
- PRINTF("Player [%s] has logged off your server.\n", sd->status_key.name); // Player logout display [Valaris]
- }
- else if (sd)
- { // not authentified! (refused by char-server or disconnect before to be authentified)
- PRINTF("Player with account [%d] has logged off your server (not auth account).\n", sd->bl_id); // Player logout display [Yor]
- map_deliddb(sd); // account_id has been included in the DB before auth answer
- }
+ PRINTF("Player [%s] has logged off your server.\n", sd->status_key.name); // Player logout display [Valaris]
+ }
+ else if (sd)
+ { // not authentified! (refused by char-server or disconnect before to be authentified)
+ PRINTF("Player with account [%d] has logged off your server (not auth account).\n", sd->bl_id); // Player logout display [Yor]
+ map_deliddb(sd); // account_id has been included in the DB before auth answer
}
}
@@ -5515,6 +5508,5 @@ void clif_parse(Session *s)
void do_init_clif(void)
{
- set_defaultparse(clif_parse, on_delete);
- make_listen_port(map_port);
+ make_listen_port(map_port, SessionParsers{func_parse: clif_parse, func_delete: clif_delete});
}
diff --git a/src/mmo/socket.cpp b/src/mmo/socket.cpp
index 322a1f4..53a891c 100644
--- a/src/mmo/socket.cpp
+++ b/src/mmo/socket.cpp
@@ -56,6 +56,23 @@ static
std::array<std::unique_ptr<Session>, FD_SETSIZE> session;
#pragma GCC diagnostic pop
+Session::Session(SessionIO io, SessionParsers p)
+{
+ set_io(io);
+ set_parsers(p);
+}
+void Session::set_io(SessionIO io)
+{
+ func_send = io.func_send;
+ func_recv = io.func_recv;
+}
+void Session::set_parsers(SessionParsers p)
+{
+ func_parse = p.func_parse;
+ func_delete = p.func_delete;
+}
+
+
void set_session(io::FD fd, std::unique_ptr<Session> sess)
{
int f = fd.uncast_dammit();
@@ -98,28 +115,10 @@ size_t RFIFOSPACE(Session *s)
}
-/// Discard all input
-static
-void null_parse(Session *s);
-/// Default parser for new connections
-static
-void (*default_func_parse)(Session *) = null_parse;
-static
-void (*default_delete)(Session *) = nullptr;
-
-void set_defaultparse(void (*defaultparse)(Session *), void (*on_delete)(Session *))
-{
- default_func_parse = defaultparse;
- default_delete = on_delete;
-}
-
/// Read from socket to the queue
static
void recv_to_fifo(Session *s)
{
- if (s->private_is_eof())
- return;
-
ssize_t len = s->fd.read(&s->rdata[s->rdata_size],
RFIFOSPACE(s));
@@ -137,9 +136,6 @@ void recv_to_fifo(Session *s)
static
void send_from_fifo(Session *s)
{
- if (s->private_is_eof())
- return;
-
ssize_t len = s->fd.write(&s->wdata[0], s->wdata_size);
if (len > 0)
@@ -158,13 +154,6 @@ void send_from_fifo(Session *s)
}
}
-static
-void null_parse(Session *s)
-{
- PRINTF("null_parse : %d\n", s);
- RFIFOSKIP(s, RFIFOREST(s));
-}
-
static
void connect_client(Session *ls)
@@ -214,24 +203,21 @@ void connect_client(Session *ls)
fd.fcntl(F_SETFL, O_NONBLOCK);
- set_session(fd, make_unique<Session>());
+ set_session(fd, make_unique<Session>(
+ SessionIO{func_recv: recv_to_fifo, func_send: send_from_fifo},
+ ls->for_inferior));
Session *s = get_session(fd);
s->fd = fd;
s->rdata.new_(RFIFO_SIZE);
s->wdata.new_(WFIFO_SIZE);
-
s->max_rdata = RFIFO_SIZE;
s->max_wdata = WFIFO_SIZE;
- s->func_recv = recv_to_fifo;
- s->func_send = send_from_fifo;
- s->func_parse = default_func_parse;
- s->func_delete = default_delete;
s->client_ip = IP4Address(client_address.sin_addr);
s->created = TimeT::now();
s->connected = 0;
}
-Session *make_listen_port(uint16_t port)
+Session *make_listen_port(uint16_t port, SessionParsers inferior)
{
struct sockaddr_in server_address;
io::FD fd = io::FD::socket(AF_INET, SOCK_STREAM, 0);
@@ -280,18 +266,20 @@ Session *make_listen_port(uint16_t port)
readfds.set(fd);
- set_session(fd, make_unique<Session>());
+ set_session(fd, make_unique<Session>(
+ SessionIO{func_recv: connect_client, func_send: nullptr},
+ SessionParsers{func_parse: nullptr, func_delete: nullptr}));
Session *s = get_session(fd);
+ s->for_inferior = inferior;
s->fd = fd;
- s->func_recv = connect_client;
s->created = TimeT::now();
s->connected = 1;
return s;
}
-Session *make_connection(IP4Address ip, uint16_t port)
+Session *make_connection(IP4Address ip, uint16_t port, SessionParsers parsers)
{
struct sockaddr_in server_address;
io::FD fd = io::FD::socket(AF_INET, SOCK_STREAM, 0);
@@ -333,7 +321,9 @@ Session *make_connection(IP4Address ip, uint16_t port)
readfds.set(fd);
- set_session(fd, make_unique<Session>());
+ set_session(fd, make_unique<Session>(
+ SessionIO{func_recv: recv_to_fifo, func_send: send_from_fifo},
+ parsers));
Session *s = get_session(fd);
s->fd = fd;
s->rdata.new_(RFIFO_SIZE);
@@ -341,10 +331,6 @@ Session *make_connection(IP4Address ip, uint16_t port)
s->max_rdata = RFIFO_SIZE;
s->max_wdata = WFIFO_SIZE;
- s->func_recv = recv_to_fifo;
- s->func_send = send_from_fifo;
- s->func_parse = default_func_parse;
- s->func_delete = default_delete;
s->created = TimeT::now();
s->connected = 1;
@@ -441,13 +427,13 @@ void do_sendrecv(interval_t next_ms)
Session *s = get_session(i);
if (!s)
continue;
- if (wfd.isset(i))
+ if (wfd.isset(i) && !s->eof)
{
if (s->func_send)
//send_from_fifo(i);
s->func_send(s);
}
- if (rfd.isset(i))
+ if (rfd.isset(i) && !s->eof)
{
if (s->func_recv)
//recv_to_fifo(i);
@@ -470,7 +456,7 @@ void do_parsepacket(void)
PRINTF("Session #%d timed out\n", s);
s->set_eof();
}
- if (s->rdata_size && !s->private_is_eof() && s->func_parse)
+ if (s->rdata_size && !s->eof && s->func_parse)
{
s->func_parse(s);
/// some func_parse may call delete_session
@@ -479,7 +465,7 @@ void do_parsepacket(void)
if (!s)
continue;
}
- if (s->private_is_eof())
+ if (s->eof)
{
delete_session(s);
continue;
diff --git a/src/mmo/socket.hpp b/src/mmo/socket.hpp
index 53e0dfd..c166794 100644
--- a/src/mmo/socket.hpp
+++ b/src/mmo/socket.hpp
@@ -51,10 +51,28 @@ struct SessionDeleter
void operator()(SessionData *sd);
};
-// Struct declaration
+struct Session;
+struct SessionIO
+{
+ void (*func_recv)(Session *);
+ void (*func_send)(Session *);
+};
+
+struct SessionParsers
+{
+ void (*func_parse)(Session *);
+ void (*func_delete)(Session *);
+};
struct Session
{
+ Session(SessionIO, SessionParsers);
+ Session(Session&&) = delete;
+ Session& operator = (Session&&) = delete;
+
+ void set_io(SessionIO);
+ void set_parsers(SessionParsers);
+
/// Checks whether a newly-connected socket actually does anything
TimeT created;
bool connected;
@@ -64,8 +82,6 @@ private:
bool eof;
public:
void set_eof() { eof = true; }
- // not everything is a member yet ...
- bool private_is_eof() { return eof; }
/// Currently used by clif_setwaitclose
Timer timed_close;
@@ -82,6 +98,7 @@ public:
IP4Address client_ip;
+private:
/// Send or recieve
/// Only called when select() indicates the socket is ready
/// If, after that, nothing is read, it sets eof
@@ -91,14 +108,23 @@ public:
/// This is the important one
/// Set to different functions depending on whether the connection
/// is a player or a server/ladmin
- /// Can be set explicitly or via set_defaultparse
void (*func_parse)(Session *);
/// Cleanup function since we're not fully RAII yet
void (*func_delete)(Session *);
+
+public:
+ // this really ought to be part of session_data, once that gets sane
+ SessionParsers for_inferior;
+
/// Server-specific data type
+ // (this really should include the deleter, but ...)
std::unique_ptr<SessionData, SessionDeleter> session_data;
io::FD fd;
+
+ friend void do_sendrecv(interval_t next);
+ friend void do_parsepacket(void);
+ friend void delete_session(Session *);
};
inline
@@ -133,10 +159,10 @@ IteratorPair<ValueIterator<io::FD, IncrFD>> iter_fds();
/// open a socket, bind, and listen. Return an fd, or -1 if socket() fails,
/// but exit if bind() or listen() fails
-Session *make_listen_port(uint16_t port);
+Session *make_listen_port(uint16_t port, SessionParsers inferior);
/// Connect to an address, return a connected socket or -1
// FIXME - this is IPv4 only!
-Session *make_connection(IP4Address ip, uint16_t port);
+Session *make_connection(IP4Address ip, uint16_t port, SessionParsers);
/// free() the structure and close() the fd
void delete_session(Session *);
/// Make a the internal queues bigger
@@ -146,11 +172,6 @@ void do_sendrecv(interval_t next);
/// Call the parser function for every socket that has read data
void do_parsepacket(void);
-/// Change the default parser for newly connected clients
-// typically called once per server, but individual clients may identify
-// themselves as servers
-void set_defaultparse(void(*defaultparse)(Session *), void(*defaultdelete)(Session *));
-
template<class T>
uint8_t *pod_addressof_m(T& structure)
{