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