...
Run Format

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

View as plain text