github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/src/net/rpc/server.go (about) 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.Println("method", mname, "has wrong number of ins:", 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.Println(mname, "argument type not exported:", 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.Println("method", mname, "reply type not a pointer:", replyType) 316 } 317 continue 318 } 319 // Reply type must be exported. 320 if !isExportedOrBuiltinType(replyType) { 321 if reportErr { 322 log.Println("method", mname, "reply type not exported:", replyType) 323 } 324 continue 325 } 326 // Method needs one out. 327 if mtype.NumOut() != 1 { 328 if reportErr { 329 log.Println("method", mname, "has wrong number of outs:", 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.Println("method", mname, "returns", returnType.String(), "not error") 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, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) { 376 mtype.Lock() 377 mtype.numCalls++ 378 mtype.Unlock() 379 function := mtype.method.Func 380 // Invoke the method, providing a new value for the reply. 381 returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv}) 382 // The return value for the method is an error. 383 errInter := returnValues[0].Interface() 384 errmsg := "" 385 if errInter != nil { 386 errmsg = errInter.(error).Error() 387 } 388 server.sendResponse(sending, req, replyv.Interface(), codec, errmsg) 389 server.freeRequest(req) 390 } 391 392 type gobServerCodec struct { 393 rwc io.ReadWriteCloser 394 dec *gob.Decoder 395 enc *gob.Encoder 396 encBuf *bufio.Writer 397 closed bool 398 } 399 400 func (c *gobServerCodec) ReadRequestHeader(r *Request) error { 401 return c.dec.Decode(r) 402 } 403 404 func (c *gobServerCodec) ReadRequestBody(body interface{}) error { 405 return c.dec.Decode(body) 406 } 407 408 func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) { 409 if err = c.enc.Encode(r); err != nil { 410 if c.encBuf.Flush() == nil { 411 // Gob couldn't encode the header. Should not happen, so if it does, 412 // shut down the connection to signal that the connection is broken. 413 log.Println("rpc: gob error encoding response:", err) 414 c.Close() 415 } 416 return 417 } 418 if err = c.enc.Encode(body); err != nil { 419 if c.encBuf.Flush() == nil { 420 // Was a gob problem encoding the body but the header has been written. 421 // Shut down the connection to signal that the connection is broken. 422 log.Println("rpc: gob error encoding body:", err) 423 c.Close() 424 } 425 return 426 } 427 return c.encBuf.Flush() 428 } 429 430 func (c *gobServerCodec) Close() error { 431 if c.closed { 432 // Only call c.rwc.Close once; otherwise the semantics are undefined. 433 return nil 434 } 435 c.closed = true 436 return c.rwc.Close() 437 } 438 439 // ServeConn runs the server on a single connection. 440 // ServeConn blocks, serving the connection until the client hangs up. 441 // The caller typically invokes ServeConn in a go statement. 442 // ServeConn uses the gob wire format (see package gob) on the 443 // connection. To use an alternate codec, use ServeCodec. 444 func (server *Server) ServeConn(conn io.ReadWriteCloser) { 445 buf := bufio.NewWriter(conn) 446 srv := &gobServerCodec{ 447 rwc: conn, 448 dec: gob.NewDecoder(conn), 449 enc: gob.NewEncoder(buf), 450 encBuf: buf, 451 } 452 server.ServeCodec(srv) 453 } 454 455 // ServeCodec is like ServeConn but uses the specified codec to 456 // decode requests and encode responses. 457 func (server *Server) ServeCodec(codec ServerCodec) { 458 sending := new(sync.Mutex) 459 for { 460 service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec) 461 if err != nil { 462 if debugLog && err != io.EOF { 463 log.Println("rpc:", err) 464 } 465 if !keepReading { 466 break 467 } 468 // send a response if we actually managed to read a header. 469 if req != nil { 470 server.sendResponse(sending, req, invalidRequest, codec, err.Error()) 471 server.freeRequest(req) 472 } 473 continue 474 } 475 go service.call(server, sending, mtype, req, argv, replyv, codec) 476 } 477 codec.Close() 478 } 479 480 // ServeRequest is like ServeCodec but synchronously serves a single request. 481 // It does not close the codec upon completion. 482 func (server *Server) ServeRequest(codec ServerCodec) error { 483 sending := new(sync.Mutex) 484 service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec) 485 if err != nil { 486 if !keepReading { 487 return err 488 } 489 // send a response if we actually managed to read a header. 490 if req != nil { 491 server.sendResponse(sending, req, invalidRequest, codec, err.Error()) 492 server.freeRequest(req) 493 } 494 return err 495 } 496 service.call(server, sending, mtype, req, argv, replyv, codec) 497 return nil 498 } 499 500 func (server *Server) getRequest() *Request { 501 server.reqLock.Lock() 502 req := server.freeReq 503 if req == nil { 504 req = new(Request) 505 } else { 506 server.freeReq = req.next 507 *req = Request{} 508 } 509 server.reqLock.Unlock() 510 return req 511 } 512 513 func (server *Server) freeRequest(req *Request) { 514 server.reqLock.Lock() 515 req.next = server.freeReq 516 server.freeReq = req 517 server.reqLock.Unlock() 518 } 519 520 func (server *Server) getResponse() *Response { 521 server.respLock.Lock() 522 resp := server.freeResp 523 if resp == nil { 524 resp = new(Response) 525 } else { 526 server.freeResp = resp.next 527 *resp = Response{} 528 } 529 server.respLock.Unlock() 530 return resp 531 } 532 533 func (server *Server) freeResponse(resp *Response) { 534 server.respLock.Lock() 535 resp.next = server.freeResp 536 server.freeResp = resp 537 server.respLock.Unlock() 538 } 539 540 func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) { 541 service, mtype, req, keepReading, err = server.readRequestHeader(codec) 542 if err != nil { 543 if !keepReading { 544 return 545 } 546 // discard body 547 codec.ReadRequestBody(nil) 548 return 549 } 550 551 // Decode the argument value. 552 argIsValue := false // if true, need to indirect before calling. 553 if mtype.ArgType.Kind() == reflect.Ptr { 554 argv = reflect.New(mtype.ArgType.Elem()) 555 } else { 556 argv = reflect.New(mtype.ArgType) 557 argIsValue = true 558 } 559 // argv guaranteed to be a pointer now. 560 if err = codec.ReadRequestBody(argv.Interface()); err != nil { 561 return 562 } 563 if argIsValue { 564 argv = argv.Elem() 565 } 566 567 replyv = reflect.New(mtype.ReplyType.Elem()) 568 569 switch mtype.ReplyType.Elem().Kind() { 570 case reflect.Map: 571 replyv.Elem().Set(reflect.MakeMap(mtype.ReplyType.Elem())) 572 case reflect.Slice: 573 replyv.Elem().Set(reflect.MakeSlice(mtype.ReplyType.Elem(), 0, 0)) 574 } 575 return 576 } 577 578 func (server *Server) readRequestHeader(codec ServerCodec) (svc *service, mtype *methodType, req *Request, keepReading bool, err error) { 579 // Grab the request header. 580 req = server.getRequest() 581 err = codec.ReadRequestHeader(req) 582 if err != nil { 583 req = nil 584 if err == io.EOF || err == io.ErrUnexpectedEOF { 585 return 586 } 587 err = errors.New("rpc: server cannot decode request: " + err.Error()) 588 return 589 } 590 591 // We read the header successfully. If we see an error now, 592 // we can still recover and move on to the next request. 593 keepReading = true 594 595 dot := strings.LastIndex(req.ServiceMethod, ".") 596 if dot < 0 { 597 err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod) 598 return 599 } 600 serviceName := req.ServiceMethod[:dot] 601 methodName := req.ServiceMethod[dot+1:] 602 603 // Look up the request. 604 svci, ok := server.serviceMap.Load(serviceName) 605 if !ok { 606 err = errors.New("rpc: can't find service " + req.ServiceMethod) 607 return 608 } 609 svc = svci.(*service) 610 mtype = svc.method[methodName] 611 if mtype == nil { 612 err = errors.New("rpc: can't find method " + req.ServiceMethod) 613 } 614 return 615 } 616 617 // Accept accepts connections on the listener and serves requests 618 // for each incoming connection. Accept blocks until the listener 619 // returns a non-nil error. The caller typically invokes Accept in a 620 // go statement. 621 func (server *Server) Accept(lis net.Listener) { 622 for { 623 conn, err := lis.Accept() 624 if err != nil { 625 log.Print("rpc.Serve: accept:", err.Error()) 626 return 627 } 628 go server.ServeConn(conn) 629 } 630 } 631 632 // Register publishes the receiver's methods in the DefaultServer. 633 func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) } 634 635 // RegisterName is like Register but uses the provided name for the type 636 // instead of the receiver's concrete type. 637 func RegisterName(name string, rcvr interface{}) error { 638 return DefaultServer.RegisterName(name, rcvr) 639 } 640 641 // A ServerCodec implements reading of RPC requests and writing of 642 // RPC responses for the server side of an RPC session. 643 // The server calls ReadRequestHeader and ReadRequestBody in pairs 644 // to read requests from the connection, and it calls WriteResponse to 645 // write a response back. The server calls Close when finished with the 646 // connection. ReadRequestBody may be called with a nil 647 // argument to force the body of the request to be read and discarded. 648 type ServerCodec interface { 649 ReadRequestHeader(*Request) error 650 ReadRequestBody(interface{}) error 651 // WriteResponse must be safe for concurrent use by multiple goroutines. 652 WriteResponse(*Response, interface{}) error 653 654 Close() error 655 } 656 657 // ServeConn runs the DefaultServer on a single connection. 658 // ServeConn blocks, serving the connection until the client hangs up. 659 // The caller typically invokes ServeConn in a go statement. 660 // ServeConn uses the gob wire format (see package gob) on the 661 // connection. To use an alternate codec, use ServeCodec. 662 func ServeConn(conn io.ReadWriteCloser) { 663 DefaultServer.ServeConn(conn) 664 } 665 666 // ServeCodec is like ServeConn but uses the specified codec to 667 // decode requests and encode responses. 668 func ServeCodec(codec ServerCodec) { 669 DefaultServer.ServeCodec(codec) 670 } 671 672 // ServeRequest is like ServeCodec but synchronously serves a single request. 673 // It does not close the codec upon completion. 674 func ServeRequest(codec ServerCodec) error { 675 return DefaultServer.ServeRequest(codec) 676 } 677 678 // Accept accepts connections on the listener and serves requests 679 // to DefaultServer for each incoming connection. 680 // Accept blocks; the caller typically invokes it in a go statement. 681 func Accept(lis net.Listener) { DefaultServer.Accept(lis) } 682 683 // Can connect to RPC service using HTTP CONNECT to rpcPath. 684 var connected = "200 Connected to Go RPC" 685 686 // ServeHTTP implements an http.Handler that answers RPC requests. 687 func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { 688 if req.Method != "CONNECT" { 689 w.Header().Set("Content-Type", "text/plain; charset=utf-8") 690 w.WriteHeader(http.StatusMethodNotAllowed) 691 io.WriteString(w, "405 must CONNECT\n") 692 return 693 } 694 conn, _, err := w.(http.Hijacker).Hijack() 695 if err != nil { 696 log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error()) 697 return 698 } 699 io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n") 700 server.ServeConn(conn) 701 } 702 703 // HandleHTTP registers an HTTP handler for RPC messages on rpcPath, 704 // and a debugging handler on debugPath. 705 // It is still necessary to invoke http.Serve(), typically in a go statement. 706 func (server *Server) HandleHTTP(rpcPath, debugPath string) { 707 http.Handle(rpcPath, server) 708 http.Handle(debugPath, debugHTTP{server}) 709 } 710 711 // HandleHTTP registers an HTTP handler for RPC messages to DefaultServer 712 // on DefaultRPCPath and a debugging handler on DefaultDebugPath. 713 // It is still necessary to invoke http.Serve(), typically in a go statement. 714 func HandleHTTP() { 715 DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath) 716 }