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