93 lines
2.2 KiB
Go
93 lines
2.2 KiB
Go
package telebit
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
// A RouteMux is a net.Conn multiplexer.
|
|
//
|
|
// It matches the port, domain, or connection type of a connection
|
|
// and selects the matching handler.
|
|
type RouteMux struct {
|
|
defaultTimeout time.Duration
|
|
routes []meta
|
|
}
|
|
|
|
type meta struct {
|
|
addr string
|
|
handler Handler
|
|
terminate bool
|
|
}
|
|
|
|
// NewRouteMux allocates and returns a new RouteMux.
|
|
func NewRouteMux() *RouteMux {
|
|
mux := &RouteMux{
|
|
defaultTimeout: 45 * time.Second,
|
|
}
|
|
return mux
|
|
}
|
|
|
|
// Serve dispatches the connection to the handler whose selectors matches the attributes.
|
|
func (m *RouteMux) Serve(client net.Conn) error {
|
|
wconn := &ConnWrap{Conn: client}
|
|
servername := wconn.Servername()
|
|
|
|
for _, meta := range m.routes {
|
|
if servername == meta.addr || "*" == meta.addr {
|
|
//fmt.Println("[debug] test of route:", meta)
|
|
if err := meta.handler.Serve(client); nil != err {
|
|
// error should be EOF if successful
|
|
return err
|
|
}
|
|
// nil err means skipped
|
|
}
|
|
}
|
|
|
|
fmt.Println("No match found for", wconn.Scheme(), wconn.Servername())
|
|
return client.Close()
|
|
}
|
|
|
|
// ForwardTCP creates and returns a connection to a local handler target.
|
|
func (m *RouteMux) ForwardTCP(servername string, target string, timeout time.Duration) error {
|
|
// TODO check servername
|
|
m.routes = append(m.routes, meta{
|
|
addr: servername,
|
|
terminate: false,
|
|
handler: NewForwarder(target, timeout),
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// HandleTCP creates and returns a connection to a local handler target.
|
|
func (m *RouteMux) HandleTCP(servername string, handler Handler) error {
|
|
// TODO check servername
|
|
m.routes = append(m.routes, meta{
|
|
addr: servername,
|
|
terminate: false,
|
|
handler: handler,
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// HandleTLS creates and returns a connection to a local handler target.
|
|
func (m *RouteMux) HandleTLS(servername string, acme *ACME, handler Handler) error {
|
|
// TODO check servername
|
|
m.routes = append(m.routes, meta{
|
|
addr: servername,
|
|
terminate: true,
|
|
handler: HandlerFunc(func(client net.Conn) error {
|
|
wrap := &ConnWrap{Conn: client}
|
|
if wrap.isTerminated() {
|
|
// nil to skip
|
|
return nil
|
|
}
|
|
//NewTerminator(acme, handler)(client)
|
|
//return handler.Serve(client)
|
|
return handler.Serve(TerminateTLS(client, acme))
|
|
}),
|
|
})
|
|
return nil
|
|
}
|