// retoor <retoor@molodetz.nl>
import "websocket" for WebSocket, WebSocketServer
import "scheduler" for Scheduler
import "timer" for Timer
var port = 8080
var clients = []
var clientId = 0
System.print("=== WebSocket Chat Server ===")
System.print("Listening on ws://0.0.0.0:%(port)")
System.print("Clients can send messages that get broadcast to all others.\n")
var broadcast = Fn.new { |sender, message|
var i = 0
while (i < clients.count) {
var client = clients[i]
if (client["ws"].isOpen && client["id"] != sender) {
client["ws"].send(message)
}
i = i + 1
}
}
var removeClient = Fn.new { |id|
var i = 0
while (i < clients.count) {
if (clients[i]["id"] == id) {
clients.removeAt(i)
break
}
i = i + 1
}
}
var handleClient = Fn.new { |ws, id|
var client = {"ws": ws, "id": id, "name": "User%(id)"}
clients.add(client)
System.print("[%(client["name"])] Connected (%(clients.count) clients online)")
broadcast.call(id, "*** %(client["name"]) joined the chat ***")
while (ws.isOpen) {
var msg = ws.receive()
if (msg == null || msg.isClose) {
break
}
if (msg.isText) {
var text = msg.text
if (text.startsWith("/name ")) {
var oldName = client["name"]
client["name"] = text[6..-1]
broadcast.call(-1, "*** %(oldName) is now known as %(client["name"]) ***")
ws.send("Name changed to %(client["name"])")
} else if (text == "/who") {
var names = []
for (c in clients) {
names.add(c["name"])
}
ws.send("Online: " + names.join(", "))
} else if (text == "/quit") {
ws.send("Goodbye!")
break
} else {
var chatMsg = "[%(client["name"])]: %(text)"
System.print(chatMsg)
broadcast.call(id, chatMsg)
ws.send(chatMsg)
}
}
}
removeClient.call(id)
System.print("[%(client["name"])] Disconnected (%(clients.count) clients online)")
broadcast.call(id, "*** %(client["name"]) left the chat ***")
}
var server = WebSocketServer.bind("0.0.0.0", port)
while (true) {
var ws = server.accept()
if (ws != null) {
clientId = clientId + 1
var id = clientId
Scheduler.add {
handleClient.call(ws, id)
}
}
}