From: ian Date: Wed, 21 May 2008 16:53:54 +0000 (+0000) Subject: wip multiplex spec and impl'n X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=59aabd21aae572d804926bab2f89cafc8b6220be;p=trains.git wip multiplex spec and impl'n --- diff --git a/hostside/README.commands b/hostside/README.commands index fdb6e6c..8dd2be7 100644 --- a/hostside/README.commands +++ b/hostside/README.commands @@ -40,12 +40,12 @@ POSSIBLY-ASYNCHRONOUS REPORTING OF MESSAGES TO/FROM (MASTER) PIC U< ?resolving - U< ?resolution inexplicable - U< ?resolution mispositioned head|tail - U< ?resolution movpos-change-failed / - U< ?resolution problems + S< ?resolution inexplicable + S< ?resolution mispositioned head|tail + S< ?resolution movpos-change-failed / + S< ?resolution problems - U< ?stastate + S< ?stastate U< ?warning [ ] : U< ?warning watchdog : PIC watchdog timer triggered @@ -54,15 +54,15 @@ POSSIBLY-ASYNCHRONOUS REPORTING OF MESSAGES TO/FROM (MASTER) PIC U< ?train signalling-problem .... U< ?train signalling-problem : - U< ?train forwards|backwards at [-]:+- - U< ?train has [-][/].... + S< ?train forwards|backwards at [-]:+- + S< ?train has [-][/].... is * for det_expected ! for foredetect @ for det_ignore - U< ?movpos feat point|relay - U< ?movpos position moving - U< ?movpos position stable + S< ?movpos feat point|relay + S< ?movpos position moving + S< ?movpos position stable may be ? for unknown U< ?debug : @@ -70,10 +70,10 @@ POSSIBLY-ASYNCHRONOUS REPORTING OF MESSAGES TO/FROM (MASTER) PIC MESSAGES TO SIMULATION LOG - S picioh in suppressed [...] - S command-in .... - S timestamp . - S timer-event . + L picioh in suppressed [...] + L command-in .... + L timestamp . + L timer-event . ====================================================================== @@ -95,14 +95,14 @@ COMMANDS AND RESPONSES inclusive, is prefixed with `-' if they are not due to this client or `+' if they are. - Some commands have ! at the end of their name + Some commands have ! at the start of their name - that means they are privileged. ====================================================================== MULTIPLEXER FACILITIES - M< = indicates messages to and from the multiplexer about this + M< = indicates messages from the multiplexer about this M> = specific client connection M< =connected @@ -113,7 +113,7 @@ MULTIPLEXER FACILITIES M< =failing : otherwise there is no need to quit - just send eof - M< =select [~]... + M< select [~]... first match wins; ~ discards the message; if nothing matches, all are selected; patterns are matched against message with _ replacing spaces and added to the end; patterns which contain @@ -121,27 +121,20 @@ MULTIPLEXER FACILITIES is limited for safety and if it is too long it is truncated. M> =select - M< =replay [~]... - -broadcast messages start with % - - C> $replay% [!] - - M< %[!] ... depends on - must be [a-z][-0-9a-z]* - M> %[!] ... echoed to all clients + M< replay [~]... + M> + M> =replay MULTIPLEXER-IMPLEMENTED FUNCTIONALITY AFFECTING WHOLE SYSTEM - P> $[!] ... - R< ?executing $[!] - R< ?ack $[!] ok + P> [!] ... + R< ?executing [!] + R< ?ack [!] ok - C> $realtime! kill|finish|start|start-manual - C> $save! + C> !realtime kill|finish|start|start-manual + C> !save - C> $reserve ====================================================================== diff --git a/hostside/multiplex b/hostside/multiplex new file mode 100755 index 0000000..5c75b85 --- /dev/null +++ b/hostside/multiplex @@ -0,0 +1,80 @@ +#!/usr/bin/tclsh8.4 + +proc find-permission {ipaddr} { + global permissions + set ipaddr [ipaddr2hex $ipaddr] + foreach keyword paddr pmask { + if {[expr {($ipaddr & $pmask) == $paddr}]} { return $keyword } + } + return deny +} + +proc connected {conn} { + upvar #0 c/$conn c + fconfigure $conn -blocking 0 -buffering none -translation auto + set perm [find-permission $c(ipaddr)] + switch -exact $perm { + deny { finally $conn =denied; return } + allow { set c(super) 0 } + super { set c(super) 1 } + default { error "$perm ?" } + } + xmit $conn =connected + xmit $conn =permission [lindex {normal super} $c(super)] + fileevent $conn readable [list trapping readable $conn] +} + +proc trapping {proc conn args} { + if {[catch { + eval $proc + +proc newconn {conn ipaddr port} { + upvar #0 c/$conn c + catch { unset c } + set c(ipaddr) $ipaddr + trapping connected $conn +} + +proc try-bind {$addr} { + global master errorInfo errorCode + if {![catch { + set master [socket -server newconn -myaddr $addr 2883] + } emsg]} { return 1 } + if {[string match {POSIX EADDRNOTAVAIL *} $errorCode]} { return 0 } + error $emsg $errorInfo $errorCode +} + +proc ipaddr2hex {addr} { + if {![regexp {^\d+\.\d+\.\d+\.\d+$} $addr]} { + error "invalid ip address $addr" + } + set val 0x + foreach octet [split $addr .] { append val [format %02x $octet] } + if {[string length $val != 10]} { + error "invalid numbers in ip address $addr (calculated $val ?!)" + } + return $val +} + +proc binding {address blist} { + global master permissions + if {[info exists master]} return + if {![try-bind $address]} return + set permissions {} + foreach {keyword pattern} $blist { + switch -exact $keyword allow - super - deny { } \ + default { error "unknown binding keyword $keyword" } + if {![regexp {^(.*)/(\d+)$} $pattern dummy host masklen]} { + set host $pattern; set masklen 32 + } + set ipaddr [ipaddr2hex $host] + set mask [expr {$masklen==0 ? 0 : 0xffffffff << (32-$masklen)}] + if {$ipaddr & $mask} { error "non-zero bits outside mask in $pattern" } + lappend permissions $keyword $ipaddr $mask + } +} + +proc readconfig {} { + catch { close $master }; catch { unset master } + source multiplex-config +} diff --git a/hostside/multiplex-config b/hostside/multiplex-config new file mode 100644 index 0000000..13c47c4 --- /dev/null +++ b/hostside/multiplex-config @@ -0,0 +1,12 @@ +binding 172.18.45.37 { + allow 172.18.45.192/26 + super 172.18.45.2 + super 172.18.45.4 + super 172.18.45.6 + super 172.18.45.37 + deny 0.0.0.0/32 +} +binding 127.0.0.1 { + super 127.0.0.1 + deny 0.0.0.0/32 +}