#!/usr/bin/ruby #====================================================================== # * Session #---------------------------------------------------------------------- # The thread for each individual user #====================================================================== class Session attr_reader :socket #------------------------------------------------------------ # Initialize #------------------------------------------------------------ def initialize(socket) @socket = socket # Socket to client @timeout = Time.now.to_i + 120 # Time to time out (2 minutes) # Add to global session list $sessions.push(self) # Debug output puts "Connected to #{socket.addr[3]}" # Listening thread @listen = Thread.new do # Until socket closes until socket.eof? # Wait for command and data command, data = socket.gets.scan(/(\S+) (.*\n)/)[0] # Reset timeout when data is recieved @timeout = Time.now.to_i + 120 # Command handlers case command when 'SAY' say(data) end end # Disconnect disconnect('Socket closed') end # Main loop until @die # Timeout if necessary if Time.now.to_i >= @timeout disconnect('Ping timeout') end # Wait sleep(1) end end #------------------------------------------------------------ # Disconnect #------------------------------------------------------------ def disconnect(reason) # Remove from session list $sessions.delete(self) # Debug output puts "Disconnected from #{@socket.addr[3]} (#{reason})" # Kill update loop @die = true # Kill listening thread @listen.kill end #------------------------------------------------------------ # Say #------------------------------------------------------------ def say(message) # Send message to all sessions for session in $sessions unless session == self session.socket.write("#{@socket.addr[3]}: #{message}") end end # Debug output puts "#{@socket.addr[3]}: #{message}" end end #====================================================================== # * Main #---------------------------------------------------------------------- # Requires, server initialization, and main loop #====================================================================== require 'net/http' # Start server server = TCPServer.new('localhost', 9090) # Debug output puts 'Listening...' # Global session list $sessions = [] # Debug threads Thread.abort_on_exception = true # Allow code from terminal Thread.new do require 'eval' end # Connection handler while (socket = server.accept) Thread.new do Session.new(socket) end end