Files
go3270/telnet.go
T

71 lines
2.1 KiB
Go

// This file is part of https://github.com/racingmars/go3270/
// Copyright 2020 by Matthew R. Wilson, licensed under the MIT license. See
// LICENSE in the project root for license information.
package go3270
import (
"net"
"time"
)
const (
binary = 0
send = 1
se = 240 // f0
sb = 250 // fa
will = 251 // fb
wont = 252 // fc
do = 253 // fd
dont = 254 // fe
iac = 255 // ff
terminalType = 24 // 18
eor = 25 // 19
)
// NegotiateTelnet will naively (e.g. not checking client responses) negotiate
// the options necessary for tn3270 on a new telnet connection, conn.
func NegotiateTelnet(conn net.Conn) error {
conn.Write([]byte{iac, do, terminalType})
conn.Write([]byte{iac, sb, terminalType, send, iac, se})
conn.Write([]byte{iac, do, eor})
conn.Write([]byte{iac, do, binary})
conn.Write([]byte{iac, will, eor, iac, will, binary})
flushConnection(conn, time.Second*5)
return nil
}
// UnNegotiateTelnet will naively (e.g. not checking client responses) attempt
// to restore the telnet options state to what it was before NegotiateTelnet()
// was called.
func UnNegotiateTelnet(conn net.Conn, timeout time.Duration) error {
conn.Write([]byte{iac, wont, eor, iac, wont, binary})
conn.Write([]byte{iac, dont, binary})
conn.Write([]byte{iac, dont, eor})
conn.Write([]byte{iac, dont, terminalType})
flushConnection(conn, timeout)
return nil
}
// flushConnection discards all bytes that it can read from conn, allowing up
// to the duration timeout for the first byte to be read.
func flushConnection(conn net.Conn, timeout time.Duration) error {
defer conn.SetReadDeadline(time.Time{})
buffer := make([]byte, 1024)
for {
conn.SetReadDeadline(time.Now().Add(timeout))
n, err := conn.Read(buffer)
if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
debugf("nothing to flush\n")
return nil
}
if err != nil {
debugf("error while flushing: %v\n", err)
return err
}
debugf("%d bytes read while flushing connection\n", n)
// for follow-up reads, reduce the timeout
timeout = time.Second / 2
}
}