Add telnet dependencies

This commit is contained in:
Manfred Touron 2017-12-28 23:52:58 +01:00
parent b9af077ef4
commit 2352a53e6e
26 changed files with 2108 additions and 0 deletions

19
vendor/github.com/reiver/go-oi/LICENSE generated vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2016 Charles Iliya Krempeaux <charles@reptile.ca> :: http://changelog.ca/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

64
vendor/github.com/reiver/go-oi/README.md generated vendored Normal file
View file

@ -0,0 +1,64 @@
# go-oi
Package **oi** provides useful tools to be used with the Go programming language's standard "io" package.
For example, did you know that when you call the `Write` method on something that fits the `io.Writer`
interface, that it is possible that not everything was be written?!
I.e., that a _**short write**_ happened.
That just doing the following is (in general) **not** enough:
```
n, err := writer.Write(p)
```
That, for example, you should be checking if `err == io.ErrShortWrite`, and then maybe calling the `Write`
method again but only with what didn't get written.
For a simple example of this (that actually is **not** sufficient to solve this problem, but illustrates
the direction you would need to go to solve this problem is):
```
n, err := w.Write(p)
if io.ErrShortWrite == err {
n2, err2 := w.Write(p[n:])
}
```
Note that the second call to the `Write` method passed `p[n:]` (instead of just `p`), to account for the `n` bytes
already being written (with the first call to the `Write` method).
A more "production quality" version of this would likely be in a loop, but such that that the loop had "guards"
against looping forever, and also possibly looping for "too long".
Well package **oi** provides tools that helps you deal with this and other problems. For example, you
can handle a _**short write**_ with the following **oi** func:
```
n, err := oi.LongWrite(writer, p)
```
## Documention
Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-oi
[![GoDoc](https://godoc.org/github.com/reiver/go-oi?status.svg)](https://godoc.org/github.com/reiver/go-oi)
## Example
```
import (
"github.com/reiver/go-oi"
)
// ...
p := []byte("It is important that this message be written!!!")
n, err := oi.LongWrite(writer, p)
if nil != err {
//@TODO: Handle error.
return
}
```

39
vendor/github.com/reiver/go-oi/doc.go generated vendored Normal file
View file

@ -0,0 +1,39 @@
/*
Package oi provides useful tools to be used with Go's standard "io" package.
For example, did you know that when you call the Write method on something that fits the io.Writer
interface, that it is possible that not everything was be written?!
I.e., that a 'short write' happened.
That just doing the following is (in general) not enough:
n, err := writer.Write(p)
That, for example, you should be checking if "err == io.ErrShortWrite", and then maybe calling the Write
method again but only with what didn't get written.
For a simple example of this (that actually is not sufficient to solve this problem, but illustrates
the direction you would need to go to solve this problem is):
n, err := w.Write(p)
if io.ErrShortWrite == err {
n2, err2 := w.Write(p[n:])
}
Note that the second call to the Write method passed "p[n:]" (instead of just "p"), to account for the "n" bytes
already being written (with the first call to the `Write` method).
A more "production quality" version of this would likely be in a loop, but such that that the loop had "guards"
against looping forever, and also possibly looping for "too long".
Well package oi provides tools that helps you deal with this and other problems. For example, you
can handle a 'short write' with the following oi func:
```
n, err := oi.LongWrite(writer, p)
```
*/
package oi

39
vendor/github.com/reiver/go-oi/longwrite.go generated vendored Normal file
View file

@ -0,0 +1,39 @@
package oi
import (
"io"
)
// LongWrite tries to write the bytes from 'p' to the writer 'w', such that it deals
// with "short writes" where w.Write would return an error of io.ErrShortWrite and
// n < len(p).
//
// Note that LongWrite still could return the error io.ErrShortWrite; but this
// would only be after trying to handle the io.ErrShortWrite a number of times, and
// then eventually giving up.
func LongWrite(w io.Writer, p []byte) (int64, error) {
numWritten := int64(0)
for {
//@TODO: Should check to make sure this doesn't get stuck in an infinite loop writting nothing!
n, err := w.Write(p)
numWritten += int64(n)
if nil != err && io.ErrShortWrite != err {
return numWritten, err
}
if !(n < len(p)) {
break
}
p = p[n:]
if len(p) < 1 {
break
}
}
return numWritten, nil
}

28
vendor/github.com/reiver/go-oi/longwritebyte.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
package oi
import (
"io"
)
// LongWriteByte trys to write the byte from 'b' to the writer 'w', such that it deals
// with "short writes" where w.Write would return an error of io.ErrShortWrite and
// n < 1.
//
// Note that LongWriteByte still could return the error io.ErrShortWrite; but this
// would only be after trying to handle the io.ErrShortWrite a number of times, and
// then eventually giving up.
func LongWriteByte(w io.Writer, b byte) error {
var buffer [1]byte
p := buffer[:]
buffer[0] = b
numWritten, err := LongWrite(w, p)
if 1 != numWritten {
return io.ErrShortWrite
}
return err
}

39
vendor/github.com/reiver/go-oi/longwritestring.go generated vendored Normal file
View file

@ -0,0 +1,39 @@
package oi
import (
"io"
)
// LongWriteString tries to write the bytes from 's' to the writer 'w', such that it deals
// with "short writes" where w.Write (or w.WriteString) would return an error of io.ErrShortWrite
// and n < len(s).
//
// Note that LongWriteString still could return the error io.ErrShortWrite; but this
// would only be after trying to handle the io.ErrShortWrite a number of times, and
// then eventually giving up.
func LongWriteString(w io.Writer, s string) (int64, error) {
numWritten := int64(0)
for {
//@TODO: Should check to make sure this doesn't get stuck in an infinite loop writting nothing!
n, err := io.WriteString(w, s)
numWritten += int64(n)
if nil != err && io.ErrShortWrite != err {
return numWritten, err
}
if !(n < len(s)) {
break
}
s = s[n:]
if len(s) < 1 {
break
}
}
return numWritten, nil
}

38
vendor/github.com/reiver/go-oi/writenopcloser.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
package oi
import (
"io"
)
// WriteNopCloser takes an io.Writer and returns an io.WriteCloser where
// calling the Write method on the returned io.WriterCloser calls the
// Write method on the io.Writer it received, but whre calling the Close
// method on the returned io.WriterCloser does "nothing" (i.e., is a "nop").
//
// This is useful in cases where an io.WriteCloser is expected, but you
// only have an io.Writer (where closing doesn't make sense) and you
// need to make your io.Writer fit. (I.e., you need an adaptor.)
func WriteNopCloser(w io.Writer) io.WriteCloser {
wc := internalWriteNopCloser{
writer:w,
}
return &wc
}
type internalWriteNopCloser struct {
writer io.Writer
}
func (wc * internalWriteNopCloser) Write(p []byte) (n int, err error) {
return wc.writer.Write(p)
}
func (wc * internalWriteNopCloser) Close() error {
return nil
}

19
vendor/github.com/reiver/go-telnet/LICENSE generated vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2016 Charles Iliya Krempeaux <charles@reptile.ca> :: http://changelog.ca/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

252
vendor/github.com/reiver/go-telnet/README.md generated vendored Normal file
View file

@ -0,0 +1,252 @@
# go-telnet
Package **telnet** provides TELNET and TELNETS client and server implementations, for the Go programming language.
The **telnet** package provides an API in a style similar to the "net/http" library that is part of the Go standard library, including support for "middleware".
(TELNETS is *secure TELNET*, with the TELNET protocol over a secured TLS (or SSL) connection.)
## Documention
Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-telnet
[![GoDoc](https://godoc.org/github.com/reiver/go-telnet?status.svg)](https://godoc.org/github.com/reiver/go-telnet)
## Very Simple TELNET Server Example
A very very simple TELNET server is shown in the following code.
This particular TELNET server just echos back to the user anything they "submit" to the server.
(By default, a TELNET client does *not* send anything to the server until the [Enter] key is pressed.
"Submit" means typing something and then pressing the [Enter] key.)
```
package main
import (
"github.com/reiver/go-telnet"
)
func main() {
var handler telnet.Handler = telnet.EchoHandler
err := telnet.ListenAndServe(":5555", handler)
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
}
```
If you wanted to test out this very very simple TELNET server, if you were on the same computer it was
running, you could connect to it using the bash command:
```
telnet localhost 5555
```
(Note that we use the same TCP port number -- "5555" -- as we had in our code. That is important, as the
value used by your TELNET server and the value used by your TELNET client **must** match.)
## Very Simple (Secure) TELNETS Server Example
TELNETS is the secure version of TELNET.
The code to make a TELNETS server is very similar to the code to make a TELNET server.
(The difference between we use the `telnet.ListenAndServeTLS` func instead of the
`telnet.ListenAndServe` func.)
```
package main
import (
"github.com/reiver/go-telnet"
)
func main() {
var handler telnet.Handler = telnet.EchoHandler
err := telnet.ListenAndServeTLS(":5555", "cert.pem", "key.pem", handler)
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
}
```
If you wanted to test out this very very simple TELNETS server, get the `telnets` client program from here:
https://github.com/reiver/telnets
## TELNET Client Example:
```
package main
import (
"github.com/reiver/go-telnet"
)
func main() {
var caller Caller = telnet.StandardCaller
//@TOOD: replace "example.net:5555" with address you want to connect to.
telnet.DialToAndCall("example.net:5555", caller)
}
```
## TELNETS Client Example:
```
package main
import (
"github.com/reiver/go-telnet"
"crypto/tls"
)
func main() {
//@TODO: Configure the TLS connection here, if you need to.
tlsConfig := &tls.Config{}
var caller Caller = telnet.StandardCaller
//@TOOD: replace "example.net:5555" with address you want to connect to.
telnet.DialToAndCallTLS("example.net:5555", caller, tlsConfig)
}
```
## TELNET Shell Server Example
A more useful TELNET servers can be made using the `"github.com/reiver/go-telnet/telsh"` sub-package.
For example:
```
package main
import (
"github.com/reiver/go-oi"
"github.com/reiver/go-telnet"
"github.com/reiver/go-telnet/telsh"
"fmt"
"io"
"time"
)
func fiveHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser)error {
oi.LongWriteString(stdout, "The number FIVE looks like this: 5\r\n")
return nil
}
func fiveProducer(ctx telsh.Context, name string, args ...string) telsh.Handler{
return telsh.PromoteHandlerFunc(fiveHandler)
}
func danceHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser)error {
for i:=0; i<20; i++ {
oi.LongWriteString(stdout, "\r⠋")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠙")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠹")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠸")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠼")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠴")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠦")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠧")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠇")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠏")
time.Sleep(50*time.Millisecond)
}
oi.LongWriteString(stdout, "\r \r\n")
return nil
}
func danceProducer(ctx telsh.Context, name string, args ...string) telsh.Handler{
return telsh.PromoteHandlerFunc(danceHandler)
}
func main() {
shellHandler := telsh.NewShellHandler()
shellHandler.WelcomeMessage = `
__ __ ______ _ _____ ____ __ __ ______
\ \ / /| ____|| | / ____| / __ \ | \/ || ____|
\ \ /\ / / | |__ | | | | | | | || \ / || |__
\ \/ \/ / | __| | | | | | | | || |\/| || __|
\ /\ / | |____ | |____ | |____ | |__| || | | || |____
\/ \/ |______||______| \_____| \____/ |_| |_||______|
`
// Register the "five" command.
commandName := "five"
commandProducer := telsh.ProducerFunc(fiveProducer)
shellHandler.Register(commandName, commandProducer)
// Register the "dance" command.
commandName = "dance"
commandProducer = telsh.ProducerFunc(danceProducer)
shellHandler.Register(commandName, commandProducer)
shellHandler.Register("dance", telsh.ProducerFunc(danceProducer))
addr := ":5555"
if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
panic(err)
}
}
```
TELNET servers made using the `"github.com/reiver/go-telnet/telsh"` sub-package will often be more useful
as it makes it easier for you to create a *shell* interface.
# More Information
There is a lot more information about documentation on all this here: http://godoc.org/github.com/reiver/go-telnet
(You should really read those.)

18
vendor/github.com/reiver/go-telnet/caller.go generated vendored Normal file
View file

@ -0,0 +1,18 @@
package telnet
// A Caller represents the client end of a TELNET (or TELNETS) connection.
//
// Writing data to the Writer passed as an argument to the CallTELNET method
// will send data to the TELNET (or TELNETS) server.
//
// Reading data from the Reader passed as an argument to the CallTELNET method
// will receive data from the TELNET server.
//
// The Writer's Write method sends "escaped" TELNET (and TELNETS) data.
//
// The Reader's Read method "un-escapes" TELNET (and TELNETS) data, and filters
// out TELNET (and TELNETS) command sequences.
type Caller interface {
CallTELNET(Context, Writer, Reader)
}

100
vendor/github.com/reiver/go-telnet/client.go generated vendored Normal file
View file

@ -0,0 +1,100 @@
package telnet
import (
"crypto/tls"
)
func DialAndCall(caller Caller) error {
conn, err := Dial()
if nil != err {
return err
}
client := &Client{Caller:caller}
return client.Call(conn)
}
func DialToAndCall(srvAddr string, caller Caller) error {
conn, err := DialTo(srvAddr)
if nil != err {
return err
}
client := &Client{Caller:caller}
return client.Call(conn)
}
func DialAndCallTLS(caller Caller, tlsConfig *tls.Config) error {
conn, err := DialTLS(tlsConfig)
if nil != err {
return err
}
client := &Client{Caller:caller}
return client.Call(conn)
}
func DialToAndCallTLS(srvAddr string, caller Caller, tlsConfig *tls.Config) error {
conn, err := DialToTLS(srvAddr, tlsConfig)
if nil != err {
return err
}
client := &Client{Caller:caller}
return client.Call(conn)
}
type Client struct {
Caller Caller
Logger Logger
}
func (client *Client) Call(conn *Conn) error {
logger := client.logger()
caller := client.Caller
if nil == caller {
logger.Debug("Defaulted caller to StandardCaller.")
caller = StandardCaller
}
var ctx Context = NewContext().InjectLogger(logger)
var w Writer = conn
var r Reader = conn
caller.CallTELNET(ctx, w, r)
conn.Close()
return nil
}
func (client *Client) logger() Logger {
logger := client.Logger
if nil == logger {
logger = internalDiscardLogger{}
}
return logger
}
func (client *Client) SetAuth(username string) {
//@TODO: #################################################
}

148
vendor/github.com/reiver/go-telnet/conn.go generated vendored Normal file
View file

@ -0,0 +1,148 @@
package telnet
import (
"crypto/tls"
"net"
)
type Conn struct {
conn interface {
Read(b []byte) (n int, err error)
Write(b []byte) (n int, err error)
Close() error
LocalAddr() net.Addr
RemoteAddr() net.Addr
}
dataReader *internalDataReader
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).
//
// If a secure connection is desired, use `DialTLS` instead.
func Dial() (*Conn, error) {
return DialTo("")
}
// DialTo makes a (un-secure) TELNET client connection to the the address specified by
// 'addr'.
//
// If a secure connection is desired, use `DialToTLS` instead.
func DialTo(addr string) (*Conn, error) {
const network = "tcp"
if "" == addr {
addr = "127.0.0.1:telnet"
}
conn, err := net.Dial(network, addr)
if nil != err {
return nil, err
}
dataReader := newDataReader(conn)
dataWriter := newDataWriter(conn)
clientConn := Conn{
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) {
return DialToTLS("", tlsConfig)
}
// DialToTLS makes a (secure) TELNETS client connection to the the address specified by
// 'addr'.
func DialToTLS(addr string, tlsConfig *tls.Config) (*Conn, error) {
const network = "tcp"
if "" == addr {
addr = "127.0.0.1:telnets"
}
conn, err := tls.Dial(network, addr, tlsConfig)
if nil != err {
return nil, err
}
dataReader := newDataReader(conn)
dataWriter := newDataWriter(conn)
clientConn := Conn{
conn:conn,
dataReader:dataReader,
dataWriter:dataWriter,
}
return &clientConn, nil
}
// Close closes the client connection.
//
// Typical usage might look like:
//
// telnetsClient, err = telnet.DialToTLS(addr, tlsConfig)
// if nil != err {
// //@TODO: Handle error.
// return err
// }
// defer telnetsClient.Close()
func (clientConn *Conn) Close() error {
return clientConn.conn.Close()
}
// Read receives `n` bytes sent from the server to the client,
// and "returns" into `p`.
//
// Note that Read can only be used for receiving TELNET (and TELNETS) data from the server.
//
// TELNET (and TELNETS) command codes cannot be received using this method, as Read deals
// with TELNET (and TELNETS) "unescaping", and (when appropriate) filters out TELNET (and TELNETS)
// command codes.
//
// Read makes Client fit the io.Reader interface.
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.
//
// TELNET (and TELNETS) command codes cannot be sent using this method, as Write deals with
// TELNET (and TELNETS) "escaping", and will properly "escape" anything written with it.
//
// Write makes Conn fit the io.Writer interface.
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()
}

31
vendor/github.com/reiver/go-telnet/context.go generated vendored Normal file
View file

@ -0,0 +1,31 @@
package telnet
type Context interface {
Logger() Logger
InjectLogger(Logger) Context
}
type internalContext struct {
logger Logger
}
func NewContext() Context {
ctx := internalContext{}
return &ctx
}
func (ctx *internalContext) Logger() Logger {
return ctx.logger
}
func (ctx *internalContext) InjectLogger(logger Logger) Context {
ctx.logger = logger
return ctx
}

173
vendor/github.com/reiver/go-telnet/data_reader.go generated vendored Normal file
View file

@ -0,0 +1,173 @@
package telnet
import (
"bufio"
"errors"
"io"
)
var (
errCorrupted = errors.New("Corrupted")
)
// An internalDataReader deals with "un-escaping" according to the TELNET protocol.
//
// In the TELNET protocol byte value 255 is special.
//
// The TELNET protocol calls byte value 255: "IAC". Which is short for "interpret as command".
//
// The TELNET protocol also has a distinction between 'data' and 'commands'.
//
//(DataReader is targetted toward TELNET 'data', not TELNET 'commands'.)
//
// If a byte with value 255 (=IAC) appears in the data, then it must be escaped.
//
// Escaping byte value 255 (=IAC) in the data is done by putting 2 of them in a row.
//
// So, for example:
//
// []byte{255} -> []byte{255, 255}
//
// Or, for a more complete example, if we started with the following:
//
// []byte{1, 55, 2, 155, 3, 255, 4, 40, 255, 30, 20}
//
// ... TELNET escaping would produce the following:
//
// []byte{1, 55, 2, 155, 3, 255, 255, 4, 40, 255, 255, 30, 20}
//
// (Notice that each "255" in the original byte array became 2 "255"s in a row.)
//
// DataReader deals with "un-escaping". In other words, it un-does what was shown
// in the examples.
//
// So, for example, it does this:
//
// []byte{255, 255} -> []byte{255}
//
// And, for example, goes from this:
//
// []byte{1, 55, 2, 155, 3, 255, 255, 4, 40, 255, 255, 30, 20}
//
// ... to this:
//
// []byte{1, 55, 2, 155, 3, 255, 4, 40, 255, 30, 20}
type internalDataReader struct {
wrapped io.Reader
buffered *bufio.Reader
}
// newDataReader creates a new DataReader reading from 'r'.
func newDataReader(r io.Reader) *internalDataReader {
buffered := bufio.NewReader(r)
reader := internalDataReader{
wrapped:r,
buffered:buffered,
}
return &reader
}
// Read reads the TELNET escaped data from the wrapped io.Reader, and "un-escapes" it into 'data'.
func (r *internalDataReader) Read(data []byte) (n int, err error) {
const IAC = 255
const SB = 250
const SE = 240
const WILL = 251
const WONT = 252
const DO = 253
const DONT = 254
p := data
for len(p) > 0 {
var b byte
b, err = r.buffered.ReadByte()
if nil != err {
return n, err
}
if IAC == b {
var peeked []byte
peeked, err = r.buffered.Peek(1)
if nil != err {
return n, err
}
switch peeked[0] {
case WILL, WONT, DO, DONT:
_, err = r.buffered.Discard(2)
if nil != err {
return n, err
}
case IAC:
p[0] = IAC
n++
p = p[1:]
_, err = r.buffered.Discard(1)
if nil != err {
return n, err
}
case SB:
for {
var b2 byte
b2, err = r.buffered.ReadByte()
if nil != err {
return n, err
}
if IAC == b2 {
peeked, err = r.buffered.Peek(1)
if nil != err {
return n, err
}
if IAC == peeked[0] {
_, err = r.buffered.Discard(1)
if nil != err {
return n, err
}
}
if SE == peeked[0] {
_, err = r.buffered.Discard(1)
if nil != err {
return n, err
}
break
}
}
}
case SE:
_, err = r.buffered.Discard(1)
if nil != err {
return n, err
}
default:
// If we get in here, this is not following the TELNET protocol.
//@TODO: Make a better error.
err = errCorrupted
return n, err
}
} else {
p[0] = b
n++
p = p[1:]
}
}
return n, nil
}

142
vendor/github.com/reiver/go-telnet/data_writer.go generated vendored Normal file
View file

@ -0,0 +1,142 @@
package telnet
import (
"github.com/reiver/go-oi"
"bytes"
"errors"
"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.
//
// The TELNET (and TELNETS) protocol calls byte value 255: "IAC". Which is short for "interpret as command".
//
// 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'.)
//
// If a byte with value 255 (=IAC) appears in the data, then it must be escaped.
//
// Escaping byte value 255 (=IAC) in the data is done by putting 2 of them in a row.
//
// So, for example:
//
// []byte{255} -> []byte{255, 255}
//
// Or, for a more complete example, if we started with the following:
//
// []byte{1, 55, 2, 155, 3, 255, 4, 40, 255, 30, 20}
//
// ... TELNET escaping would produce the following:
//
// []byte{1, 55, 2, 155, 3, 255, 255, 4, 40, 255, 255, 30, 20}
//
// (Notice that each "255" in the original byte array became 2 "255"s in a row.)
//
// internalDataWriter takes care of all this for you, so you do not have to do it.
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
// the TELNET (and TELNETS) protocol.
//
// I.e., byte 255 (= IAC) gets encoded as 255, 255.
//
// For example, if the following it written to the *internalDataWriter's Write method:
//
// []byte{1, 55, 2, 155, 3, 255, 4, 40, 255, 30, 20}
//
// ... then (conceptually) the following is written to 'w's Write method:
//
// []byte{1, 55, 2, 155, 3, 255, 255, 4, 40, 255, 255, 30, 20}
//
// (Notice that each "255" in the original byte array became 2 "255"s in a row.)
//
// *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,
}
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
n64, err = w.write64(data)
n = int(n64)
if int64(n) != n64 {
panic(errOverflow)
}
return n, err
}
func (w *internalDataWriter) write64(data []byte) (n int64, err error) {
if len(data) <= 0 {
return 0, nil
}
const IAC = 255
var buffer bytes.Buffer
for _, datum := range data {
if IAC == datum {
if buffer.Len() > 0 {
var numWritten int64
numWritten, err = oi.LongWrite(w.wrapped, buffer.Bytes())
n += numWritten
if nil != err {
return n, err
}
buffer.Reset()
}
var numWritten int64
//@TODO: Should we worry about "iaciac" potentially being modified by the .Write()?
numWritten, err = oi.LongWrite(w.wrapped, iaciac)
if int64(len(iaciac)) != numWritten {
//@TODO: Do we really want to panic() here?
panic(errPartialIACIACWrite)
}
n += 1
if nil != err {
return n, err
}
} else {
buffer.WriteByte(datum) // The returned error is always nil, so we ignore it.
}
}
if buffer.Len() > 0 {
var numWritten int64
numWritten, err = oi.LongWrite(w.wrapped, buffer.Bytes())
n += numWritten
}
return n, err
}

21
vendor/github.com/reiver/go-telnet/discard_logger.go generated vendored Normal file
View file

@ -0,0 +1,21 @@
package telnet
type internalDiscardLogger struct{}
func (internalDiscardLogger) Debug(...interface{}) {}
func (internalDiscardLogger) Debugf(string, ...interface{}) {}
func (internalDiscardLogger) Debugln(...interface{}) {}
func (internalDiscardLogger) Error(...interface{}) {}
func (internalDiscardLogger) Errorf(string, ...interface{}) {}
func (internalDiscardLogger) Errorln(...interface{}) {}
func (internalDiscardLogger) Trace(...interface{}) {}
func (internalDiscardLogger) Tracef(string, ...interface{}) {}
func (internalDiscardLogger) Traceln(...interface{}) {}
func (internalDiscardLogger) Warn(...interface{}) {}
func (internalDiscardLogger) Warnf(string, ...interface{}) {}
func (internalDiscardLogger) Warnln(...interface{}) {}

450
vendor/github.com/reiver/go-telnet/doc.go generated vendored Normal file
View file

@ -0,0 +1,450 @@
/*
Package telnet provides TELNET and TELNETS client and server implementations
in a style similar to the "net/http" library that is part of the Go standard library,
including support for "middleware"; TELNETS is secure TELNET, with the TELNET protocol
over a secured TLS (or SSL) connection.
Example TELNET Server
ListenAndServe starts a (un-secure) TELNET server with a given address and handler.
handler := telnet.EchoHandler
err := telnet.ListenAndServe(":23", handler)
if nil != err {
panic(err)
}
Example TELNETS Server
ListenAndServeTLS starts a (secure) TELNETS server with a given address and handler,
using the specified "cert.pem" and "key.pem" files.
handler := telnet.EchoHandler
err := telnet.ListenAndServeTLS(":992", "cert.pem", "key.pem", handler)
if nil != err {
panic(err)
}
Example TELNET Client:
DialToAndCall creates a (un-secure) TELNET client, which connects to a given address using the specified caller.
package main
import (
"github.com/reiver/go-telnet"
)
func main() {
var caller Caller = telnet.StandardCaller
//@TOOD: replace "example.net:23" with address you want to connect to.
telnet.DialToAndCall("example.net:23", caller)
}
Example TELNETS Client:
DialToAndCallTLS creates a (secure) TELNETS client, which connects to a given address using the specified caller.
package main
import (
"github.com/reiver/go-telnet"
"crypto/tls"
)
func main() {
//@TODO: Configure the TLS connection here, if you need to.
tlsConfig := &tls.Config{}
var caller Caller = telnet.StandardCaller
//@TOOD: replace "example.net:992" with address you want to connect to.
telnet.DialToAndCallTLS("example.net:992", caller, tlsConfig)
}
TELNET vs TELNETS
If you are communicating over the open Internet, you should be using (the secure) TELNETS protocol and ListenAndServeTLS.
If you are communicating just on localhost, then using just (the un-secure) TELNET protocol and telnet.ListenAndServe may be OK.
If you are not sure which to use, use TELNETS and ListenAndServeTLS.
Example TELNET Shell Server
The previous 2 exaple servers were very very simple. Specifically, they just echoed back whatever
you submitted to it.
If you typed:
Apple Banana Cherry\r\n
... it would send back:
Apple Banana Cherry\r\n
(Exactly the same data you sent it.)
A more useful TELNET server can be made using the "github.com/reiver/go-telnet/telsh" sub-package.
The `telsh` sub-package provides "middleware" that enables you to create a "shell" interface (also
called a "command line interface" or "CLI") which most people would expect when using TELNET OR TELNETS.
For example:
package main
import (
"github.com/reiver/go-oi"
"github.com/reiver/go-telnet"
"github.com/reiver/go-telnet/telsh"
"time"
)
func main() {
shellHandler := telsh.NewShellHandler()
commandName := "date"
shellHandler.Register(commandName, danceProducer)
commandName = "animate"
shellHandler.Register(commandName, animateProducer)
addr := ":23"
if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
panic(err)
}
}
Note that in the example, so far, we have registered 2 commands: `date` and `animate`.
For this to actually work, we need to have code for the `date` and `animate` commands.
The actual implemenation for the `date` command could be done like the following:
func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
s := time.Now().Format(layout)
if _, err := oi.LongWriteString(stdout, s); nil != err {
return err
}
return nil
}
func dateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
return telsh.PromoteHandlerFunc(dateHandler)
}
var dateProducer = ProducerFunc(dateProducerFunc)
Note that your "real" work is in the `dateHandlerFunc` func.
And the actual implementation for the `animate` command could be done as follows:
func animateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
for i:=0; i<20; i++ {
oi.LongWriteString(stdout, "\r⠋")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠙")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠹")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠸")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠼")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠴")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠦")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠧")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠇")
time.Sleep(50*time.Millisecond)
oi.LongWriteString(stdout, "\r⠏")
time.Sleep(50*time.Millisecond)
}
oi.LongWriteString(stdout, "\r \r\n")
return nil
}
func animateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
return telsh.PromoteHandlerFunc(animateHandler)
}
var animateProducer = ProducerFunc(animateProducerFunc)
Again, note that your "real" work is in the `animateHandlerFunc` func.
Generating PEM Files
If you are using the telnet.ListenAndServeTLS func or the telnet.Server.ListenAndServeTLS method, you will need to
supply "cert.pem" and "key.pem" files.
If you do not already have these files, the Go soure code contains a tool for generating these files for you.
It can be found at:
$GOROOT/src/crypto/tls/generate_cert.go
So, for example, if your `$GOROOT` is the "/usr/local/go" directory, then it would be at:
/usr/local/go/src/crypto/tls/generate_cert.go
If you run the command:
go run $GOROOT/src/crypto/tls/generate_cert.go --help
... then you get the help information for "generate_cert.go".
Of course, you would replace or set `$GOROOT` with whatever your path actually is. Again, for example,
if your `$GOROOT` is the "/usr/local/go" directory, then it would be:
go run /usr/local/go/src/crypto/tls/generate_cert.go --help
To demonstrate the usage of "generate_cert.go", you might run the following to generate certificates
that were bound to the hosts `127.0.0.1` and `localhost`:
go run /usr/local/go/src/crypto/tls/generate_cert.go --ca --host='127.0.0.1,localhost'
If you are not sure where "generate_cert.go" is on your computer, on Linux and Unix based systems, you might
be able to find the file with the command:
locate /src/crypto/tls/generate_cert.go
(If it finds it, it should output the full path to this file.)
Example TELNET Client
You can make a simple (un-secure) TELNET client with code like the following:
package main
import (
"github.com/reiver/go-telnet"
)
func main() {
var caller Caller = telnet.StandardCaller
//@TOOD: replace "example.net:5555" with address you want to connect to.
telnet.DialToAndCall("example.net:5555", caller)
}
Example TELNETS Client
You can make a simple (secure) TELNETS client with code like the following:
package main
import (
"github.com/reiver/go-telnet"
)
func main() {
var caller Caller = telnet.StandardCaller
//@TOOD: replace "example.net:5555" with address you want to connect to.
telnet.DialToAndCallTLS("example.net:5555", caller)
}
TELNET Story
The TELNET protocol is best known for providing a means of connecting to a remote computer, using a (text-based) shell interface, and being able to interact with it, (more or less) as if you were sitting at that computer.
(Shells are also known as command-line interfaces or CLIs.)
Although this was the original usage of the TELNET protocol, it can be (and is) used for other purposes as well.
The Era
The TELNET protocol came from an era in computing when text-based shell interface where the common way of interacting with computers.
The common interface for computers during this era was a keyboard and a monochromatic (i.e., single color) text-based monitors called "video terminals".
(The word "video" in that era of computing did not refer to things such as movies. But instead was meant to contrast it with paper. In particular, the teletype machines, which were typewriter like devices that had a keyboard, but instead of having a monitor had paper that was printed onto.)
Early Office Computers
In that era, in the early days of office computers, it was rare that an individual would have a computer at their desk. (A single computer was much too expensive.)
Instead, there would be a single central computer that everyone would share. The style of computer used (for the single central shared computer) was called a "mainframe".
What individuals would have at their desks, instead of their own compuer, would be some type of video terminal.
The different types of video terminals had named such as:
VT52
VT100
VT220
VT240
("VT" in those named was short for "video terminal".)
Teletype
To understand this era, we need to go back a bit in time to what came before it: teletypes.
Terminal Codes
Terminal codes (also sometimes called 'terminal control codes') are used to issue various kinds of commands
to the terminal.
(Note that 'terminal control codes' are a completely separate concept for 'TELNET commands',
and the two should NOT be conflated or confused.)
The most common types of 'terminal codes' are the 'ANSI escape codes'. (Although there are other types too.)
ANSI Escape Codes
ANSI escape codes (also sometimes called 'ANSI escape sequences') are a common type of 'terminal code' used
to do things such as:
moving the cursor,
erasing the display,
erasing the line,
setting the graphics mode,
setting the foregroup color,
setting the background color,
setting the screen resolution, and
setting keyboard strings.
Setting The Foreground Color With ANSI Escape Codes
One of the abilities of ANSI escape codes is to set the foreground color.
Here is a table showing codes for this:
| ANSI Color | Go string | Go []byte |
| ------------ | ---------- | ----------------------------- |
| Black | "\x1b[30m" | []byte{27, '[', '3','0', 'm'} |
| Red | "\x1b[31m" | []byte{27, '[', '3','1', 'm'} |
| Green | "\x1b[32m" | []byte{27, '[', '3','2', 'm'} |
| Brown/Yellow | "\x1b[33m" | []byte{27, '[', '3','3', 'm'} |
| Blue | "\x1b[34m" | []byte{27, '[', '3','4', 'm'} |
| Magenta | "\x1b[35m" | []byte{27, '[', '3','5', 'm'} |
| Cyan | "\x1b[36m" | []byte{27, '[', '3','6', 'm'} |
| Gray/White | "\x1b[37m" | []byte{27, '[', '3','7', 'm'} |
(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'3'` and whatever.)
Setting The Background Color With ANSI Escape Codes
Another of the abilities of ANSI escape codes is to set the background color.
| ANSI Color | Go string | Go []byte |
| ------------ | ---------- | ----------------------------- |
| Black | "\x1b[40m" | []byte{27, '[', '4','0', 'm'} |
| Red | "\x1b[41m" | []byte{27, '[', '4','1', 'm'} |
| Green | "\x1b[42m" | []byte{27, '[', '4','2', 'm'} |
| Brown/Yellow | "\x1b[43m" | []byte{27, '[', '4','3', 'm'} |
| Blue | "\x1b[44m" | []byte{27, '[', '4','4', 'm'} |
| Magenta | "\x1b[45m" | []byte{27, '[', '4','5', 'm'} |
| Cyan | "\x1b[46m" | []byte{27, '[', '4','6', 'm'} |
| Gray/White | "\x1b[47m" | []byte{27, '[', '4','7', 'm'} |
(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'4'` and whatever.)
Using ANSI Escape Codes
In Go code, if I wanted to use an ANSI escape code to use a blue background,
a white foreground, and bold, I could do that with the ANSI escape code:
"\x1b[44;37;1m"
Note that that start with byte value 27, which we have encoded as hexadecimal
as \x1b. Followed by the '[' character.
Coming after that is the sub-string "44", which is the code that sets our background color to blue.
We follow that with the ';' character (which separates codes).
And the after that comes the sub-string "37", which is the code that set our foreground color to white.
After that, we follow with another ";" character (which, again, separates codes).
And then we follow it the sub-string "1", which is the code that makes things bold.
And finally, the ANSI escape sequence is finished off with the 'm' character.
To show this in a more complete example, our `dateHandlerFunc` from before could incorporate ANSI escape sequences as follows:
func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
s := "\x1b[44;37;1m" + time.Now().Format(layout) + "\x1b[0m"
if _, err := oi.LongWriteString(stdout, s); nil != err {
return err
}
return nil
}
Note that in that example, in addition to using the ANSI escape sequence "\x1b[44;37;1m"
to set the background color to blue, set the foreground color to white, and make it bold,
we also used the ANSI escape sequence "\x1b[0m" to reset the background and foreground colors
and boldness back to "normal".
*/
package telnet

33
vendor/github.com/reiver/go-telnet/echo_handler.go generated vendored Normal file
View file

@ -0,0 +1,33 @@
package telnet
import (
"github.com/reiver/go-oi"
)
// EchoHandler is a simple TELNET server which "echos" back to the client any (non-command)
// data back to the TELNET client, it received from the TELNET client.
var EchoHandler Handler = internalEchoHandler{}
type internalEchoHandler struct{}
func (handler internalEchoHandler) ServeTELNET(ctx Context, w Writer, r Reader) {
var buffer [1]byte // Seems like the length of the buffer needs to be small, otherwise will have to wait for buffer to fill up.
p := buffer[:]
for {
n, err := r.Read(p)
if n > 0 {
oi.LongWrite(w, p[:n])
}
if nil != err {
break
}
}
}

18
vendor/github.com/reiver/go-telnet/handler.go generated vendored Normal file
View file

@ -0,0 +1,18 @@
package telnet
// A Handler serves a TELNET (or TELNETS) connection.
//
// Writing data to the Writer passed as an argument to the ServeTELNET method
// will send data to the TELNET (or TELNETS) client.
//
// Reading data from the Reader passed as an argument to the ServeTELNET method
// will receive data from the TELNET client.
//
// The Writer's Write method sends "escaped" TELNET (and TELNETS) data.
//
// The Reader's Read method "un-escapes" TELNET (and TELNETS) data, and filters
// out TELNET (and TELNETS) command sequences.
type Handler interface {
ServeTELNET(Context, Writer, Reader)
}

16
vendor/github.com/reiver/go-telnet/logger.go generated vendored Normal file
View file

@ -0,0 +1,16 @@
package telnet
type Logger interface{
Debug(...interface{})
Debugf(string, ...interface{})
Error(...interface{})
Errorf(string, ...interface{})
Trace(...interface{})
Tracef(string, ...interface{})
Warn(...interface{})
Warnf(string, ...interface{})
}

6
vendor/github.com/reiver/go-telnet/reader.go generated vendored Normal file
View file

@ -0,0 +1,6 @@
package telnet
type Reader interface {
Read([]byte) (int, error)
}

191
vendor/github.com/reiver/go-telnet/server.go generated vendored Normal file
View file

@ -0,0 +1,191 @@
package telnet
import (
"crypto/tls"
"net"
)
// ListenAndServe listens on the TCP network address `addr` and then spawns a call to the ServeTELNET
// method on the `handler` to serve each incoming connection.
//
// For a very simple example:
//
// package main
//
// import (
// "github.com/reiver/go-telnet"
// )
//
// func main() {
//
// //@TODO: In your code, you would probably want to use a different handler.
// var handler telnet.Handler = telnet.EchoHandler
//
// err := telnet.ListenAndServe(":5555", handler)
// if nil != err {
// //@TODO: Handle this error better.
// panic(err)
// }
// }
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
// Serve accepts an incoming TELNET or TELNETS client connection on the net.Listener `listener`.
func Serve(listener net.Listener, handler Handler) error {
server := &Server{Handler: handler}
return server.Serve(listener)
}
// A Server defines parameters of a running TELNET server.
//
// For a simple example:
//
// package main
//
// import (
// "github.com/reiver/go-telnet"
// )
//
// func main() {
//
// var handler telnet.Handler = telnet.EchoHandler
//
// server := &telnet.Server{
// Addr:":5555",
// Handler:handler,
// }
//
// err := server.ListenAndServe()
// if nil != err {
// //@TODO: Handle this error better.
// panic(err)
// }
// }
type Server struct {
Addr string // TCP address to listen on; ":telnet" or ":telnets" if empty (when used with ListenAndServe or ListenAndServeTLS respectively).
Handler Handler // handler to invoke; telnet.EchoServer if nil
TLSConfig *tls.Config // optional TLS configuration; used by ListenAndServeTLS.
Logger Logger
}
// ListenAndServe listens on the TCP network address 'server.Addr' and then spawns a call to the ServeTELNET
// method on the 'server.Handler' to serve each incoming connection.
//
// For a simple example:
//
// package main
//
// import (
// "github.com/reiver/go-telnet"
// )
//
// func main() {
//
// var handler telnet.Handler = telnet.EchoHandler
//
// server := &telnet.Server{
// Addr:":5555",
// Handler:handler,
// }
//
// err := server.ListenAndServe()
// if nil != err {
// //@TODO: Handle this error better.
// panic(err)
// }
// }
func (server *Server) ListenAndServe() error {
addr := server.Addr
if "" == addr {
addr = ":telnet"
}
listener, err := net.Listen("tcp", addr)
if nil != err {
return err
}
return server.Serve(listener)
}
// Serve accepts an incoming TELNET client connection on the net.Listener `listener`.
func (server *Server) Serve(listener net.Listener) error {
defer listener.Close()
logger := server.logger()
handler := server.Handler
if nil == handler {
//@TODO: Should this be a "ShellHandler" instead, that gives a shell-like experience by default
// If this is changd, then need to change the comment in the "type Server struct" definition.
logger.Debug("Defaulted handler to EchoHandler.")
handler = EchoHandler
}
for {
// Wait for a new TELNET client connection.
logger.Debugf("Listening at %q.", listener.Addr())
conn, err := listener.Accept()
if err != nil {
//@TODO: Could try to recover from certain kinds of errors. Maybe waiting a while before trying again.
return err
}
logger.Debugf("Received new connection from %q.", conn.RemoteAddr())
// Handle the new TELNET client connection by spawning
// a new goroutine.
go server.handle(conn, handler)
logger.Debugf("Spawned handler to handle connection from %q.", conn.RemoteAddr())
}
}
func (server *Server) handle(c net.Conn, handler Handler) {
defer c.Close()
logger := server.logger()
defer func(){
if r := recover(); nil != r {
if nil != logger {
logger.Errorf("Recovered from: (%T) %v", r, r)
}
}
}()
var ctx Context = NewContext().InjectLogger(logger)
var w Writer = newDataWriter(c)
var r Reader = newDataReader(c)
handler.ServeTELNET(ctx, w, r)
c.Close()
}
func (server *Server) logger() Logger {
logger := server.Logger
if nil == logger {
logger = internalDiscardLogger{}
}
return logger
}

93
vendor/github.com/reiver/go-telnet/standard_caller.go generated vendored Normal file
View file

@ -0,0 +1,93 @@
package telnet
import (
"github.com/reiver/go-oi"
"bufio"
"bytes"
"fmt"
"io"
"os"
"time"
)
// StandardCaller is a simple TELNET client which sends to the server any data it gets from os.Stdin
// as TELNET (and TELNETS) data, and writes any TELNET (or TELNETS) data it receives from
// the server to os.Stdout, and writes any error it has to os.Stderr.
var StandardCaller Caller = internalStandardCaller{}
type internalStandardCaller struct{}
func (caller internalStandardCaller) CallTELNET(ctx Context, w Writer, r Reader) {
standardCallerCallTELNET(os.Stdin, os.Stdout, os.Stderr, ctx, w, r)
}
func standardCallerCallTELNET(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, ctx Context, w Writer, r Reader) {
go func(writer io.Writer, reader io.Reader) {
var buffer [1]byte // Seems like the length of the buffer needs to be small, otherwise will have to wait for buffer to fill up.
p := buffer[:]
for {
// Read 1 byte.
n, err := reader.Read(p)
if n <= 0 && nil == err {
continue
} else if n <= 0 && nil != err {
break
}
oi.LongWrite(writer, p)
}
}(stdout, r)
var buffer bytes.Buffer
var p []byte
var crlfBuffer [2]byte = [2]byte{'\r','\n'}
crlf := crlfBuffer[:]
scanner := bufio.NewScanner(stdin)
scanner.Split(scannerSplitFunc)
for scanner.Scan() {
buffer.Write(scanner.Bytes())
buffer.Write(crlf)
p = buffer.Bytes()
n, err := oi.LongWrite(w, p)
if nil != err {
break
}
if expected, actual := int64(len(p)), n; expected != actual {
err := fmt.Errorf("Transmission problem: tried sending %d bytes, but actually only sent %d bytes.", expected, actual)
fmt.Fprint(stderr, err.Error())
return
}
buffer.Reset()
}
// Wait a bit to receive data from the server (that we would send to io.Stdout).
time.Sleep(3 * time.Millisecond)
}
func scannerSplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF {
return 0, nil, nil
}
return bufio.ScanLines(data, atEOF)
}

113
vendor/github.com/reiver/go-telnet/tls.go generated vendored Normal file
View file

@ -0,0 +1,113 @@
package telnet
import (
"crypto/tls"
"net"
)
// ListenAndServeTLS acts identically to ListenAndServe, except that it
// uses the TELNET protocol over TLS.
//
// From a TELNET protocol point-of-view, it allows for 'secured telnet', also known as TELNETS,
// which by default listens to port 992.
//
// Of course, this port can be overridden using the 'addr' argument.
//
// For a very simple example:
//
// package main
//
// import (
// "github.com/reiver/go-telnet"
// )
//
// func main() {
//
// //@TODO: In your code, you would probably want to use a different handler.
// var handler telnet.Handler = telnet.EchoHandler
//
// err := telnet.ListenAndServeTLS(":5555", "cert.pem", "key.pem", handler)
// if nil != err {
// //@TODO: Handle this error better.
// panic(err)
// }
// }
func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServeTLS(certFile, keyFile)
}
// ListenAndServeTLS acts identically to ListenAndServe, except that it
// uses the TELNET protocol over TLS.
//
// From a TELNET protocol point-of-view, it allows for 'secured telnet', also known as TELNETS,
// which by default listens to port 992.
func (server *Server) ListenAndServeTLS(certFile string, keyFile string) error {
addr := server.Addr
if "" == addr {
addr = ":telnets"
}
listener, err := net.Listen("tcp", addr)
if nil != err {
return err
}
// Apparently have to make a copy of the TLS config this way, rather than by
// simple assignment, to prevent some unexported fields from being copied over.
//
// It would be nice if tls.Config had a method that would do this "safely".
// (I.e., what happens if in the future more exported fields are added to
// tls.Config?)
var tlsConfig *tls.Config = nil
if nil == server.TLSConfig {
tlsConfig = &tls.Config{}
} else {
tlsConfig = &tls.Config{
Rand: server.TLSConfig.Rand,
Time: server.TLSConfig.Time,
Certificates: server.TLSConfig.Certificates,
NameToCertificate: server.TLSConfig.NameToCertificate,
GetCertificate: server.TLSConfig.GetCertificate,
RootCAs: server.TLSConfig.RootCAs,
NextProtos: server.TLSConfig.NextProtos,
ServerName: server.TLSConfig.ServerName,
ClientAuth: server.TLSConfig.ClientAuth,
ClientCAs: server.TLSConfig.ClientCAs,
InsecureSkipVerify: server.TLSConfig.InsecureSkipVerify,
CipherSuites: server.TLSConfig.CipherSuites,
PreferServerCipherSuites: server.TLSConfig.PreferServerCipherSuites,
SessionTicketsDisabled: server.TLSConfig.SessionTicketsDisabled,
SessionTicketKey: server.TLSConfig.SessionTicketKey,
ClientSessionCache: server.TLSConfig.ClientSessionCache,
MinVersion: server.TLSConfig.MinVersion,
MaxVersion: server.TLSConfig.MaxVersion,
CurvePreferences: server.TLSConfig.CurvePreferences,
}
}
tlsConfigHasCertificate := len(tlsConfig.Certificates) > 0 || nil != tlsConfig.GetCertificate
if "" == certFile || "" == keyFile || !tlsConfigHasCertificate {
tlsConfig.Certificates = make([]tls.Certificate, 1)
var err error
tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
if nil != err {
return err
}
}
tlsListener := tls.NewListener(listener, tlsConfig)
return server.Serve(tlsListener)
}

6
vendor/github.com/reiver/go-telnet/writer.go generated vendored Normal file
View file

@ -0,0 +1,6 @@
package telnet
type Writer interface {
Write([]byte) (int, error)
}

12
vendor/vendor.json vendored
View file

@ -110,6 +110,18 @@
"revision": "a7a4c189eb47ed33ce7b35f2880070a0c82a67d4", "revision": "a7a4c189eb47ed33ce7b35f2880070a0c82a67d4",
"revisionTime": "2017-09-25T23:40:30Z" "revisionTime": "2017-09-25T23:40:30Z"
}, },
{
"checksumSHA1": "7BsTyiYZMTvIGT/KsF9a3tAoN0g=",
"path": "github.com/reiver/go-oi",
"revision": "431c83978379297f04f85f6eb94f129f25ab741d",
"revisionTime": "2016-03-25T06:16:15Z"
},
{
"checksumSHA1": "sb1kOSRpAu22ovV0dXHkPlG06i4=",
"path": "github.com/reiver/go-telnet",
"revision": "6b696f32801a8f8dd07947f1e1fdb1a7dc4766ff",
"revisionTime": "2016-03-30T05:09:16Z"
},
{ {
"checksumSHA1": "zRAcxJW8WNDMryOBS4VE03V6ivw=", "checksumSHA1": "zRAcxJW8WNDMryOBS4VE03V6ivw=",
"path": "github.com/urfave/cli", "path": "github.com/urfave/cli",