github.com/micro/go-micro/v2@v2.9.1/tunnel/listener.go (about) 1 package tunnel 2 3 import ( 4 "io" 5 "sync" 6 7 "github.com/micro/go-micro/v2/logger" 8 ) 9 10 type tunListener struct { 11 // address of the listener 12 channel string 13 // token is the tunnel token 14 token string 15 // the accept channel 16 accept chan *session 17 // the tunnel closed channel 18 tunClosed chan bool 19 // the listener session 20 session *session 21 // del func to kill listener 22 delFunc func() 23 24 sync.RWMutex 25 // the channel to close 26 closed chan bool 27 } 28 29 func (t *tunListener) process() { 30 // our connection map for session 31 conns := make(map[string]*session) 32 33 defer func() { 34 // close the sessions 35 for id, conn := range conns { 36 conn.Close() 37 delete(conns, id) 38 } 39 // unassign 40 conns = nil 41 }() 42 43 for { 44 select { 45 case <-t.closed: 46 return 47 case <-t.tunClosed: 48 t.Close() 49 return 50 // receive a new message 51 case m := <-t.session.recv: 52 var sessionId string 53 var linkId string 54 55 switch t.session.mode { 56 case Multicast: 57 sessionId = "multicast" 58 linkId = "multicast" 59 case Broadcast: 60 sessionId = "broadcast" 61 linkId = "broadcast" 62 default: 63 sessionId = m.session 64 linkId = m.link 65 } 66 67 // get a session 68 sess, ok := conns[sessionId] 69 if logger.V(logger.TraceLevel, log) { 70 log.Tracef("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, m.session, m.typ, ok) 71 } 72 if !ok { 73 // we only process open and session types 74 switch m.typ { 75 case "open", "session": 76 default: 77 continue 78 } 79 80 // create a new session session 81 sess = &session{ 82 // the session key 83 key: []byte(t.token + m.channel + sessionId), 84 // the id of the remote side 85 tunnel: m.tunnel, 86 // the channel 87 channel: m.channel, 88 // the session id 89 session: sessionId, 90 // tunnel token 91 token: t.token, 92 // is loopback conn 93 loopback: m.loopback, 94 // the link the message was received on 95 link: linkId, 96 // set the connection mode 97 mode: t.session.mode, 98 // close chan 99 closed: make(chan bool), 100 // recv called by the acceptor 101 recv: make(chan *message, 128), 102 // use the internal send buffer 103 send: t.session.send, 104 // error channel 105 errChan: make(chan error, 1), 106 // set the read timeout 107 readTimeout: t.session.readTimeout, 108 } 109 110 // save the session 111 conns[sessionId] = sess 112 113 select { 114 case <-t.closed: 115 return 116 // send to accept chan 117 case t.accept <- sess: 118 } 119 } 120 121 // an existing session was found 122 123 switch m.typ { 124 case "close": 125 // don't close multicast sessions 126 if sess.mode > Unicast { 127 continue 128 } 129 130 // received a close message 131 select { 132 // check if the session is closed 133 case <-sess.closed: 134 // no op 135 delete(conns, sessionId) 136 default: 137 // only close if unicast session 138 // close and delete session 139 close(sess.closed) 140 delete(conns, sessionId) 141 } 142 143 // continue 144 continue 145 case "session": 146 // operate on this 147 default: 148 // non operational type 149 continue 150 } 151 152 // send this to the accept chan 153 select { 154 case <-sess.closed: 155 delete(conns, sessionId) 156 case sess.recv <- m: 157 if logger.V(logger.TraceLevel, log) { 158 log.Tracef("Tunnel listener sent to recv chan channel %s session %s type %s", m.channel, sessionId, m.typ) 159 } 160 } 161 } 162 } 163 } 164 165 func (t *tunListener) Channel() string { 166 return t.channel 167 } 168 169 // Close closes tunnel listener 170 func (t *tunListener) Close() error { 171 t.Lock() 172 defer t.Unlock() 173 174 select { 175 case <-t.closed: 176 return nil 177 default: 178 // close and delete 179 t.delFunc() 180 t.session.Close() 181 close(t.closed) 182 } 183 return nil 184 } 185 186 // Everytime accept is called we essentially block till we get a new connection 187 func (t *tunListener) Accept() (Session, error) { 188 select { 189 // if the session is closed return 190 case <-t.closed: 191 return nil, io.EOF 192 case <-t.tunClosed: 193 // close the listener when the tunnel closes 194 return nil, io.EOF 195 // wait for a new connection 196 case c, ok := <-t.accept: 197 // check if the accept chan is closed 198 if !ok { 199 return nil, io.EOF 200 } 201 // return without accept 202 if c.mode != Unicast { 203 return c, nil 204 } 205 // send back the accept 206 if err := c.Accept(); err != nil { 207 return nil, err 208 } 209 return c, nil 210 } 211 }