wip: SNI detection: add Peek()
This commit is contained in:
parent
d0910ed07e
commit
8ae19f341b
|
@ -1,6 +1,7 @@
|
|||
package telebit
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
@ -16,6 +17,7 @@ var encryptedSchemes = map[string]struct{}{
|
|||
type Conn struct {
|
||||
relaySourceAddr Addr
|
||||
relayTargetAddr Addr
|
||||
peeker *bufio.Reader
|
||||
relay net.Conn
|
||||
local net.Conn
|
||||
//terminated bool
|
||||
|
@ -37,9 +39,19 @@ func NewConn(conn *Conn) *Conn {
|
|||
// Read can be made to time out and return an Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetReadDeadline.
|
||||
func (c *Conn) Read(b []byte) (n int, err error) {
|
||||
if nil != c.peeker {
|
||||
return c.peeker.Read(b)
|
||||
}
|
||||
return c.relay.Read(b)
|
||||
}
|
||||
|
||||
func (c *Conn) Peek(n int) (b []byte, err error) {
|
||||
if nil == c.peeker {
|
||||
c.peeker = bufio.NewReaderSize(c, defaultPeekerSize)
|
||||
}
|
||||
return c.peeker.Peek(n)
|
||||
}
|
||||
|
||||
// Write writes data to the connection.
|
||||
// Write can be made to time out and return an Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
|
||||
|
|
|
@ -1,17 +1,46 @@
|
|||
package telebit
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConnWrap is just a cheap way to DRY up some switch conn.(type) statements to handle special features of Conn
|
||||
type ConnWrap struct {
|
||||
//Conn net.Conn
|
||||
peeker *bufio.Reader
|
||||
Conn net.Conn
|
||||
Plain net.Conn
|
||||
}
|
||||
|
||||
type Peeker interface {
|
||||
Peek(n int) ([]byte, error)
|
||||
}
|
||||
|
||||
func (c *ConnWrap) Peek(n int) ([]byte, error) {
|
||||
if nil != c.peeker {
|
||||
return c.peeker.Peek(n)
|
||||
}
|
||||
|
||||
switch conn := c.Conn.(type) {
|
||||
case *ConnWrap:
|
||||
return conn.Peek(n)
|
||||
case *Conn:
|
||||
return conn.Peek(n)
|
||||
default:
|
||||
// *net.UDPConn,*net.TCPConn,*net.IPConn,*net.UnixConn
|
||||
if nil == c.peeker {
|
||||
c.peeker = bufio.NewReaderSize(c, defaultPeekerSize)
|
||||
}
|
||||
return c.peeker.Peek(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConnWrap) Read(b []byte) (n int, err error) {
|
||||
if nil != c.peeker {
|
||||
return c.peeker.Read(b)
|
||||
}
|
||||
return c.Conn.Read(b)
|
||||
}
|
||||
|
||||
|
@ -48,7 +77,7 @@ func (c *ConnWrap) Scheme() string {
|
|||
func (c *ConnWrap) Servername() string {
|
||||
if nil != c.Plain {
|
||||
tlsConn := &ConnWrap{Conn: c.Plain}
|
||||
return tlsConn.Scheme()
|
||||
return tlsConn.Servername()
|
||||
}
|
||||
|
||||
switch conn := c.Conn.(type) {
|
||||
|
@ -63,6 +92,7 @@ func (c *ConnWrap) Servername() string {
|
|||
// isTerminated returns true if net.Conn is either a ConnWrap{ tls.Conn },
|
||||
// or a telebit.Conn with a non-encrypted `scheme` such as "tcp" or "http".
|
||||
func (c *ConnWrap) isTerminated() bool {
|
||||
// TODO look at SNI, may need context for Peek() timeout
|
||||
if nil != c.Plain {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
// Nerds posting benchmarks on SO show that 8k seems about right,
|
||||
// but even 1024b could work well.
|
||||
var defaultBufferSize = 8192
|
||||
var defaultPeekerSize = 1024
|
||||
|
||||
// ErrBadGateway means that the target did not accept the connection
|
||||
var ErrBadGateway = errors.New("EBADGATEWAY")
|
||||
|
|
Loading…
Reference in New Issue