--[[
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