micro/tunnel/listener.go

212 lines
4.2 KiB
Go
Raw Normal View History

2019-08-07 18:44:33 +01:00
package tunnel
import (
"io"
2019-12-12 17:10:32 +00:00
"sync"
2019-08-11 18:11:33 +01:00
"github.com/micro/go-micro/v3/logger"
2019-08-07 18:44:33 +01:00
)
type tunListener struct {
// address of the listener
2019-08-30 20:05:00 +01:00
channel string
// token is the tunnel token
token string
2019-08-07 18:44:33 +01:00
// the accept channel
2019-08-30 20:05:00 +01:00
accept chan *session
// the tunnel closed channel
tunClosed chan bool
2019-08-30 20:05:00 +01:00
// the listener session
session *session
// del func to kill listener
delFunc func()
2019-12-12 17:10:32 +00:00
sync.RWMutex
// the channel to close
closed chan bool
}
2019-08-07 18:44:33 +01:00
func (t *tunListener) process() {
// our connection map for session
2019-08-30 20:05:00 +01:00
conns := make(map[string]*session)
2019-08-07 18:44:33 +01:00
defer func() {
// close the sessions
for id, conn := range conns {
conn.Close()
delete(conns, id)
}
// unassign
conns = nil
}()
2019-08-07 18:44:33 +01:00
for {
select {
case <-t.closed:
return
case <-t.tunClosed:
t.Close()
return
2019-08-07 18:44:33 +01:00
// receive a new message
2019-08-30 20:05:00 +01:00
case m := <-t.session.recv:
2019-12-08 00:53:55 +00:00
var sessionId string
var linkId string
2019-12-12 17:10:32 +00:00
switch t.session.mode {
2019-12-08 00:53:55 +00:00
case Multicast:
sessionId = "multicast"
linkId = "multicast"
case Broadcast:
sessionId = "broadcast"
linkId = "broadcast"
default:
sessionId = m.session
linkId = m.link
}
2019-08-30 20:05:00 +01:00
// get a session
sess, ok := conns[sessionId]
if logger.V(logger.TraceLevel, log) {
log.Tracef("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, m.session, m.typ, ok)
}
2019-08-07 18:44:33 +01:00
if !ok {
// we only process open and session types
switch m.typ {
case "open", "session":
default:
continue
}
2019-08-30 20:05:00 +01:00
// create a new session session
sess = &session{
// the session key
key: []byte(t.token + m.channel + sessionId),
2019-08-30 20:05:00 +01:00
// the id of the remote side
2019-09-03 15:56:37 +01:00
tunnel: m.tunnel,
2019-08-30 20:05:00 +01:00
// the channel
channel: m.channel,
2019-08-07 18:44:33 +01:00
// the session id
session: sessionId,
// tunnel token
token: t.token,
// is loopback conn
loopback: m.loopback,
2019-08-29 12:42:27 +01:00
// the link the message was received on
2019-12-08 00:53:55 +00:00
link: linkId,
2019-10-15 15:40:04 +01:00
// set the connection mode
2019-12-12 17:10:32 +00:00
mode: t.session.mode,
2019-08-07 18:44:33 +01:00
// close chan
closed: make(chan bool),
// recv called by the acceptor
recv: make(chan *message, 128),
// use the internal send buffer
2019-08-30 20:05:00 +01:00
send: t.session.send,
// error channel
errChan: make(chan error, 1),
2019-12-07 23:28:39 +00:00
// set the read timeout
readTimeout: t.session.readTimeout,
2019-08-07 18:44:33 +01:00
}
2019-08-30 20:05:00 +01:00
// save the session
conns[sessionId] = sess
2019-08-07 18:44:33 +01:00
select {
case <-t.closed:
return
// send to accept chan
2019-08-30 20:05:00 +01:00
case t.accept <- sess:
2019-08-07 18:44:33 +01:00
}
}
// an existing session was found
switch m.typ {
case "close":
2019-12-12 17:10:32 +00:00
// don't close multicast sessions
if sess.mode > Unicast {
continue
}
// received a close message
select {
// check if the session is closed
case <-sess.closed:
// no op
delete(conns, sessionId)
default:
2019-12-07 23:28:39 +00:00
// only close if unicast session
// close and delete session
close(sess.closed)
delete(conns, sessionId)
}
// continue
continue
case "session":
// operate on this
default:
// non operational type
continue
2019-08-07 18:44:33 +01:00
}
// send this to the accept chan
select {
2019-08-30 20:05:00 +01:00
case <-sess.closed:
delete(conns, sessionId)
2019-08-30 20:05:00 +01:00
case sess.recv <- m:
if logger.V(logger.TraceLevel, log) {
log.Tracef("Tunnel listener sent to recv chan channel %s session %s type %s", m.channel, sessionId, m.typ)
}
2019-08-07 18:44:33 +01:00
}
}
}
}
2019-08-30 20:05:00 +01:00
func (t *tunListener) Channel() string {
return t.channel
2019-08-07 18:44:33 +01:00
}
// Close closes tunnel listener
2019-08-07 18:44:33 +01:00
func (t *tunListener) Close() error {
2019-12-12 17:10:32 +00:00
t.Lock()
defer t.Unlock()
2019-08-07 18:44:33 +01:00
select {
case <-t.closed:
return nil
default:
// close and delete
t.delFunc()
t.session.Close()
2019-08-07 18:44:33 +01:00
close(t.closed)
}
return nil
}
// Everytime accept is called we essentially block till we get a new connection
2019-08-30 20:05:00 +01:00
func (t *tunListener) Accept() (Session, error) {
2019-08-07 18:44:33 +01:00
select {
2019-08-30 20:05:00 +01:00
// if the session is closed return
2019-08-07 18:44:33 +01:00
case <-t.closed:
return nil, io.EOF
case <-t.tunClosed:
// close the listener when the tunnel closes
return nil, io.EOF
2019-08-07 18:44:33 +01:00
// wait for a new connection
case c, ok := <-t.accept:
// check if the accept chan is closed
2019-08-07 18:44:33 +01:00
if !ok {
return nil, io.EOF
}
2019-12-06 00:18:40 +00:00
// return without accept
if c.mode != Unicast {
return c, nil
}
// send back the accept
if err := c.Accept(); err != nil {
return nil, err
}
2019-08-07 18:44:33 +01:00
return c, nil
}
}