micro/network/default.go

161 lines
2.8 KiB
Go
Raw Normal View History

package network
import (
2019-07-01 13:55:15 +03:00
"fmt"
2019-07-08 18:24:57 +03:00
"io"
"sync"
2019-07-01 13:55:15 +03:00
"github.com/google/uuid"
"github.com/micro/go-micro/config/options"
2019-07-08 18:24:57 +03:00
"github.com/micro/go-micro/network/transport"
"github.com/micro/go-micro/util/addr"
)
2019-07-08 18:24:57 +03:00
// default network implementation
type network struct {
options.Options
2019-07-08 18:24:57 +03:00
// name of the network
2019-07-07 12:10:38 +03:00
name string
2019-07-09 18:37:59 +03:00
// network address used where one is specified
address string
2019-07-08 18:24:57 +03:00
// transport
transport transport.Transport
}
2019-07-08 18:24:57 +03:00
type listener struct {
// start accepting once
once sync.Once
// close channel to close the connection
closed chan bool
// the listener
listener transport.Listener
// the connection queue
conns chan Conn
2019-07-01 13:55:15 +03:00
}
2019-07-08 18:24:57 +03:00
func (n *network) Create() (*Node, error) {
2019-07-09 18:37:59 +03:00
ip, err := addr.Extract(n.address)
2019-07-01 13:55:15 +03:00
if err != nil {
2019-07-08 18:24:57 +03:00
return nil, err
2019-07-01 13:55:15 +03:00
}
2019-07-08 18:24:57 +03:00
return &Node{
Id: fmt.Sprintf("%s-%s", n.name, uuid.New().String()),
Address: ip,
2019-07-09 18:37:59 +03:00
Network: n.Name(),
2019-07-08 18:24:57 +03:00
Metadata: map[string]string{
2019-07-09 18:37:59 +03:00
"network": n.String(),
2019-07-08 18:32:12 +03:00
"transport": n.transport.String(),
2019-07-08 18:24:57 +03:00
},
}, nil
}
2019-07-01 13:55:15 +03:00
2019-07-08 18:24:57 +03:00
func (n *network) Name() string {
return n.name
}
2019-07-01 13:55:15 +03:00
2019-07-08 18:24:57 +03:00
func (n *network) Connect(node *Node) (Conn, error) {
c, err := n.transport.Dial(node.Address)
2019-07-01 13:55:15 +03:00
if err != nil {
2019-07-08 18:24:57 +03:00
return nil, err
2019-07-01 13:55:15 +03:00
}
2019-07-08 18:24:57 +03:00
return newLink(c.(transport.Socket)), nil
2019-07-01 13:55:15 +03:00
}
2019-07-08 18:24:57 +03:00
func (n *network) Listen(node *Node) (Listener, error) {
l, err := n.transport.Listen(node.Address)
if err != nil {
return nil, err
}
return newListener(l), nil
}
2019-07-08 18:24:57 +03:00
func (l *listener) process() {
if err := l.listener.Accept(l.accept); err != nil {
// close the listener
l.Close()
}
}
2019-07-08 18:24:57 +03:00
func (l *listener) accept(sock transport.Socket) {
// create a new link and pass it through
link := newLink(sock)
2019-07-01 13:55:15 +03:00
2019-07-08 18:24:57 +03:00
// send it
l.conns <- link
2019-07-01 13:55:15 +03:00
2019-07-08 18:24:57 +03:00
// wait for it to be closed
select {
case <-l.closed:
return
case <-link.closed:
return
}
}
2019-07-01 13:55:15 +03:00
2019-07-08 18:24:57 +03:00
func (l *listener) Address() string {
return l.listener.Addr()
}
2019-07-01 13:55:15 +03:00
2019-07-08 18:24:57 +03:00
func (l *listener) Close() error {
select {
case <-l.closed:
return nil
default:
close(l.closed)
}
return nil
}
func (l *listener) Accept() (Conn, error) {
l.once.Do(func() {
// TODO: catch the error
go l.process()
})
select {
case c := <-l.conns:
return c, nil
case <-l.closed:
return nil, io.EOF
}
}
func newListener(l transport.Listener) *listener {
return &listener{
closed: make(chan bool),
conns: make(chan Conn),
listener: l,
}
}
2019-07-02 00:59:11 +03:00
func newNetwork(opts ...options.Option) *network {
options := options.NewOptions(opts...)
net := &network{
2019-07-08 18:24:57 +03:00
name: DefaultName,
transport: transport.DefaultTransport,
2019-07-02 00:59:11 +03:00
}
2019-07-07 12:10:38 +03:00
// get network name
name, ok := options.Values().Get("network.name")
2019-07-02 00:59:11 +03:00
if ok {
2019-07-07 12:10:38 +03:00
net.name = name.(string)
2019-07-02 00:59:11 +03:00
}
2019-07-09 18:37:59 +03:00
// get network name
address, ok := options.Values().Get("network.address")
if ok {
net.address = address.(string)
}
2019-07-08 18:24:57 +03:00
// get network transport
t, ok := options.Values().Get("network.transport")
2019-07-02 00:59:11 +03:00
if ok {
2019-07-08 18:24:57 +03:00
net.transport = t.(transport.Transport)
2019-07-02 00:59:11 +03:00
}
return net
}