Consolidating my various blogs into one. This was originally posted on 2010/2/26
Using my scala DSL for State Machine.
Here's the definition (in-work) of the high-level telnet state machine, a little more complicated than the example above, but not much.
The picture (thanks to http://tomi.vanek.sk/index.php?page=telnet):
The state machine is:
implicit val sm = this
val sstates @ (data, cmd, app, param, neg, subneg) = ("data", "cmd", "app", "param", "neg", "subneg")
override def start = state("data")
override val transitions : Seq[Transition] =
(data, IAC) -> cmd ::
(data, 0) -> data :: // NOP - don't know why i get these after CR
(data, 10) -> data :: // NOP - LF ignored?
(data, 13) -> data + eatLine + echo ("") :: // CR
(data, {_:Event=>true}) -> data + eatChar + echo ("") :: // remaining chars
(cmd, IAC) -> data ::
(cmd, Seq(WILL, WONT, DO, DONT)) -> neg + push ::
// TODO 3-2 should negociate stuff, i.e. reply with will/won't
(neg, {_:Event=>last==SM(DO)}) -> data + mode(true) + pop ::
(neg, {_:Event=>last==SM(DONT)}) -> data + mode(false) + pop ::
(neg, AnyEvent) -> data + echo("interesting sequence...") + pop :: // What is this?
(cmd, SB) -> subneg ::
(""".*""".r, CR) -> data :: // it's important to reset the thing on ENTRE
Nil
def eatChar (sm:StateMachine, t:Transition, e:Event)
def eatLine (sm:StateMachine, t:Transition, e:Event)
Enjoy and, more importantly, have fun!
The entire code, together with the full implementation of the Telnet receiver over a plain socket is available at TelnetReceiver.scala. As a bonus, this one comes with a full implementation of a scala REPL dialog, including content assist, part of my Scripster project!
Not only that, but you can telnet right now to demo.razie.com port 4445 and play with it... "online":
$ telnet demo.razie.com 4445
Trying 162.243.37.42...
Connected to demo.razie.com.
Escape character is '^]'.
1+2
3
Cool, huh?