-
Notifications
You must be signed in to change notification settings - Fork 8
/
registry.go
122 lines (108 loc) · 4.07 KB
/
registry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package flow
import (
"fmt"
"sync"
"time"
"v.io/v23/context"
"v.io/v23/naming"
)
// Protocol is the interface that protocols for use with vanadium RPCs must implement.
type Protocol interface {
// Dial is the function used to create Conn objects given a
// protocol-specific string representation of an address.
// The returned Conn must also frame the connection.
Dial(ctx *context.T, protocol, address string, timeout time.Duration) (Conn, error)
// Resolve is the function used for protocol-specific address normalization.
// e.g. the TCP resolve performs DNS resolution.
// Resolve returns the protocol and resolved addresses.
Resolve(ctx *context.T, protocol, address string) (string, []string, error)
// Listen is the function used to create Listener objects given a
// protocol-specific string representation of the address a server will listen on.
// The Conns returned from Listener must frame connections.
Listen(ctx *context.T, protocol, address string) (Listener, error)
}
// RegisterProtocol makes available a Protocol to RegisteredProtocol.
// If the protocol represents other actual protocols, you need to specify all the
// actual protocols. E.g, "wsh" represents "tcp4", "tcp6", "ws4", and "ws6".
//
// Implementations of the Manager interface are expected to use this registry
// in order to expand the reach of the types of network protocols they can
// handle.
//
// Successive calls to RegisterProtocol replace the contents of a previous
// call to it and returns trues if a previous value was replaced, false otherwise.
func RegisterProtocol(protocol string, obj Protocol, p ...string) bool {
// This is for handling the common case where protocol is a "singleton", to
// make it easier to specify.
if len(p) == 0 {
p = []string{protocol}
}
registryLock.Lock()
defer registryLock.Unlock()
_, present := registry[protocol]
registry[protocol] = registryEntry{obj, p}
return present
}
// RegisterUnknownProtocol registers a Protocol for endpoints with
// no specified protocol.
//
// The desired protocol provided in the first argument will be passed to the
// Protocol methods as the actual protocol to use when dialing, resolving, or listening.
//
// The protocol itself must have already been registered before RegisterUnknownProtocol
// is called, otherwise we'll panic.
func RegisterUnknownProtocol(protocol string, obj Protocol) bool {
var p []string
registryLock.RLock()
r, present := registry[protocol]
if !present {
panic(fmt.Sprintf("%s not registered", protocol))
}
p = r.p
registryLock.RUnlock()
return RegisterProtocol(naming.UnknownProtocol, wrappedProtocol{protocol, obj}, p...)
}
type wrappedProtocol struct {
protocol string
obj Protocol
}
func (p wrappedProtocol) Dial(ctx *context.T, _, address string, timeout time.Duration) (Conn, error) {
return p.obj.Dial(ctx, p.protocol, address, timeout)
}
func (p wrappedProtocol) Resolve(ctx *context.T, _, address string) (string, []string, error) {
return p.obj.Resolve(ctx, p.protocol, address)
}
func (p wrappedProtocol) Listen(ctx *context.T, _, address string) (Listener, error) {
return p.obj.Listen(ctx, p.protocol, address)
}
// RegisteredProtocol returns the Protocol object registered with a
// previous call to RegisterProtocol.
func RegisteredProtocol(protocol string) (Protocol, []string) {
registryLock.RLock()
e := registry[protocol]
registryLock.RUnlock()
return e.obj, e.p
}
// RegisteredProtocols returns the list of protocols that have been previously
// registered using RegisterProtocol. The underlying implementation will
// support additional protocols such as those supported by the native RPC stack.
func RegisteredProtocols() []string {
registryLock.RLock()
defer registryLock.RUnlock()
p := make([]string, 0, len(registry))
for k, _ := range registry {
p = append(p, k)
}
return p
}
type registryEntry struct {
obj Protocol
p []string
}
var (
registryLock sync.RWMutex
registry = make(map[string]registryEntry)
)