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 }