telebit/parser.go

96 lines
1.7 KiB
Go

package telebit
import (
"errors"
"fmt"
"os"
"git.rootprojects.org/root/telebit/dbg"
)
type Parser struct {
handler Router
newConns chan *Conn
conns map[string]*Conn
state ParserState
parseState State
dataReady chan struct{}
data []byte
consumed int
}
type ParserState struct {
consumed int
version byte
headerLen int
header []byte
payloadLen int
srcAddr Addr
dstAddr Addr
payloadWritten int
}
type State int
const (
V1 byte = 255 - (1 + iota)
V2
)
const (
VersionState State = 0
)
func NewParser(handler Router) *Parser {
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,
}
}
type Router interface {
RouteBytes(src, dst Addr, payload []byte)
}
// 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")
}
/*
// 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
}
*/
switch p.parseState {
case VersionState:
if dbg.Debug {
fmt.Fprintf(os.Stderr, "[debug] MPLEXY version byte %v %s", b[0], string(b))
}
p.state.version = b[0]
b = b[1:]
p.consumed++
p.parseState++
default:
// do nothing
}
switch p.state.version {
case V1:
if dbg.Debug {
fmt.Fprintf(os.Stderr, "[debug] MPLEXY packet is of type v1\n")
}
return p.unpackV1(b)
default:
return 0, errors.New("incorrect version or version not implemented")
}
}