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