From b0d3b261f454e921f90a3a2c748731d3379e2db7 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Fri, 18 Apr 2014 08:38:18 -0700 Subject: Die sensibly, take 2 --- src/mmo/socket.cpp | 80 ++++++++++++++++++++++-------------------------------- src/mmo/socket.hpp | 43 +++++++++++++++++++++-------- 2 files changed, 65 insertions(+), 58 deletions(-) (limited to 'src/mmo') 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, 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 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()); + set_session(fd, make_unique( + 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()); + set_session(fd, make_unique( + 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()); + set_session(fd, make_unique( + 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 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> 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 uint8_t *pod_addressof_m(T& structure) { -- cgit v1.2.3-70-g09d2