function GetNewConnections () local s -- handle new connections repeat s = server:accept () -- new client? if s then AddClient (s) end -- if new client until not s end -- GetNewConnections function GetNewInput () local t, s, v t = {} -- build table of sockets for select for s in pairs (sockets) do table.insert (t, s) end -- looping through all clients -- use select to see if input from clients local readable, _, err = socket.select(t, nil, 1) -- check for new input for _, s in ipairs(readable) do local line, err = s:receive() if err then RemoveClient (s) else local client = sockets [s] -- print ("Received", line, "from client", s) client.last_input = os.time () -- note when we last received something if not client.thread or coroutine.status (client.thread) ~= "suspended" then client.thread = coroutine.create (client.handler) end -- let worker thread do something with input line local ok, err = coroutine.resume (client.thread, line, client) if not ok then print ("Got error", err, "from socket", s) Send (client, "\n\nAn server error occurred, this has been logged.\n" .. "Press to continue ...") client.thread = nil end -- of error in client thread end -- not error on input end -- for each readable client end -- GetNewInput function SendOutstandingOutput () local t, s, v t = {} -- build table of sockets that need writing to for s in pairs (sockets) do if sockets [s].output then table.insert (t, s) end -- having outstanding output end -- looping through all clients -- see if output can be sent to clients local _, writeable, err = socket.select (nil, t, 0) -- check if we can send for _, s in ipairs(writeable) do local client = sockets [s] assert (client.socket == s, "client/socket pair not found") local len = math.min (string.len (client.output), config.max_output) local count, err, count2 = s:send (client.output, 1, len) -- timeout just means we are trying to send too much if err and err == "timeout" then err = nil count = count2 end -- timeout -- other errors? drop client if err then print ("Error in send", err) RemoveClient (s) else client.output = string.sub (client.output, count + 1) if string.len (client.output) <= 0 then client.output = nil end -- if end -- not error on output end -- for each writeable client end -- SendOutstandingOutput -- remove socket 's' from active sockets list function RemoveClient (s) s:close() local client = sockets [s] sockets [s] = nil -- that socket not in use now client.socket = nil -- this may be premature here ... if client.name then SaveCharacter (client.name) -- save him chars [client.name] = nil print (client.name, "has left the game") end -- removing character too print ("Removed client socket", s, "from server") end -- RemoveClient -- add socket 's' to list of connected clients function AddClient (s) ip, port = s:getpeername () print ("Connection from", ip, "port", port) s:settimeout(0) local client = {} -- make a new client now sockets [s] = client -- client related to this socket client.socket = s -- which socket it has client.connected = os.time () client.handler = NewConnection client.thread = coroutine.create (client.handler) assert (coroutine.resume (client.thread, nil, client)) -- input handler end -- AddClient -- send text to client (buffers it) function Send (client, str, sameline) local newline = "" if not sameline then newline = "\n" end -- not sameline client.output = (client.output or "" ).. str .. newline end -- Send