Browse Source

Added door32 routine for testing.

Steve Thielemann 2 years ago
parent
commit
6b81c3a430
2 changed files with 256 additions and 0 deletions
  1. 250 0
      door32.go
  2. 6 0
      run4044

+ 250 - 0
door32.go

@@ -0,0 +1,250 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"log"
+	"net"
+	"os"
+	"os/exec"
+	"strconv"
+	"strings"
+	"time"
+)
+
+const (
+	connHost = "0.0.0.0"
+	connPort = "8080"
+	connType = "tcp"
+)
+
+func main() {
+	var port int
+	var drain int
+	var cp437 bool
+
+	flag.IntVar(&port, "p", 0, "Port number to listen on")
+	flag.IntVar(&drain, "d", 2, "Drain seconds")
+	flag.BoolVar(&cp437, "c", false, "Force CP437 translation")
+	flag.Parse()
+
+	if port == 0 && flag.NArg() != 1 {
+		fmt.Println("I need a Port and a commandline to execute.")
+		flag.PrintDefaults()
+		os.Exit(2)
+	}
+
+	fmt.Println("Starting " + connType + " server on " + connHost + ":" + strconv.Itoa(port))
+	l, err := net.Listen("tcp", "0.0.0.0:"+strconv.Itoa(port))
+	if err != nil {
+		log.Println("Error listening:", err)
+		os.Exit(1)
+	}
+	defer l.Close()
+
+	for {
+		var c net.Conn
+		var err error
+
+		c, err = l.Accept()
+		if err != nil {
+			log.Println("Error connecting:", err)
+			return
+		}
+		go Connection(c, drain, flag.Arg(0), cp437)
+	}
+}
+
+func Conn_to_File(conn net.Conn) *os.File {
+	var tcpconn *net.TCPConn = conn.(*net.TCPConn)
+
+	// This creates a duplicate fd, but once closed -- the fd gets reused!
+	var conn_file *os.File
+	// var err error
+	conn_file, _ = tcpconn.File()
+
+	return conn_file
+}
+
+func ReadFrom_WriteTo(read net.Conn, write net.Conn, closed *bool) {
+	var buff []byte = make([]byte, 128)
+	var n int
+	var err error
+
+	defer func() {
+		read.Close()
+		write.Close()
+		if !*closed {
+			log.Println("*Closed*")
+			*closed = true
+		}
+	}()
+
+	for {
+		n, err = read.Read(buff)
+		if err != nil {
+			return
+		}
+		n, err = write.Write(buff[:n])
+		if err != nil {
+			return
+		}
+	}
+}
+
+func ReadFrom_WriteToCP437(read net.Conn, write net.Conn, closed *bool) {
+	var buff []byte = make([]byte, 128)
+	var n int
+	var err error
+
+	defer func() {
+		read.Close()
+		write.Close()
+		if !*closed {
+			log.Println("*Closed*")
+			*closed = true
+		}
+	}()
+
+	for {
+		n, err = read.Read(buff)
+		if err != nil {
+			return
+		}
+		var line = string(buff[:n])
+
+		// This does convert everything to unicode
+		// syncterm doesn't like it (because it doesn't understand
+		// unicode!)
+		// The "door" detects CP437 (not unicode)
+
+		// This would allow a CP437 door to run as unicode.
+		n, err = write.Write([]byte(CP437_to_Unicode(line)))
+		if err != nil {
+			return
+		}
+	}
+}
+
+func StartProxy(live net.Conn, monitor net.Conn, closed *bool, cp437 bool) {
+	go ReadFrom_WriteTo(live, monitor, closed)
+
+	if cp437 {
+		go ReadFrom_WriteToCP437(monitor, live, closed)
+	} else {
+		go ReadFrom_WriteTo(monitor, live, closed)
+	}
+}
+
+/*
+	Read from live, write to server.
+	Read from server, write to live.
+*/
+func setup_monitor(live net.Conn, closed *bool, cp437 bool) (monitor net.Conn) {
+	var err error
+	var tempsock net.Listener
+
+	tempsock, err = net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		panic(err)
+	}
+
+	// I only need address for making the connection.
+	// Get address of listening socket
+	var address string
+	address = tempsock.Addr().String()
+
+	monitor, err = net.Dial("tcp", address)
+
+	if err != nil {
+		panic(err)
+	}
+
+	var server net.Conn
+	server, err = tempsock.Accept()
+	if err != nil {
+		panic(err)
+	}
+	tempsock.Close()
+
+	*closed = false
+	// monitor established - forward live <-> monitor
+	go StartProxy(live, server, closed, cp437)
+
+	return monitor
+}
+
+func Connection(conn net.Conn, drain int, cmd string, cp437 bool) {
+	log.Println("Client " + conn.RemoteAddr().String() + " connected.")
+
+	// Configure telnet connection to work
+	// local echo off, handle CRNL.
+	conn.Write([]byte("\xff\xfb\x01\xff\xfb\x03\xff\xfd\x10"))
+	Drain(conn, drain)
+
+	var closed bool
+	var proxy net.Conn
+	proxy = setup_monitor(conn, &closed, cp437)
+
+	// Write out dropfile
+	var conn_file *os.File = Conn_to_File(proxy)
+	var handle int = 3
+	var err error
+	var fp *os.File
+	fp, err = os.Create("door32.sys")
+	if err != nil {
+		log.Println("os.Create:", err)
+		return
+	}
+
+	fmt.Fprintf(fp, "2\n%d\n38400\nFake Door32\n1\nBugz Laundry\nBugz\n100\n120\n1\n1\n", handle)
+	fp.Close()
+
+	var parts []string = strings.Split(cmd, " ")
+	var Exe *exec.Cmd = exec.Command(parts[0], parts[1:]...)
+	Exe.ExtraFiles = make([]*os.File, 1)
+	Exe.ExtraFiles[0] = conn_file
+
+	Exe.Stderr = os.Stderr
+	Exe.Stdout = os.Stdout
+
+	err = Exe.Start()
+	if err != nil {
+		log.Println("exec.Cmd.Start():", err)
+		return
+	}
+	log.Println("Door running..." + conn.RemoteAddr().String())
+	// Add a timeout here - to make sure the door isn't hung.
+	// Is there a way to detect if the conn is disconnected?
+
+	err = Exe.Wait()
+	if err != nil {
+		log.Println("exec.Cmd.Wait():", err)
+		return
+	}
+
+	if closed {
+		log.Println("Closed!")
+	}
+	log.Println("Door ended..." + conn.RemoteAddr().String())
+	conn_file.Close()
+	proxy.Close()
+
+	conn.Write([]byte("\r\nWelcome back...\r\n"))
+	conn.Close()
+}
+
+func Drain(conn net.Conn, drain int) {
+	conn.SetReadDeadline(time.Now().Add(time.Second * time.Duration(drain)))
+	var buff []byte = make([]byte, 32)
+	var n int
+	var err error
+	n, err = conn.Read(buff)
+	if n > 0 {
+		log.Printf("Drained %d bytes.\n", n)
+	}
+	if err != nil {
+		log.Println("Drain:", err)
+	}
+	conn.SetReadDeadline(time.Time{})
+}

+ 6 - 0
run4044

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# We now chdir, so ../door32.sys
+
+./door32 -p 4044 "testdoor/testdoor -d ../door32.sys"
+