github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/client/client.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  //
    26  
    27  package client
    28  
    29  import (
    30  	"context"
    31  	"errors"
    32  	"fmt"
    33  	"sync"
    34  	"time"
    35  
    36  	"github.com/ethereum/go-ethereum/common/hexutil"
    37  	"github.com/ethereum/go-ethereum/p2p"
    38  	"github.com/ethereum/go-ethereum/p2p/discover"
    39  	"github.com/ethereum/go-ethereum/p2p/protocols"
    40  	"github.com/ethereum/go-ethereum/rlp"
    41  	"github.com/ethereum/go-ethereum/rpc"
    42  	"github.com/ethereum/go-ethereum/swarm/log"
    43  	"github.com/ethereum/go-ethereum/swarm/pss"
    44  )
    45  
    46  const (
    47  	handshakeRetryTimeout = 1000
    48  	handshakeRetryCount   = 3
    49  )
    50  
    51  //
    52  //
    53  type Client struct {
    54  	BaseAddrHex string
    55  
    56  //
    57  	peerPool map[pss.Topic]map[string]*pssRPCRW
    58  	protos   map[pss.Topic]*p2p.Protocol
    59  
    60  //
    61  	rpc  *rpc.Client
    62  	subs []*rpc.ClientSubscription
    63  
    64  //
    65  	topicsC chan []byte
    66  	quitC   chan struct{}
    67  
    68  	poolMu sync.Mutex
    69  }
    70  
    71  //
    72  type pssRPCRW struct {
    73  	*Client
    74  	topic    string
    75  	msgC     chan []byte
    76  	addr     pss.PssAddress
    77  	pubKeyId string
    78  	lastSeen time.Time
    79  	closed   bool
    80  }
    81  
    82  func (c *Client) newpssRPCRW(pubkeyid string, addr pss.PssAddress, topicobj pss.Topic) (*pssRPCRW, error) {
    83  	topic := topicobj.String()
    84  	err := c.rpc.Call(nil, "pss_setPeerPublicKey", pubkeyid, topic, hexutil.Encode(addr[:]))
    85  	if err != nil {
    86  		return nil, fmt.Errorf("setpeer %s %s: %v", topic, pubkeyid, err)
    87  	}
    88  	return &pssRPCRW{
    89  		Client:   c,
    90  		topic:    topic,
    91  		msgC:     make(chan []byte),
    92  		addr:     addr,
    93  		pubKeyId: pubkeyid,
    94  	}, nil
    95  }
    96  
    97  func (rw *pssRPCRW) ReadMsg() (p2p.Msg, error) {
    98  	msg := <-rw.msgC
    99  	log.Trace("pssrpcrw read", "msg", msg)
   100  	pmsg, err := pss.ToP2pMsg(msg)
   101  	if err != nil {
   102  		return p2p.Msg{}, err
   103  	}
   104  
   105  	return pmsg, nil
   106  }
   107  
   108  //
   109  //
   110  //
   111  //
   112  //
   113  //
   114  //
   115  //
   116  func (rw *pssRPCRW) WriteMsg(msg p2p.Msg) error {
   117  	log.Trace("got writemsg pssclient", "msg", msg)
   118  	if rw.closed {
   119  		return fmt.Errorf("connection closed")
   120  	}
   121  	rlpdata := make([]byte, msg.Size)
   122  	msg.Payload.Read(rlpdata)
   123  	pmsg, err := rlp.EncodeToBytes(pss.ProtocolMsg{
   124  		Code:    msg.Code,
   125  		Size:    msg.Size,
   126  		Payload: rlpdata,
   127  	})
   128  	if err != nil {
   129  		return err
   130  	}
   131  
   132  //
   133  	var symkeyids []string
   134  	err = rw.Client.rpc.Call(&symkeyids, "pss_getHandshakeKeys", rw.pubKeyId, rw.topic, false, true)
   135  	if err != nil {
   136  		return err
   137  	}
   138  
   139  //
   140  	var symkeycap uint16
   141  	if len(symkeyids) > 0 {
   142  		err = rw.Client.rpc.Call(&symkeycap, "pss_getHandshakeKeyCapacity", symkeyids[0])
   143  		if err != nil {
   144  			return err
   145  		}
   146  	}
   147  
   148  	err = rw.Client.rpc.Call(nil, "pss_sendSym", symkeyids[0], rw.topic, hexutil.Encode(pmsg))
   149  	if err != nil {
   150  		return err
   151  	}
   152  
   153  //
   154  	if symkeycap == 1 {
   155  		var retries int
   156  		var sync bool
   157  //
   158  		if len(symkeyids) == 1 {
   159  			sync = true
   160  		}
   161  //
   162  		_, err := rw.handshake(retries, sync, false)
   163  		if err != nil {
   164  			log.Warn("failing", "err", err)
   165  			return err
   166  		}
   167  	}
   168  	return nil
   169  }
   170  
   171  //
   172  //
   173  func (rw *pssRPCRW) handshake(retries int, sync bool, flush bool) (string, error) {
   174  
   175  	var symkeyids []string
   176  	var i int
   177  //
   178  //
   179  	for i = 0; i < 1+retries; i++ {
   180  		log.Debug("handshake attempt pssrpcrw", "pubkeyid", rw.pubKeyId, "topic", rw.topic, "sync", sync)
   181  		err := rw.Client.rpc.Call(&symkeyids, "pss_handshake", rw.pubKeyId, rw.topic, sync, flush)
   182  		if err == nil {
   183  			var keyid string
   184  			if sync {
   185  				keyid = symkeyids[0]
   186  			}
   187  			return keyid, nil
   188  		}
   189  		if i-1+retries > 1 {
   190  			time.Sleep(time.Millisecond * handshakeRetryTimeout)
   191  		}
   192  	}
   193  
   194  	return "", fmt.Errorf("handshake failed after %d attempts", i)
   195  }
   196  
   197  //
   198  //
   199  //
   200  func NewClient(rpcurl string) (*Client, error) {
   201  	rpcclient, err := rpc.Dial(rpcurl)
   202  	if err != nil {
   203  		return nil, err
   204  	}
   205  
   206  	client, err := NewClientWithRPC(rpcclient)
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  	return client, nil
   211  }
   212  
   213  //
   214  //
   215  //
   216  func NewClientWithRPC(rpcclient *rpc.Client) (*Client, error) {
   217  	client := newClient()
   218  	client.rpc = rpcclient
   219  	err := client.rpc.Call(&client.BaseAddrHex, "pss_baseAddr")
   220  	if err != nil {
   221  		return nil, fmt.Errorf("cannot get pss node baseaddress: %v", err)
   222  	}
   223  	return client, nil
   224  }
   225  
   226  func newClient() (client *Client) {
   227  	client = &Client{
   228  		quitC:    make(chan struct{}),
   229  		peerPool: make(map[pss.Topic]map[string]*pssRPCRW),
   230  		protos:   make(map[pss.Topic]*p2p.Protocol),
   231  	}
   232  	return
   233  }
   234  
   235  //
   236  //
   237  //
   238  //
   239  //
   240  //
   241  //
   242  func (c *Client) RunProtocol(ctx context.Context, proto *p2p.Protocol) error {
   243  	topicobj := pss.BytesToTopic([]byte(fmt.Sprintf("%s:%d", proto.Name, proto.Version)))
   244  	topichex := topicobj.String()
   245  	msgC := make(chan pss.APIMsg)
   246  	c.peerPool[topicobj] = make(map[string]*pssRPCRW)
   247  	sub, err := c.rpc.Subscribe(ctx, "pss", msgC, "receive", topichex)
   248  	if err != nil {
   249  		return fmt.Errorf("pss event subscription failed: %v", err)
   250  	}
   251  	c.subs = append(c.subs, sub)
   252  	err = c.rpc.Call(nil, "pss_addHandshake", topichex)
   253  	if err != nil {
   254  		return fmt.Errorf("pss handshake activation failed: %v", err)
   255  	}
   256  
   257  //
   258  	go func() {
   259  		for {
   260  			select {
   261  			case msg := <-msgC:
   262  //
   263  				if msg.Asymmetric {
   264  					continue
   265  				}
   266  //
   267  //
   268  				var pubkeyid string
   269  				err = c.rpc.Call(&pubkeyid, "pss_getHandshakePublicKey", msg.Key)
   270  				if err != nil || pubkeyid == "" {
   271  					log.Trace("proto err or no pubkey", "err", err, "symkeyid", msg.Key)
   272  					continue
   273  				}
   274  //
   275  //
   276  				if c.peerPool[topicobj][pubkeyid] == nil {
   277  					var addrhex string
   278  					err := c.rpc.Call(&addrhex, "pss_getAddress", topichex, false, msg.Key)
   279  					if err != nil {
   280  						log.Trace(err.Error())
   281  						continue
   282  					}
   283  					addrbytes, err := hexutil.Decode(addrhex)
   284  					if err != nil {
   285  						log.Trace(err.Error())
   286  						break
   287  					}
   288  					addr := pss.PssAddress(addrbytes)
   289  					rw, err := c.newpssRPCRW(pubkeyid, addr, topicobj)
   290  					if err != nil {
   291  						break
   292  					}
   293  					c.peerPool[topicobj][pubkeyid] = rw
   294  					nid, _ := discover.HexID("0x00")
   295  					p := p2p.NewPeer(nid, fmt.Sprintf("%v", addr), []p2p.Cap{})
   296  					go proto.Run(p, c.peerPool[topicobj][pubkeyid])
   297  				}
   298  				go func() {
   299  					c.peerPool[topicobj][pubkeyid].msgC <- msg.Msg
   300  				}()
   301  			case <-c.quitC:
   302  				return
   303  			}
   304  		}
   305  	}()
   306  
   307  	c.protos[topicobj] = proto
   308  	return nil
   309  }
   310  
   311  //
   312  func (c *Client) Close() error {
   313  	for _, s := range c.subs {
   314  		s.Unsubscribe()
   315  	}
   316  	return nil
   317  }
   318  
   319  //
   320  //
   321  //
   322  //
   323  //
   324  //
   325  //
   326  //
   327  //
   328  func (c *Client) AddPssPeer(pubkeyid string, addr []byte, spec *protocols.Spec) error {
   329  	topic := pss.ProtocolTopic(spec)
   330  	if c.peerPool[topic] == nil {
   331  		return errors.New("addpeer on unset topic")
   332  	}
   333  	if c.peerPool[topic][pubkeyid] == nil {
   334  		rw, err := c.newpssRPCRW(pubkeyid, addr, topic)
   335  		if err != nil {
   336  			return err
   337  		}
   338  		_, err = rw.handshake(handshakeRetryCount, true, true)
   339  		if err != nil {
   340  			return err
   341  		}
   342  		c.poolMu.Lock()
   343  		c.peerPool[topic][pubkeyid] = rw
   344  		c.poolMu.Unlock()
   345  		nid, _ := discover.HexID("0x00")
   346  		p := p2p.NewPeer(nid, fmt.Sprintf("%v", addr), []p2p.Cap{})
   347  		go c.protos[topic].Run(p, c.peerPool[topic][pubkeyid])
   348  	}
   349  	return nil
   350  }
   351  
   352  //
   353  //
   354  //
   355  func (c *Client) RemovePssPeer(pubkeyid string, spec *protocols.Spec) {
   356  	log.Debug("closing pss client peer", "pubkey", pubkeyid, "protoname", spec.Name, "protoversion", spec.Version)
   357  	c.poolMu.Lock()
   358  	defer c.poolMu.Unlock()
   359  	topic := pss.ProtocolTopic(spec)
   360  	c.peerPool[topic][pubkeyid].closed = true
   361  	delete(c.peerPool[topic], pubkeyid)
   362  }