Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / rpc / server.go
blobdbb68dde8486735feb565fc36aff6ed0096e673f
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.
5 /*
6 The rpc package 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.
13 Only methods that satisfy these criteria will be made available for remote access;
14 other methods will be ignored:
16 - the method receiver and name are exported, that is, begin with an upper case letter.
17 - the method has two arguments, both pointers to exported types.
18 - the method has return type os.Error.
20 The method's first argument represents the arguments provided by the caller; the
21 second argument represents the result parameters to be returned to the caller.
22 The method's return value, if non-nil, is passed back as a string that the client
23 sees as an os.ErrorString.
25 The server may handle requests on a single connection by calling ServeConn. More
26 typically it will create a network listener and call Accept or, for an HTTP
27 listener, HandleHTTP and http.Serve.
29 A client wishing to use the service establishes a connection and then invokes
30 NewClient on the connection. The convenience function Dial (DialHTTP) performs
31 both steps for a raw network connection (an HTTP connection). The resulting
32 Client object has two methods, Call and Go, that specify the service and method to
33 call, a pointer containing the arguments, and a pointer to receive the result
34 parameters.
36 Call waits for the remote call to complete; Go launches the call asynchronously
37 and returns a channel that will signal completion.
39 Package "gob" is used to transport the data.
41 Here is a simple example. A server wishes to export an object of type Arith:
43 package server
45 type Args struct {
46 A, B int
49 type Quotient struct {
50 Quo, Rem int
53 type Arith int
55 func (t *Arith) Multiply(args *Args, reply *int) os.Error {
56 *reply = args.A * args.B
57 return nil
60 func (t *Arith) Divide(args *Args, quo *Quotient) os.Error {
61 if args.B == 0 {
62 return os.ErrorString("divide by zero")
64 quo.Quo = args.A / args.B
65 quo.Rem = args.A % args.B
66 return nil
69 The server calls (for HTTP service):
71 arith := new(Arith)
72 rpc.Register(arith)
73 rpc.HandleHTTP()
74 l, e := net.Listen("tcp", ":1234")
75 if e != nil {
76 log.Exit("listen error:", e)
78 go http.Serve(l, nil)
80 At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
81 "Arith.Divide". To invoke one, a client first dials the server:
83 client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
84 if err != nil {
85 log.Exit("dialing:", err)
88 Then it can make a remote call:
90 // Synchronous call
91 args := &server.Args{7,8}
92 var reply int
93 err = client.Call("Arith.Multiply", args, &reply)
94 if err != nil {
95 log.Exit("arith error:", err)
97 fmt.Printf("Arith: %d*%d=%d", args.A, args.B, *reply)
101 // Asynchronous call
102 quotient := new(Quotient)
103 divCall := client.Go("Arith.Divide", args, &quotient, nil)
104 replyCall := <-divCall.Done // will be equal to divCall
105 // check errors, print, etc.
107 A server implementation will often provide a simple, type-safe wrapper for the
108 client.
110 package rpc
112 import (
113 "gob"
114 "http"
115 "log"
116 "io"
117 "net"
118 "os"
119 "reflect"
120 "strings"
121 "sync"
122 "unicode"
123 "utf8"
126 const (
127 // Defaults used by HandleHTTP
128 DefaultRPCPath = "/_goRPC_"
129 DefaultDebugPath = "/debug/rpc"
132 // Precompute the reflect type for os.Error. Can't use os.Error directly
133 // because Typeof takes an empty interface value. This is annoying.
134 var unusedError *os.Error
135 var typeOfOsError = reflect.Typeof(unusedError).(*reflect.PtrType).Elem()
137 type methodType struct {
138 sync.Mutex // protects counters
139 method reflect.Method
140 argType *reflect.PtrType
141 replyType *reflect.PtrType
142 numCalls uint
145 type service struct {
146 name string // name of service
147 rcvr reflect.Value // receiver of methods for the service
148 typ reflect.Type // type of the receiver
149 method map[string]*methodType // registered methods
152 // Request is a header written before every RPC call. It is used internally
153 // but documented here as an aid to debugging, such as when analyzing
154 // network traffic.
155 type Request struct {
156 ServiceMethod string // format: "Service.Method"
157 Seq uint64 // sequence number chosen by client
160 // Response is a header written before every RPC return. It is used internally
161 // but documented here as an aid to debugging, such as when analyzing
162 // network traffic.
163 type Response struct {
164 ServiceMethod string // echoes that of the Request
165 Seq uint64 // echoes that of the request
166 Error string // error, if any.
169 // ClientInfo records information about an RPC client connection.
170 type ClientInfo struct {
171 LocalAddr string
172 RemoteAddr string
175 // Server represents an RPC Server.
176 type Server struct {
177 sync.Mutex // protects the serviceMap
178 serviceMap map[string]*service
181 // NewServer returns a new Server.
182 func NewServer() *Server {
183 return &Server{serviceMap: make(map[string]*service)}
186 // DefaultServer is the default instance of *Server.
187 var DefaultServer = NewServer()
189 // Is this an exported - upper case - name?
190 func isExported(name string) bool {
191 rune, _ := utf8.DecodeRuneInString(name)
192 return unicode.IsUpper(rune)
195 // Register publishes in the server the set of methods of the
196 // receiver value that satisfy the following conditions:
197 // - exported method
198 // - two arguments, both pointers to exported structs
199 // - one return value, of type os.Error
200 // It returns an error if the receiver is not an exported type or has no
201 // suitable methods.
202 func (server *Server) Register(rcvr interface{}) os.Error {
203 server.Lock()
204 defer server.Unlock()
205 if server.serviceMap == nil {
206 server.serviceMap = make(map[string]*service)
208 s := new(service)
209 s.typ = reflect.Typeof(rcvr)
210 s.rcvr = reflect.NewValue(rcvr)
211 sname := reflect.Indirect(s.rcvr).Type().Name()
212 if sname == "" {
213 log.Exit("rpc: no service name for type", s.typ.String())
215 if s.typ.PkgPath() != "" && !isExported(sname) {
216 s := "rpc Register: type " + sname + " is not exported"
217 log.Print(s)
218 return os.ErrorString(s)
220 if _, present := server.serviceMap[sname]; present {
221 return os.ErrorString("rpc: service already defined: " + sname)
223 s.name = sname
224 s.method = make(map[string]*methodType)
226 // Install the methods
227 for m := 0; m < s.typ.NumMethod(); m++ {
228 method := s.typ.Method(m)
229 mtype := method.Type
230 mname := method.Name
231 if mtype.PkgPath() != "" || !isExported(mname) {
232 continue
234 // Method needs three ins: receiver, *args, *reply.
235 if mtype.NumIn() != 3 {
236 log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
237 continue
239 argType, ok := mtype.In(1).(*reflect.PtrType)
240 if !ok {
241 log.Println(mname, "arg type not a pointer:", mtype.In(1))
242 continue
244 replyType, ok := mtype.In(2).(*reflect.PtrType)
245 if !ok {
246 log.Println(mname, "reply type not a pointer:", mtype.In(2))
247 continue
249 if argType.Elem().PkgPath() != "" && !isExported(argType.Elem().Name()) {
250 log.Println(mname, "argument type not exported:", argType)
251 continue
253 if replyType.Elem().PkgPath() != "" && !isExported(replyType.Elem().Name()) {
254 log.Println(mname, "reply type not exported:", replyType)
255 continue
257 if mtype.NumIn() == 4 {
258 t := mtype.In(3)
259 if t != reflect.Typeof((*ClientInfo)(nil)) {
260 log.Println(mname, "last argument not *ClientInfo")
261 continue
264 // Method needs one out: os.Error.
265 if mtype.NumOut() != 1 {
266 log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
267 continue
269 if returnType := mtype.Out(0); returnType != typeOfOsError {
270 log.Println("method", mname, "returns", returnType.String(), "not os.Error")
271 continue
273 s.method[mname] = &methodType{method: method, argType: argType, replyType: replyType}
276 if len(s.method) == 0 {
277 s := "rpc Register: type " + sname + " has no exported methods of suitable type"
278 log.Print(s)
279 return os.ErrorString(s)
281 server.serviceMap[s.name] = s
282 return nil
285 // A value sent as a placeholder for the response when the server receives an invalid request.
286 type InvalidRequest struct {
287 marker int
290 var invalidRequest = InvalidRequest{1}
292 func _new(t *reflect.PtrType) *reflect.PtrValue {
293 v := reflect.MakeZero(t).(*reflect.PtrValue)
294 v.PointTo(reflect.MakeZero(t.Elem()))
295 return v
298 func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
299 resp := new(Response)
300 // Encode the response header
301 resp.ServiceMethod = req.ServiceMethod
302 if errmsg != "" {
303 resp.Error = errmsg
305 resp.Seq = req.Seq
306 sending.Lock()
307 err := codec.WriteResponse(resp, reply)
308 if err != nil {
309 log.Println("rpc: writing response:", err)
311 sending.Unlock()
314 func (s *service) call(sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
315 mtype.Lock()
316 mtype.numCalls++
317 mtype.Unlock()
318 function := mtype.method.Func
319 // Invoke the method, providing a new value for the reply.
320 returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
321 // The return value for the method is an os.Error.
322 errInter := returnValues[0].Interface()
323 errmsg := ""
324 if errInter != nil {
325 errmsg = errInter.(os.Error).String()
327 sendResponse(sending, req, replyv.Interface(), codec, errmsg)
330 type gobServerCodec struct {
331 rwc io.ReadWriteCloser
332 dec *gob.Decoder
333 enc *gob.Encoder
336 func (c *gobServerCodec) ReadRequestHeader(r *Request) os.Error {
337 return c.dec.Decode(r)
340 func (c *gobServerCodec) ReadRequestBody(body interface{}) os.Error {
341 return c.dec.Decode(body)
344 func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) os.Error {
345 if err := c.enc.Encode(r); err != nil {
346 return err
348 return c.enc.Encode(body)
351 func (c *gobServerCodec) Close() os.Error {
352 return c.rwc.Close()
356 // ServeConn runs the server on a single connection.
357 // ServeConn blocks, serving the connection until the client hangs up.
358 // The caller typically invokes ServeConn in a go statement.
359 // ServeConn uses the gob wire format (see package gob) on the
360 // connection. To use an alternate codec, use ServeCodec.
361 func (server *Server) ServeConn(conn io.ReadWriteCloser) {
362 server.ServeCodec(&gobServerCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(conn)})
365 // ServeCodec is like ServeConn but uses the specified codec to
366 // decode requests and encode responses.
367 func (server *Server) ServeCodec(codec ServerCodec) {
368 sending := new(sync.Mutex)
369 for {
370 // Grab the request header.
371 req := new(Request)
372 err := codec.ReadRequestHeader(req)
373 if err != nil {
374 if err == os.EOF || err == io.ErrUnexpectedEOF {
375 if err == io.ErrUnexpectedEOF {
376 log.Println("rpc:", err)
378 break
380 s := "rpc: server cannot decode request: " + err.String()
381 sendResponse(sending, req, invalidRequest, codec, s)
382 break
384 serviceMethod := strings.Split(req.ServiceMethod, ".", -1)
385 if len(serviceMethod) != 2 {
386 s := "rpc: service/method request ill-formed: " + req.ServiceMethod
387 sendResponse(sending, req, invalidRequest, codec, s)
388 continue
390 // Look up the request.
391 server.Lock()
392 service, ok := server.serviceMap[serviceMethod[0]]
393 server.Unlock()
394 if !ok {
395 s := "rpc: can't find service " + req.ServiceMethod
396 sendResponse(sending, req, invalidRequest, codec, s)
397 continue
399 mtype, ok := service.method[serviceMethod[1]]
400 if !ok {
401 s := "rpc: can't find method " + req.ServiceMethod
402 sendResponse(sending, req, invalidRequest, codec, s)
403 continue
405 // Decode the argument value.
406 argv := _new(mtype.argType)
407 replyv := _new(mtype.replyType)
408 err = codec.ReadRequestBody(argv.Interface())
409 if err != nil {
410 log.Println("rpc: tearing down", serviceMethod[0], "connection:", err)
411 sendResponse(sending, req, replyv.Interface(), codec, err.String())
412 break
414 go service.call(sending, mtype, req, argv, replyv, codec)
416 codec.Close()
419 // Accept accepts connections on the listener and serves requests
420 // for each incoming connection. Accept blocks; the caller typically
421 // invokes it in a go statement.
422 func (server *Server) Accept(lis net.Listener) {
423 for {
424 conn, err := lis.Accept()
425 if err != nil {
426 log.Exit("rpc.Serve: accept:", err.String()) // TODO(r): exit?
428 go server.ServeConn(conn)
432 // Register publishes in the DefaultServer the set of methods
433 // of the receiver value that satisfy the following conditions:
434 // - exported method
435 // - two arguments, both pointers to exported structs
436 // - one return value, of type os.Error
437 // It returns an error if the receiver is not an exported type or has no
438 // suitable methods.
439 func Register(rcvr interface{}) os.Error { return DefaultServer.Register(rcvr) }
441 // A ServerCodec implements reading of RPC requests and writing of
442 // RPC responses for the server side of an RPC session.
443 // The server calls ReadRequestHeader and ReadRequestBody in pairs
444 // to read requests from the connection, and it calls WriteResponse to
445 // write a response back. The server calls Close when finished with the
446 // connection.
447 type ServerCodec interface {
448 ReadRequestHeader(*Request) os.Error
449 ReadRequestBody(interface{}) os.Error
450 WriteResponse(*Response, interface{}) os.Error
452 Close() os.Error
455 // ServeConn runs the DefaultServer on a single connection.
456 // ServeConn blocks, serving the connection until the client hangs up.
457 // The caller typically invokes ServeConn in a go statement.
458 // ServeConn uses the gob wire format (see package gob) on the
459 // connection. To use an alternate codec, use ServeCodec.
460 func ServeConn(conn io.ReadWriteCloser) {
461 DefaultServer.ServeConn(conn)
464 // ServeCodec is like ServeConn but uses the specified codec to
465 // decode requests and encode responses.
466 func ServeCodec(codec ServerCodec) {
467 DefaultServer.ServeCodec(codec)
470 // Accept accepts connections on the listener and serves requests
471 // to DefaultServer for each incoming connection.
472 // Accept blocks; the caller typically invokes it in a go statement.
473 func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
475 // Can connect to RPC service using HTTP CONNECT to rpcPath.
476 var connected = "200 Connected to Go RPC"
478 // ServeHTTP implements an http.Handler that answers RPC requests.
479 func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
480 if req.Method != "CONNECT" {
481 w.SetHeader("Content-Type", "text/plain; charset=utf-8")
482 w.WriteHeader(http.StatusMethodNotAllowed)
483 io.WriteString(w, "405 must CONNECT\n")
484 return
486 conn, _, err := w.Hijack()
487 if err != nil {
488 log.Print("rpc hijacking ", w.RemoteAddr(), ": ", err.String())
489 return
491 io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
492 server.ServeConn(conn)
495 // HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
496 // and a debugging handler on debugPath.
497 // It is still necessary to invoke http.Serve(), typically in a go statement.
498 func (server *Server) HandleHTTP(rpcPath, debugPath string) {
499 http.Handle(rpcPath, server)
500 http.Handle(debugPath, debugHTTP{server})
503 // HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
504 // on DefaultRPCPath and a debugging handler on DefaultDebugPath.
505 // It is still necessary to invoke http.Serve(), typically in a go statement.
506 func HandleHTTP() {
507 DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath)