2019-08-07 20:44:33 +03:00
|
|
|
package tunnel
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
2019-08-11 20:11:33 +03:00
|
|
|
|
|
|
|
"github.com/micro/go-micro/util/log"
|
2019-08-07 20:44:33 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
type tunListener struct {
|
|
|
|
// address of the listener
|
|
|
|
addr string
|
|
|
|
// the accept channel
|
|
|
|
accept chan *socket
|
|
|
|
// the channel to close
|
|
|
|
closed chan bool
|
2019-08-08 17:20:53 +03:00
|
|
|
// the tunnel closed channel
|
|
|
|
tunClosed chan bool
|
2019-08-07 20:44:33 +03:00
|
|
|
// the connection
|
|
|
|
conn Conn
|
|
|
|
// the listener socket
|
|
|
|
socket *socket
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *tunListener) process() {
|
|
|
|
// our connection map for session
|
|
|
|
conns := make(map[string]*socket)
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-t.closed:
|
|
|
|
return
|
|
|
|
// receive a new message
|
|
|
|
case m := <-t.socket.recv:
|
|
|
|
// get a socket
|
|
|
|
sock, ok := conns[m.session]
|
2019-08-11 20:11:33 +03:00
|
|
|
log.Debugf("Tunnel listener received id %s session %s exists: %t", m.id, m.session, ok)
|
2019-08-07 20:44:33 +03:00
|
|
|
if !ok {
|
|
|
|
// create a new socket session
|
|
|
|
sock = &socket{
|
|
|
|
// our tunnel id
|
|
|
|
id: m.id,
|
|
|
|
// the session id
|
|
|
|
session: m.session,
|
2019-08-29 01:12:22 +03:00
|
|
|
// is loopback conn
|
|
|
|
loopback: m.loopback,
|
2019-08-29 14:42:27 +03:00
|
|
|
// the link the message was received on
|
|
|
|
link: m.link,
|
2019-08-07 20:44:33 +03:00
|
|
|
// close chan
|
|
|
|
closed: make(chan bool),
|
|
|
|
// recv called by the acceptor
|
|
|
|
recv: make(chan *message, 128),
|
|
|
|
// use the internal send buffer
|
|
|
|
send: t.socket.send,
|
|
|
|
// wait
|
|
|
|
wait: make(chan bool),
|
|
|
|
}
|
|
|
|
|
|
|
|
// save the socket
|
|
|
|
conns[m.session] = sock
|
|
|
|
|
|
|
|
// send to accept chan
|
|
|
|
select {
|
|
|
|
case <-t.closed:
|
|
|
|
return
|
|
|
|
case t.accept <- sock:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// send this to the accept chan
|
|
|
|
select {
|
|
|
|
case <-sock.closed:
|
|
|
|
delete(conns, m.session)
|
|
|
|
case sock.recv <- m:
|
2019-08-11 20:11:33 +03:00
|
|
|
log.Debugf("Tunnel listener sent to recv chan id %s session %s", m.id, m.session)
|
2019-08-07 20:44:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *tunListener) Addr() string {
|
|
|
|
return t.addr
|
|
|
|
}
|
|
|
|
|
2019-08-08 17:20:53 +03:00
|
|
|
// Close closes tunnel listener
|
2019-08-07 20:44:33 +03:00
|
|
|
func (t *tunListener) Close() error {
|
|
|
|
select {
|
|
|
|
case <-t.closed:
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
close(t.closed)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Everytime accept is called we essentially block till we get a new connection
|
|
|
|
func (t *tunListener) Accept() (Conn, error) {
|
|
|
|
select {
|
|
|
|
// if the socket is closed return
|
|
|
|
case <-t.closed:
|
|
|
|
return nil, io.EOF
|
2019-08-08 17:20:53 +03:00
|
|
|
case <-t.tunClosed:
|
|
|
|
// close the listener when the tunnel closes
|
2019-08-11 20:11:33 +03:00
|
|
|
t.Close()
|
2019-08-08 17:20:53 +03:00
|
|
|
return nil, io.EOF
|
2019-08-07 20:44:33 +03:00
|
|
|
// wait for a new connection
|
|
|
|
case c, ok := <-t.accept:
|
|
|
|
if !ok {
|
|
|
|
return nil, io.EOF
|
|
|
|
}
|
|
|
|
return c, nil
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|