New APIs added:
    client.RegisterName(namespace, service) // makes service available to server
    client.Notify(ctx, method, args...)     // sends a notification
    ClientFromContext(ctx)                  // to get a client in handler method
This is essentially a rewrite of the server-side code. JSON-RPC
processing code is now the same on both server and client side. Many
minor issues were fixed in the process and there is a new test suite for
JSON-RPC spec compliance (and non-compliance in some cases).
List of behavior changes:
- Method handlers are now called with a per-request context instead of a
  per-connection context. The context is canceled right after the method
  returns.
- Subscription error channels are always closed when the connection
  ends. There is no need to also wait on the Notifier's Closed channel
  to detect whether the subscription has ended.
- Client now omits "params" instead of sending "params": null when there
  are no arguments to a call. The previous behavior was not compliant
  with the spec. The server still accepts "params": null.
- Floating point numbers are allowed as "id". The spec doesn't allow
  them, but we handle request "id" as json.RawMessage and guarantee that
  the same number will be sent back.
- Logging is improved significantly. There is now a message at DEBUG
  level for each RPC call served.
		
	
			
		
			
				
	
	
		
			119 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 The go-ethereum Authors
 | |
| // This file is part of the go-ethereum library.
 | |
| //
 | |
| // The go-ethereum library is free software: you can redistribute it and/or modify
 | |
| // it under the terms of the GNU Lesser General Public License as published by
 | |
| // the Free Software Foundation, either version 3 of the License, or
 | |
| // (at your option) any later version.
 | |
| //
 | |
| // The go-ethereum library is distributed in the hope that it will be useful,
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | |
| // GNU Lesser General Public License for more details.
 | |
| //
 | |
| // You should have received a copy of the GNU Lesser General Public License
 | |
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| /*
 | |
| 
 | |
| Package rpc implements bi-directional JSON-RPC 2.0 on multiple transports.
 | |
| 
 | |
| It provides access to the exported methods of an object across a network or other I/O
 | |
| connection. After creating a server or client instance, objects can be registered to make
 | |
| them visible as 'services'. Exported methods that follow specific conventions can be
 | |
| called remotely. It also has support for the publish/subscribe pattern.
 | |
| 
 | |
| RPC Methods
 | |
| 
 | |
| Methods that satisfy the following criteria are made available for remote access:
 | |
| 
 | |
|  - method must be exported
 | |
|  - method returns 0, 1 (response or error) or 2 (response and error) values
 | |
|  - method argument(s) must be exported or builtin types
 | |
|  - method returned value(s) must be exported or builtin types
 | |
| 
 | |
| An example method:
 | |
| 
 | |
|  func (s *CalcService) Add(a, b int) (int, error)
 | |
| 
 | |
| When the returned error isn't nil the returned integer is ignored and the error is sent
 | |
| back to the client. Otherwise the returned integer is sent back to the client.
 | |
| 
 | |
| Optional arguments are supported by accepting pointer values as arguments. E.g. if we want
 | |
| to do the addition in an optional finite field we can accept a mod argument as pointer
 | |
| value.
 | |
| 
 | |
|  func (s *CalcService) Add(a, b int, mod *int) (int, error)
 | |
| 
 | |
| This RPC method can be called with 2 integers and a null value as third argument. In that
 | |
| case the mod argument will be nil. Or it can be called with 3 integers, in that case mod
 | |
| will be pointing to the given third argument. Since the optional argument is the last
 | |
| argument the RPC package will also accept 2 integers as arguments. It will pass the mod
 | |
| argument as nil to the RPC method.
 | |
| 
 | |
| The server offers the ServeCodec method which accepts a ServerCodec instance. It will read
 | |
| requests from the codec, process the request and sends the response back to the client
 | |
| using the codec. The server can execute requests concurrently. Responses can be sent back
 | |
| to the client out of order.
 | |
| 
 | |
| An example server which uses the JSON codec:
 | |
| 
 | |
|  type CalculatorService struct {}
 | |
| 
 | |
|  func (s *CalculatorService) Add(a, b int) int {
 | |
| 	return a + b
 | |
|  }
 | |
| 
 | |
|  func (s *CalculatorService) Div(a, b int) (int, error) {
 | |
| 	if b == 0 {
 | |
| 		return 0, errors.New("divide by zero")
 | |
| 	}
 | |
| 	return a/b, nil
 | |
|  }
 | |
| 
 | |
|  calculator := new(CalculatorService)
 | |
|  server := NewServer()
 | |
|  server.RegisterName("calculator", calculator")
 | |
| 
 | |
|  l, _ := net.ListenUnix("unix", &net.UnixAddr{Net: "unix", Name: "/tmp/calculator.sock"})
 | |
|  for {
 | |
| 	c, _ := l.AcceptUnix()
 | |
| 	codec := v2.NewJSONCodec(c)
 | |
| 	go server.ServeCodec(codec, 0)
 | |
|  }
 | |
| 
 | |
| Subscriptions
 | |
| 
 | |
| The package also supports the publish subscribe pattern through the use of subscriptions.
 | |
| A method that is considered eligible for notifications must satisfy the following
 | |
| criteria:
 | |
| 
 | |
|  - method must be exported
 | |
|  - first method argument type must be context.Context
 | |
|  - method argument(s) must be exported or builtin types
 | |
|  - method must have return types (rpc.Subscription, error)
 | |
| 
 | |
| An example method:
 | |
| 
 | |
|  func (s *BlockChainService) NewBlocks(ctx context.Context) (rpc.Subscription, error) {
 | |
|  	...
 | |
|  }
 | |
| 
 | |
| When the service containing the subscription method is registered to the server, for
 | |
| example under the "blockchain" namespace, a subscription is created by calling the
 | |
| "blockchain_subscribe" method.
 | |
| 
 | |
| Subscriptions are deleted when the user sends an unsubscribe request or when the
 | |
| connection which was used to create the subscription is closed. This can be initiated by
 | |
| the client and server. The server will close the connection for any write error.
 | |
| 
 | |
| For more information about subscriptions, see https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB.
 | |
| 
 | |
| Reverse Calls
 | |
| 
 | |
| In any method handler, an instance of rpc.Client can be accessed through the
 | |
| ClientFromContext method. Using this client instance, server-to-client method calls can be
 | |
| performed on the RPC connection.
 | |
| */
 | |
| package rpc
 |