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