Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/rpc/server.go

Documentation: net/rpc

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6  	Package rpc provides access to the exported methods of an object across a
     7  	network or other I/O connection.  A server registers an object, making it visible
     8  	as a service with the name of the type of the object.  After registration, exported
     9  	methods of the object will be accessible remotely.  A server may register multiple
    10  	objects (services) of different types but it is an error to register multiple
    11  	objects of the same type.
    12  
    13  	Only methods that satisfy these criteria will be made available for remote access;
    14  	other methods will be ignored:
    15  
    16  		- the method's type is exported.
    17  		- the method is exported.
    18  		- the method has two arguments, both exported (or builtin) types.
    19  		- the method's second argument is a pointer.
    20  		- the method has return type error.
    21  
    22  	In effect, the method must look schematically like
    23  
    24  		func (t *T) MethodName(argType T1, replyType *T2) error
    25  
    26  	where T1 and T2 can be marshaled by encoding/gob.
    27  	These requirements apply even if a different codec is used.
    28  	(In the future, these requirements may soften for custom codecs.)
    29  
    30  	The method's first argument represents the arguments provided by the caller; the
    31  	second argument represents the result parameters to be returned to the caller.
    32  	The method's return value, if non-nil, is passed back as a string that the client
    33  	sees as if created by errors.New.  If an error is returned, the reply parameter
    34  	will not be sent back to the client.
    35  
    36  	The server may handle requests on a single connection by calling ServeConn.  More
    37  	typically it will create a network listener and call Accept or, for an HTTP
    38  	listener, HandleHTTP and http.Serve.
    39  
    40  	A client wishing to use the service establishes a connection and then invokes
    41  	NewClient on the connection.  The convenience function Dial (DialHTTP) performs
    42  	both steps for a raw network connection (an HTTP connection).  The resulting
    43  	Client object has two methods, Call and Go, that specify the service and method to
    44  	call, a pointer containing the arguments, and a pointer to receive the result
    45  	parameters.
    46  
    47  	The Call method waits for the remote call to complete while the Go method
    48  	launches the call asynchronously and signals completion using the Call
    49  	structure's Done channel.
    50  
    51  	Unless an explicit codec is set up, package encoding/gob is used to
    52  	transport the data.
    53  
    54  	Here is a simple example.  A server wishes to export an object of type Arith:
    55  
    56  		package server
    57  
    58  		import "errors"
    59  
    60  		type Args struct {
    61  			A, B int
    62  		}
    63  
    64  		type Quotient struct {
    65  			Quo, Rem int
    66  		}
    67  
    68  		type Arith int
    69  
    70  		func (t *Arith) Multiply(args *Args, reply *int) error {
    71  			*reply = args.A * args.B
    72  			return nil
    73  		}
    74  
    75  		func (t *Arith) Divide(args *Args, quo *Quotient) error {
    76  			if args.B == 0 {
    77  				return errors.New("divide by zero")
    78  			}
    79  			quo.Quo = args.A / args.B
    80  			quo.Rem = args.A % args.B
    81  			return nil
    82  		}
    83  
    84  	The server calls (for HTTP service):
    85  
    86  		arith := new(Arith)
    87  		rpc.Register(arith)
    88  		rpc.HandleHTTP()
    89  		l, e := net.Listen("tcp", ":1234")
    90  		if e != nil {
    91  			log.Fatal("listen error:", e)
    92  		}
    93  		go http.Serve(l, nil)
    94  
    95  	At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
    96  	"Arith.Divide".  To invoke one, a client first dials the server:
    97  
    98  		client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
    99  		if err != nil {
   100  			log.Fatal("dialing:", err)
   101  		}
   102  
   103  	Then it can make a remote call:
   104  
   105  		// Synchronous call
   106  		args := &server.Args{7,8}
   107  		var reply int
   108  		err = client.Call("Arith.Multiply", args, &reply)
   109  		if err != nil {
   110  			log.Fatal("arith error:", err)
   111  		}
   112  		fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
   113  
   114  	or
   115  
   116  		// Asynchronous call
   117  		quotient := new(Quotient)
   118  		divCall := client.Go("Arith.Divide", args, quotient, nil)
   119  		replyCall := <-divCall.Done	// will be equal to divCall
   120  		// check errors, print, etc.
   121  
   122  	A server implementation will often provide a simple, type-safe wrapper for the
   123  	client.
   124  
   125  	The net/rpc package is frozen and is not accepting new features.
   126  */
   127  package rpc
   128  
   129  import (
   130  	"bufio"
   131  	"encoding/gob"
   132  	"errors"
   133  	"go/token"
   134  	"io"
   135  	"log"
   136  	"net"
   137  	"net/http"
   138  	"reflect"
   139  	"strings"
   140  	"sync"
   141  )
   142  
   143  const (
   144  	// Defaults used by HandleHTTP
   145  	DefaultRPCPath   = "/_goRPC_"
   146  	DefaultDebugPath = "/debug/rpc"
   147  )
   148  
   149  // Precompute the reflect type for error. Can't use error directly
   150  // because Typeof takes an empty interface value. This is annoying.
   151  var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
   152  
   153  type methodType struct {
   154  	sync.Mutex // protects counters
   155  	method     reflect.Method
   156  	ArgType    reflect.Type
   157  	ReplyType  reflect.Type
   158  	numCalls   uint
   159  }
   160  
   161  type service struct {
   162  	name   string                 // name of service
   163  	rcvr   reflect.Value          // receiver of methods for the service
   164  	typ    reflect.Type           // type of the receiver
   165  	method map[string]*methodType // registered methods
   166  }
   167  
   168  // Request is a header written before every RPC call. It is used internally
   169  // but documented here as an aid to debugging, such as when analyzing
   170  // network traffic.
   171  type Request struct {
   172  	ServiceMethod string   // format: "Service.Method"
   173  	Seq           uint64   // sequence number chosen by client
   174  	next          *Request // for free list in Server
   175  }
   176  
   177  // Response is a header written before every RPC return. It is used internally
   178  // but documented here as an aid to debugging, such as when analyzing
   179  // network traffic.
   180  type Response struct {
   181  	ServiceMethod string    // echoes that of the Request
   182  	Seq           uint64    // echoes that of the request
   183  	Error         string    // error, if any.
   184  	next          *Response // for free list in Server
   185  }
   186  
   187  // Server represents an RPC Server.
   188  type Server struct {
   189  	serviceMap sync.Map   // map[string]*service
   190  	reqLock    sync.Mutex // protects freeReq
   191  	freeReq    *Request
   192  	respLock   sync.Mutex // protects freeResp
   193  	freeResp   *Response
   194  }
   195  
   196  // NewServer returns a new Server.
   197  func NewServer() *Server {
   198  	return &Server{}
   199  }
   200  
   201  // DefaultServer is the default instance of *Server.
   202  var DefaultServer = NewServer()
   203  
   204  // Is this type exported or a builtin?
   205  func isExportedOrBuiltinType(t reflect.Type) bool {
   206  	for t.Kind() == reflect.Ptr {
   207  		t = t.Elem()
   208  	}
   209  	// PkgPath will be non-empty even for an exported type,
   210  	// so we need to check the type name as well.
   211  	return token.IsExported(t.Name()) || t.PkgPath() == ""
   212  }
   213  
   214  // Register publishes in the server the set of methods of the
   215  // receiver value that satisfy the following conditions:
   216  //	- exported method of exported type
   217  //	- two arguments, both of exported type
   218  //	- the second argument is a pointer
   219  //	- one return value, of type error
   220  // It returns an error if the receiver is not an exported type or has
   221  // no suitable methods. It also logs the error using package log.
   222  // The client accesses each method using a string of the form "Type.Method",
   223  // where Type is the receiver's concrete type.
   224  func (server *Server) Register(rcvr interface{}) error {
   225  	return server.register(rcvr, "", false)
   226  }
   227  
   228  // RegisterName is like Register but uses the provided name for the type
   229  // instead of the receiver's concrete type.
   230  func (server *Server) RegisterName(name string, rcvr interface{}) error {
   231  	return server.register(rcvr, name, true)
   232  }
   233  
   234  func (server *Server) register(rcvr interface{}, name string, useName bool) error {
   235  	s := new(service)
   236  	s.typ = reflect.TypeOf(rcvr)
   237  	s.rcvr = reflect.ValueOf(rcvr)
   238  	sname := reflect.Indirect(s.rcvr).Type().Name()
   239  	if useName {
   240  		sname = name
   241  	}
   242  	if sname == "" {
   243  		s := "rpc.Register: no service name for type " + s.typ.String()
   244  		log.Print(s)
   245  		return errors.New(s)
   246  	}
   247  	if !token.IsExported(sname) && !useName {
   248  		s := "rpc.Register: type " + sname + " is not exported"
   249  		log.Print(s)
   250  		return errors.New(s)
   251  	}
   252  	s.name = sname
   253  
   254  	// Install the methods
   255  	s.method = suitableMethods(s.typ, true)
   256  
   257  	if len(s.method) == 0 {
   258  		str := ""
   259  
   260  		// To help the user, see if a pointer receiver would work.
   261  		method := suitableMethods(reflect.PtrTo(s.typ), false)
   262  		if len(method) != 0 {
   263  			str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)"
   264  		} else {
   265  			str = "rpc.Register: type " + sname + " has no exported methods of suitable type"
   266  		}
   267  		log.Print(str)
   268  		return errors.New(str)
   269  	}
   270  
   271  	if _, dup := server.serviceMap.LoadOrStore(sname, s); dup {
   272  		return errors.New("rpc: service already defined: " + sname)
   273  	}
   274  	return nil
   275  }
   276  
   277  // suitableMethods returns suitable Rpc methods of typ, it will report
   278  // error using log if reportErr is true.
   279  func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
   280  	methods := make(map[string]*methodType)
   281  	for m := 0; m < typ.NumMethod(); m++ {
   282  		method := typ.Method(m)
   283  		mtype := method.Type
   284  		mname := method.Name
   285  		// Method must be exported.
   286  		if !method.IsExported() {
   287  			continue
   288  		}
   289  		// Method needs three ins: receiver, *args, *reply.
   290  		if mtype.NumIn() != 3 {
   291  			if reportErr {
   292  				log.Printf("rpc.Register: method %q has %d input parameters; needs exactly three\n", mname, mtype.NumIn())
   293  			}
   294  			continue
   295  		}
   296  		// First arg need not be a pointer.
   297  		argType := mtype.In(1)
   298  		if !isExportedOrBuiltinType(argType) {
   299  			if reportErr {
   300  				log.Printf("rpc.Register: argument type of method %q is not exported: %q\n", mname, argType)
   301  			}
   302  			continue
   303  		}
   304  		// Second arg must be a pointer.
   305  		replyType := mtype.In(2)
   306  		if replyType.Kind() != reflect.Ptr {
   307  			if reportErr {
   308  				log.Printf("rpc.Register: reply type of method %q is not a pointer: %q\n", mname, replyType)
   309  			}
   310  			continue
   311  		}
   312  		// Reply type must be exported.
   313  		if !isExportedOrBuiltinType(replyType) {
   314  			if reportErr {
   315  				log.Printf("rpc.Register: reply type of method %q is not exported: %q\n", mname, replyType)
   316  			}
   317  			continue
   318  		}
   319  		// Method needs one out.
   320  		if mtype.NumOut() != 1 {
   321  			if reportErr {
   322  				log.Printf("rpc.Register: method %q has %d output parameters; needs exactly one\n", mname, mtype.NumOut())
   323  			}
   324  			continue
   325  		}
   326  		// The return type of the method must be error.
   327  		if returnType := mtype.Out(0); returnType != typeOfError {
   328  			if reportErr {
   329  				log.Printf("rpc.Register: return type of method %q is %q, must be error\n", mname, returnType)
   330  			}
   331  			continue
   332  		}
   333  		methods[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
   334  	}
   335  	return methods
   336  }
   337  
   338  // A value sent as a placeholder for the server's response value when the server
   339  // receives an invalid request. It is never decoded by the client since the Response
   340  // contains an error when it is used.
   341  var invalidRequest = struct{}{}
   342  
   343  func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
   344  	resp := server.getResponse()
   345  	// Encode the response header
   346  	resp.ServiceMethod = req.ServiceMethod
   347  	if errmsg != "" {
   348  		resp.Error = errmsg
   349  		reply = invalidRequest
   350  	}
   351  	resp.Seq = req.Seq
   352  	sending.Lock()
   353  	err := codec.WriteResponse(resp, reply)
   354  	if debugLog && err != nil {
   355  		log.Println("rpc: writing response:", err)
   356  	}
   357  	sending.Unlock()
   358  	server.freeResponse(resp)
   359  }
   360  
   361  func (m *methodType) NumCalls() (n uint) {
   362  	m.Lock()
   363  	n = m.numCalls
   364  	m.Unlock()
   365  	return n
   366  }
   367  
   368  func (s *service) call(server *Server, sending *sync.Mutex, wg *sync.WaitGroup, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
   369  	if wg != nil {
   370  		defer wg.Done()
   371  	}
   372  	mtype.Lock()
   373  	mtype.numCalls++
   374  	mtype.Unlock()
   375  	function := mtype.method.Func
   376  	// Invoke the method, providing a new value for the reply.
   377  	returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
   378  	// The return value for the method is an error.
   379  	errInter := returnValues[0].Interface()
   380  	errmsg := ""
   381  	if errInter != nil {
   382  		errmsg = errInter.(error).Error()
   383  	}
   384  	server.sendResponse(sending, req, replyv.Interface(), codec, errmsg)
   385  	server.freeRequest(req)
   386  }
   387  
   388  type gobServerCodec struct {
   389  	rwc    io.ReadWriteCloser
   390  	dec    *gob.Decoder
   391  	enc    *gob.Encoder
   392  	encBuf *bufio.Writer
   393  	closed bool
   394  }
   395  
   396  func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
   397  	return c.dec.Decode(r)
   398  }
   399  
   400  func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
   401  	return c.dec.Decode(body)
   402  }
   403  
   404  func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
   405  	if err = c.enc.Encode(r); err != nil {
   406  		if c.encBuf.Flush() == nil {
   407  			// Gob couldn't encode the header. Should not happen, so if it does,
   408  			// shut down the connection to signal that the connection is broken.
   409  			log.Println("rpc: gob error encoding response:", err)
   410  			c.Close()
   411  		}
   412  		return
   413  	}
   414  	if err = c.enc.Encode(body); err != nil {
   415  		if c.encBuf.Flush() == nil {
   416  			// Was a gob problem encoding the body but the header has been written.
   417  			// Shut down the connection to signal that the connection is broken.
   418  			log.Println("rpc: gob error encoding body:", err)
   419  			c.Close()
   420  		}
   421  		return
   422  	}
   423  	return c.encBuf.Flush()
   424  }
   425  
   426  func (c *gobServerCodec) Close() error {
   427  	if c.closed {
   428  		// Only call c.rwc.Close once; otherwise the semantics are undefined.
   429  		return nil
   430  	}
   431  	c.closed = true
   432  	return c.rwc.Close()
   433  }
   434  
   435  // ServeConn runs the server on a single connection.
   436  // ServeConn blocks, serving the connection until the client hangs up.
   437  // The caller typically invokes ServeConn in a go statement.
   438  // ServeConn uses the gob wire format (see package gob) on the
   439  // connection. To use an alternate codec, use ServeCodec.
   440  // See NewClient's comment for information about concurrent access.
   441  func (server *Server) ServeConn(conn io.ReadWriteCloser) {
   442  	buf := bufio.NewWriter(conn)
   443  	srv := &gobServerCodec{
   444  		rwc:    conn,
   445  		dec:    gob.NewDecoder(conn),
   446  		enc:    gob.NewEncoder(buf),
   447  		encBuf: buf,
   448  	}
   449  	server.ServeCodec(srv)
   450  }
   451  
   452  // ServeCodec is like ServeConn but uses the specified codec to
   453  // decode requests and encode responses.
   454  func (server *Server) ServeCodec(codec ServerCodec) {
   455  	sending := new(sync.Mutex)
   456  	wg := new(sync.WaitGroup)
   457  	for {
   458  		service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
   459  		if err != nil {
   460  			if debugLog && err != io.EOF {
   461  				log.Println("rpc:", err)
   462  			}
   463  			if !keepReading {
   464  				break
   465  			}
   466  			// send a response if we actually managed to read a header.
   467  			if req != nil {
   468  				server.sendResponse(sending, req, invalidRequest, codec, err.Error())
   469  				server.freeRequest(req)
   470  			}
   471  			continue
   472  		}
   473  		wg.Add(1)
   474  		go service.call(server, sending, wg, mtype, req, argv, replyv, codec)
   475  	}
   476  	// We've seen that there are no more requests.
   477  	// Wait for responses to be sent before closing codec.
   478  	wg.Wait()
   479  	codec.Close()
   480  }
   481  
   482  // ServeRequest is like ServeCodec but synchronously serves a single request.
   483  // It does not close the codec upon completion.
   484  func (server *Server) ServeRequest(codec ServerCodec) error {
   485  	sending := new(sync.Mutex)
   486  	service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
   487  	if err != nil {
   488  		if !keepReading {
   489  			return err
   490  		}
   491  		// send a response if we actually managed to read a header.
   492  		if req != nil {
   493  			server.sendResponse(sending, req, invalidRequest, codec, err.Error())
   494  			server.freeRequest(req)
   495  		}
   496  		return err
   497  	}
   498  	service.call(server, sending, nil, mtype, req, argv, replyv, codec)
   499  	return nil
   500  }
   501  
   502  func (server *Server) getRequest() *Request {
   503  	server.reqLock.Lock()
   504  	req := server.freeReq
   505  	if req == nil {
   506  		req = new(Request)
   507  	} else {
   508  		server.freeReq = req.next
   509  		*req = Request{}
   510  	}
   511  	server.reqLock.Unlock()
   512  	return req
   513  }
   514  
   515  func (server *Server) freeRequest(req *Request) {
   516  	server.reqLock.Lock()
   517  	req.next = server.freeReq
   518  	server.freeReq = req
   519  	server.reqLock.Unlock()
   520  }
   521  
   522  func (server *Server) getResponse() *Response {
   523  	server.respLock.Lock()
   524  	resp := server.freeResp
   525  	if resp == nil {
   526  		resp = new(Response)
   527  	} else {
   528  		server.freeResp = resp.next
   529  		*resp = Response{}
   530  	}
   531  	server.respLock.Unlock()
   532  	return resp
   533  }
   534  
   535  func (server *Server) freeResponse(resp *Response) {
   536  	server.respLock.Lock()
   537  	resp.next = server.freeResp
   538  	server.freeResp = resp
   539  	server.respLock.Unlock()
   540  }
   541  
   542  func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) {
   543  	service, mtype, req, keepReading, err = server.readRequestHeader(codec)
   544  	if err != nil {
   545  		if !keepReading {
   546  			return
   547  		}
   548  		// discard body
   549  		codec.ReadRequestBody(nil)
   550  		return
   551  	}
   552  
   553  	// Decode the argument value.
   554  	argIsValue := false // if true, need to indirect before calling.
   555  	if mtype.ArgType.Kind() == reflect.Ptr {
   556  		argv = reflect.New(mtype.ArgType.Elem())
   557  	} else {
   558  		argv = reflect.New(mtype.ArgType)
   559  		argIsValue = true
   560  	}
   561  	// argv guaranteed to be a pointer now.
   562  	if err = codec.ReadRequestBody(argv.Interface()); err != nil {
   563  		return
   564  	}
   565  	if argIsValue {
   566  		argv = argv.Elem()
   567  	}
   568  
   569  	replyv = reflect.New(mtype.ReplyType.Elem())
   570  
   571  	switch mtype.ReplyType.Elem().Kind() {
   572  	case reflect.Map:
   573  		replyv.Elem().Set(reflect.MakeMap(mtype.ReplyType.Elem()))
   574  	case reflect.Slice:
   575  		replyv.Elem().Set(reflect.MakeSlice(mtype.ReplyType.Elem(), 0, 0))
   576  	}
   577  	return
   578  }
   579  
   580  func (server *Server) readRequestHeader(codec ServerCodec) (svc *service, mtype *methodType, req *Request, keepReading bool, err error) {
   581  	// Grab the request header.
   582  	req = server.getRequest()
   583  	err = codec.ReadRequestHeader(req)
   584  	if err != nil {
   585  		req = nil
   586  		if err == io.EOF || err == io.ErrUnexpectedEOF {
   587  			return
   588  		}
   589  		err = errors.New("rpc: server cannot decode request: " + err.Error())
   590  		return
   591  	}
   592  
   593  	// We read the header successfully. If we see an error now,
   594  	// we can still recover and move on to the next request.
   595  	keepReading = true
   596  
   597  	dot := strings.LastIndex(req.ServiceMethod, ".")
   598  	if dot < 0 {
   599  		err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod)
   600  		return
   601  	}
   602  	serviceName := req.ServiceMethod[:dot]
   603  	methodName := req.ServiceMethod[dot+1:]
   604  
   605  	// Look up the request.
   606  	svci, ok := server.serviceMap.Load(serviceName)
   607  	if !ok {
   608  		err = errors.New("rpc: can't find service " + req.ServiceMethod)
   609  		return
   610  	}
   611  	svc = svci.(*service)
   612  	mtype = svc.method[methodName]
   613  	if mtype == nil {
   614  		err = errors.New("rpc: can't find method " + req.ServiceMethod)
   615  	}
   616  	return
   617  }
   618  
   619  // Accept accepts connections on the listener and serves requests
   620  // for each incoming connection. Accept blocks until the listener
   621  // returns a non-nil error. The caller typically invokes Accept in a
   622  // go statement.
   623  func (server *Server) Accept(lis net.Listener) {
   624  	for {
   625  		conn, err := lis.Accept()
   626  		if err != nil {
   627  			log.Print("rpc.Serve: accept:", err.Error())
   628  			return
   629  		}
   630  		go server.ServeConn(conn)
   631  	}
   632  }
   633  
   634  // Register publishes the receiver's methods in the DefaultServer.
   635  func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }
   636  
   637  // RegisterName is like Register but uses the provided name for the type
   638  // instead of the receiver's concrete type.
   639  func RegisterName(name string, rcvr interface{}) error {
   640  	return DefaultServer.RegisterName(name, rcvr)
   641  }
   642  
   643  // A ServerCodec implements reading of RPC requests and writing of
   644  // RPC responses for the server side of an RPC session.
   645  // The server calls ReadRequestHeader and ReadRequestBody in pairs
   646  // to read requests from the connection, and it calls WriteResponse to
   647  // write a response back. The server calls Close when finished with the
   648  // connection. ReadRequestBody may be called with a nil
   649  // argument to force the body of the request to be read and discarded.
   650  // See NewClient's comment for information about concurrent access.
   651  type ServerCodec interface {
   652  	ReadRequestHeader(*Request) error
   653  	ReadRequestBody(interface{}) error
   654  	WriteResponse(*Response, interface{}) error
   655  
   656  	// Close can be called multiple times and must be idempotent.
   657  	Close() error
   658  }
   659  
   660  // ServeConn runs the DefaultServer on a single connection.
   661  // ServeConn blocks, serving the connection until the client hangs up.
   662  // The caller typically invokes ServeConn in a go statement.
   663  // ServeConn uses the gob wire format (see package gob) on the
   664  // connection. To use an alternate codec, use ServeCodec.
   665  // See NewClient's comment for information about concurrent access.
   666  func ServeConn(conn io.ReadWriteCloser) {
   667  	DefaultServer.ServeConn(conn)
   668  }
   669  
   670  // ServeCodec is like ServeConn but uses the specified codec to
   671  // decode requests and encode responses.
   672  func ServeCodec(codec ServerCodec) {
   673  	DefaultServer.ServeCodec(codec)
   674  }
   675  
   676  // ServeRequest is like ServeCodec but synchronously serves a single request.
   677  // It does not close the codec upon completion.
   678  func ServeRequest(codec ServerCodec) error {
   679  	return DefaultServer.ServeRequest(codec)
   680  }
   681  
   682  // Accept accepts connections on the listener and serves requests
   683  // to DefaultServer for each incoming connection.
   684  // Accept blocks; the caller typically invokes it in a go statement.
   685  func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
   686  
   687  // Can connect to RPC service using HTTP CONNECT to rpcPath.
   688  var connected = "200 Connected to Go RPC"
   689  
   690  // ServeHTTP implements an http.Handler that answers RPC requests.
   691  func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   692  	if req.Method != "CONNECT" {
   693  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
   694  		w.WriteHeader(http.StatusMethodNotAllowed)
   695  		io.WriteString(w, "405 must CONNECT\n")
   696  		return
   697  	}
   698  	conn, _, err := w.(http.Hijacker).Hijack()
   699  	if err != nil {
   700  		log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
   701  		return
   702  	}
   703  	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
   704  	server.ServeConn(conn)
   705  }
   706  
   707  // HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
   708  // and a debugging handler on debugPath.
   709  // It is still necessary to invoke http.Serve(), typically in a go statement.
   710  func (server *Server) HandleHTTP(rpcPath, debugPath string) {
   711  	http.Handle(rpcPath, server)
   712  	http.Handle(debugPath, debugHTTP{server})
   713  }
   714  
   715  // HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
   716  // on DefaultRPCPath and a debugging handler on DefaultDebugPath.
   717  // It is still necessary to invoke http.Serve(), typically in a go statement.
   718  func HandleHTTP() {
   719  	DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath)
   720  }
   721  

View as plain text