OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [rpc/] [server.go] - Blame information for rev 747

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.