github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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 "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 }