[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: telnet to MzScheme



On Mar  5, Scorzelli Giorgio wrote:
> Hy all,
> 
> I have defined the following script to make MzScheme usable by a simple 
> telnet connection:
> 
> (define (server port)
>      (let ([l (tcp-listen port)])
>        (let-values ([(r w) (tcp-accept l)])
>          (current-output-port w)
>          (current-input-port r)
>          (current-error-port w))))
> 
> but I have a problem: how can I reset MzScheme input port to reset
> (as I normally do with CTRL+C) its contents.

The problem is that the telnet protocol is not too trivial...  I once
wanted a remote-scheme (actually, Swindle) thing similar to what
you're trying to do, but with user logins, background jobs (and C-z to
kick the current evaluation to the bg) etc etc.  After some digging I
managed to get basic functionality, here is the relevant piece of
code:

    ;; some constants for telnet protocol
    (define telnet-escape-ch (integer->char 255))
    (define eof-ch (integer->char 4))

    ;; this function manage telnet input processing
    (define (filter-proc in out)
      ;; get a character
      (define ch (read-char in))
      (cond
       ;; end-of-file (eof-object? shouldn't be #t)
       ((or (eof-object? ch) (eq? ch eof-ch))
        ;; suffocate eval's input
        (close-output-port out))
       ((eq? ch telnet-escape-ch)
        ;; handle telnet escapes
        (case (char->integer (read-char in))
          ((244) ; C-c
           (if (thread-running? eval-thread)
             ;; break the thread
             (break-thread eval-thread)
             ;; if eval-thread is dead - we're waiting for background
             ;; expressions, kill all
             (for-each break-thread background-exprs)))
          ((236) ; C-d
           ;; this is what telnet is supposed to send on an end-of-file
           (close-output-port out))
          ((237) ; C-z
           ;; mark this interrupt as suspension
           (set! suspending? #t)
           (break-thread eval-thread))
          ((253)
           ;; Telnet protocol: DO X --> WON'T X, except for DO ECHO
           (set! ch (read-char in))
           (unless (= 1 (char->integer ch))
             (write-char telnet-escape-ch telnet-out)
             (write-char (integer->char 252) telnet-out)
             (write-char ch telnet-out)))
          ((251 252 254)
           ;; ignore WILL/WONT/DONT
           (read-char in))
          ((255)
           ;; escape escape is escape
           (write-char ch telnet-out))
          (else #f)))
       (else
        ;; out shouldn't be dead but be safe
        (no-errors (write-char ch out))))
      ;; loop forever
      (filter-proc in out))

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!