#lang racket (define threads-going 0) (define (read-word-integer-line) ; reads an integer between 0 and 65535 from the current input port (let* ([l (read-line)] [n (string->number l)]) (if (and (integer? n) (<= 0 n 65535)) n (begin (display l) (display " is incorrect. Please enter an integer between 0 and 65535: ") (read-word-integer-line))))) (define (connect-ports i o) ; connects i to o (like a reverse pipe) using a thread. (define (end) (with-handlers ([exn? (lambda (e) #f)]) (close-input-port i)) (with-handlers ([exn? (lambda (e) #f)]) (close-output-port o)) (set! threads-going (- threads-going 1)) (kill-thread (current-thread))) (define (iter) (sleep) (let ([c (with-handlers ([exn? (lambda (e) (end))]) (read-char i))]) (if (equal? c eof) (end) (with-handlers ([exn? (lambda (e) (end))]) (display c o) (flush-output o) (iter))))) (set! threads-going (+ threads-going 1)) (thread iter)) (define (wait-until-cease) ; waits until threads-going reaches 0 then exits (if (> threads-going 0) (begin (sleep) (wait-until-cease)) (exit))) (define-values (local-i local-o) (values (current-input-port) (current-output-port))) (define-values (remote-i remote-o) (let ([ip (begin (display "Please enter ip: ") (read-line))] [port (begin (display "Please enter port: ") (read-word-integer-line))]) (with-handlers ([exn? (lambda (e) (display "Couldn't connect - ") (display (exn-message e)) (exit))]) (tcp-connect ip port)))) (connect-ports local-i remote-o) (connect-ports remote-i local-o) (wait-until-cease)