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