for test use
This commit is contained in:
parent
aa3ccbbfee
commit
94b80580fa
34
connection.go
Normal file
34
connection.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
type Connection struct {
|
||||||
|
RX <-chan *DataFrame
|
||||||
|
TX chan<- *DataFrame
|
||||||
|
ID ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Read(p []byte) (int, error) {
|
||||||
|
df, ok := <-c.RX
|
||||||
|
if !ok {
|
||||||
|
return 0, c.Close()
|
||||||
|
}
|
||||||
|
return df.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Write(p []byte) (int, error) {
|
||||||
|
defer recover()
|
||||||
|
df := &DataFrame{
|
||||||
|
ID: c.ID,
|
||||||
|
Type: TypeNormal,
|
||||||
|
}
|
||||||
|
n, err := df.Write(p)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
c.TX <- df
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Close() error {
|
||||||
|
defer close(c.TX)
|
||||||
|
return nil
|
||||||
|
}
|
9
consts.go
Normal file
9
consts.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeNormal Type = iota
|
||||||
|
TypeRequest
|
||||||
|
TypeConnected
|
||||||
|
TypeClosed
|
||||||
|
TypeInvalid Type = 0xff
|
||||||
|
)
|
38
dataframe.go
Normal file
38
dataframe.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"compress/gzip"
|
||||||
|
"encoding/gob"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DataFrame struct {
|
||||||
|
ID ID
|
||||||
|
Type Type
|
||||||
|
Payload []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DataFrame) Encode(w io.Writer) error {
|
||||||
|
gz := gzip.NewWriter(w)
|
||||||
|
defer gz.Close()
|
||||||
|
gob := gob.NewEncoder(gz)
|
||||||
|
return gob.Encode(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DataFrame) Decode(r io.Reader) error {
|
||||||
|
gz, err := gzip.NewReader(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer gz.Close()
|
||||||
|
gob := gob.NewDecoder(gz)
|
||||||
|
return gob.Decode(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DataFrame) Read(p []byte) (int, error) {
|
||||||
|
return copy(p, d.Payload), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DataFrame) Write(p []byte) (int, error) {
|
||||||
|
return copy(d.Payload, p), nil
|
||||||
|
}
|
72
manager.go
Normal file
72
manager.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
Tunnel io.ReadWriter
|
||||||
|
Connections map[ID]*Connection
|
||||||
|
incoming chan *DataFrame
|
||||||
|
outgoing chan *DataFrame
|
||||||
|
accept chan *DataFrame
|
||||||
|
closed chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager(tun io.ReadWriter) *Manager {
|
||||||
|
return &Manager{
|
||||||
|
Tunnel: tun,
|
||||||
|
Connections: make(map[ID]*Connection),
|
||||||
|
incoming: make(chan *DataFrame, 1024),
|
||||||
|
outgoing: make(chan *DataFrame, 1024),
|
||||||
|
accept: make(chan *DataFrame, 1024),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Run() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-m.closed:
|
||||||
|
return
|
||||||
|
case df := <-m.incoming:
|
||||||
|
go df.Encode(m.Tunnel)
|
||||||
|
default:
|
||||||
|
go func() {
|
||||||
|
df := new(DataFrame)
|
||||||
|
df.Decode(m.Tunnel)
|
||||||
|
switch df.Type {
|
||||||
|
case TypeRequest:
|
||||||
|
m.accept <- df
|
||||||
|
case TypeClosed:
|
||||||
|
connection, ok := m.Connections[df.ID]
|
||||||
|
if ok {
|
||||||
|
connection.Close()
|
||||||
|
delete(m.Connections, df.ID)
|
||||||
|
}
|
||||||
|
case TypeNormal:
|
||||||
|
connection, ok := m.Connections[df.ID]
|
||||||
|
if ok {
|
||||||
|
connection.RX = m.outgoing
|
||||||
|
m.outgoing <- df
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Connect()
|
||||||
|
|
||||||
|
func (m *Manager) Accept()
|
||||||
|
|
||||||
|
func (m *Manager) Close() error {
|
||||||
|
defer close(m.closed)
|
||||||
|
defer close(m.accept)
|
||||||
|
defer close(m.incoming)
|
||||||
|
defer close(m.outgoing)
|
||||||
|
for _, connection := range m.Connections {
|
||||||
|
connection.Close()
|
||||||
|
}
|
||||||
|
m.closed <- true
|
||||||
|
return nil
|
||||||
|
}
|
Reference in New Issue
Block a user