exec tclsh "$0" "$@"
set state(wait) 1
set state(openSock) {}
source setopt.tcl
source message.tcl
proc evalOptions args {
global state
setopt port 4242
setopt trace 2
setopt chat 0
set state(port) $port
set state(trace) $trace
set state(chat) $chat
message 2 "port: $state(port)"
message 2 "chat: $state(chat)"
}
proc echoData {socket req} {
sendAnswer $socket $req
}
proc chatData {socket req} {
global state
foreach soc $state(openSock) {
sendAnswer $soc $req
}
}
proc sendAnswer {socket ans} {
if {[catch \
{
puts $socket $ans
flush $socket
} err]} {
message 1 "sendAnswer($socket): error: $err"
closeServer $socket
return
}
message 3 "sendAnswer($socket): message written: $ans"
}
proc processRequest {socket} {
if {[catch \
{
set cnt [gets $socket req]
} err]} {
message 1 "processRequest($socket): $err"
set cnt -1
}
if {$cnt == -1} {
closeServer $socket
return
}
message 3 "processRequest($socket): message read: $req"
processData $socket $req
global state
set state(wait) 1
}
proc openServer {socket args} {
global state
message 2 "openServer: install file event on $socket"
lappend state(openSock) $socket
fileevent $socket readable "processRequest $socket"
}
proc closeServer {socket} {
global state
message 2 "closeServer: close socket $socket"
close $socket
set i [lsearch -exact $state(openSock) $socket]
set state(openSock) [lreplace $state(openSock) $i $i]
if {"$state(openSock)" == ""} {
message 2 "closeServer: server idle, no open connections"
}
}
proc initServer {} {
global state
message 2 "initServer: port is $state(port)"
if {[catch {socket -server openServer $state(port)} err]} {
message 1 "initServer failed: $err"
exit
}
}
proc eventLoop {} {
global state
while {1} {
vwait state(wait)
message 3 "eventLoop: do one event"
update
}
}
proc init {} {
global argv state
eval evalOptions $argv
if {$state(chat) == 1} {
rename chatData processData
} else {
rename echoData processData
}
initServer
eventLoop
}
init