github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/pss/protocol.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:48</date>
    10  //</624342678011645952>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  //
    29  
    30  package pss
    31  
    32  import (
    33  	"bytes"
    34  	"fmt"
    35  	"sync"
    36  	"time"
    37  
    38  	"github.com/ethereum/go-ethereum/p2p"
    39  	"github.com/ethereum/go-ethereum/p2p/protocols"
    40  	"github.com/ethereum/go-ethereum/rlp"
    41  	"github.com/ethereum/go-ethereum/swarm/log"
    42  )
    43  
    44  const (
    45  	IsActiveProtocol = true
    46  )
    47  
    48  //
    49  type ProtocolMsg struct {
    50  	Code       uint64
    51  	Size       uint32
    52  	Payload    []byte
    53  	ReceivedAt time.Time
    54  }
    55  
    56  //
    57  func NewProtocolMsg(code uint64, msg interface{}) ([]byte, error) {
    58  
    59  	rlpdata, err := rlp.EncodeToBytes(msg)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  //
    65  	smsg := &ProtocolMsg{
    66  		Code:    code,
    67  		Size:    uint32(len(rlpdata)),
    68  		Payload: rlpdata,
    69  	}
    70  
    71  	return rlp.EncodeToBytes(smsg)
    72  }
    73  
    74  //
    75  //
    76  //
    77  type ProtocolParams struct {
    78  	Asymmetric bool
    79  	Symmetric  bool
    80  }
    81  
    82  //
    83  //
    84  //
    85  type PssReadWriter struct {
    86  	*Pss
    87  	LastActive time.Time
    88  	rw         chan p2p.Msg
    89  	spec       *protocols.Spec
    90  	topic      *Topic
    91  	sendFunc   func(string, Topic, []byte) error
    92  	key        string
    93  	closed     bool
    94  }
    95  
    96  //
    97  func (prw *PssReadWriter) ReadMsg() (p2p.Msg, error) {
    98  	msg := <-prw.rw
    99  	log.Trace(fmt.Sprintf("pssrw readmsg: %v", msg))
   100  	return msg, nil
   101  }
   102  
   103  //
   104  func (prw *PssReadWriter) WriteMsg(msg p2p.Msg) error {
   105  	log.Trace("pssrw writemsg", "msg", msg)
   106  	if prw.closed {
   107  		return fmt.Errorf("connection closed")
   108  	}
   109  	rlpdata := make([]byte, msg.Size)
   110  	msg.Payload.Read(rlpdata)
   111  	pmsg, err := rlp.EncodeToBytes(ProtocolMsg{
   112  		Code:    msg.Code,
   113  		Size:    msg.Size,
   114  		Payload: rlpdata,
   115  	})
   116  	if err != nil {
   117  		return err
   118  	}
   119  	return prw.sendFunc(prw.key, *prw.topic, pmsg)
   120  }
   121  
   122  //
   123  func (prw *PssReadWriter) injectMsg(msg p2p.Msg) error {
   124  	log.Trace(fmt.Sprintf("pssrw injectmsg: %v", msg))
   125  	prw.rw <- msg
   126  	return nil
   127  }
   128  
   129  //
   130  type Protocol struct {
   131  	*Pss
   132  	proto        *p2p.Protocol
   133  	topic        *Topic
   134  	spec         *protocols.Spec
   135  	pubKeyRWPool map[string]p2p.MsgReadWriter
   136  	symKeyRWPool map[string]p2p.MsgReadWriter
   137  	Asymmetric   bool
   138  	Symmetric    bool
   139  	RWPoolMu     sync.Mutex
   140  }
   141  
   142  //
   143  //
   144  //
   145  //
   146  //
   147  //
   148  func RegisterProtocol(ps *Pss, topic *Topic, spec *protocols.Spec, targetprotocol *p2p.Protocol, options *ProtocolParams) (*Protocol, error) {
   149  	if !options.Asymmetric && !options.Symmetric {
   150  		return nil, fmt.Errorf("specify at least one of asymmetric or symmetric messaging mode")
   151  	}
   152  	pp := &Protocol{
   153  		Pss:          ps,
   154  		proto:        targetprotocol,
   155  		topic:        topic,
   156  		spec:         spec,
   157  		pubKeyRWPool: make(map[string]p2p.MsgReadWriter),
   158  		symKeyRWPool: make(map[string]p2p.MsgReadWriter),
   159  		Asymmetric:   options.Asymmetric,
   160  		Symmetric:    options.Symmetric,
   161  	}
   162  	return pp, nil
   163  }
   164  
   165  //
   166  //
   167  //
   168  //
   169  //
   170  //
   171  //
   172  //
   173  //
   174  //
   175  //
   176  func (p *Protocol) Handle(msg []byte, peer *p2p.Peer, asymmetric bool, keyid string) error {
   177  	var vrw *PssReadWriter
   178  	if p.Asymmetric != asymmetric && p.Symmetric == !asymmetric {
   179  		return fmt.Errorf("invalid protocol encryption")
   180  	} else if (!p.isActiveSymKey(keyid, *p.topic) && !asymmetric) ||
   181  		(!p.isActiveAsymKey(keyid, *p.topic) && asymmetric) {
   182  
   183  		rw, err := p.AddPeer(peer, *p.topic, asymmetric, keyid)
   184  		if err != nil {
   185  			return err
   186  		} else if rw == nil {
   187  			return fmt.Errorf("handle called on nil MsgReadWriter for new key " + keyid)
   188  		}
   189  		vrw = rw.(*PssReadWriter)
   190  	}
   191  
   192  	pmsg, err := ToP2pMsg(msg)
   193  	if err != nil {
   194  		return fmt.Errorf("could not decode pssmsg")
   195  	}
   196  	if asymmetric {
   197  		if p.pubKeyRWPool[keyid] == nil {
   198  			return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid)
   199  		}
   200  		vrw = p.pubKeyRWPool[keyid].(*PssReadWriter)
   201  	} else {
   202  		if p.symKeyRWPool[keyid] == nil {
   203  			return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid)
   204  		}
   205  		vrw = p.symKeyRWPool[keyid].(*PssReadWriter)
   206  	}
   207  	vrw.injectMsg(pmsg)
   208  	return nil
   209  }
   210  
   211  //
   212  func (p *Protocol) isActiveSymKey(key string, topic Topic) bool {
   213  	return p.symKeyRWPool[key] != nil
   214  }
   215  
   216  //
   217  func (p *Protocol) isActiveAsymKey(key string, topic Topic) bool {
   218  	return p.pubKeyRWPool[key] != nil
   219  }
   220  
   221  //
   222  func ToP2pMsg(msg []byte) (p2p.Msg, error) {
   223  	payload := &ProtocolMsg{}
   224  	if err := rlp.DecodeBytes(msg, payload); err != nil {
   225  		return p2p.Msg{}, fmt.Errorf("pss protocol handler unable to decode payload as p2p message: %v", err)
   226  	}
   227  
   228  	return p2p.Msg{
   229  		Code:       payload.Code,
   230  		Size:       uint32(len(payload.Payload)),
   231  		ReceivedAt: time.Now(),
   232  		Payload:    bytes.NewBuffer(payload.Payload),
   233  	}, nil
   234  }
   235  
   236  //
   237  //
   238  //
   239  //
   240  //
   241  func (p *Protocol) AddPeer(peer *p2p.Peer, topic Topic, asymmetric bool, key string) (p2p.MsgReadWriter, error) {
   242  	rw := &PssReadWriter{
   243  		Pss:   p.Pss,
   244  		rw:    make(chan p2p.Msg),
   245  		spec:  p.spec,
   246  		topic: p.topic,
   247  		key:   key,
   248  	}
   249  	if asymmetric {
   250  		rw.sendFunc = p.Pss.SendAsym
   251  	} else {
   252  		rw.sendFunc = p.Pss.SendSym
   253  	}
   254  	if asymmetric {
   255  		p.Pss.pubKeyPoolMu.Lock()
   256  		if _, ok := p.Pss.pubKeyPool[key]; !ok {
   257  			return nil, fmt.Errorf("asym key does not exist: %s", key)
   258  		}
   259  		p.Pss.pubKeyPoolMu.Unlock()
   260  		p.RWPoolMu.Lock()
   261  		p.pubKeyRWPool[key] = rw
   262  		p.RWPoolMu.Unlock()
   263  	} else {
   264  		p.Pss.symKeyPoolMu.Lock()
   265  		if _, ok := p.Pss.symKeyPool[key]; !ok {
   266  			return nil, fmt.Errorf("symkey does not exist: %s", key)
   267  		}
   268  		p.Pss.symKeyPoolMu.Unlock()
   269  		p.RWPoolMu.Lock()
   270  		p.symKeyRWPool[key] = rw
   271  		p.RWPoolMu.Unlock()
   272  	}
   273  	go func() {
   274  		err := p.proto.Run(peer, rw)
   275  		log.Warn(fmt.Sprintf("pss vprotocol quit on %v topic %v: %v", peer, topic, err))
   276  	}()
   277  	return rw, nil
   278  }
   279  
   280  func (p *Protocol) RemovePeer(asymmetric bool, key string) {
   281  	log.Debug("closing pss peer", "asym", asymmetric, "key", key)
   282  	p.RWPoolMu.Lock()
   283  	defer p.RWPoolMu.Unlock()
   284  	if asymmetric {
   285  		rw := p.pubKeyRWPool[key].(*PssReadWriter)
   286  		rw.closed = true
   287  		delete(p.pubKeyRWPool, key)
   288  	} else {
   289  		rw := p.symKeyRWPool[key].(*PssReadWriter)
   290  		rw.closed = true
   291  		delete(p.symKeyRWPool, key)
   292  	}
   293  }
   294  
   295  //
   296  func ProtocolTopic(spec *protocols.Spec) Topic {
   297  	return BytesToTopic([]byte(fmt.Sprintf("%s:%d", spec.Name, spec.Version)))
   298  }
   299