108 lines
2.9 KiB
CoffeeScript
108 lines
2.9 KiB
CoffeeScript
net = require("net")
|
|
sys = require("sys")
|
|
EventEmitter = require("events").EventEmitter
|
|
|
|
isNicknameLegal = (nickname) ->
|
|
return false unless nickname.replace(/[A-Za-z0-9]*/, "") is ""
|
|
for used_nick of @chatters
|
|
return false if used_nick is nickname
|
|
true
|
|
|
|
class ChatServer
|
|
constructor: ->
|
|
@chatters = {}
|
|
@server = net.createServer @handleConnection
|
|
@server.listen 1212, "localhost"
|
|
|
|
handleConnection: (connection) =>
|
|
console.log "Incoming connection from " + connection.remoteAddress
|
|
connection.setEncoding "utf8"
|
|
chatter = new Chatter(connection, this)
|
|
chatter.on "chat", @handleChat
|
|
chatter.on "join", @handleJoin
|
|
chatter.on "leave", @handleLeave
|
|
|
|
handleChat: (chatter, message) =>
|
|
@sendToEveryChatterExcept chatter, chatter.nickname + ": " + message
|
|
|
|
handleJoin: (chatter) =>
|
|
console.log chatter.nickname + " has joined the chat."
|
|
@sendToEveryChatter chatter.nickname + " has joined the chat."
|
|
@addChatter chatter
|
|
|
|
handleLeave: (chatter) =>
|
|
console.log chatter.nickname + " has left the chat."
|
|
@removeChatter chatter
|
|
@sendToEveryChatter chatter.nickname + " has left the chat."
|
|
|
|
addChatter: (chatter) =>
|
|
@chatters[chatter.nickname] = chatter
|
|
|
|
removeChatter: (chatter) =>
|
|
delete @chatters[chatter.nickname]
|
|
|
|
sendToEveryChatter: (data) =>
|
|
for nickname of @chatters
|
|
@chatters[nickname].send data
|
|
|
|
sendToEveryChatterExcept: (chatter, data) =>
|
|
for nickname of @chatters
|
|
@chatters[nickname].send data unless nickname is chatter.nickname
|
|
|
|
|
|
class Chatter extends EventEmitter
|
|
constructor: (socket, server) ->
|
|
EventEmitter.call this
|
|
@socket = socket
|
|
@server = server
|
|
@nickname = ""
|
|
@lineBuffer = new SocketLineBuffer(socket)
|
|
@lineBuffer.on "line", @handleNickname
|
|
@socket.on "close", @handleDisconnect
|
|
@send "Welcome! What is your nickname?"
|
|
|
|
handleNickname: (nickname) =>
|
|
if isNicknameLegal(nickname)
|
|
@nickname = nickname
|
|
@lineBuffer.removeAllListeners "line"
|
|
@lineBuffer.on "line", @handleChat
|
|
@send "Welcome to the chat, " + nickname + "!"
|
|
@emit "join", this
|
|
else
|
|
@send "Sorry, but that nickname is not legal or is already in use!"
|
|
@send "What is your nickname?"
|
|
|
|
handleChat: (line) =>
|
|
@emit "chat", this, line
|
|
|
|
handleDisconnect: =>
|
|
@emit "leave", this
|
|
|
|
send: (data) =>
|
|
@socket.write data + "\r\n"
|
|
|
|
|
|
class SocketLineBuffer extends EventEmitter
|
|
constructor: (socket) ->
|
|
EventEmitter.call this
|
|
@socket = socket
|
|
@buffer = ""
|
|
@socket.on "data", @handleData
|
|
|
|
handleData: (data) =>
|
|
console.log "Handling data", data
|
|
i = 0
|
|
|
|
while i < data.length
|
|
char = data.charAt(i)
|
|
@buffer += char
|
|
if char is "\n"
|
|
@buffer = @buffer.replace("\r\n", "")
|
|
@buffer = @buffer.replace("\n", "")
|
|
@emit "line", @buffer
|
|
console.log "incoming line: #{@buffer}"
|
|
@buffer = ""
|
|
i++
|
|
|
|
server = new ChatServer()
|