github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/rpc/server.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package rpc
     5  
     6  import (
     7  	"io"
     8  	"reflect"
     9  	"sync"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/loggo"
    13  
    14  	"github.com/juju/juju/rpc/rpcreflect"
    15  )
    16  
    17  const codeNotImplemented = "not implemented"
    18  
    19  var logger = loggo.GetLogger("juju.rpc")
    20  
    21  // A Codec implements reading and writing of messages in an RPC
    22  // session.  The RPC code calls WriteMessage to write a message to the
    23  // connection and calls ReadHeader and ReadBody in pairs to read
    24  // messages.
    25  type Codec interface {
    26  	// ReadHeader reads a message header into hdr.
    27  	ReadHeader(hdr *Header) error
    28  
    29  	// ReadBody reads a message body into the given body value.  The
    30  	// isRequest parameter specifies whether the message being read
    31  	// is a request; if not, it's a response.  The body value will
    32  	// be a non-nil struct pointer, or nil to signify that the body
    33  	// should be read and discarded.
    34  	ReadBody(body interface{}, isRequest bool) error
    35  
    36  	// WriteMessage writes a message with the given header and body.
    37  	// The body will always be a struct. It may be called concurrently
    38  	// with ReadHeader and ReadBody, but will not be called
    39  	// concurrently with itself.
    40  	WriteMessage(hdr *Header, body interface{}) error
    41  
    42  	// Close closes the codec. It may be called concurrently
    43  	// and should cause the Read methods to unblock.
    44  	Close() error
    45  }
    46  
    47  // Header is a header written before every RPC call.  Since RPC requests
    48  // can be initiated from either side, the header may represent a request
    49  // from the other side or a response to an outstanding request.
    50  type Header struct {
    51  	// RequestId holds the sequence number of the request.
    52  	// For replies, it holds the sequence number of the request
    53  	// that is being replied to.
    54  	RequestId uint64
    55  
    56  	// Request holds the action to invoke.
    57  	Request Request
    58  
    59  	// Error holds the error, if any.
    60  	Error string
    61  
    62  	// ErrorCode holds the code of the error, if any.
    63  	ErrorCode string
    64  
    65  	// Version defines the wire format of the request and response structure.
    66  	Version int
    67  }
    68  
    69  // Request represents an RPC to be performed, absent its parameters.
    70  type Request struct {
    71  	// Type holds the type of object to act on.
    72  	Type string
    73  
    74  	// Version holds the version of Type we will be acting on
    75  	Version int
    76  
    77  	// Id holds the id of the object to act on.
    78  	Id string
    79  
    80  	// Action holds the action to perform on the object.
    81  	Action string
    82  }
    83  
    84  // IsRequest returns whether the header represents an RPC request.  If
    85  // it is not a request, it is a response.
    86  func (hdr *Header) IsRequest() bool {
    87  	return hdr.Request.Type != "" || hdr.Request.Action != ""
    88  }
    89  
    90  // ObserverFactory is a type which can construct a new Observer.
    91  type ObserverFactory interface {
    92  
    93  	// RPCObserver will return a new Observer usually constructed
    94  	// from the state previously built up in the Observer. The
    95  	// returned instance will be utilized per RPC request.
    96  	RPCObserver() Observer
    97  }
    98  
    99  // Note that we use "client request" and "server request" to name
   100  // requests initiated locally and remotely respectively.
   101  
   102  // Conn represents an RPC endpoint.  It can both initiate and receive
   103  // RPC requests.  There may be multiple outstanding Calls associated
   104  // with a single Client, and a Client may be used by multiple goroutines
   105  // simultaneously.
   106  type Conn struct {
   107  	// codec holds the underlying RPC connection.
   108  	codec Codec
   109  
   110  	// srvPending represents the current server requests.
   111  	srvPending sync.WaitGroup
   112  
   113  	// sending guards the write side of the codec - it ensures
   114  	// that codec.WriteMessage is not called concurrently.
   115  	// It also guards shutdown.
   116  	sending sync.Mutex
   117  
   118  	// mutex guards the following values.
   119  	mutex sync.Mutex
   120  
   121  	// root represents  the current root object that serves the RPC requests.
   122  	// It may be nil if nothing is being served.
   123  	root Root
   124  
   125  	// transformErrors is used to transform returned errors.
   126  	transformErrors func(error) error
   127  
   128  	// reqId holds the latest client request id.
   129  	reqId uint64
   130  
   131  	// clientPending holds all pending client requests.
   132  	clientPending map[uint64]*Call
   133  
   134  	// closing is set when the connection is shutting down via
   135  	// Close.  When this is set, no more client or server requests
   136  	// will be initiated.
   137  	closing bool
   138  
   139  	// shutdown is set when the input loop terminates. When this
   140  	// is set, no more client requests will be sent to the server.
   141  	shutdown bool
   142  
   143  	// dead is closed when the input loop terminates.
   144  	dead chan struct{}
   145  
   146  	// inputLoopError holds the error that caused the input loop to
   147  	// terminate prematurely.  It is set before dead is closed.
   148  	inputLoopError error
   149  
   150  	observerFactory ObserverFactory
   151  }
   152  
   153  // NewConn creates a new connection that uses the given codec for
   154  // transport, but it does not start it. Conn.Start must be called before
   155  // any requests are sent or received. If notifier is non-nil, the
   156  // appropriate method will be called for every RPC request.
   157  func NewConn(codec Codec, observerFactory ObserverFactory) *Conn {
   158  	return &Conn{
   159  		codec:           codec,
   160  		clientPending:   make(map[uint64]*Call),
   161  		observerFactory: observerFactory,
   162  	}
   163  }
   164  
   165  // Start starts the RPC connection running.  It must be called at
   166  // least once for any RPC connection (client or server side) It has no
   167  // effect if it has already been called.  By default, a connection
   168  // serves no methods.  See Conn.Serve for a description of how to
   169  // serve methods on a Conn.
   170  func (conn *Conn) Start() {
   171  	conn.mutex.Lock()
   172  	defer conn.mutex.Unlock()
   173  	if conn.dead == nil {
   174  		conn.dead = make(chan struct{})
   175  		go conn.input()
   176  	}
   177  }
   178  
   179  // Serve serves RPC requests on the connection by invoking methods on
   180  // root. Note that it does not start the connection running,
   181  // though it may be called once the connection is already started.
   182  //
   183  // The server executes each client request by calling a method on root
   184  // to obtain an object to act on; then it invokes an method on that
   185  // object with the request parameters, possibly returning some result.
   186  //
   187  // Methods on the root value are of the form:
   188  //
   189  //      M(id string) (O, error)
   190  //
   191  // where M is an exported name, conventionally naming the object type,
   192  // id is some identifier for the object and O is the type of the
   193  // returned object.
   194  //
   195  // Methods defined on O may defined in one of the following forms, where
   196  // T and R must be struct types.
   197  //
   198  //	Method()
   199  //	Method() R
   200  //	Method() (R, error)
   201  //	Method() error
   202  //	Method(T)
   203  //	Method(T) R
   204  //	Method(T) (R, error)
   205  //	Method(T) error
   206  //
   207  // If transformErrors is non-nil, it will be called on all returned
   208  // non-nil errors, for example to transform the errors into ServerErrors
   209  // with specified codes.  There will be a panic if transformErrors
   210  // returns nil.
   211  //
   212  // Serve may be called at any time on a connection to change the
   213  // set of methods being served by the connection. This will have
   214  // no effect on calls that are currently being services.
   215  // If root is nil, the connection will serve no methods.
   216  func (conn *Conn) Serve(root interface{}, transformErrors func(error) error) {
   217  	rootValue := rpcreflect.ValueOf(reflect.ValueOf(root))
   218  	if rootValue.IsValid() {
   219  		conn.serve(rootValue, transformErrors)
   220  	} else {
   221  		conn.serve(nil, transformErrors)
   222  	}
   223  }
   224  
   225  // ServeRoot is like Serve except that it gives the root object dynamic
   226  // control over what methods are available instead of using reflection
   227  // on the type.
   228  //
   229  // The server executes each client request by calling FindMethod to obtain a
   230  // method to invoke. It invokes that method with the request parameters,
   231  // possibly returning some result.
   232  //
   233  // The Kill method will be called when the connection is closed.
   234  func (conn *Conn) ServeRoot(root Root, transformErrors func(error) error) {
   235  	conn.serve(root, transformErrors)
   236  }
   237  
   238  func (conn *Conn) serve(root Root, transformErrors func(error) error) {
   239  	if transformErrors == nil {
   240  		transformErrors = noopTransform
   241  	}
   242  	conn.mutex.Lock()
   243  	defer conn.mutex.Unlock()
   244  	conn.root = root
   245  	conn.transformErrors = transformErrors
   246  }
   247  
   248  // noopTransform is used when transformErrors is not supplied to Serve.
   249  func noopTransform(err error) error {
   250  	return err
   251  }
   252  
   253  // Dead returns a channel that is closed when the connection
   254  // has been closed or the underlying transport has received
   255  // an error. There may still be outstanding requests.
   256  // Dead must be called after conn.Start has been called.
   257  func (conn *Conn) Dead() <-chan struct{} {
   258  	return conn.dead
   259  }
   260  
   261  // Close closes the connection and its underlying codec; it returns when
   262  // all requests have been terminated.
   263  //
   264  // If the connection is serving requests, and the root value implements
   265  // the Killer interface, its Kill method will be called.  The codec will
   266  // then be closed only when all its outstanding server calls have
   267  // completed.
   268  //
   269  // Calling Close multiple times is not an error.
   270  func (conn *Conn) Close() error {
   271  	conn.mutex.Lock()
   272  	if conn.closing {
   273  		conn.mutex.Unlock()
   274  		// Golang's net/rpc returns rpc.ErrShutdown if you ask to close
   275  		// a closing or shutdown connection. Our choice is that Close
   276  		// is an idempotent way to ask for resources to be released and
   277  		// isn't a failure if called multiple times.
   278  		return nil
   279  	}
   280  	conn.closing = true
   281  	if conn.root != nil {
   282  		conn.root.Kill()
   283  	}
   284  	conn.mutex.Unlock()
   285  
   286  	// Wait for any outstanding server requests to complete
   287  	// and write their replies before closing the codec.
   288  	conn.srvPending.Wait()
   289  
   290  	// Closing the codec should cause the input loop to terminate.
   291  	if err := conn.codec.Close(); err != nil {
   292  		logger.Infof("error closing codec: %v", err)
   293  	}
   294  	<-conn.dead
   295  
   296  	return conn.inputLoopError
   297  }
   298  
   299  // ErrorCoder represents an any error that has an associated
   300  // error code. An error code is a short string that represents the
   301  // kind of an error.
   302  type ErrorCoder interface {
   303  	ErrorCode() string
   304  }
   305  
   306  // Root represents a type that can be used to lookup a Method and place
   307  // calls on that method.
   308  type Root interface {
   309  	FindMethod(rootName string, version int, methodName string) (rpcreflect.MethodCaller, error)
   310  	Killer
   311  }
   312  
   313  // Killer represents a type that can be asked to abort any outstanding
   314  // requests.  The Kill method should return immediately.
   315  type Killer interface {
   316  	Kill()
   317  }
   318  
   319  // input reads messages from the connection and handles them
   320  // appropriately.
   321  func (conn *Conn) input() {
   322  	err := conn.loop()
   323  	conn.sending.Lock()
   324  	defer conn.sending.Unlock()
   325  	conn.mutex.Lock()
   326  	defer conn.mutex.Unlock()
   327  
   328  	if conn.closing || err == io.EOF {
   329  		err = ErrShutdown
   330  	} else {
   331  		// Make the error available for Conn.Close to see.
   332  		conn.inputLoopError = err
   333  	}
   334  	// Terminate all client requests.
   335  	for _, call := range conn.clientPending {
   336  		call.Error = err
   337  		call.done()
   338  	}
   339  	conn.clientPending = nil
   340  	conn.shutdown = true
   341  	close(conn.dead)
   342  }
   343  
   344  // loop implements the looping part of Conn.input.
   345  func (conn *Conn) loop() error {
   346  	for {
   347  		var hdr Header
   348  		err := conn.codec.ReadHeader(&hdr)
   349  		switch {
   350  		case err == io.EOF:
   351  			// handle sentinel error specially
   352  			return err
   353  		case err != nil:
   354  			return errors.Annotate(err, "codec.ReadHeader error")
   355  		case hdr.IsRequest():
   356  			if err := conn.handleRequest(&hdr); err != nil {
   357  				return errors.Annotatef(err, "codec.handleRequest %#v error", hdr)
   358  			}
   359  		default:
   360  			if err := conn.handleResponse(&hdr); err != nil {
   361  				return errors.Annotatef(err, "codec.handleResponse %#v error", hdr)
   362  			}
   363  		}
   364  	}
   365  }
   366  
   367  func (conn *Conn) readBody(resp interface{}, isRequest bool) error {
   368  	if resp == nil {
   369  		resp = &struct{}{}
   370  	}
   371  	return conn.codec.ReadBody(resp, isRequest)
   372  }
   373  
   374  func (conn *Conn) handleRequest(hdr *Header) error {
   375  	observer := conn.observerFactory.RPCObserver()
   376  	req, err := conn.bindRequest(hdr)
   377  	if err != nil {
   378  		observer.ServerRequest(hdr, nil)
   379  		if err := conn.readBody(nil, true); err != nil {
   380  			return err
   381  		}
   382  		// We don't transform the error here. bindRequest will have
   383  		// already transformed it and returned a zero req.
   384  		return conn.writeErrorResponse(hdr, err, observer)
   385  	}
   386  	var argp interface{}
   387  	var arg reflect.Value
   388  	if req.ParamsType() != nil {
   389  		v := reflect.New(req.ParamsType())
   390  		arg = v.Elem()
   391  		argp = v.Interface()
   392  	}
   393  	if err := conn.readBody(argp, true); err != nil {
   394  		observer.ServerRequest(hdr, nil)
   395  
   396  		// If we get EOF, we know the connection is a
   397  		// goner, so don't try to respond.
   398  		if err == io.EOF || err == io.ErrUnexpectedEOF {
   399  			return err
   400  		}
   401  		// An error reading the body often indicates bad
   402  		// request parameters rather than an issue with
   403  		// the connection itself, so we reply with an
   404  		// error rather than tearing down the connection
   405  		// unless it's obviously a connection issue.  If
   406  		// the error is actually a framing or syntax
   407  		// problem, then the next ReadHeader should pick
   408  		// up the problem and abort.
   409  		return conn.writeErrorResponse(hdr, req.transformErrors(err), observer)
   410  	}
   411  	if req.ParamsType() != nil {
   412  		observer.ServerRequest(hdr, arg.Interface())
   413  	} else {
   414  		observer.ServerRequest(hdr, struct{}{})
   415  	}
   416  	conn.mutex.Lock()
   417  	closing := conn.closing
   418  	if !closing {
   419  		conn.srvPending.Add(1)
   420  		go conn.runRequest(req, arg, hdr.Version, observer)
   421  	}
   422  	conn.mutex.Unlock()
   423  	if closing {
   424  		// We're closing down - no new requests may be initiated.
   425  		return conn.writeErrorResponse(hdr, req.transformErrors(ErrShutdown), observer)
   426  	}
   427  	return nil
   428  }
   429  
   430  func (conn *Conn) writeErrorResponse(reqHdr *Header, err error, observer Observer) error {
   431  	conn.sending.Lock()
   432  	defer conn.sending.Unlock()
   433  	hdr := &Header{
   434  		RequestId: reqHdr.RequestId,
   435  		Version:   reqHdr.Version,
   436  	}
   437  	if err, ok := err.(ErrorCoder); ok {
   438  		hdr.ErrorCode = err.ErrorCode()
   439  	} else {
   440  		hdr.ErrorCode = ""
   441  	}
   442  	hdr.Error = err.Error()
   443  	observer.ServerReply(reqHdr.Request, hdr, struct{}{})
   444  
   445  	return conn.codec.WriteMessage(hdr, struct{}{})
   446  }
   447  
   448  // boundRequest represents an RPC request that is
   449  // bound to an actual implementation.
   450  type boundRequest struct {
   451  	rpcreflect.MethodCaller
   452  	transformErrors func(error) error
   453  	hdr             Header
   454  }
   455  
   456  // bindRequest searches for methods implementing the
   457  // request held in the given header and returns
   458  // a boundRequest that can call those methods.
   459  func (conn *Conn) bindRequest(hdr *Header) (boundRequest, error) {
   460  	conn.mutex.Lock()
   461  	root := conn.root
   462  	transformErrors := conn.transformErrors
   463  	conn.mutex.Unlock()
   464  
   465  	if root == nil {
   466  		return boundRequest{}, errors.New("no service")
   467  	}
   468  	caller, err := root.FindMethod(
   469  		hdr.Request.Type, hdr.Request.Version, hdr.Request.Action)
   470  	if err != nil {
   471  		if _, ok := err.(*rpcreflect.CallNotImplementedError); ok {
   472  			err = &serverError{
   473  				error: err,
   474  			}
   475  		} else {
   476  			err = transformErrors(err)
   477  		}
   478  		return boundRequest{}, err
   479  	}
   480  	return boundRequest{
   481  		MethodCaller:    caller,
   482  		transformErrors: transformErrors,
   483  		hdr:             *hdr,
   484  	}, nil
   485  }
   486  
   487  // runRequest runs the given request and sends the reply.
   488  func (conn *Conn) runRequest(req boundRequest, arg reflect.Value, version int, observer Observer) {
   489  	defer conn.srvPending.Done()
   490  	rv, err := req.Call(req.hdr.Request.Id, arg)
   491  	if err != nil {
   492  		err = conn.writeErrorResponse(&req.hdr, req.transformErrors(err), observer)
   493  	} else {
   494  		hdr := &Header{
   495  			RequestId: req.hdr.RequestId,
   496  			Version:   version,
   497  		}
   498  		var rvi interface{}
   499  		if rv.IsValid() {
   500  			rvi = rv.Interface()
   501  		} else {
   502  			rvi = struct{}{}
   503  		}
   504  		observer.ServerReply(req.hdr.Request, hdr, rvi)
   505  		conn.sending.Lock()
   506  		err = conn.codec.WriteMessage(hdr, rvi)
   507  		conn.sending.Unlock()
   508  	}
   509  	if err != nil {
   510  		logger.Errorf("error writing response: %v", err)
   511  	}
   512  }
   513  
   514  type serverError struct {
   515  	error
   516  }
   517  
   518  func (e *serverError) ErrorCode() string {
   519  	// serverError only knows one error code.
   520  	return codeNotImplemented
   521  }