go-ethereum/swarm/network/pssapi.go
nolash d5daa9a323 swarm/network: event feed/websockets pss msg notification
Adds pub/sub of incoming Pss messages using event.Feed,
and a websockets interface for pss send and notifications
through persistent connection using rpc.notifier.

Websocket RPC are started automatically on the swarm executable
if the --pss flag is present. If more instances are to be run,
alternate ws ports can be specified with the --pssport flag.

Current implementation also includes a shallow builtin ping/pong handler
with topic "pss" and version 1, to simplify POCs and testing against pss.
This will eventually be removed, so no code should be made dependent on it.
2017-05-06 14:25:00 +01:00

66 lines
1.5 KiB
Go

package network
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
)
type PssApi struct {
*Pss
}
func NewPssApi(ps *Pss) *PssApi {
return &PssApi{Pss: ps}
}
func (self *PssApi) NewMsg(ctx context.Context, topic PssTopic) (*rpc.Subscription, error) {
notifier, supported := rpc.NotifierFromContext(ctx)
if !supported {
return nil, fmt.Errorf("Subscribe not supported")
}
sub := notifier.CreateSubscription()
ch := make(chan []byte)
psssub, err := self.Pss.Subscribe(&topic, ch)
if err != nil {
return nil, fmt.Errorf("pss subscription topic %v (rpc sub id %v) failed: %v", topic, sub.ID, err)
}
go func(topic PssTopic) error {
for {
select {
case msg := <-ch:
if err := notifier.Notify(sub.ID, msg); err != nil {
log.Warn(fmt.Sprintf("notification on pss sub topic %v rpc (sub %v) msg %v failed!", topic, sub.ID, msg))
return err
}
case err := <-psssub.Err():
log.Warn(fmt.Sprintf("caught subscription error in pss sub topic: %v", topic, err))
return err
case <-notifier.Closed():
log.Warn(fmt.Sprintf("rpc sub notifier closed"))
psssub.Unsubscribe()
return nil
case err := <-sub.Err():
log.Warn(fmt.Sprintf("rpc sub closed: %v", err))
psssub.Unsubscribe()
return nil
}
}
return nil
}(topic)
return sub, nil
}
func (self *PssApi) SendRaw(to []byte, topic PssTopic, msg []byte) error {
err := self.Pss.Send(to, topic, msg)
if err != nil {
return fmt.Errorf("send error: %v", err)
}
return fmt.Errorf("ok sent")
}