use timecache
This commit is contained in:
parent
17e835cd17
commit
f3f2cb2c82
|
@ -0,0 +1,21 @@
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.7
|
||||||
|
|
||||||
|
install: true
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make deps
|
||||||
|
- go test ./...
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $GOPATH/src/gx
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email: false
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 Jeromy Johnson
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,7 @@
|
||||||
|
gx:
|
||||||
|
go get -u github.com/whyrusleeping/gx
|
||||||
|
go get -u github.com/whyrusleeping/gx-go
|
||||||
|
|
||||||
|
deps: gx
|
||||||
|
gx --verbose install --global
|
||||||
|
gx-go rewrite
|
226
floodsub.go
226
floodsub.go
|
@ -3,6 +3,7 @@ package floodsub
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
host "github.com/libp2p/go-libp2p/p2p/host"
|
host "github.com/libp2p/go-libp2p/p2p/host"
|
||||||
inet "github.com/libp2p/go-libp2p/p2p/net"
|
inet "github.com/libp2p/go-libp2p/p2p/net"
|
||||||
protocol "github.com/libp2p/go-libp2p/p2p/protocol"
|
protocol "github.com/libp2p/go-libp2p/p2p/protocol"
|
||||||
|
timecache "github.com/whyrusleeping/timecache"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ID = protocol.ID("/floodsub/1.0.0")
|
const ID = protocol.ID("/floodsub/1.0.0")
|
||||||
|
@ -33,16 +35,16 @@ type PubSub struct {
|
||||||
host host.Host
|
host host.Host
|
||||||
|
|
||||||
incoming chan *RPC
|
incoming chan *RPC
|
||||||
outgoing chan *RPC
|
publish chan *Message
|
||||||
newPeers chan inet.Stream
|
newPeers chan inet.Stream
|
||||||
peerDead chan peer.ID
|
peerDead chan peer.ID
|
||||||
|
|
||||||
myTopics map[string]chan *Message
|
myTopics map[string]chan *Message
|
||||||
pubsubLk sync.Mutex
|
pubsubLk sync.Mutex
|
||||||
|
|
||||||
topics map[string]map[peer.ID]struct{}
|
topics map[string]map[peer.ID]struct{}
|
||||||
peers map[peer.ID]chan *RPC
|
peers map[peer.ID]chan *RPC
|
||||||
lastMsg map[peer.ID]uint64
|
seenMessages *timecache.TimeCache
|
||||||
|
|
||||||
addSub chan *addSub
|
addSub chan *addSub
|
||||||
|
|
||||||
|
@ -66,17 +68,17 @@ type RPC struct {
|
||||||
|
|
||||||
func NewFloodSub(ctx context.Context, h host.Host) *PubSub {
|
func NewFloodSub(ctx context.Context, h host.Host) *PubSub {
|
||||||
ps := &PubSub{
|
ps := &PubSub{
|
||||||
host: h,
|
host: h,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
incoming: make(chan *RPC, 32),
|
incoming: make(chan *RPC, 32),
|
||||||
outgoing: make(chan *RPC),
|
publish: make(chan *Message),
|
||||||
newPeers: make(chan inet.Stream),
|
newPeers: make(chan inet.Stream),
|
||||||
peerDead: make(chan peer.ID),
|
peerDead: make(chan peer.ID),
|
||||||
addSub: make(chan *addSub),
|
addSub: make(chan *addSub),
|
||||||
myTopics: make(map[string]chan *Message),
|
myTopics: make(map[string]chan *Message),
|
||||||
topics: make(map[string]map[peer.ID]struct{}),
|
topics: make(map[string]map[peer.ID]struct{}),
|
||||||
peers: make(map[peer.ID]chan *RPC),
|
peers: make(map[peer.ID]chan *RPC),
|
||||||
lastMsg: make(map[peer.ID]uint64),
|
seenMessages: timecache.NewTimeCache(time.Second * 30),
|
||||||
}
|
}
|
||||||
|
|
||||||
h.SetStreamHandler(ID, ps.handleNewStream)
|
h.SetStreamHandler(ID, ps.handleNewStream)
|
||||||
|
@ -90,9 +92,12 @@ func NewFloodSub(ctx context.Context, h host.Host) *PubSub {
|
||||||
func (p *PubSub) getHelloPacket() *RPC {
|
func (p *PubSub) getHelloPacket() *RPC {
|
||||||
var rpc RPC
|
var rpc RPC
|
||||||
for t, _ := range p.myTopics {
|
for t, _ := range p.myTopics {
|
||||||
rpc.Topics = append(rpc.Topics, t)
|
as := &pb.RPC_SubOpts{
|
||||||
|
Topicid: proto.String(t),
|
||||||
|
Subscribe: proto.Bool(true),
|
||||||
|
}
|
||||||
|
rpc.Subscriptions = append(rpc.Subscriptions, as)
|
||||||
}
|
}
|
||||||
rpc.Type = &AddSubMessageType
|
|
||||||
return &rpc
|
return &rpc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,23 +193,15 @@ func (p *PubSub) processLoop(ctx context.Context) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("handling RPC: ", err)
|
log.Error("handling RPC: ", err)
|
||||||
}
|
}
|
||||||
case rpc := <-p.outgoing:
|
case msg := <-p.publish:
|
||||||
switch rpc.GetType() {
|
err := p.recvMessage(msg.Message)
|
||||||
case AddSubMessageType, UnsubMessageType:
|
if err != nil {
|
||||||
for _, mch := range p.peers {
|
log.Error("error receiving message: ", err)
|
||||||
mch <- rpc
|
}
|
||||||
}
|
|
||||||
case PubMessageType:
|
|
||||||
//fmt.Println("publishing outgoing message")
|
|
||||||
err := p.recvMessage(rpc)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("error receiving message: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.publishMessage(rpc)
|
err = p.publishMessage(p.host.ID(), msg.Message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("publishing message: ", err)
|
log.Error("publishing message: ", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
log.Info("pubsub processloop shutting down")
|
log.Info("pubsub processloop shutting down")
|
||||||
|
@ -213,22 +210,14 @@ func (p *PubSub) processLoop(ctx context.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (p *PubSub) handleSubscriptionChange(sub *addSub) {
|
func (p *PubSub) handleSubscriptionChange(sub *addSub) {
|
||||||
ch, ok := p.myTopics[sub.topic]
|
|
||||||
out := &RPC{
|
subopt := pb.RPC_SubOpts{
|
||||||
RPC: pb.RPC{
|
Topicid: &sub.topic,
|
||||||
Topics: []string{sub.topic},
|
Subscribe: &sub.sub,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if sub.cancel {
|
ch, ok := p.myTopics[sub.topic]
|
||||||
if !ok {
|
if sub.sub {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
close(ch)
|
|
||||||
delete(p.myTopics, sub.topic)
|
|
||||||
out.Type = &UnsubMessageType
|
|
||||||
} else {
|
|
||||||
if ok {
|
if ok {
|
||||||
// we don't allow multiple subs per topic at this point
|
// we don't allow multiple subs per topic at this point
|
||||||
sub.resp <- nil
|
sub.resp <- nil
|
||||||
|
@ -238,27 +227,58 @@ func (p *PubSub) handleSubscriptionChange(sub *addSub) {
|
||||||
resp := make(chan *Message, 16)
|
resp := make(chan *Message, 16)
|
||||||
p.myTopics[sub.topic] = resp
|
p.myTopics[sub.topic] = resp
|
||||||
sub.resp <- resp
|
sub.resp <- resp
|
||||||
out.Type = &AddSubMessageType
|
} else {
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ch)
|
||||||
|
delete(p.myTopics, sub.topic)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
out := &RPC{
|
||||||
p.outgoing <- out
|
RPC: pb.RPC{
|
||||||
}()
|
Subscriptions: []*pb.RPC_SubOpts{
|
||||||
|
&subopt,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, peer := range p.peers {
|
||||||
|
peer <- out
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub) recvMessage(rpc *RPC) error {
|
func (p *PubSub) recvMessage(msg *pb.Message) error {
|
||||||
subch, ok := p.myTopics[rpc.Msg.GetTopic()]
|
if len(msg.GetTopicIDs()) > 1 {
|
||||||
|
return fmt.Errorf("Dont yet handle multiple topics per message")
|
||||||
|
}
|
||||||
|
if len(msg.GetTopicIDs()) == 0 {
|
||||||
|
return fmt.Errorf("no topic on received message")
|
||||||
|
}
|
||||||
|
|
||||||
|
topic := msg.GetTopicIDs()[0]
|
||||||
|
subch, ok := p.myTopics[topic]
|
||||||
if ok {
|
if ok {
|
||||||
//fmt.Println("writing out to subscriber!")
|
subch <- &Message{msg}
|
||||||
subch <- &Message{rpc.Msg}
|
} else {
|
||||||
|
log.Error("received message we we'rent subscribed to")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PubSub) seenMessage(id string) bool {
|
||||||
|
return p.seenMessages.Has(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PubSub) markSeen(id string) {
|
||||||
|
p.seenMessages.Add(id)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PubSub) handleIncomingRPC(rpc *RPC) error {
|
func (p *PubSub) handleIncomingRPC(rpc *RPC) error {
|
||||||
switch rpc.GetType() {
|
for _, subopt := range rpc.GetSubscriptions() {
|
||||||
case AddSubMessageType:
|
t := subopt.GetTopicid()
|
||||||
for _, t := range rpc.Topics {
|
if subopt.GetSubscribe() {
|
||||||
tmap, ok := p.topics[t]
|
tmap, ok := p.topics[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
tmap = make(map[peer.ID]struct{})
|
tmap = make(map[peer.ID]struct{})
|
||||||
|
@ -266,28 +286,22 @@ func (p *PubSub) handleIncomingRPC(rpc *RPC) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
tmap[rpc.from] = struct{}{}
|
tmap[rpc.from] = struct{}{}
|
||||||
}
|
} else {
|
||||||
case UnsubMessageType:
|
|
||||||
for _, t := range rpc.Topics {
|
|
||||||
tmap, ok := p.topics[t]
|
tmap, ok := p.topics[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
continue
|
||||||
}
|
}
|
||||||
delete(tmap, rpc.from)
|
delete(tmap, rpc.from)
|
||||||
}
|
}
|
||||||
case PubMessageType:
|
}
|
||||||
if rpc.Msg == nil {
|
|
||||||
return fmt.Errorf("nil pub message")
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := &Message{rpc.Msg}
|
for _, pmsg := range rpc.GetPublish() {
|
||||||
|
msg := &Message{pmsg}
|
||||||
|
|
||||||
// Note: Obviously this is an incredibly insecure way of
|
id := msg.Message.GetFrom() + string(msg.GetSeqno())
|
||||||
// filtering out "messages we've already seen". But it works for a
|
|
||||||
// cool demo, so i'm not gonna waste time thinking about it any more
|
if p.seenMessage(id) {
|
||||||
if p.lastMsg[msg.GetFrom()] >= msg.GetSeqno() {
|
continue
|
||||||
//log.Error("skipping 'old' message")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.GetFrom() == p.host.ID() {
|
if msg.GetFrom() == p.host.ID() {
|
||||||
|
@ -295,13 +309,13 @@ func (p *PubSub) handleIncomingRPC(rpc *RPC) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
p.lastMsg[msg.GetFrom()] = msg.GetSeqno()
|
p.markSeen(id)
|
||||||
|
|
||||||
if err := p.recvMessage(rpc); err != nil {
|
if err := p.recvMessage(pmsg); err != nil {
|
||||||
log.Error("error receiving message: ", err)
|
log.Error("error receiving message: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.publishMessage(rpc)
|
err := p.publishMessage(rpc.from, pmsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("publish message: ", err)
|
log.Error("publish message: ", err)
|
||||||
}
|
}
|
||||||
|
@ -309,14 +323,20 @@ func (p *PubSub) handleIncomingRPC(rpc *RPC) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub) publishMessage(rpc *RPC) error {
|
func (p *PubSub) publishMessage(from peer.ID, msg *pb.Message) error {
|
||||||
tmap, ok := p.topics[rpc.Msg.GetTopic()]
|
if len(msg.GetTopicIDs()) != 1 {
|
||||||
|
return fmt.Errorf("don't support publishing to multiple topics in a single message")
|
||||||
|
}
|
||||||
|
|
||||||
|
tmap, ok := p.topics[msg.GetTopicIDs()[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out := &RPC{RPC: pb.RPC{Publish: []*pb.Message{msg}}}
|
||||||
|
|
||||||
for pid, _ := range tmap {
|
for pid, _ := range tmap {
|
||||||
if pid == rpc.from || pid == peer.ID(rpc.Msg.GetFrom()) {
|
if pid == from || pid == peer.ID(msg.GetFrom()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,23 +345,38 @@ func (p *PubSub) publishMessage(rpc *RPC) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() { mch <- rpc }()
|
go func() { mch <- out }()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type addSub struct {
|
type addSub struct {
|
||||||
topic string
|
topic string
|
||||||
cancel bool
|
sub bool
|
||||||
resp chan chan *Message
|
resp chan chan *Message
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub) Subscribe(topic string) (<-chan *Message, error) {
|
func (p *PubSub) Subscribe(topic string) (<-chan *Message, error) {
|
||||||
|
return p.SubscribeComplicated(&pb.TopicDescriptor{
|
||||||
|
Name: proto.String(topic),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PubSub) SubscribeComplicated(td *pb.TopicDescriptor) (<-chan *Message, error) {
|
||||||
|
if td.GetAuth().GetMode() != pb.TopicDescriptor_AuthOpts_NONE {
|
||||||
|
return nil, fmt.Errorf("Auth method not yet supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
if td.GetEnc().GetMode() != pb.TopicDescriptor_EncOpts_NONE {
|
||||||
|
return nil, fmt.Errorf("Encryption method not yet supported")
|
||||||
|
}
|
||||||
|
|
||||||
resp := make(chan chan *Message)
|
resp := make(chan chan *Message)
|
||||||
p.addSub <- &addSub{
|
p.addSub <- &addSub{
|
||||||
topic: topic,
|
topic: td.GetName(),
|
||||||
resp: resp,
|
resp: resp,
|
||||||
|
sub: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
outch := <-resp
|
outch := <-resp
|
||||||
|
@ -354,22 +389,21 @@ func (p *PubSub) Subscribe(topic string) (<-chan *Message, error) {
|
||||||
|
|
||||||
func (p *PubSub) Unsub(topic string) {
|
func (p *PubSub) Unsub(topic string) {
|
||||||
p.addSub <- &addSub{
|
p.addSub <- &addSub{
|
||||||
topic: topic,
|
topic: topic,
|
||||||
cancel: true,
|
sub: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub) Publish(topic string, data []byte) error {
|
func (p *PubSub) Publish(topic string, data []byte) error {
|
||||||
seqno := uint64(time.Now().UnixNano())
|
seqno := make([]byte, 8)
|
||||||
p.outgoing <- &RPC{
|
binary.BigEndian.PutUint64(seqno, uint64(time.Now().UnixNano()))
|
||||||
RPC: pb.RPC{
|
|
||||||
Msg: &pb.Message{
|
p.publish <- &Message{
|
||||||
Data: data,
|
&pb.Message{
|
||||||
Topic: &topic,
|
Data: data,
|
||||||
From: proto.String(string(p.host.ID())),
|
TopicIDs: []string{topic},
|
||||||
Seqno: &seqno,
|
From: proto.String(string(p.host.ID())),
|
||||||
},
|
Seqno: seqno,
|
||||||
Type: &PubMessageType,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
"hash": "QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV",
|
"hash": "QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV",
|
||||||
"name": "gogo-protobuf",
|
"name": "gogo-protobuf",
|
||||||
"version": "0.0.0"
|
"version": "0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "whyrusleeping",
|
||||||
|
"hash": "QmYftoT56eEfUBTD3erR6heXuPSUhGRezSmhSU8LeczP8b",
|
||||||
|
"name": "timecache",
|
||||||
|
"version": "1.0.0"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"gxVersion": "0.9.0",
|
"gxVersion": "0.9.0",
|
||||||
|
|
242
pb/rpc.pb.go
242
pb/rpc.pb.go
|
@ -11,6 +11,7 @@ It is generated from these files:
|
||||||
It has these top-level messages:
|
It has these top-level messages:
|
||||||
RPC
|
RPC
|
||||||
Message
|
Message
|
||||||
|
TopicDescriptor
|
||||||
*/
|
*/
|
||||||
package floodsub_pb
|
package floodsub_pb
|
||||||
|
|
||||||
|
@ -23,44 +24,132 @@ var _ = proto.Marshal
|
||||||
var _ = fmt.Errorf
|
var _ = fmt.Errorf
|
||||||
var _ = math.Inf
|
var _ = math.Inf
|
||||||
|
|
||||||
|
type TopicDescriptor_AuthOpts_AuthMode int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
TopicDescriptor_AuthOpts_NONE TopicDescriptor_AuthOpts_AuthMode = 0
|
||||||
|
TopicDescriptor_AuthOpts_KEY TopicDescriptor_AuthOpts_AuthMode = 1
|
||||||
|
TopicDescriptor_AuthOpts_WOT TopicDescriptor_AuthOpts_AuthMode = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var TopicDescriptor_AuthOpts_AuthMode_name = map[int32]string{
|
||||||
|
0: "NONE",
|
||||||
|
1: "KEY",
|
||||||
|
2: "WOT",
|
||||||
|
}
|
||||||
|
var TopicDescriptor_AuthOpts_AuthMode_value = map[string]int32{
|
||||||
|
"NONE": 0,
|
||||||
|
"KEY": 1,
|
||||||
|
"WOT": 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x TopicDescriptor_AuthOpts_AuthMode) Enum() *TopicDescriptor_AuthOpts_AuthMode {
|
||||||
|
p := new(TopicDescriptor_AuthOpts_AuthMode)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
func (x TopicDescriptor_AuthOpts_AuthMode) String() string {
|
||||||
|
return proto.EnumName(TopicDescriptor_AuthOpts_AuthMode_name, int32(x))
|
||||||
|
}
|
||||||
|
func (x *TopicDescriptor_AuthOpts_AuthMode) UnmarshalJSON(data []byte) error {
|
||||||
|
value, err := proto.UnmarshalJSONEnum(TopicDescriptor_AuthOpts_AuthMode_value, data, "TopicDescriptor_AuthOpts_AuthMode")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*x = TopicDescriptor_AuthOpts_AuthMode(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopicDescriptor_EncOpts_EncMode int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
TopicDescriptor_EncOpts_NONE TopicDescriptor_EncOpts_EncMode = 0
|
||||||
|
TopicDescriptor_EncOpts_SHAREDKEY TopicDescriptor_EncOpts_EncMode = 1
|
||||||
|
TopicDescriptor_EncOpts_WOT TopicDescriptor_EncOpts_EncMode = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var TopicDescriptor_EncOpts_EncMode_name = map[int32]string{
|
||||||
|
0: "NONE",
|
||||||
|
1: "SHAREDKEY",
|
||||||
|
2: "WOT",
|
||||||
|
}
|
||||||
|
var TopicDescriptor_EncOpts_EncMode_value = map[string]int32{
|
||||||
|
"NONE": 0,
|
||||||
|
"SHAREDKEY": 1,
|
||||||
|
"WOT": 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x TopicDescriptor_EncOpts_EncMode) Enum() *TopicDescriptor_EncOpts_EncMode {
|
||||||
|
p := new(TopicDescriptor_EncOpts_EncMode)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
func (x TopicDescriptor_EncOpts_EncMode) String() string {
|
||||||
|
return proto.EnumName(TopicDescriptor_EncOpts_EncMode_name, int32(x))
|
||||||
|
}
|
||||||
|
func (x *TopicDescriptor_EncOpts_EncMode) UnmarshalJSON(data []byte) error {
|
||||||
|
value, err := proto.UnmarshalJSONEnum(TopicDescriptor_EncOpts_EncMode_value, data, "TopicDescriptor_EncOpts_EncMode")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*x = TopicDescriptor_EncOpts_EncMode(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type RPC struct {
|
type RPC struct {
|
||||||
Type *string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
|
Subscriptions []*RPC_SubOpts `protobuf:"bytes,1,rep,name=subscriptions" json:"subscriptions,omitempty"`
|
||||||
Topics []string `protobuf:"bytes,2,rep,name=topics" json:"topics,omitempty"`
|
Publish []*Message `protobuf:"bytes,2,rep,name=publish" json:"publish,omitempty"`
|
||||||
Msg *Message `protobuf:"bytes,3,opt,name=msg" json:"msg,omitempty"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RPC) Reset() { *m = RPC{} }
|
func (m *RPC) Reset() { *m = RPC{} }
|
||||||
func (m *RPC) String() string { return proto.CompactTextString(m) }
|
func (m *RPC) String() string { return proto.CompactTextString(m) }
|
||||||
func (*RPC) ProtoMessage() {}
|
func (*RPC) ProtoMessage() {}
|
||||||
|
|
||||||
func (m *RPC) GetType() string {
|
func (m *RPC) GetSubscriptions() []*RPC_SubOpts {
|
||||||
if m != nil && m.Type != nil {
|
if m != nil {
|
||||||
return *m.Type
|
return m.Subscriptions
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *RPC) GetPublish() []*Message {
|
||||||
|
if m != nil {
|
||||||
|
return m.Publish
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type RPC_SubOpts struct {
|
||||||
|
Subscribe *bool `protobuf:"varint,1,opt,name=subscribe" json:"subscribe,omitempty"`
|
||||||
|
Topicid *string `protobuf:"bytes,2,opt,name=topicid" json:"topicid,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *RPC_SubOpts) Reset() { *m = RPC_SubOpts{} }
|
||||||
|
func (m *RPC_SubOpts) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*RPC_SubOpts) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (m *RPC_SubOpts) GetSubscribe() bool {
|
||||||
|
if m != nil && m.Subscribe != nil {
|
||||||
|
return *m.Subscribe
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *RPC_SubOpts) GetTopicid() string {
|
||||||
|
if m != nil && m.Topicid != nil {
|
||||||
|
return *m.Topicid
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RPC) GetTopics() []string {
|
|
||||||
if m != nil {
|
|
||||||
return m.Topics
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *RPC) GetMsg() *Message {
|
|
||||||
if m != nil {
|
|
||||||
return m.Msg
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
From *string `protobuf:"bytes,1,opt,name=from" json:"from,omitempty"`
|
From *string `protobuf:"bytes,1,opt,name=from" json:"from,omitempty"`
|
||||||
Data []byte `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
|
Data []byte `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
|
||||||
Seqno *uint64 `protobuf:"varint,3,opt,name=seqno" json:"seqno,omitempty"`
|
Seqno []byte `protobuf:"bytes,3,opt,name=seqno" json:"seqno,omitempty"`
|
||||||
Topic *string `protobuf:"bytes,4,opt,name=topic" json:"topic,omitempty"`
|
TopicIDs []string `protobuf:"bytes,4,rep,name=topicIDs" json:"topicIDs,omitempty"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) Reset() { *m = Message{} }
|
func (m *Message) Reset() { *m = Message{} }
|
||||||
|
@ -81,21 +170,108 @@ func (m *Message) GetData() []byte {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) GetSeqno() uint64 {
|
func (m *Message) GetSeqno() []byte {
|
||||||
if m != nil && m.Seqno != nil {
|
if m != nil {
|
||||||
return *m.Seqno
|
return m.Seqno
|
||||||
}
|
}
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) GetTopic() string {
|
func (m *Message) GetTopicIDs() []string {
|
||||||
if m != nil && m.Topic != nil {
|
if m != nil {
|
||||||
return *m.Topic
|
return m.TopicIDs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// topicID = hash(topicDescriptor); (not the topic.name)
|
||||||
|
type TopicDescriptor struct {
|
||||||
|
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||||
|
Auth *TopicDescriptor_AuthOpts `protobuf:"bytes,2,opt,name=auth" json:"auth,omitempty"`
|
||||||
|
Enc *TopicDescriptor_EncOpts `protobuf:"bytes,3,opt,name=enc" json:"enc,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor) Reset() { *m = TopicDescriptor{} }
|
||||||
|
func (m *TopicDescriptor) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*TopicDescriptor) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor) GetName() string {
|
||||||
|
if m != nil && m.Name != nil {
|
||||||
|
return *m.Name
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor) GetAuth() *TopicDescriptor_AuthOpts {
|
||||||
|
if m != nil {
|
||||||
|
return m.Auth
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor) GetEnc() *TopicDescriptor_EncOpts {
|
||||||
|
if m != nil {
|
||||||
|
return m.Enc
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopicDescriptor_AuthOpts struct {
|
||||||
|
Mode *TopicDescriptor_AuthOpts_AuthMode `protobuf:"varint,1,opt,name=mode,enum=floodsub.pb.TopicDescriptor_AuthOpts_AuthMode" json:"mode,omitempty"`
|
||||||
|
Keys [][]byte `protobuf:"bytes,2,rep,name=keys" json:"keys,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor_AuthOpts) Reset() { *m = TopicDescriptor_AuthOpts{} }
|
||||||
|
func (m *TopicDescriptor_AuthOpts) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*TopicDescriptor_AuthOpts) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor_AuthOpts) GetMode() TopicDescriptor_AuthOpts_AuthMode {
|
||||||
|
if m != nil && m.Mode != nil {
|
||||||
|
return *m.Mode
|
||||||
|
}
|
||||||
|
return TopicDescriptor_AuthOpts_NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor_AuthOpts) GetKeys() [][]byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Keys
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopicDescriptor_EncOpts struct {
|
||||||
|
Mode *TopicDescriptor_EncOpts_EncMode `protobuf:"varint,1,opt,name=mode,enum=floodsub.pb.TopicDescriptor_EncOpts_EncMode" json:"mode,omitempty"`
|
||||||
|
KeyHashes [][]byte `protobuf:"bytes,2,rep,name=keyHashes" json:"keyHashes,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor_EncOpts) Reset() { *m = TopicDescriptor_EncOpts{} }
|
||||||
|
func (m *TopicDescriptor_EncOpts) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*TopicDescriptor_EncOpts) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor_EncOpts) GetMode() TopicDescriptor_EncOpts_EncMode {
|
||||||
|
if m != nil && m.Mode != nil {
|
||||||
|
return *m.Mode
|
||||||
|
}
|
||||||
|
return TopicDescriptor_EncOpts_NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TopicDescriptor_EncOpts) GetKeyHashes() [][]byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.KeyHashes
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*RPC)(nil), "floodsub.pb.RPC")
|
proto.RegisterType((*RPC)(nil), "floodsub.pb.RPC")
|
||||||
|
proto.RegisterType((*RPC_SubOpts)(nil), "floodsub.pb.RPC.SubOpts")
|
||||||
proto.RegisterType((*Message)(nil), "floodsub.pb.Message")
|
proto.RegisterType((*Message)(nil), "floodsub.pb.Message")
|
||||||
|
proto.RegisterType((*TopicDescriptor)(nil), "floodsub.pb.TopicDescriptor")
|
||||||
|
proto.RegisterType((*TopicDescriptor_AuthOpts)(nil), "floodsub.pb.TopicDescriptor.AuthOpts")
|
||||||
|
proto.RegisterType((*TopicDescriptor_EncOpts)(nil), "floodsub.pb.TopicDescriptor.EncOpts")
|
||||||
|
proto.RegisterEnum("floodsub.pb.TopicDescriptor_AuthOpts_AuthMode", TopicDescriptor_AuthOpts_AuthMode_name, TopicDescriptor_AuthOpts_AuthMode_value)
|
||||||
|
proto.RegisterEnum("floodsub.pb.TopicDescriptor_EncOpts_EncMode", TopicDescriptor_EncOpts_EncMode_name, TopicDescriptor_EncOpts_EncMode_value)
|
||||||
}
|
}
|
||||||
|
|
45
pb/rpc.proto
45
pb/rpc.proto
|
@ -1,20 +1,47 @@
|
||||||
package floodsub.pb;
|
package floodsub.pb;
|
||||||
|
|
||||||
message RPC {
|
message RPC {
|
||||||
optional string type = 1;
|
repeated SubOpts subscriptions = 1;
|
||||||
|
repeated Message publish = 2;
|
||||||
|
|
||||||
repeated string topics = 2;
|
message SubOpts {
|
||||||
|
optional bool subscribe = 1; // subscribe or unsubcribe
|
||||||
optional Message msg = 3;
|
optional string topicid = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message Message {
|
message Message {
|
||||||
optional string from = 1;
|
optional string from = 1;
|
||||||
|
|
||||||
optional bytes data = 2;
|
optional bytes data = 2;
|
||||||
|
optional bytes seqno = 3;
|
||||||
optional uint64 seqno = 3;
|
repeated string topicIDs = 4;
|
||||||
|
|
||||||
optional string topic = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// topicID = hash(topicDescriptor); (not the topic.name)
|
||||||
|
message TopicDescriptor {
|
||||||
|
optional string name = 1;
|
||||||
|
optional AuthOpts auth = 2;
|
||||||
|
optional EncOpts enc = 3;
|
||||||
|
|
||||||
|
message AuthOpts {
|
||||||
|
optional AuthMode mode = 1;
|
||||||
|
repeated bytes keys = 2; // root keys to trust
|
||||||
|
|
||||||
|
enum AuthMode {
|
||||||
|
NONE = 0; // no authentication, anyone can publish
|
||||||
|
KEY = 1; // only messages signed by keys in the topic descriptor are accepted
|
||||||
|
WOT = 2; // web of trust, certificates can allow publisher set to grow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message EncOpts {
|
||||||
|
optional EncMode mode = 1;
|
||||||
|
repeated bytes keyHashes = 2; // the hashes of the shared keys used (salted)
|
||||||
|
|
||||||
|
enum EncMode {
|
||||||
|
NONE = 0; // no encryption, anyone can read
|
||||||
|
SHAREDKEY = 1; // messages are encrypted with shared key
|
||||||
|
WOT = 2; // web of trust, certificates can allow publisher set to grow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue