--[[ lama is a MUD server made in Lua. Copyright (C) 2013 Curtis Erickson This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. ]] --- Cloneable that listens on a port and connects new Clients. -- @author milkmanjack module("obj.Server", package.seeall) local Cloneable = require("obj.Cloneable") local Client = require("obj.Client") --- Cloneable that listens on a port and connects new Clients. -- @class table -- @name Server -- @field socket The socket associated with this Server. local Server = Cloneable.clone() -- runtime data Server.socket = nil --- Contains all of the Clients a Server is listening to. -- @class table -- @name Server.clients Server.clients = nil --- Creates a unique clients table per Server. function Server:initialize(socket) self.clients = {} if socket then self:setSocket(socket) end end --- Host the server. -- @param port The port to host on. -- @return true on success.<br/>false otherwise. function Server:host(port) local socket = socket.tcp() -- bind it to the port _, err = socket:bind("*", port, 3) if not _ then return false, err end -- begin listening local _, err = socket:listen(3) if not _ then return false, err end self:initializeServerSocket(socket) self:setSocket(socket) return true end --- Close the Server. -- @return true on success.<br/>false otherwise. function Server:close() if not self:isHosted() then return false end self.socket:close() self.socket = nil return true end --- Attempt to accept a new Client. -- @return true if a Client is accepted.<br/>false otherwise. function Server:accept() if not self:isHosted() then return false end local socket, err = self.socket:accept() if not socket then return false, err end local client = Client:new(socket) self:connectClient(client) return client end --- Start managing a Client. -- @param client The Client to manage. function Server:connectClient(client) table.insert(self.clients, client) self:initializeClientSocket(client:getSocket()) end --- Stop managing a Client. -- @param client The Client to stop managing. function Server:disconnectClient(client) table.removeValue(self.clients, client) --[[ for i,v in ipairs(self.clients) do if v == client then table.remove(self.clients, i) end end ]] client:getSocket():close() end --- Initialize the socket's settings for this Server. -- By default, the Server socket is made to act asynchroniously, -- with a 1/1000th second timeout for I/O operations. -- @param socket The socket to initialize. function Server:initializeServerSocket(socket) socket:settimeout(0.001) end --- Initialize the socket's settings for an incoming Client. -- By default, the Client socket is made to act asynchroniously, -- with a 1/1000th second timeout for I/O operations. -- @param socket The socket to initialize. function Server:initializeClientSocket(socket) socket:settimeout(0.001) end --- Manually assign a socket. -- @param socket Socket to be assigned. function Server:setSocket(socket) self.socket = socket end --- Check if the Server is hosted. -- @return true if it is being hosted.<br/>false otherwise. function Server:isHosted() return (self.socket ~= nil and self.socket:getsockname() ~= nil) end -- Return the Server's socket. -- @return Server's socket. function Server:getSocket() return self.socket end --- Return the Server's list of Clients. -- @return The list of Clients. function Server:getClients() return self.clients end return Server