90 lines
1.6 KiB
Go
90 lines
1.6 KiB
Go
package packer
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
type Parser struct {
|
|
ctx context.Context
|
|
handler Handler
|
|
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
|
|
addr Addr
|
|
payloadWritten int
|
|
}
|
|
|
|
type State int
|
|
|
|
const (
|
|
V1 byte = 255 - (1 + iota)
|
|
V2
|
|
)
|
|
|
|
const (
|
|
VersionState State = 0
|
|
)
|
|
|
|
func NewParser(ctx context.Context, handler Handler) *Parser {
|
|
return &Parser{
|
|
ctx: ctx,
|
|
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 Handler interface {
|
|
WriteMessage(Addr, []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:
|
|
//fmt.Println("[debug] version state", b[0])
|
|
p.state.version = b[0]
|
|
b = b[1:]
|
|
p.consumed += 1
|
|
p.parseState += 1
|
|
default:
|
|
// do nothing
|
|
}
|
|
|
|
switch p.state.version {
|
|
case V1:
|
|
//fmt.Println("[debug] v1 unmarshal")
|
|
return p.unpackV1(b)
|
|
default:
|
|
return 0, errors.New("incorrect version or version not implemented")
|
|
}
|
|
}
|