Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow arbitrary connection protocols #26

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 12 additions & 20 deletions conn.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package telnet


import (
"crypto/tls"
"net"
)


type Conn struct {
conn interface {
Read(b []byte) (n int, err error)
Expand All @@ -19,7 +17,6 @@ type Conn struct {
dataWriter *internalDataWriter
}


// Dial makes a (un-secure) TELNET client connection to the system's 'loopback address'
// (also known as "localhost" or 127.0.0.1).
//
Expand All @@ -33,9 +30,10 @@ func Dial() (*Conn, error) {
//
// If a secure connection is desired, use `DialToTLS` instead.
func DialTo(addr string) (*Conn, error) {
return DialToNetwork("tcp", addr)
}

const network = "tcp"

func DialToNetwork(network string, addr string) (*Conn, error) {
if "" == addr {
addr = "127.0.0.1:telnet"
}
Expand All @@ -49,15 +47,14 @@ func DialTo(addr string) (*Conn, error) {
dataWriter := newDataWriter(conn)

clientConn := Conn{
conn:conn,
dataReader:dataReader,
dataWriter:dataWriter,
conn: conn,
dataReader: dataReader,
dataWriter: dataWriter,
}

return &clientConn, nil
}


// DialTLS makes a (secure) TELNETS client connection to the system's 'loopback address'
// (also known as "localhost" or 127.0.0.1).
func DialTLS(tlsConfig *tls.Config) (*Conn, error) {
Expand All @@ -67,9 +64,10 @@ func DialTLS(tlsConfig *tls.Config) (*Conn, error) {
// DialToTLS makes a (secure) TELNETS client connection to the the address specified by
// 'addr'.
func DialToTLS(addr string, tlsConfig *tls.Config) (*Conn, error) {
return DialToNetworkTLS("tcp", addr, tlsConfig)
}

const network = "tcp"

func DialToNetworkTLS(network string, addr string, tlsConfig *tls.Config) (*Conn, error) {
if "" == addr {
addr = "127.0.0.1:telnets"
}
Expand All @@ -83,16 +81,14 @@ func DialToTLS(addr string, tlsConfig *tls.Config) (*Conn, error) {
dataWriter := newDataWriter(conn)

clientConn := Conn{
conn:conn,
dataReader:dataReader,
dataWriter:dataWriter,
conn: conn,
dataReader: dataReader,
dataWriter: dataWriter,
}

return &clientConn, nil
}



// Close closes the client connection.
//
// Typical usage might look like:
Expand All @@ -107,7 +103,6 @@ func (clientConn *Conn) Close() error {
return clientConn.conn.Close()
}


// Read receives `n` bytes sent from the server to the client,
// and "returns" into `p`.
//
Expand All @@ -122,7 +117,6 @@ func (clientConn *Conn) Read(p []byte) (n int, err error) {
return clientConn.dataReader.Read(p)
}


// Write sends `n` bytes from 'p' to the server.
//
// Note that Write can only be used for sending TELNET (and TELNETS) data to the server.
Expand All @@ -135,13 +129,11 @@ func (clientConn *Conn) Write(p []byte) (n int, err error) {
return clientConn.dataWriter.Write(p)
}


// LocalAddr returns the local network address.
func (clientConn *Conn) LocalAddr() net.Addr {
return clientConn.conn.LocalAddr()
}


// RemoteAddr returns the remote network address.
func (clientConn *Conn) RemoteAddr() net.Addr {
return clientConn.conn.RemoteAddr()
Expand Down
11 changes: 2 additions & 9 deletions data_writer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package telnet


import (
"github.com/reiver/go-oi"

Expand All @@ -9,13 +8,11 @@ import (
"io"
)


var iaciac []byte = []byte{255, 255}

var errOverflow = errors.New("Overflow")
var errPartialIACIACWrite = errors.New("Partial IAC IAC write.")


// An internalDataWriter deals with "escaping" according to the TELNET (and TELNETS) protocol.
//
// In the TELNET (and TELNETS) protocol byte value 255 is special.
Expand All @@ -24,7 +21,7 @@ var errPartialIACIACWrite = errors.New("Partial IAC IAC write.")
//
// The TELNET (and TELNETS) protocol also has a distinction between 'data' and 'commands'.
//
//(DataWriter is targetted toward TELNET (and TELNETS) 'data', not TELNET (and TELNETS) 'commands'.)
// (DataWriter is targeted toward TELNET (and TELNETS) 'data', not TELNET (and TELNETS) 'commands'.)
//
// If a byte with value 255 (=IAC) appears in the data, then it must be escaped.
//
Expand All @@ -49,7 +46,6 @@ type internalDataWriter struct {
wrapped io.Writer
}


// newDataWriter creates a new internalDataWriter writing to 'w'.
//
// 'w' receives what is written to the *internalDataWriter but escaped according to
Expand All @@ -70,13 +66,12 @@ type internalDataWriter struct {
// *internalDataWriter takes care of all this for you, so you do not have to do it.
func newDataWriter(w io.Writer) *internalDataWriter {
writer := internalDataWriter{
wrapped:w,
wrapped: w,
}

return &writer
}


// Write writes the TELNET (and TELNETS) escaped data for of the data in 'data' to the wrapped io.Writer.
func (w *internalDataWriter) Write(data []byte) (n int, err error) {
var n64 int64
Expand All @@ -90,7 +85,6 @@ func (w *internalDataWriter) Write(data []byte) (n int, err error) {
return n, err
}


func (w *internalDataWriter) write64(data []byte) (n int64, err error) {

if len(data) <= 0 {
Expand All @@ -115,7 +109,6 @@ func (w *internalDataWriter) write64(data []byte) (n int64, err error) {
buffer.Reset()
}


var numWritten int64
//@TODO: Should we worry about "iaciac" potentially being modified by the .Write()?
numWritten, err = oi.LongWrite(w.wrapped, iaciac)
Expand Down