github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/rpc/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  //版权所有2016 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package rpc
    26  
    27  import (
    28  	"bytes"
    29  	"container/list"
    30  	"context"
    31  	"encoding/json"
    32  	"errors"
    33  	"fmt"
    34  	"net"
    35  	"net/url"
    36  	"os"
    37  	"reflect"
    38  	"strconv"
    39  	"strings"
    40  	"sync"
    41  	"sync/atomic"
    42  	"time"
    43  
    44  	"github.com/ethereum/go-ethereum/log"
    45  )
    46  
    47  var (
    48  	ErrClientQuit                = errors.New("client is closed")
    49  	ErrNoResult                  = errors.New("no result in JSON-RPC response")
    50  	ErrSubscriptionQueueOverflow = errors.New("subscription queue overflow")
    51  )
    52  
    53  const (
    54  //超时
    55  	tcpKeepAliveInterval = 30 * time.Second
    56  defaultDialTimeout   = 10 * time.Second //如果上下文没有截止时间,则在拨号时使用
    57  defaultWriteTimeout  = 10 * time.Second //如果上下文没有截止时间,则用于调用
    58  subscribeTimeout     = 5 * time.Second  //总超时eth_subscribe,rpc_模块调用
    59  )
    60  
    61  const (
    62  //当订阅服务器无法跟上时,将删除订阅。
    63  //
    64  //这可以通过为通道提供足够大的缓冲区来解决,
    65  //但这在文件中可能不方便也很难解释。另一个问题是
    66  //缓冲通道是指即使不需要缓冲区,缓冲区也是静态的。
    67  //大部分时间。
    68  //
    69  //这里采用的方法是维护每个订阅的链表缓冲区
    70  //按需缩小。如果缓冲区达到以下大小,则订阅为
    71  //下降。
    72  	maxClientSubscriptionBuffer = 20000
    73  )
    74  
    75  //batchelem是批处理请求中的元素。
    76  type BatchElem struct {
    77  	Method string
    78  	Args   []interface{}
    79  //结果未显示在此字段中。结果必须设置为
    80  //所需类型的非零指针值,否则响应将为
    81  //丢弃的。
    82  	Result interface{}
    83  //如果服务器返回此请求的错误,或如果
    84  //解组为结果失败。未设置I/O错误。
    85  	Error error
    86  }
    87  
    88  //此类型的值可以是JSON-RPC请求、通知、成功响应或
    89  //错误响应。它是哪一个取决于田地。
    90  type jsonrpcMessage struct {
    91  	Version string          `json:"jsonrpc"`
    92  	ID      json.RawMessage `json:"id,omitempty"`
    93  	Method  string          `json:"method,omitempty"`
    94  	Params  json.RawMessage `json:"params,omitempty"`
    95  	Error   *jsonError      `json:"error,omitempty"`
    96  	Result  json.RawMessage `json:"result,omitempty"`
    97  }
    98  
    99  func (msg *jsonrpcMessage) isNotification() bool {
   100  	return msg.ID == nil && msg.Method != ""
   101  }
   102  
   103  func (msg *jsonrpcMessage) isResponse() bool {
   104  	return msg.hasValidID() && msg.Method == "" && len(msg.Params) == 0
   105  }
   106  
   107  func (msg *jsonrpcMessage) hasValidID() bool {
   108  	return len(msg.ID) > 0 && msg.ID[0] != '{' && msg.ID[0] != '['
   109  }
   110  
   111  func (msg *jsonrpcMessage) String() string {
   112  	b, _ := json.Marshal(msg)
   113  	return string(b)
   114  }
   115  
   116  //客户端表示到RPC服务器的连接。
   117  type Client struct {
   118  	idCounter   uint32
   119  	connectFunc func(ctx context.Context) (net.Conn, error)
   120  	isHTTP      bool
   121  
   122  //WRITECONN只能安全地访问外部调度,使用
   123  //写入锁定保持。通过发送
   124  //请求操作并通过发送发送完成释放。
   125  	writeConn net.Conn
   126  
   127  //派遣
   128  	close       chan struct{}
   129  didQuit     chan struct{}                  //客户端退出时关闭
   130  reconnected chan net.Conn                  //写入/重新连接发送新连接的位置
   131  readErr     chan error                     //读取错误
   132  readResp    chan []*jsonrpcMessage         //读取的有效消息
   133  requestOp   chan *requestOp                //用于注册响应ID
   134  sendDone    chan error                     //信号写入完成,释放写入锁定
   135  respWait    map[string]*requestOp          //主动请求
   136  subs        map[string]*ClientSubscription //活动订阅
   137  }
   138  
   139  type requestOp struct {
   140  	ids  []json.RawMessage
   141  	err  error
   142  resp chan *jsonrpcMessage //接收最多len(id)响应
   143  sub  *ClientSubscription  //仅为ethsubscribe请求设置
   144  }
   145  
   146  func (op *requestOp) wait(ctx context.Context) (*jsonrpcMessage, error) {
   147  	select {
   148  	case <-ctx.Done():
   149  		return nil, ctx.Err()
   150  	case resp := <-op.resp:
   151  		return resp, op.err
   152  	}
   153  }
   154  
   155  //拨号为给定的URL创建新的客户端。
   156  //
   157  //当前支持的URL方案有“http”、“https”、“ws”和“wss”。如果RAWURL是
   158  //没有URL方案的文件名,使用Unix建立本地套接字连接
   159  //支持的平台上的域套接字和Windows上的命名管道。如果你想
   160  //配置传输选项,使用dialHTTP、dialWebSocket或dialIPC。
   161  //
   162  //对于WebSocket连接,原点设置为本地主机名。
   163  //
   164  //如果连接丢失,客户端将自动重新连接。
   165  func Dial(rawurl string) (*Client, error) {
   166  	return DialContext(context.Background(), rawurl)
   167  }
   168  
   169  //DialContext创建一个新的RPC客户端,就像Dial一样。
   170  //
   171  //上下文用于取消或超时初始连接建立。它确实
   172  //不影响与客户的后续交互。
   173  func DialContext(ctx context.Context, rawurl string) (*Client, error) {
   174  	u, err := url.Parse(rawurl)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  	switch u.Scheme {
   179  	case "http", "https":
   180  		return DialHTTP(rawurl)
   181  	case "ws", "wss":
   182  		return DialWebsocket(ctx, rawurl, "")
   183  	case "stdio":
   184  		return DialStdIO(ctx)
   185  	case "":
   186  		return DialIPC(ctx, rawurl)
   187  	default:
   188  		return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme)
   189  	}
   190  }
   191  
   192  type StdIOConn struct{}
   193  
   194  func (io StdIOConn) Read(b []byte) (n int, err error) {
   195  	return os.Stdin.Read(b)
   196  }
   197  
   198  func (io StdIOConn) Write(b []byte) (n int, err error) {
   199  	return os.Stdout.Write(b)
   200  }
   201  
   202  func (io StdIOConn) Close() error {
   203  	return nil
   204  }
   205  
   206  func (io StdIOConn) LocalAddr() net.Addr {
   207  	return &net.UnixAddr{Name: "stdio", Net: "stdio"}
   208  }
   209  
   210  func (io StdIOConn) RemoteAddr() net.Addr {
   211  	return &net.UnixAddr{Name: "stdio", Net: "stdio"}
   212  }
   213  
   214  func (io StdIOConn) SetDeadline(t time.Time) error {
   215  	return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
   216  }
   217  
   218  func (io StdIOConn) SetReadDeadline(t time.Time) error {
   219  	return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
   220  }
   221  
   222  func (io StdIOConn) SetWriteDeadline(t time.Time) error {
   223  	return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
   224  }
   225  func DialStdIO(ctx context.Context) (*Client, error) {
   226  	return newClient(ctx, func(_ context.Context) (net.Conn, error) {
   227  		return StdIOConn{}, nil
   228  	})
   229  }
   230  
   231  func newClient(initctx context.Context, connectFunc func(context.Context) (net.Conn, error)) (*Client, error) {
   232  	conn, err := connectFunc(initctx)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  	_, isHTTP := conn.(*httpConn)
   237  	c := &Client{
   238  		writeConn:   conn,
   239  		isHTTP:      isHTTP,
   240  		connectFunc: connectFunc,
   241  		close:       make(chan struct{}),
   242  		didQuit:     make(chan struct{}),
   243  		reconnected: make(chan net.Conn),
   244  		readErr:     make(chan error),
   245  		readResp:    make(chan []*jsonrpcMessage),
   246  		requestOp:   make(chan *requestOp),
   247  		sendDone:    make(chan error, 1),
   248  		respWait:    make(map[string]*requestOp),
   249  		subs:        make(map[string]*ClientSubscription),
   250  	}
   251  	if !isHTTP {
   252  		go c.dispatch(conn)
   253  	}
   254  	return c, nil
   255  }
   256  
   257  func (c *Client) nextID() json.RawMessage {
   258  	id := atomic.AddUint32(&c.idCounter, 1)
   259  	return []byte(strconv.FormatUint(uint64(id), 10))
   260  }
   261  
   262  //supportedmodules调用rpc_modules方法,检索
   263  //服务器上可用的API。
   264  func (c *Client) SupportedModules() (map[string]string, error) {
   265  	var result map[string]string
   266  	ctx, cancel := context.WithTimeout(context.Background(), subscribeTimeout)
   267  	defer cancel()
   268  	err := c.CallContext(ctx, &result, "rpc_modules")
   269  	return result, err
   270  }
   271  
   272  //CLOSE关闭客户机,中止任何飞行中的请求。
   273  func (c *Client) Close() {
   274  	if c.isHTTP {
   275  		return
   276  	}
   277  	select {
   278  	case c.close <- struct{}{}:
   279  		<-c.didQuit
   280  	case <-c.didQuit:
   281  	}
   282  }
   283  
   284  //调用使用给定的参数执行JSON-RPC调用,并将其解组为
   285  //如果没有发生错误,则返回结果。
   286  //
   287  //结果必须是一个指针,以便包JSON可以解组到其中。你
   288  //也可以传递nil,在这种情况下,结果将被忽略。
   289  func (c *Client) Call(result interface{}, method string, args ...interface{}) error {
   290  	ctx := context.Background()
   291  	return c.CallContext(ctx, result, method, args...)
   292  }
   293  
   294  //callContext使用给定的参数执行JSON-RPC调用。如果上下文是
   295  //在成功返回调用之前取消,callContext立即返回。
   296  //
   297  //结果必须是一个指针,以便包JSON可以解组到其中。你
   298  //也可以传递nil,在这种情况下,结果将被忽略。
   299  func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
   300  	msg, err := c.newMessage(method, args...)
   301  	if err != nil {
   302  		return err
   303  	}
   304  	op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
   305  
   306  	if c.isHTTP {
   307  		err = c.sendHTTP(ctx, op, msg)
   308  	} else {
   309  		err = c.send(ctx, op, msg)
   310  	}
   311  	if err != nil {
   312  		return err
   313  	}
   314  
   315  //调度已接受请求,并将在退出时关闭通道。
   316  	switch resp, err := op.wait(ctx); {
   317  	case err != nil:
   318  		return err
   319  	case resp.Error != nil:
   320  		return resp.Error
   321  	case len(resp.Result) == 0:
   322  		return ErrNoResult
   323  	default:
   324  		return json.Unmarshal(resp.Result, &result)
   325  	}
   326  }
   327  
   328  //批处理调用将所有给定的请求作为单个批处理发送,并等待服务器
   329  //为所有人返回响应。
   330  //
   331  //与调用不同,批调用只返回I/O错误。任何特定于的错误
   332  //通过相应批处理元素的错误字段报告请求。
   333  //
   334  //注意,批处理调用不能在服务器端以原子方式执行。
   335  func (c *Client) BatchCall(b []BatchElem) error {
   336  	ctx := context.Background()
   337  	return c.BatchCallContext(ctx, b)
   338  }
   339  
   340  //批处理调用将所有给定的请求作为单个批处理发送,并等待服务器
   341  //为所有人返回响应。等待持续时间由
   342  //上下文的最后期限。
   343  //
   344  //与callContext不同,batchcallContext只返回已发生的错误
   345  //发送请求时。任何特定于请求的错误都会通过
   346  //对应批处理元素的错误字段。
   347  //
   348  //注意,批处理调用不能在服务器端以原子方式执行。
   349  func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
   350  	msgs := make([]*jsonrpcMessage, len(b))
   351  	op := &requestOp{
   352  		ids:  make([]json.RawMessage, len(b)),
   353  		resp: make(chan *jsonrpcMessage, len(b)),
   354  	}
   355  	for i, elem := range b {
   356  		msg, err := c.newMessage(elem.Method, elem.Args...)
   357  		if err != nil {
   358  			return err
   359  		}
   360  		msgs[i] = msg
   361  		op.ids[i] = msg.ID
   362  	}
   363  
   364  	var err error
   365  	if c.isHTTP {
   366  		err = c.sendBatchHTTP(ctx, op, msgs)
   367  	} else {
   368  		err = c.send(ctx, op, msgs)
   369  	}
   370  
   371  //等待所有响应返回。
   372  	for n := 0; n < len(b) && err == nil; n++ {
   373  		var resp *jsonrpcMessage
   374  		resp, err = op.wait(ctx)
   375  		if err != nil {
   376  			break
   377  		}
   378  //找到与此响应对应的元素。
   379  //由于调度,元素被保证存在
   380  //只向我们的频道发送有效的ID。
   381  		var elem *BatchElem
   382  		for i := range msgs {
   383  			if bytes.Equal(msgs[i].ID, resp.ID) {
   384  				elem = &b[i]
   385  				break
   386  			}
   387  		}
   388  		if resp.Error != nil {
   389  			elem.Error = resp.Error
   390  			continue
   391  		}
   392  		if len(resp.Result) == 0 {
   393  			elem.Error = ErrNoResult
   394  			continue
   395  		}
   396  		elem.Error = json.Unmarshal(resp.Result, elem.Result)
   397  	}
   398  	return err
   399  }
   400  
   401  //ethsubscribe在“eth”名称空间下注册一个订阅。
   402  func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) {
   403  	return c.Subscribe(ctx, "eth", channel, args...)
   404  }
   405  
   406  //shhsubscribe在“shh”名称空间下注册一个订阅。
   407  func (c *Client) ShhSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) {
   408  	return c.Subscribe(ctx, "shh", channel, args...)
   409  }
   410  
   411  //subscribe使用给定的参数调用“<namespace>\u subscribe”方法,
   412  //注册订阅。订阅的服务器通知为
   413  //发送到给定的频道。通道的元素类型必须与
   414  //订阅返回的内容类型应为。
   415  //
   416  //context参数取消设置订阅但没有的RPC请求
   417  //订阅返回后对订阅的影响。
   418  //
   419  //缓慢的订户最终将被删除。客户端缓冲区最多8000个通知
   420  //在考虑用户死亡之前。订阅错误通道将接收
   421  //errSubscriptionQueueOverflow。在通道上使用足够大的缓冲区或确保
   422  //通道通常至少有一个读卡器来防止这个问题。
   423  func (c *Client) Subscribe(ctx context.Context, namespace string, channel interface{}, args ...interface{}) (*ClientSubscription, error) {
   424  //首先检查通道类型。
   425  	chanVal := reflect.ValueOf(channel)
   426  	if chanVal.Kind() != reflect.Chan || chanVal.Type().ChanDir()&reflect.SendDir == 0 {
   427  		panic("first argument to Subscribe must be a writable channel")
   428  	}
   429  	if chanVal.IsNil() {
   430  		panic("channel given to Subscribe must not be nil")
   431  	}
   432  	if c.isHTTP {
   433  		return nil, ErrNotificationsUnsupported
   434  	}
   435  
   436  	msg, err := c.newMessage(namespace+subscribeMethodSuffix, args...)
   437  	if err != nil {
   438  		return nil, err
   439  	}
   440  	op := &requestOp{
   441  		ids:  []json.RawMessage{msg.ID},
   442  		resp: make(chan *jsonrpcMessage),
   443  		sub:  newClientSubscription(c, namespace, chanVal),
   444  	}
   445  
   446  //发送订阅请求。
   447  //响应的到达和有效性在Sub.Quit上发出信号。
   448  	if err := c.send(ctx, op, msg); err != nil {
   449  		return nil, err
   450  	}
   451  	if _, err := op.wait(ctx); err != nil {
   452  		return nil, err
   453  	}
   454  	return op.sub, nil
   455  }
   456  
   457  func (c *Client) newMessage(method string, paramsIn ...interface{}) (*jsonrpcMessage, error) {
   458  	params, err := json.Marshal(paramsIn)
   459  	if err != nil {
   460  		return nil, err
   461  	}
   462  	return &jsonrpcMessage{Version: "2.0", ID: c.nextID(), Method: method, Params: params}, nil
   463  }
   464  
   465  //发送寄存器op和调度循环,然后在连接上发送msg。
   466  //如果发送失败,则注销OP。
   467  func (c *Client) send(ctx context.Context, op *requestOp, msg interface{}) error {
   468  	select {
   469  	case c.requestOp <- op:
   470  		log.Trace("", "msg", log.Lazy{Fn: func() string {
   471  			return fmt.Sprint("sending ", msg)
   472  		}})
   473  		err := c.write(ctx, msg)
   474  		c.sendDone <- err
   475  		return err
   476  	case <-ctx.Done():
   477  //如果客户端过载或无法跟上,就会发生这种情况。
   478  //订阅通知。
   479  		return ctx.Err()
   480  	case <-c.didQuit:
   481  		return ErrClientQuit
   482  	}
   483  }
   484  
   485  func (c *Client) write(ctx context.Context, msg interface{}) error {
   486  	deadline, ok := ctx.Deadline()
   487  	if !ok {
   488  		deadline = time.Now().Add(defaultWriteTimeout)
   489  	}
   490  //上一次写入失败。尝试建立新连接。
   491  	if c.writeConn == nil {
   492  		if err := c.reconnect(ctx); err != nil {
   493  			return err
   494  		}
   495  	}
   496  	c.writeConn.SetWriteDeadline(deadline)
   497  	err := json.NewEncoder(c.writeConn).Encode(msg)
   498  	if err != nil {
   499  		c.writeConn = nil
   500  	}
   501  	return err
   502  }
   503  
   504  func (c *Client) reconnect(ctx context.Context) error {
   505  	newconn, err := c.connectFunc(ctx)
   506  	if err != nil {
   507  		log.Trace(fmt.Sprintf("reconnect failed: %v", err))
   508  		return err
   509  	}
   510  	select {
   511  	case c.reconnected <- newconn:
   512  		c.writeConn = newconn
   513  		return nil
   514  	case <-c.didQuit:
   515  		newconn.Close()
   516  		return ErrClientQuit
   517  	}
   518  }
   519  
   520  //调度是客户机的主循环。
   521  //它向等待调用和批调用发送读取消息
   522  //注册订阅的订阅通知。
   523  func (c *Client) dispatch(conn net.Conn) {
   524  //生成初始读取循环。
   525  	go c.read(conn)
   526  
   527  	var (
   528  lastOp        *requestOp    //跟踪上次发送操作
   529  requestOpLock = c.requestOp //保持发送锁时为零
   530  reading       = true        //如果为真,则运行读取循环
   531  	)
   532  	defer close(c.didQuit)
   533  	defer func() {
   534  		c.closeRequestOps(ErrClientQuit)
   535  		conn.Close()
   536  		if reading {
   537  //清空读取通道,直到读取结束。
   538  			for {
   539  				select {
   540  				case <-c.readResp:
   541  				case <-c.readErr:
   542  					return
   543  				}
   544  			}
   545  		}
   546  	}()
   547  
   548  	for {
   549  		select {
   550  		case <-c.close:
   551  			return
   552  
   553  //读取路径。
   554  		case batch := <-c.readResp:
   555  			for _, msg := range batch {
   556  				switch {
   557  				case msg.isNotification():
   558  					log.Trace("", "msg", log.Lazy{Fn: func() string {
   559  						return fmt.Sprint("<-readResp: notification ", msg)
   560  					}})
   561  					c.handleNotification(msg)
   562  				case msg.isResponse():
   563  					log.Trace("", "msg", log.Lazy{Fn: func() string {
   564  						return fmt.Sprint("<-readResp: response ", msg)
   565  					}})
   566  					c.handleResponse(msg)
   567  				default:
   568  					log.Debug("", "msg", log.Lazy{Fn: func() string {
   569  						return fmt.Sprint("<-readResp: dropping weird message", msg)
   570  					}})
   571  //托多:也许接近
   572  				}
   573  			}
   574  
   575  		case err := <-c.readErr:
   576  			log.Debug("<-readErr", "err", err)
   577  			c.closeRequestOps(err)
   578  			conn.Close()
   579  			reading = false
   580  
   581  		case newconn := <-c.reconnected:
   582  			log.Debug("<-reconnected", "reading", reading, "remote", conn.RemoteAddr())
   583  			if reading {
   584  //等待上一个读取循环退出。这是一个罕见的病例。
   585  				conn.Close()
   586  				<-c.readErr
   587  			}
   588  			go c.read(newconn)
   589  			reading = true
   590  			conn = newconn
   591  
   592  //发送路径。
   593  		case op := <-requestOpLock:
   594  //停止侦听进一步的发送操作,直到当前操作完成。
   595  			requestOpLock = nil
   596  			lastOp = op
   597  			for _, id := range op.ids {
   598  				c.respWait[string(id)] = op
   599  			}
   600  
   601  		case err := <-c.sendDone:
   602  			if err != nil {
   603  //删除上次发送的响应处理程序。我们把它们移到这里
   604  //因为错误已经在call或batchcall中处理。当
   605  //读取循环停止,它将发出所有其他当前操作的信号。
   606  				for _, id := range lastOp.ids {
   607  					delete(c.respWait, string(id))
   608  				}
   609  			}
   610  //再次收听发送操作。
   611  			requestOpLock = c.requestOp
   612  			lastOp = nil
   613  		}
   614  	}
   615  }
   616  
   617  //closerequestops取消阻止挂起的发送操作和活动订阅。
   618  func (c *Client) closeRequestOps(err error) {
   619  	didClose := make(map[*requestOp]bool)
   620  
   621  	for id, op := range c.respWait {
   622  //删除op,以便以后的调用不会再次关闭op.resp。
   623  		delete(c.respWait, id)
   624  
   625  		if !didClose[op] {
   626  			op.err = err
   627  			close(op.resp)
   628  			didClose[op] = true
   629  		}
   630  	}
   631  	for id, sub := range c.subs {
   632  		delete(c.subs, id)
   633  		sub.quitWithError(err, false)
   634  	}
   635  }
   636  
   637  func (c *Client) handleNotification(msg *jsonrpcMessage) {
   638  	if !strings.HasSuffix(msg.Method, notificationMethodSuffix) {
   639  		log.Debug("dropping non-subscription message", "msg", msg)
   640  		return
   641  	}
   642  	var subResult struct {
   643  		ID     string          `json:"subscription"`
   644  		Result json.RawMessage `json:"result"`
   645  	}
   646  	if err := json.Unmarshal(msg.Params, &subResult); err != nil {
   647  		log.Debug("dropping invalid subscription message", "msg", msg)
   648  		return
   649  	}
   650  	if c.subs[subResult.ID] != nil {
   651  		c.subs[subResult.ID].deliver(subResult.Result)
   652  	}
   653  }
   654  
   655  func (c *Client) handleResponse(msg *jsonrpcMessage) {
   656  	op := c.respWait[string(msg.ID)]
   657  	if op == nil {
   658  		log.Debug("unsolicited response", "msg", msg)
   659  		return
   660  	}
   661  	delete(c.respWait, string(msg.ID))
   662  //对于正常响应,只需将响应转发到call/batchcall。
   663  	if op.sub == nil {
   664  		op.resp <- msg
   665  		return
   666  	}
   667  //对于订阅响应,如果服务器
   668  //表示成功。ethsubscribe在任何情况下都可以通过
   669  //Op.Resp频道。
   670  	defer close(op.resp)
   671  	if msg.Error != nil {
   672  		op.err = msg.Error
   673  		return
   674  	}
   675  	if op.err = json.Unmarshal(msg.Result, &op.sub.subid); op.err == nil {
   676  		go op.sub.start()
   677  		c.subs[op.sub.subid] = op.sub
   678  	}
   679  }
   680  
   681  //阅读发生在一个专门的Goroutine上。
   682  
   683  func (c *Client) read(conn net.Conn) error {
   684  	var (
   685  		buf json.RawMessage
   686  		dec = json.NewDecoder(conn)
   687  	)
   688  	readMessage := func() (rs []*jsonrpcMessage, err error) {
   689  		buf = buf[:0]
   690  		if err = dec.Decode(&buf); err != nil {
   691  			return nil, err
   692  		}
   693  		if isBatch(buf) {
   694  			err = json.Unmarshal(buf, &rs)
   695  		} else {
   696  			rs = make([]*jsonrpcMessage, 1)
   697  			err = json.Unmarshal(buf, &rs[0])
   698  		}
   699  		return rs, err
   700  	}
   701  
   702  	for {
   703  		resp, err := readMessage()
   704  		if err != nil {
   705  			c.readErr <- err
   706  			return err
   707  		}
   708  		c.readResp <- resp
   709  	}
   710  }
   711  
   712  //订阅。
   713  
   714  //客户端订阅表示通过ethsubscribe建立的订阅。
   715  type ClientSubscription struct {
   716  	client    *Client
   717  	etype     reflect.Type
   718  	channel   reflect.Value
   719  	namespace string
   720  	subid     string
   721  	in        chan json.RawMessage
   722  
   723  quitOnce sync.Once     //确保退出关闭一次
   724  quit     chan struct{} //退出订阅时将关闭Quit
   725  errOnce  sync.Once     //确保err关闭一次
   726  	err      chan error
   727  }
   728  
   729  func newClientSubscription(c *Client, namespace string, channel reflect.Value) *ClientSubscription {
   730  	sub := &ClientSubscription{
   731  		client:    c,
   732  		namespace: namespace,
   733  		etype:     channel.Type().Elem(),
   734  		channel:   channel,
   735  		quit:      make(chan struct{}),
   736  		err:       make(chan error, 1),
   737  		in:        make(chan json.RawMessage),
   738  	}
   739  	return sub
   740  }
   741  
   742  //err返回订阅错误通道。err的预期用途是
   743  //客户端连接意外关闭时重新订阅。
   744  //
   745  //当订阅到期时,错误通道接收到一个值。
   746  //出错。如果调用了close,则接收到的错误为nil。
   747  //在基础客户端上,没有发生其他错误。
   748  //
   749  //当对订阅调用Unsubscribe时,错误通道将关闭。
   750  func (sub *ClientSubscription) Err() <-chan error {
   751  	return sub.err
   752  }
   753  
   754  //取消订阅取消订阅通知并关闭错误通道。
   755  //它可以安全地被多次调用。
   756  func (sub *ClientSubscription) Unsubscribe() {
   757  	sub.quitWithError(nil, true)
   758  	sub.errOnce.Do(func() { close(sub.err) })
   759  }
   760  
   761  func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) {
   762  	sub.quitOnce.Do(func() {
   763  //调度循环将无法执行取消订阅调用
   764  //如果交货时受阻。关闭Sub.Quit First,因为它
   765  //解除锁定传递。
   766  		close(sub.quit)
   767  		if unsubscribeServer {
   768  			sub.requestUnsubscribe()
   769  		}
   770  		if err != nil {
   771  			if err == ErrClientQuit {
   772  err = nil //遵循订阅语义。
   773  			}
   774  			sub.err <- err
   775  		}
   776  	})
   777  }
   778  
   779  func (sub *ClientSubscription) deliver(result json.RawMessage) (ok bool) {
   780  	select {
   781  	case sub.in <- result:
   782  		return true
   783  	case <-sub.quit:
   784  		return false
   785  	}
   786  }
   787  
   788  func (sub *ClientSubscription) start() {
   789  	sub.quitWithError(sub.forward())
   790  }
   791  
   792  func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) {
   793  	cases := []reflect.SelectCase{
   794  		{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)},
   795  		{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.in)},
   796  		{Dir: reflect.SelectSend, Chan: sub.channel},
   797  	}
   798  	buffer := list.New()
   799  	defer buffer.Init()
   800  	for {
   801  		var chosen int
   802  		var recv reflect.Value
   803  		if buffer.Len() == 0 {
   804  //空闲,省略发送案例。
   805  			chosen, recv, _ = reflect.Select(cases[:2])
   806  		} else {
   807  //非空缓冲区,发送第一个排队的项目。
   808  			cases[2].Send = reflect.ValueOf(buffer.Front().Value)
   809  			chosen, recv, _ = reflect.Select(cases)
   810  		}
   811  
   812  		switch chosen {
   813  case 0: //<退出
   814  			return nil, false
   815  case 1: //<-in in
   816  			val, err := sub.unmarshal(recv.Interface().(json.RawMessage))
   817  			if err != nil {
   818  				return err, true
   819  			}
   820  			if buffer.Len() == maxClientSubscriptionBuffer {
   821  				return ErrSubscriptionQueueOverflow, true
   822  			}
   823  			buffer.PushBack(val)
   824  case 2: //子通道<
   825  cases[2].Send = reflect.Value{} //不要抓住价值。
   826  			buffer.Remove(buffer.Front())
   827  		}
   828  	}
   829  }
   830  
   831  func (sub *ClientSubscription) unmarshal(result json.RawMessage) (interface{}, error) {
   832  	val := reflect.New(sub.etype)
   833  	err := json.Unmarshal(result, val.Interface())
   834  	return val.Elem().Interface(), err
   835  }
   836  
   837  func (sub *ClientSubscription) requestUnsubscribe() error {
   838  	var result interface{}
   839  	return sub.client.Call(&result, sub.namespace+unsubscribeMethodSuffix, sub.subid)
   840  }