github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/network/tunnel/broker/broker.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); 2 // you may not use this file except in compliance with the License. 3 // You may obtain a copy of the License at 4 // 5 // https://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, 9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 // See the License for the specific language governing permissions and 11 // limitations under the License. 12 // 13 // Original source: github.com/micro/go-micro/v3/network/tunnel/broker/broker.go 14 15 // Package broker is a tunnel broker 16 package broker 17 18 import ( 19 "context" 20 21 "github.com/tickoalcantara12/micro/v3/service/broker" 22 "github.com/tickoalcantara12/micro/v3/service/network/transport" 23 "github.com/tickoalcantara12/micro/v3/service/network/tunnel" 24 "github.com/tickoalcantara12/micro/v3/service/network/tunnel/mucp" 25 ) 26 27 type tunBroker struct { 28 opts broker.Options 29 tunnel tunnel.Tunnel 30 } 31 32 type tunSubscriber struct { 33 topic string 34 handler broker.Handler 35 opts broker.SubscribeOptions 36 37 closed chan bool 38 listener tunnel.Listener 39 } 40 41 type tunEvent struct { 42 topic string 43 message *broker.Message 44 } 45 46 // used to access tunnel from options context 47 type tunnelKey struct{} 48 type tunnelAddr struct{} 49 50 func (t *tunBroker) Init(opts ...broker.Option) error { 51 for _, o := range opts { 52 o(&t.opts) 53 } 54 return nil 55 } 56 57 func (t *tunBroker) Options() broker.Options { 58 return t.opts 59 } 60 61 func (t *tunBroker) Address() string { 62 return t.tunnel.Address() 63 } 64 65 func (t *tunBroker) Connect() error { 66 return t.tunnel.Connect() 67 } 68 69 func (t *tunBroker) Disconnect() error { 70 return t.tunnel.Close() 71 } 72 73 func (t *tunBroker) Publish(topic string, m *broker.Message, opts ...broker.PublishOption) error { 74 // TODO: this is probably inefficient, we might want to just maintain an open connection 75 // it may be easier to add broadcast to the tunnel 76 c, err := t.tunnel.Dial(topic, tunnel.DialMode(tunnel.Multicast)) 77 if err != nil { 78 return err 79 } 80 defer c.Close() 81 82 return c.Send(&transport.Message{ 83 Header: m.Header, 84 Body: m.Body, 85 }) 86 } 87 88 func (t *tunBroker) Subscribe(topic string, h broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) { 89 l, err := t.tunnel.Listen(topic, tunnel.ListenMode(tunnel.Multicast)) 90 if err != nil { 91 return nil, err 92 } 93 94 var options broker.SubscribeOptions 95 for _, o := range opts { 96 o(&options) 97 } 98 99 tunSub := &tunSubscriber{ 100 topic: topic, 101 handler: h, 102 opts: options, 103 closed: make(chan bool), 104 listener: l, 105 } 106 107 // start processing 108 go tunSub.run() 109 110 return tunSub, nil 111 } 112 113 func (t *tunBroker) String() string { 114 return "tunnel" 115 } 116 117 func (t *tunSubscriber) run() { 118 for { 119 // accept a new connection 120 c, err := t.listener.Accept() 121 if err != nil { 122 select { 123 case <-t.closed: 124 return 125 default: 126 continue 127 } 128 } 129 130 // receive message 131 m := new(transport.Message) 132 if err := c.Recv(m); err != nil { 133 c.Close() 134 continue 135 } 136 137 // close the connection 138 c.Close() 139 140 // handle the message 141 go t.handler(&broker.Message{ 142 Header: m.Header, 143 Body: m.Body, 144 }) 145 } 146 } 147 148 func (t *tunSubscriber) Options() broker.SubscribeOptions { 149 return t.opts 150 } 151 152 func (t *tunSubscriber) Topic() string { 153 return t.topic 154 } 155 156 func (t *tunSubscriber) Unsubscribe() error { 157 select { 158 case <-t.closed: 159 return nil 160 default: 161 close(t.closed) 162 return t.listener.Close() 163 } 164 } 165 166 func (t *tunEvent) Topic() string { 167 return t.topic 168 } 169 170 func (t *tunEvent) Message() *broker.Message { 171 return t.message 172 } 173 174 func (t *tunEvent) Ack() error { 175 return nil 176 } 177 178 func (t *tunEvent) Error() error { 179 return nil 180 } 181 182 func NewBroker(opts ...broker.Option) broker.Broker { 183 options := broker.Options{ 184 Context: context.Background(), 185 } 186 for _, o := range opts { 187 o(&options) 188 } 189 t, ok := options.Context.Value(tunnelKey{}).(tunnel.Tunnel) 190 if !ok { 191 t = mucp.NewTunnel() 192 } 193 194 a, ok := options.Context.Value(tunnelAddr{}).(string) 195 if ok { 196 // initialise address 197 t.Init(tunnel.Address(a)) 198 } 199 200 if len(options.Addrs) > 0 { 201 // initialise nodes 202 t.Init(tunnel.Nodes(options.Addrs...)) 203 } 204 205 return &tunBroker{ 206 opts: options, 207 tunnel: t, 208 } 209 } 210 211 // WithAddress sets the tunnel address 212 func WithAddress(a string) broker.Option { 213 return func(o *broker.Options) { 214 if o.Context == nil { 215 o.Context = context.Background() 216 } 217 o.Context = context.WithValue(o.Context, tunnelAddr{}, a) 218 } 219 } 220 221 // WithTunnel sets the internal tunnel 222 func WithTunnel(t tunnel.Tunnel) broker.Option { 223 return func(o *broker.Options) { 224 if o.Context == nil { 225 o.Context = context.Background() 226 } 227 o.Context = context.WithValue(o.Context, tunnelKey{}, t) 228 } 229 }