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