github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/rpc/server.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package rpc 5 6 import ( 7 "io" 8 "reflect" 9 "sync" 10 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 14 "github.com/juju/juju/rpc/rpcreflect" 15 ) 16 17 const codeNotImplemented = "not implemented" 18 19 var logger = loggo.GetLogger("juju.rpc") 20 21 // A Codec implements reading and writing of messages in an RPC 22 // session. The RPC code calls WriteMessage to write a message to the 23 // connection and calls ReadHeader and ReadBody in pairs to read 24 // messages. 25 type Codec interface { 26 // ReadHeader reads a message header into hdr. 27 ReadHeader(hdr *Header) error 28 29 // ReadBody reads a message body into the given body value. The 30 // isRequest parameter specifies whether the message being read 31 // is a request; if not, it's a response. The body value will 32 // be a non-nil struct pointer, or nil to signify that the body 33 // should be read and discarded. 34 ReadBody(body interface{}, isRequest bool) error 35 36 // WriteMessage writes a message with the given header and body. 37 // The body will always be a struct. It may be called concurrently 38 // with ReadHeader and ReadBody, but will not be called 39 // concurrently with itself. 40 WriteMessage(hdr *Header, body interface{}) error 41 42 // Close closes the codec. It may be called concurrently 43 // and should cause the Read methods to unblock. 44 Close() error 45 } 46 47 // Header is a header written before every RPC call. Since RPC requests 48 // can be initiated from either side, the header may represent a request 49 // from the other side or a response to an outstanding request. 50 type Header struct { 51 // RequestId holds the sequence number of the request. 52 // For replies, it holds the sequence number of the request 53 // that is being replied to. 54 RequestId uint64 55 56 // Request holds the action to invoke. 57 Request Request 58 59 // Error holds the error, if any. 60 Error string 61 62 // ErrorCode holds the code of the error, if any. 63 ErrorCode string 64 65 // Version defines the wire format of the request and response structure. 66 Version int 67 } 68 69 // Request represents an RPC to be performed, absent its parameters. 70 type Request struct { 71 // Type holds the type of object to act on. 72 Type string 73 74 // Version holds the version of Type we will be acting on 75 Version int 76 77 // Id holds the id of the object to act on. 78 Id string 79 80 // Action holds the action to perform on the object. 81 Action string 82 } 83 84 // IsRequest returns whether the header represents an RPC request. If 85 // it is not a request, it is a response. 86 func (hdr *Header) IsRequest() bool { 87 return hdr.Request.Type != "" || hdr.Request.Action != "" 88 } 89 90 // ObserverFactory is a type which can construct a new Observer. 91 type ObserverFactory interface { 92 93 // RPCObserver will return a new Observer usually constructed 94 // from the state previously built up in the Observer. The 95 // returned instance will be utilized per RPC request. 96 RPCObserver() Observer 97 } 98 99 // Note that we use "client request" and "server request" to name 100 // requests initiated locally and remotely respectively. 101 102 // Conn represents an RPC endpoint. It can both initiate and receive 103 // RPC requests. There may be multiple outstanding Calls associated 104 // with a single Client, and a Client may be used by multiple goroutines 105 // simultaneously. 106 type Conn struct { 107 // codec holds the underlying RPC connection. 108 codec Codec 109 110 // srvPending represents the current server requests. 111 srvPending sync.WaitGroup 112 113 // sending guards the write side of the codec - it ensures 114 // that codec.WriteMessage is not called concurrently. 115 // It also guards shutdown. 116 sending sync.Mutex 117 118 // mutex guards the following values. 119 mutex sync.Mutex 120 121 // root represents the current root object that serves the RPC requests. 122 // It may be nil if nothing is being served. 123 root Root 124 125 // transformErrors is used to transform returned errors. 126 transformErrors func(error) error 127 128 // reqId holds the latest client request id. 129 reqId uint64 130 131 // clientPending holds all pending client requests. 132 clientPending map[uint64]*Call 133 134 // closing is set when the connection is shutting down via 135 // Close. When this is set, no more client or server requests 136 // will be initiated. 137 closing bool 138 139 // shutdown is set when the input loop terminates. When this 140 // is set, no more client requests will be sent to the server. 141 shutdown bool 142 143 // dead is closed when the input loop terminates. 144 dead chan struct{} 145 146 // inputLoopError holds the error that caused the input loop to 147 // terminate prematurely. It is set before dead is closed. 148 inputLoopError error 149 150 observerFactory ObserverFactory 151 } 152 153 // NewConn creates a new connection that uses the given codec for 154 // transport, but it does not start it. Conn.Start must be called before 155 // any requests are sent or received. If notifier is non-nil, the 156 // appropriate method will be called for every RPC request. 157 func NewConn(codec Codec, observerFactory ObserverFactory) *Conn { 158 return &Conn{ 159 codec: codec, 160 clientPending: make(map[uint64]*Call), 161 observerFactory: observerFactory, 162 } 163 } 164 165 // Start starts the RPC connection running. It must be called at 166 // least once for any RPC connection (client or server side) It has no 167 // effect if it has already been called. By default, a connection 168 // serves no methods. See Conn.Serve for a description of how to 169 // serve methods on a Conn. 170 func (conn *Conn) Start() { 171 conn.mutex.Lock() 172 defer conn.mutex.Unlock() 173 if conn.dead == nil { 174 conn.dead = make(chan struct{}) 175 go conn.input() 176 } 177 } 178 179 // Serve serves RPC requests on the connection by invoking methods on 180 // root. Note that it does not start the connection running, 181 // though it may be called once the connection is already started. 182 // 183 // The server executes each client request by calling a method on root 184 // to obtain an object to act on; then it invokes an method on that 185 // object with the request parameters, possibly returning some result. 186 // 187 // Methods on the root value are of the form: 188 // 189 // M(id string) (O, error) 190 // 191 // where M is an exported name, conventionally naming the object type, 192 // id is some identifier for the object and O is the type of the 193 // returned object. 194 // 195 // Methods defined on O may defined in one of the following forms, where 196 // T and R must be struct types. 197 // 198 // Method() 199 // Method() R 200 // Method() (R, error) 201 // Method() error 202 // Method(T) 203 // Method(T) R 204 // Method(T) (R, error) 205 // Method(T) error 206 // 207 // If transformErrors is non-nil, it will be called on all returned 208 // non-nil errors, for example to transform the errors into ServerErrors 209 // with specified codes. There will be a panic if transformErrors 210 // returns nil. 211 // 212 // Serve may be called at any time on a connection to change the 213 // set of methods being served by the connection. This will have 214 // no effect on calls that are currently being services. 215 // If root is nil, the connection will serve no methods. 216 func (conn *Conn) Serve(root interface{}, transformErrors func(error) error) { 217 rootValue := rpcreflect.ValueOf(reflect.ValueOf(root)) 218 if rootValue.IsValid() { 219 conn.serve(rootValue, transformErrors) 220 } else { 221 conn.serve(nil, transformErrors) 222 } 223 } 224 225 // ServeRoot is like Serve except that it gives the root object dynamic 226 // control over what methods are available instead of using reflection 227 // on the type. 228 // 229 // The server executes each client request by calling FindMethod to obtain a 230 // method to invoke. It invokes that method with the request parameters, 231 // possibly returning some result. 232 // 233 // The Kill method will be called when the connection is closed. 234 func (conn *Conn) ServeRoot(root Root, transformErrors func(error) error) { 235 conn.serve(root, transformErrors) 236 } 237 238 func (conn *Conn) serve(root Root, transformErrors func(error) error) { 239 if transformErrors == nil { 240 transformErrors = noopTransform 241 } 242 conn.mutex.Lock() 243 defer conn.mutex.Unlock() 244 conn.root = root 245 conn.transformErrors = transformErrors 246 } 247 248 // noopTransform is used when transformErrors is not supplied to Serve. 249 func noopTransform(err error) error { 250 return err 251 } 252 253 // Dead returns a channel that is closed when the connection 254 // has been closed or the underlying transport has received 255 // an error. There may still be outstanding requests. 256 // Dead must be called after conn.Start has been called. 257 func (conn *Conn) Dead() <-chan struct{} { 258 return conn.dead 259 } 260 261 // Close closes the connection and its underlying codec; it returns when 262 // all requests have been terminated. 263 // 264 // If the connection is serving requests, and the root value implements 265 // the Killer interface, its Kill method will be called. The codec will 266 // then be closed only when all its outstanding server calls have 267 // completed. 268 // 269 // Calling Close multiple times is not an error. 270 func (conn *Conn) Close() error { 271 conn.mutex.Lock() 272 if conn.closing { 273 conn.mutex.Unlock() 274 // Golang's net/rpc returns rpc.ErrShutdown if you ask to close 275 // a closing or shutdown connection. Our choice is that Close 276 // is an idempotent way to ask for resources to be released and 277 // isn't a failure if called multiple times. 278 return nil 279 } 280 conn.closing = true 281 if conn.root != nil { 282 conn.root.Kill() 283 } 284 conn.mutex.Unlock() 285 286 // Wait for any outstanding server requests to complete 287 // and write their replies before closing the codec. 288 conn.srvPending.Wait() 289 290 // Closing the codec should cause the input loop to terminate. 291 if err := conn.codec.Close(); err != nil { 292 logger.Infof("error closing codec: %v", err) 293 } 294 <-conn.dead 295 296 return conn.inputLoopError 297 } 298 299 // ErrorCoder represents an any error that has an associated 300 // error code. An error code is a short string that represents the 301 // kind of an error. 302 type ErrorCoder interface { 303 ErrorCode() string 304 } 305 306 // Root represents a type that can be used to lookup a Method and place 307 // calls on that method. 308 type Root interface { 309 FindMethod(rootName string, version int, methodName string) (rpcreflect.MethodCaller, error) 310 Killer 311 } 312 313 // Killer represents a type that can be asked to abort any outstanding 314 // requests. The Kill method should return immediately. 315 type Killer interface { 316 Kill() 317 } 318 319 // input reads messages from the connection and handles them 320 // appropriately. 321 func (conn *Conn) input() { 322 err := conn.loop() 323 conn.sending.Lock() 324 defer conn.sending.Unlock() 325 conn.mutex.Lock() 326 defer conn.mutex.Unlock() 327 328 if conn.closing || err == io.EOF { 329 err = ErrShutdown 330 } else { 331 // Make the error available for Conn.Close to see. 332 conn.inputLoopError = err 333 } 334 // Terminate all client requests. 335 for _, call := range conn.clientPending { 336 call.Error = err 337 call.done() 338 } 339 conn.clientPending = nil 340 conn.shutdown = true 341 close(conn.dead) 342 } 343 344 // loop implements the looping part of Conn.input. 345 func (conn *Conn) loop() error { 346 for { 347 var hdr Header 348 err := conn.codec.ReadHeader(&hdr) 349 switch { 350 case err == io.EOF: 351 // handle sentinel error specially 352 return err 353 case err != nil: 354 return errors.Annotate(err, "codec.ReadHeader error") 355 case hdr.IsRequest(): 356 if err := conn.handleRequest(&hdr); err != nil { 357 return errors.Annotatef(err, "codec.handleRequest %#v error", hdr) 358 } 359 default: 360 if err := conn.handleResponse(&hdr); err != nil { 361 return errors.Annotatef(err, "codec.handleResponse %#v error", hdr) 362 } 363 } 364 } 365 } 366 367 func (conn *Conn) readBody(resp interface{}, isRequest bool) error { 368 if resp == nil { 369 resp = &struct{}{} 370 } 371 return conn.codec.ReadBody(resp, isRequest) 372 } 373 374 func (conn *Conn) handleRequest(hdr *Header) error { 375 observer := conn.observerFactory.RPCObserver() 376 req, err := conn.bindRequest(hdr) 377 if err != nil { 378 observer.ServerRequest(hdr, nil) 379 if err := conn.readBody(nil, true); err != nil { 380 return err 381 } 382 // We don't transform the error here. bindRequest will have 383 // already transformed it and returned a zero req. 384 return conn.writeErrorResponse(hdr, err, observer) 385 } 386 var argp interface{} 387 var arg reflect.Value 388 if req.ParamsType() != nil { 389 v := reflect.New(req.ParamsType()) 390 arg = v.Elem() 391 argp = v.Interface() 392 } 393 if err := conn.readBody(argp, true); err != nil { 394 observer.ServerRequest(hdr, nil) 395 396 // If we get EOF, we know the connection is a 397 // goner, so don't try to respond. 398 if err == io.EOF || err == io.ErrUnexpectedEOF { 399 return err 400 } 401 // An error reading the body often indicates bad 402 // request parameters rather than an issue with 403 // the connection itself, so we reply with an 404 // error rather than tearing down the connection 405 // unless it's obviously a connection issue. If 406 // the error is actually a framing or syntax 407 // problem, then the next ReadHeader should pick 408 // up the problem and abort. 409 return conn.writeErrorResponse(hdr, req.transformErrors(err), observer) 410 } 411 if req.ParamsType() != nil { 412 observer.ServerRequest(hdr, arg.Interface()) 413 } else { 414 observer.ServerRequest(hdr, struct{}{}) 415 } 416 conn.mutex.Lock() 417 closing := conn.closing 418 if !closing { 419 conn.srvPending.Add(1) 420 go conn.runRequest(req, arg, hdr.Version, observer) 421 } 422 conn.mutex.Unlock() 423 if closing { 424 // We're closing down - no new requests may be initiated. 425 return conn.writeErrorResponse(hdr, req.transformErrors(ErrShutdown), observer) 426 } 427 return nil 428 } 429 430 func (conn *Conn) writeErrorResponse(reqHdr *Header, err error, observer Observer) error { 431 conn.sending.Lock() 432 defer conn.sending.Unlock() 433 hdr := &Header{ 434 RequestId: reqHdr.RequestId, 435 Version: reqHdr.Version, 436 } 437 if err, ok := err.(ErrorCoder); ok { 438 hdr.ErrorCode = err.ErrorCode() 439 } else { 440 hdr.ErrorCode = "" 441 } 442 hdr.Error = err.Error() 443 observer.ServerReply(reqHdr.Request, hdr, struct{}{}) 444 445 return conn.codec.WriteMessage(hdr, struct{}{}) 446 } 447 448 // boundRequest represents an RPC request that is 449 // bound to an actual implementation. 450 type boundRequest struct { 451 rpcreflect.MethodCaller 452 transformErrors func(error) error 453 hdr Header 454 } 455 456 // bindRequest searches for methods implementing the 457 // request held in the given header and returns 458 // a boundRequest that can call those methods. 459 func (conn *Conn) bindRequest(hdr *Header) (boundRequest, error) { 460 conn.mutex.Lock() 461 root := conn.root 462 transformErrors := conn.transformErrors 463 conn.mutex.Unlock() 464 465 if root == nil { 466 return boundRequest{}, errors.New("no service") 467 } 468 caller, err := root.FindMethod( 469 hdr.Request.Type, hdr.Request.Version, hdr.Request.Action) 470 if err != nil { 471 if _, ok := err.(*rpcreflect.CallNotImplementedError); ok { 472 err = &serverError{ 473 error: err, 474 } 475 } else { 476 err = transformErrors(err) 477 } 478 return boundRequest{}, err 479 } 480 return boundRequest{ 481 MethodCaller: caller, 482 transformErrors: transformErrors, 483 hdr: *hdr, 484 }, nil 485 } 486 487 // runRequest runs the given request and sends the reply. 488 func (conn *Conn) runRequest(req boundRequest, arg reflect.Value, version int, observer Observer) { 489 defer conn.srvPending.Done() 490 rv, err := req.Call(req.hdr.Request.Id, arg) 491 if err != nil { 492 err = conn.writeErrorResponse(&req.hdr, req.transformErrors(err), observer) 493 } else { 494 hdr := &Header{ 495 RequestId: req.hdr.RequestId, 496 Version: version, 497 } 498 var rvi interface{} 499 if rv.IsValid() { 500 rvi = rv.Interface() 501 } else { 502 rvi = struct{}{} 503 } 504 observer.ServerReply(req.hdr.Request, hdr, rvi) 505 conn.sending.Lock() 506 err = conn.codec.WriteMessage(hdr, rvi) 507 conn.sending.Unlock() 508 } 509 if err != nil { 510 logger.Errorf("error writing response: %v", err) 511 } 512 } 513 514 type serverError struct { 515 error 516 } 517 518 func (e *serverError) ErrorCode() string { 519 // serverError only knows one error code. 520 return codeNotImplemented 521 }