...

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, err := net.Listen("tcp", ":1234")
    90  	if err != nil {
    91  		log.Fatal("listen error:", err)
    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.Pointer {
   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  //
   221  // It returns an error if the receiver is not an exported type or has
   222  // no suitable methods. It also logs the error using package log.
   223  // The client accesses each method using a string of the form "Type.Method",
   224  // where Type is the receiver's concrete type.
   225  func (server *Server) Register(rcvr any) error {
   226  	return server.register(rcvr, "", false)
   227  }
   228  
   229  // RegisterName is like Register but uses the provided name for the type
   230  // instead of the receiver's concrete type.
   231  func (server *Server) RegisterName(name string, rcvr any) error {
   232  	return server.register(rcvr, name, true)
   233  }
   234  
   235  // logRegisterError specifies whether to log problems during method registration.
   236  // To debug registration, recompile the package with this set to true.
   237  const logRegisterError = false
   238  
   239  func (server *Server) register(rcvr any, name string, useName bool) error {
   240  	s := new(service)
   241  	s.typ = reflect.TypeOf(rcvr)
   242  	s.rcvr = reflect.ValueOf(rcvr)
   243  	sname := name
   244  	if !useName {
   245  		sname = reflect.Indirect(s.rcvr).Type().Name()
   246  	}
   247  	if sname == "" {
   248  		s := "rpc.Register: no service name for type " + s.typ.String()
   249  		log.Print(s)
   250  		return errors.New(s)
   251  	}
   252  	if !useName && !token.IsExported(sname) {
   253  		s := "rpc.Register: type " + sname + " is not exported"
   254  		log.Print(s)
   255  		return errors.New(s)
   256  	}
   257  	s.name = sname
   258  
   259  	// Install the methods
   260  	s.method = suitableMethods(s.typ, logRegisterError)
   261  
   262  	if len(s.method) == 0 {
   263  		str := ""
   264  
   265  		// To help the user, see if a pointer receiver would work.
   266  		method := suitableMethods(reflect.PointerTo(s.typ), false)
   267  		if len(method) != 0 {
   268  			str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)"
   269  		} else {
   270  			str = "rpc.Register: type " + sname + " has no exported methods of suitable type"
   271  		}
   272  		log.Print(str)
   273  		return errors.New(str)
   274  	}
   275  
   276  	if _, dup := server.serviceMap.LoadOrStore(sname, s); dup {
   277  		return errors.New("rpc: service already defined: " + sname)
   278  	}
   279  	return nil
   280  }
   281  
   282  // suitableMethods returns suitable Rpc methods of typ. It will log
   283  // errors if logErr is true.
   284  func suitableMethods(typ reflect.Type, logErr bool) map[string]*methodType {
   285  	methods := make(map[string]*methodType)
   286  	for m := 0; m < typ.NumMethod(); m++ {
   287  		method := typ.Method(m)
   288  		mtype := method.Type
   289  		mname := method.Name
   290  		// Method must be exported.
   291  		if !method.IsExported() {
   292  			continue
   293  		}
   294  		// Method needs three ins: receiver, *args, *reply.
   295  		if mtype.NumIn() != 3 {
   296  			if logErr {
   297  				log.Printf("rpc.Register: method %q has %d input parameters; needs exactly three\n", mname, mtype.NumIn())
   298  			}
   299  			continue
   300  		}
   301  		// First arg need not be a pointer.
   302  		argType := mtype.In(1)
   303  		if !isExportedOrBuiltinType(argType) {
   304  			if logErr {
   305  				log.Printf("rpc.Register: argument type of method %q is not exported: %q\n", mname, argType)
   306  			}
   307  			continue
   308  		}
   309  		// Second arg must be a pointer.
   310  		replyType := mtype.In(2)
   311  		if replyType.Kind() != reflect.Pointer {
   312  			if logErr {
   313  				log.Printf("rpc.Register: reply type of method %q is not a pointer: %q\n", mname, replyType)
   314  			}
   315  			continue
   316  		}
   317  		// Reply type must be exported.
   318  		if !isExportedOrBuiltinType(replyType) {
   319  			if logErr {
   320  				log.Printf("rpc.Register: reply type of method %q is not exported: %q\n", mname, replyType)
   321  			}
   322  			continue
   323  		}
   324  		// Method needs one out.
   325  		if mtype.NumOut() != 1 {
   326  			if logErr {
   327  				log.Printf("rpc.Register: method %q has %d output parameters; needs exactly one\n", mname, mtype.NumOut())
   328  			}
   329  			continue
   330  		}
   331  		// The return type of the method must be error.
   332  		if returnType := mtype.Out(0); returnType != typeOfError {
   333  			if logErr {
   334  				log.Printf("rpc.Register: return type of method %q is %q, must be error\n", mname, returnType)
   335  			}
   336  			continue
   337  		}
   338  		methods[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
   339  	}
   340  	return methods
   341  }
   342  
   343  // A value sent as a placeholder for the server's response value when the server
   344  // receives an invalid request. It is never decoded by the client since the Response
   345  // contains an error when it is used.
   346  var invalidRequest = struct{}{}
   347  
   348  func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply any, codec ServerCodec, errmsg string) {
   349  	resp := server.getResponse()
   350  	// Encode the response header
   351  	resp.ServiceMethod = req.ServiceMethod
   352  	if errmsg != "" {
   353  		resp.Error = errmsg
   354  		reply = invalidRequest
   355  	}
   356  	resp.Seq = req.Seq
   357  	sending.Lock()
   358  	err := codec.WriteResponse(resp, reply)
   359  	if debugLog && err != nil {
   360  		log.Println("rpc: writing response:", err)
   361  	}
   362  	sending.Unlock()
   363  	server.freeResponse(resp)
   364  }
   365  
   366  func (m *methodType) NumCalls() (n uint) {
   367  	m.Lock()
   368  	n = m.numCalls
   369  	m.Unlock()
   370  	return n
   371  }
   372  
   373  func (s *service) call(server *Server, sending *sync.Mutex, wg *sync.WaitGroup, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
   374  	if wg != nil {
   375  		defer wg.Done()
   376  	}
   377  	mtype.Lock()
   378  	mtype.numCalls++
   379  	mtype.Unlock()
   380  	function := mtype.method.Func
   381  	// Invoke the method, providing a new value for the reply.
   382  	returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
   383  	// The return value for the method is an error.
   384  	errInter := returnValues[0].Interface()
   385  	errmsg := ""
   386  	if errInter != nil {
   387  		errmsg = errInter.(error).Error()
   388  	}
   389  	server.sendResponse(sending, req, replyv.Interface(), codec, errmsg)
   390  	server.freeRequest(req)
   391  }
   392  
   393  type gobServerCodec struct {
   394  	rwc    io.ReadWriteCloser
   395  	dec    *gob.Decoder
   396  	enc    *gob.Encoder
   397  	encBuf *bufio.Writer
   398  	closed bool
   399  }
   400  
   401  func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
   402  	return c.dec.Decode(r)
   403  }
   404  
   405  func (c *gobServerCodec) ReadRequestBody(body any) error {
   406  	return c.dec.Decode(body)
   407  }
   408  
   409  func (c *gobServerCodec) WriteResponse(r *Response, body any) (err error) {
   410  	if err = c.enc.Encode(r); err != nil {
   411  		if c.encBuf.Flush() == nil {
   412  			// Gob couldn't encode the header. Should not happen, so if it does,
   413  			// shut down the connection to signal that the connection is broken.
   414  			log.Println("rpc: gob error encoding response:", err)
   415  			c.Close()
   416  		}
   417  		return
   418  	}
   419  	if err = c.enc.Encode(body); err != nil {
   420  		if c.encBuf.Flush() == nil {
   421  			// Was a gob problem encoding the body but the header has been written.
   422  			// Shut down the connection to signal that the connection is broken.
   423  			log.Println("rpc: gob error encoding body:", err)
   424  			c.Close()
   425  		}
   426  		return
   427  	}
   428  	return c.encBuf.Flush()
   429  }
   430  
   431  func (c *gobServerCodec) Close() error {
   432  	if c.closed {
   433  		// Only call c.rwc.Close once; otherwise the semantics are undefined.
   434  		return nil
   435  	}
   436  	c.closed = true
   437  	return c.rwc.Close()
   438  }
   439  
   440  // ServeConn runs the server on a single connection.
   441  // ServeConn blocks, serving the connection until the client hangs up.
   442  // The caller typically invokes ServeConn in a go statement.
   443  // ServeConn uses the gob wire format (see package gob) on the
   444  // connection. To use an alternate codec, use ServeCodec.
   445  // See NewClient's comment for information about concurrent access.
   446  func (server *Server) ServeConn(conn io.ReadWriteCloser) {
   447  	buf := bufio.NewWriter(conn)
   448  	srv := &gobServerCodec{
   449  		rwc:    conn,
   450  		dec:    gob.NewDecoder(conn),
   451  		enc:    gob.NewEncoder(buf),
   452  		encBuf: buf,
   453  	}
   454  	server.ServeCodec(srv)
   455  }
   456  
   457  // ServeCodec is like ServeConn but uses the specified codec to
   458  // decode requests and encode responses.
   459  func (server *Server) ServeCodec(codec ServerCodec) {
   460  	sending := new(sync.Mutex)
   461  	wg := new(sync.WaitGroup)
   462  	for {
   463  		service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
   464  		if err != nil {
   465  			if debugLog && err != io.EOF {
   466  				log.Println("rpc:", err)
   467  			}
   468  			if !keepReading {
   469  				break
   470  			}
   471  			// send a response if we actually managed to read a header.
   472  			if req != nil {
   473  				server.sendResponse(sending, req, invalidRequest, codec, err.Error())
   474  				server.freeRequest(req)
   475  			}
   476  			continue
   477  		}
   478  		wg.Add(1)
   479  		go service.call(server, sending, wg, mtype, req, argv, replyv, codec)
   480  	}
   481  	// We've seen that there are no more requests.
   482  	// Wait for responses to be sent before closing codec.
   483  	wg.Wait()
   484  	codec.Close()
   485  }
   486  
   487  // ServeRequest is like ServeCodec but synchronously serves a single request.
   488  // It does not close the codec upon completion.
   489  func (server *Server) ServeRequest(codec ServerCodec) error {
   490  	sending := new(sync.Mutex)
   491  	service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
   492  	if err != nil {
   493  		if !keepReading {
   494  			return err
   495  		}
   496  		// send a response if we actually managed to read a header.
   497  		if req != nil {
   498  			server.sendResponse(sending, req, invalidRequest, codec, err.Error())
   499  			server.freeRequest(req)
   500  		}
   501  		return err
   502  	}
   503  	service.call(server, sending, nil, mtype, req, argv, replyv, codec)
   504  	return nil
   505  }
   506  
   507  func (server *Server) getRequest() *Request {
   508  	server.reqLock.Lock()
   509  	req := server.freeReq
   510  	if req == nil {
   511  		req = new(Request)
   512  	} else {
   513  		server.freeReq = req.next
   514  		*req = Request{}
   515  	}
   516  	server.reqLock.Unlock()
   517  	return req
   518  }
   519  
   520  func (server *Server) freeRequest(req *Request) {
   521  	server.reqLock.Lock()
   522  	req.next = server.freeReq
   523  	server.freeReq = req
   524  	server.reqLock.Unlock()
   525  }
   526  
   527  func (server *Server) getResponse() *Response {
   528  	server.respLock.Lock()
   529  	resp := server.freeResp
   530  	if resp == nil {
   531  		resp = new(Response)
   532  	} else {
   533  		server.freeResp = resp.next
   534  		*resp = Response{}
   535  	}
   536  	server.respLock.Unlock()
   537  	return resp
   538  }
   539  
   540  func (server *Server) freeResponse(resp *Response) {
   541  	server.respLock.Lock()
   542  	resp.next = server.freeResp
   543  	server.freeResp = resp
   544  	server.respLock.Unlock()
   545  }
   546  
   547  func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) {
   548  	service, mtype, req, keepReading, err = server.readRequestHeader(codec)
   549  	if err != nil {
   550  		if !keepReading {
   551  			return
   552  		}
   553  		// discard body
   554  		codec.ReadRequestBody(nil)
   555  		return
   556  	}
   557  
   558  	// Decode the argument value.
   559  	argIsValue := false // if true, need to indirect before calling.
   560  	if mtype.ArgType.Kind() == reflect.Pointer {
   561  		argv = reflect.New(mtype.ArgType.Elem())
   562  	} else {
   563  		argv = reflect.New(mtype.ArgType)
   564  		argIsValue = true
   565  	}
   566  	// argv guaranteed to be a pointer now.
   567  	if err = codec.ReadRequestBody(argv.Interface()); err != nil {
   568  		return
   569  	}
   570  	if argIsValue {
   571  		argv = argv.Elem()
   572  	}
   573  
   574  	replyv = reflect.New(mtype.ReplyType.Elem())
   575  
   576  	switch mtype.ReplyType.Elem().Kind() {
   577  	case reflect.Map:
   578  		replyv.Elem().Set(reflect.MakeMap(mtype.ReplyType.Elem()))
   579  	case reflect.Slice:
   580  		replyv.Elem().Set(reflect.MakeSlice(mtype.ReplyType.Elem(), 0, 0))
   581  	}
   582  	return
   583  }
   584  
   585  func (server *Server) readRequestHeader(codec ServerCodec) (svc *service, mtype *methodType, req *Request, keepReading bool, err error) {
   586  	// Grab the request header.
   587  	req = server.getRequest()
   588  	err = codec.ReadRequestHeader(req)
   589  	if err != nil {
   590  		req = nil
   591  		if err == io.EOF || err == io.ErrUnexpectedEOF {
   592  			return
   593  		}
   594  		err = errors.New("rpc: server cannot decode request: " + err.Error())
   595  		return
   596  	}
   597  
   598  	// We read the header successfully. If we see an error now,
   599  	// we can still recover and move on to the next request.
   600  	keepReading = true
   601  
   602  	dot := strings.LastIndex(req.ServiceMethod, ".")
   603  	if dot < 0 {
   604  		err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod)
   605  		return
   606  	}
   607  	serviceName := req.ServiceMethod[:dot]
   608  	methodName := req.ServiceMethod[dot+1:]
   609  
   610  	// Look up the request.
   611  	svci, ok := server.serviceMap.Load(serviceName)
   612  	if !ok {
   613  		err = errors.New("rpc: can't find service " + req.ServiceMethod)
   614  		return
   615  	}
   616  	svc = svci.(*service)
   617  	mtype = svc.method[methodName]
   618  	if mtype == nil {
   619  		err = errors.New("rpc: can't find method " + req.ServiceMethod)
   620  	}
   621  	return
   622  }
   623  
   624  // Accept accepts connections on the listener and serves requests
   625  // for each incoming connection. Accept blocks until the listener
   626  // returns a non-nil error. The caller typically invokes Accept in a
   627  // go statement.
   628  func (server *Server) Accept(lis net.Listener) {
   629  	for {
   630  		conn, err := lis.Accept()
   631  		if err != nil {
   632  			log.Print("rpc.Serve: accept:", err.Error())
   633  			return
   634  		}
   635  		go server.ServeConn(conn)
   636  	}
   637  }
   638  
   639  // Register publishes the receiver's methods in the DefaultServer.
   640  func Register(rcvr any) error { return DefaultServer.Register(rcvr) }
   641  
   642  // RegisterName is like Register but uses the provided name for the type
   643  // instead of the receiver's concrete type.
   644  func RegisterName(name string, rcvr any) error {
   645  	return DefaultServer.RegisterName(name, rcvr)
   646  }
   647  
   648  // A ServerCodec implements reading of RPC requests and writing of
   649  // RPC responses for the server side of an RPC session.
   650  // The server calls ReadRequestHeader and ReadRequestBody in pairs
   651  // to read requests from the connection, and it calls WriteResponse to
   652  // write a response back. The server calls Close when finished with the
   653  // connection. ReadRequestBody may be called with a nil
   654  // argument to force the body of the request to be read and discarded.
   655  // See NewClient's comment for information about concurrent access.
   656  type ServerCodec interface {
   657  	ReadRequestHeader(*Request) error
   658  	ReadRequestBody(any) error
   659  	WriteResponse(*Response, any) error
   660  
   661  	// Close can be called multiple times and must be idempotent.
   662  	Close() error
   663  }
   664  
   665  // ServeConn runs the DefaultServer on a single connection.
   666  // ServeConn blocks, serving the connection until the client hangs up.
   667  // The caller typically invokes ServeConn in a go statement.
   668  // ServeConn uses the gob wire format (see package gob) on the
   669  // connection. To use an alternate codec, use ServeCodec.
   670  // See NewClient's comment for information about concurrent access.
   671  func ServeConn(conn io.ReadWriteCloser) {
   672  	DefaultServer.ServeConn(conn)
   673  }
   674  
   675  // ServeCodec is like ServeConn but uses the specified codec to
   676  // decode requests and encode responses.
   677  func ServeCodec(codec ServerCodec) {
   678  	DefaultServer.ServeCodec(codec)
   679  }
   680  
   681  // ServeRequest is like ServeCodec but synchronously serves a single request.
   682  // It does not close the codec upon completion.
   683  func ServeRequest(codec ServerCodec) error {
   684  	return DefaultServer.ServeRequest(codec)
   685  }
   686  
   687  // Accept accepts connections on the listener and serves requests
   688  // to DefaultServer for each incoming connection.
   689  // Accept blocks; the caller typically invokes it in a go statement.
   690  func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
   691  
   692  // Can connect to RPC service using HTTP CONNECT to rpcPath.
   693  var connected = "200 Connected to Go RPC"
   694  
   695  // ServeHTTP implements an http.Handler that answers RPC requests.
   696  func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   697  	if req.Method != "CONNECT" {
   698  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
   699  		w.WriteHeader(http.StatusMethodNotAllowed)
   700  		io.WriteString(w, "405 must CONNECT\n")
   701  		return
   702  	}
   703  	conn, _, err := w.(http.Hijacker).Hijack()
   704  	if err != nil {
   705  		log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
   706  		return
   707  	}
   708  	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
   709  	server.ServeConn(conn)
   710  }
   711  
   712  // HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
   713  // and a debugging handler on debugPath.
   714  // It is still necessary to invoke http.Serve(), typically in a go statement.
   715  func (server *Server) HandleHTTP(rpcPath, debugPath string) {
   716  	http.Handle(rpcPath, server)
   717  	http.Handle(debugPath, debugHTTP{server})
   718  }
   719  
   720  // HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
   721  // on DefaultRPCPath and a debugging handler on DefaultDebugPath.
   722  // It is still necessary to invoke http.Serve(), typically in a go statement.
   723  func HandleHTTP() {
   724  	DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath)
   725  }
   726  

View as plain text