2020-05-22 10:41:24 +00:00
|
|
|
package telebit
|
2020-05-18 08:43:06 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2020-07-15 10:46:02 +00:00
|
|
|
"fmt"
|
2020-07-18 05:28:12 +00:00
|
|
|
|
|
|
|
"git.coolaj86.com/coolaj86/go-telebitd/dbg"
|
2020-05-18 08:43:06 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Parser struct {
|
2020-05-21 05:30:24 +00:00
|
|
|
handler Router
|
2020-05-18 08:43:06 +00:00
|
|
|
newConns chan *Conn
|
|
|
|
conns map[string]*Conn
|
|
|
|
state ParserState
|
|
|
|
parseState State
|
|
|
|
dataReady chan struct{}
|
|
|
|
data []byte
|
2020-05-19 04:36:20 +00:00
|
|
|
consumed int
|
2020-05-18 08:43:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ParserState struct {
|
2020-05-19 04:36:20 +00:00
|
|
|
consumed int
|
2020-05-18 08:43:06 +00:00
|
|
|
version byte
|
|
|
|
headerLen int
|
|
|
|
header []byte
|
|
|
|
payloadLen int
|
2020-05-21 10:29:05 +00:00
|
|
|
srcAddr Addr
|
|
|
|
dstAddr Addr
|
2020-05-18 08:43:06 +00:00
|
|
|
payloadWritten int
|
|
|
|
}
|
|
|
|
|
|
|
|
type State int
|
|
|
|
|
|
|
|
const (
|
|
|
|
V1 byte = 255 - (1 + iota)
|
|
|
|
V2
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
VersionState State = 0
|
|
|
|
)
|
|
|
|
|
2020-05-21 05:30:24 +00:00
|
|
|
func NewParser(handler Router) *Parser {
|
2020-05-18 08:43:06 +00:00
|
|
|
return &Parser{
|
|
|
|
conns: make(map[string]*Conn),
|
|
|
|
newConns: make(chan *Conn, 2), // Buffered to make testing easier
|
|
|
|
dataReady: make(chan struct{}, 2),
|
|
|
|
data: []byte{},
|
|
|
|
handler: handler,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-21 05:30:24 +00:00
|
|
|
type Router interface {
|
2020-05-21 10:29:05 +00:00
|
|
|
RouteBytes(src, dst Addr, payload []byte)
|
2020-05-18 08:43:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write receives tunnel data and creates or writes to connections
|
|
|
|
func (p *Parser) Write(b []byte) (int, error) {
|
|
|
|
if len(b) < 1 {
|
|
|
|
return 0, errors.New("developer error: wrote 0 bytes")
|
|
|
|
}
|
|
|
|
|
2020-05-19 04:36:20 +00:00
|
|
|
/*
|
|
|
|
// so that we can overwrite the main state
|
|
|
|
// as soon as a full message has completed
|
|
|
|
// but still keep the number of bytes written
|
|
|
|
if 0 == p.state.written {
|
|
|
|
p.written = 0
|
|
|
|
}
|
|
|
|
*/
|
2020-05-18 08:43:06 +00:00
|
|
|
|
|
|
|
switch p.parseState {
|
|
|
|
case VersionState:
|
2020-07-18 05:28:12 +00:00
|
|
|
if dbg.Debug {
|
|
|
|
fmt.Println("[debug] MPLEXY version byte", b[0], string(b))
|
|
|
|
}
|
2020-05-18 08:43:06 +00:00
|
|
|
p.state.version = b[0]
|
|
|
|
b = b[1:]
|
2020-05-19 07:06:10 +00:00
|
|
|
p.consumed++
|
|
|
|
p.parseState++
|
2020-05-18 08:43:06 +00:00
|
|
|
default:
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
switch p.state.version {
|
|
|
|
case V1:
|
2020-07-18 05:28:12 +00:00
|
|
|
if dbg.Debug {
|
|
|
|
fmt.Println("[debug] MPLEXY packet is of type v1")
|
|
|
|
}
|
2020-05-19 04:36:20 +00:00
|
|
|
return p.unpackV1(b)
|
2020-05-18 08:43:06 +00:00
|
|
|
default:
|
|
|
|
return 0, errors.New("incorrect version or version not implemented")
|
|
|
|
}
|
|
|
|
}
|