~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/syscall/srpc_nacl.go

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-11-18 15:12:26 UTC
  • mfrom: (14.2.12 vivid-proposed)
  • Revision ID: package-import@ubuntu.com-20141118151226-zug7vn93mn3dtiz3
Tags: 2:1.3.2-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - Support co-installability with gccgo-go tool:
    - d/rules,golang-go.install: Rename bin/go -> bin/golang-go
    - d/golang-go.{postinst,prerm}: Install/remove /usr/bin/go using
      alternatives.
  - d/copyright: Amendments for full compiliance with copyright format.
  - d/control: Demote golang-go.tools to Suggests to support Ubuntu MIR.
  - dropped patches (now upstream):
    - d/p/issue27650045_40001_50001.diff
    - d/p/issue28050043_60001_70001.diff
    - d/p/issue54790044_100001_110001.diff

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 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
// Native Client SRPC message passing.
 
6
// This code is needed to invoke SecureRandom, the NaCl equivalent of /dev/random.
 
7
 
 
8
package syscall
 
9
 
 
10
import (
 
11
        "errors"
 
12
        "sync"
 
13
        "unsafe"
 
14
)
 
15
 
 
16
// An srpcClient represents the client side of an SRPC connection.
 
17
type srpcClient struct {
 
18
        fd      int // to server
 
19
        r       msgReceiver
 
20
        s       msgSender
 
21
        service map[string]srpcService // services by name
 
22
 
 
23
        outMu sync.Mutex // protects writing to connection
 
24
 
 
25
        mu      sync.Mutex // protects following fields
 
26
        muxer   bool       // is someone reading and muxing responses
 
27
        pending map[uint32]*srpc
 
28
        idGen   uint32 // generator for request IDs
 
29
}
 
30
 
 
31
// An srpcService is a single method that the server offers.
 
32
type srpcService struct {
 
33
        num uint32 // method number
 
34
        fmt string // argument format; see "parsing of RPC messages" below
 
35
}
 
36
 
 
37
// An srpc represents a single srpc issued by a client.
 
38
type srpc struct {
 
39
        Ret  []interface{}
 
40
        Done chan *srpc
 
41
        Err  error
 
42
        c    *srpcClient
 
43
        id   uint32
 
44
}
 
45
 
 
46
// newClient allocates a new SRPC client using the file descriptor fd.
 
47
func newClient(fd int) (*srpcClient, error) {
 
48
        c := new(srpcClient)
 
49
        c.fd = fd
 
50
        c.r.fd = fd
 
51
        c.s.fd = fd
 
52
        c.service = make(map[string]srpcService)
 
53
        c.pending = make(map[uint32]*srpc)
 
54
 
 
55
        // service discovery request
 
56
        m := &msg{
 
57
                isRequest: 1,
 
58
                template:  []interface{}{[]byte(nil)},
 
59
                size:      []int{4000}, // max size to accept for returned byte slice
 
60
        }
 
61
        if err := m.pack(); err != nil {
 
62
                return nil, errors.New("Native Client SRPC service_discovery: preparing request: " + err.Error())
 
63
        }
 
64
        c.s.send(m)
 
65
        m, err := c.r.recv()
 
66
        if err != nil {
 
67
                return nil, err
 
68
        }
 
69
        m.unpack()
 
70
        if m.status != uint32(srpcOK) {
 
71
                return nil, errors.New("Native Client SRPC service_discovery: " + srpcErrno(m.status).Error())
 
72
        }
 
73
        list := m.value[0].([]byte)
 
74
        var n uint32
 
75
        for len(list) > 0 {
 
76
                var line []byte
 
77
                i := byteIndex(list, '\n')
 
78
                if i < 0 {
 
79
                        line, list = list, nil
 
80
                } else {
 
81
                        line, list = list[:i], list[i+1:]
 
82
                }
 
83
                i = byteIndex(line, ':')
 
84
                if i >= 0 {
 
85
                        c.service[string(line)] = srpcService{n, string(line[i+1:])}
 
86
                }
 
87
                n++
 
88
        }
 
89
 
 
90
        return c, nil
 
91
}
 
92
 
 
93
func byteIndex(b []byte, c byte) int {
 
94
        for i, bi := range b {
 
95
                if bi == c {
 
96
                        return i
 
97
                }
 
98
        }
 
99
        return -1
 
100
}
 
101
 
 
102
var yourTurn srpc
 
103
 
 
104
func (c *srpcClient) wait(r *srpc) {
 
105
        var rx *srpc
 
106
        for rx = range r.Done {
 
107
                if rx != &yourTurn {
 
108
                        break
 
109
                }
 
110
                c.input()
 
111
        }
 
112
        return
 
113
}
 
114
 
 
115
func (c *srpcClient) input() {
 
116
        // read message
 
117
        m, err := c.r.recv()
 
118
        if err != nil {
 
119
                println("Native Client SRPC receive error:", err.Error())
 
120
                return
 
121
        }
 
122
        if m.unpack(); m.status != uint32(srpcOK) {
 
123
                println("Native Client SRPC receive error: invalid message: ", srpcErrno(m.status).Error())
 
124
                return
 
125
        }
 
126
 
 
127
        // deliver to intended recipient
 
128
        c.mu.Lock()
 
129
        rpc, ok := c.pending[m.id]
 
130
        if ok {
 
131
                delete(c.pending, m.id)
 
132
        }
 
133
 
 
134
        // wake a new muxer if there are more RPCs to read
 
135
        c.muxer = false
 
136
        for _, rpc := range c.pending {
 
137
                c.muxer = true
 
138
                rpc.Done <- &yourTurn
 
139
                break
 
140
        }
 
141
        c.mu.Unlock()
 
142
        if !ok {
 
143
                println("Native Client: unexpected response for ID", m.id)
 
144
                return
 
145
        }
 
146
        rpc.Ret = m.value
 
147
        rpc.Done <- rpc
 
148
}
 
149
 
 
150
// Wait blocks until the RPC has finished.
 
151
func (r *srpc) Wait() {
 
152
        r.c.wait(r)
 
153
}
 
154
 
 
155
// Start issues an RPC request for method name with the given arguments.
 
156
// The RPC r must not be in use for another pending request.
 
157
// To wait for the RPC to finish, receive from r.Done and then
 
158
// inspect r.Ret and r.Errno.
 
159
func (r *srpc) Start(name string, arg []interface{}) {
 
160
        r.Err = nil
 
161
        r.c.mu.Lock()
 
162
        srv, ok := r.c.service[name]
 
163
        if !ok {
 
164
                r.c.mu.Unlock()
 
165
                r.Err = srpcErrBadRPCNumber
 
166
                r.Done <- r
 
167
                return
 
168
        }
 
169
        r.c.pending[r.id] = r
 
170
        if !r.c.muxer {
 
171
                r.c.muxer = true
 
172
                r.Done <- &yourTurn
 
173
        }
 
174
        r.c.mu.Unlock()
 
175
 
 
176
        var m msg
 
177
        m.id = r.id
 
178
        m.isRequest = 1
 
179
        m.rpc = srv.num
 
180
        m.value = arg
 
181
 
 
182
        // Fill in the return values and sizes to generate
 
183
        // the right type chars.  We'll take most any size.
 
184
 
 
185
        // Skip over input arguments.
 
186
        // We could check them against arg, but the server
 
187
        // will do that anyway.
 
188
        i := 0
 
189
        for srv.fmt[i] != ':' {
 
190
                i++
 
191
        }
 
192
        format := srv.fmt[i+1:]
 
193
 
 
194
        // Now the return prototypes.
 
195
        m.template = make([]interface{}, len(format))
 
196
        m.size = make([]int, len(format))
 
197
        for i := 0; i < len(format); i++ {
 
198
                switch format[i] {
 
199
                default:
 
200
                        println("Native Client SRPC: unexpected service type " + string(format[i]))
 
201
                        r.Err = srpcErrBadRPCNumber
 
202
                        r.Done <- r
 
203
                        return
 
204
                case 'b':
 
205
                        m.template[i] = false
 
206
                case 'C':
 
207
                        m.template[i] = []byte(nil)
 
208
                        m.size[i] = 1 << 30
 
209
                case 'd':
 
210
                        m.template[i] = float64(0)
 
211
                case 'D':
 
212
                        m.template[i] = []float64(nil)
 
213
                        m.size[i] = 1 << 30
 
214
                case 'h':
 
215
                        m.template[i] = int(-1)
 
216
                case 'i':
 
217
                        m.template[i] = int32(0)
 
218
                case 'I':
 
219
                        m.template[i] = []int32(nil)
 
220
                        m.size[i] = 1 << 30
 
221
                case 's':
 
222
                        m.template[i] = ""
 
223
                        m.size[i] = 1 << 30
 
224
                }
 
225
        }
 
226
 
 
227
        if err := m.pack(); err != nil {
 
228
                r.Err = errors.New("Native Client RPC Start " + name + ": preparing request: " + err.Error())
 
229
                r.Done <- r
 
230
                return
 
231
        }
 
232
 
 
233
        r.c.outMu.Lock()
 
234
        r.c.s.send(&m)
 
235
        r.c.outMu.Unlock()
 
236
}
 
237
 
 
238
// Call is a convenience wrapper that starts the RPC request,
 
239
// waits for it to finish, and then returns the results.
 
240
// Its implementation is:
 
241
//
 
242
//      r.Start(name, arg)
 
243
//      r.Wait()
 
244
//      return r.Ret, r.Errno
 
245
//
 
246
func (c *srpcClient) Call(name string, arg ...interface{}) (ret []interface{}, err error) {
 
247
        r := c.NewRPC(nil)
 
248
        r.Start(name, arg)
 
249
        r.Wait()
 
250
        return r.Ret, r.Err
 
251
}
 
252
 
 
253
// NewRPC creates a new RPC on the client connection.
 
254
func (c *srpcClient) NewRPC(done chan *srpc) *srpc {
 
255
        if done == nil {
 
256
                done = make(chan *srpc, 1)
 
257
        }
 
258
        c.mu.Lock()
 
259
        id := c.idGen
 
260
        c.idGen++
 
261
        c.mu.Unlock()
 
262
        return &srpc{Done: done, c: c, id: id}
 
263
}
 
264
 
 
265
// The current protocol number.
 
266
// Kind of useless, since there have been backwards-incompatible changes
 
267
// to the wire protocol that did not update the protocol number.
 
268
// At this point it's really just a sanity check.
 
269
const protocol = 0xc0da0002
 
270
 
 
271
// An srpcErrno is an SRPC status code.
 
272
type srpcErrno uint32
 
273
 
 
274
const (
 
275
        srpcOK srpcErrno = 256 + iota
 
276
        srpcErrBreak
 
277
        srpcErrMessageTruncated
 
278
        srpcErrNoMemory
 
279
        srpcErrProtocolMismatch
 
280
        srpcErrBadRPCNumber
 
281
        srpcErrBadArgType
 
282
        srpcErrTooFewArgs
 
283
        srpcErrTooManyArgs
 
284
        srpcErrInArgTypeMismatch
 
285
        srpcErrOutArgTypeMismatch
 
286
        srpcErrInternalError
 
287
        srpcErrAppError
 
288
)
 
289
 
 
290
var srpcErrstr = [...]string{
 
291
        srpcOK - srpcOK:                    "ok",
 
292
        srpcErrBreak - srpcOK:              "break",
 
293
        srpcErrMessageTruncated - srpcOK:   "message truncated",
 
294
        srpcErrNoMemory - srpcOK:           "out of memory",
 
295
        srpcErrProtocolMismatch - srpcOK:   "protocol mismatch",
 
296
        srpcErrBadRPCNumber - srpcOK:       "invalid RPC method number",
 
297
        srpcErrBadArgType - srpcOK:         "unexpected argument type",
 
298
        srpcErrTooFewArgs - srpcOK:         "too few arguments",
 
299
        srpcErrTooManyArgs - srpcOK:        "too many arguments",
 
300
        srpcErrInArgTypeMismatch - srpcOK:  "input argument type mismatch",
 
301
        srpcErrOutArgTypeMismatch - srpcOK: "output argument type mismatch",
 
302
        srpcErrInternalError - srpcOK:      "internal error",
 
303
        srpcErrAppError - srpcOK:           "application error",
 
304
}
 
305
 
 
306
func (e srpcErrno) Error() string {
 
307
        if e < srpcOK || int(e-srpcOK) >= len(srpcErrstr) {
 
308
                return "srpcErrno(" + itoa(int(e)) + ")"
 
309
        }
 
310
        return srpcErrstr[e-srpcOK]
 
311
}
 
312
 
 
313
// A msgHdr is the data argument to the imc_recvmsg
 
314
// and imc_sendmsg system calls.
 
315
type msgHdr struct {
 
316
        iov   *iov
 
317
        niov  int32
 
318
        desc  *int32
 
319
        ndesc int32
 
320
        flags uint32
 
321
}
 
322
 
 
323
// A single region for I/O.
 
324
type iov struct {
 
325
        base *byte
 
326
        len  int32
 
327
}
 
328
 
 
329
const maxMsgSize = 1<<16 - 4*4
 
330
 
 
331
// A msgReceiver receives messages from a file descriptor.
 
332
type msgReceiver struct {
 
333
        fd   int
 
334
        data [maxMsgSize]byte
 
335
        desc [8]int32
 
336
        hdr  msgHdr
 
337
        iov  iov
 
338
}
 
339
 
 
340
func (r *msgReceiver) recv() (*msg, error) {
 
341
        // Init pointers to buffers where syscall recvmsg can write.
 
342
        r.iov.base = &r.data[0]
 
343
        r.iov.len = int32(len(r.data))
 
344
        r.hdr.iov = &r.iov
 
345
        r.hdr.niov = 1
 
346
        r.hdr.desc = &r.desc[0]
 
347
        r.hdr.ndesc = int32(len(r.desc))
 
348
        n, _, e := Syscall(sys_imc_recvmsg, uintptr(r.fd), uintptr(unsafe.Pointer(&r.hdr)), 0)
 
349
        if e != 0 {
 
350
                println("Native Client imc_recvmsg: ", e.Error())
 
351
                return nil, e
 
352
        }
 
353
 
 
354
        // Make a copy of the data so that the next recvmsg doesn't
 
355
        // smash it.  The system call did not update r.iov.len.  Instead it
 
356
        // returned the total byte count as n.
 
357
        m := new(msg)
 
358
        m.data = make([]byte, n)
 
359
        copy(m.data, r.data[0:])
 
360
 
 
361
        // Make a copy of the desc too.
 
362
        // The system call *did* update r.hdr.ndesc.
 
363
        if r.hdr.ndesc > 0 {
 
364
                m.desc = make([]int32, r.hdr.ndesc)
 
365
                copy(m.desc, r.desc[:])
 
366
        }
 
367
 
 
368
        return m, nil
 
369
}
 
370
 
 
371
// A msgSender sends messages on a file descriptor.
 
372
type msgSender struct {
 
373
        fd  int
 
374
        hdr msgHdr
 
375
        iov iov
 
376
}
 
377
 
 
378
func (s *msgSender) send(m *msg) error {
 
379
        if len(m.data) > 0 {
 
380
                s.iov.base = &m.data[0]
 
381
        }
 
382
        s.iov.len = int32(len(m.data))
 
383
        s.hdr.iov = &s.iov
 
384
        s.hdr.niov = 1
 
385
        s.hdr.desc = nil
 
386
        s.hdr.ndesc = 0
 
387
        _, _, e := Syscall(sys_imc_sendmsg, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0)
 
388
        if e != 0 {
 
389
                println("Native Client imc_sendmsg: ", e.Error())
 
390
                return e
 
391
        }
 
392
        return nil
 
393
}
 
394
 
 
395
// A msg is the Go representation of an SRPC message.
 
396
type msg struct {
 
397
        data []byte  // message data
 
398
        desc []int32 // message file descriptors
 
399
 
 
400
        // parsed version of message
 
401
        id        uint32
 
402
        isRequest uint32
 
403
        rpc       uint32
 
404
        status    uint32
 
405
        value     []interface{}
 
406
        template  []interface{}
 
407
        size      []int
 
408
        format    string
 
409
        broken    bool
 
410
}
 
411
 
 
412
// reading from a msg
 
413
 
 
414
func (m *msg) uint32() uint32 {
 
415
        if m.broken {
 
416
                return 0
 
417
        }
 
418
        if len(m.data) < 4 {
 
419
                m.broken = true
 
420
                return 0
 
421
        }
 
422
        b := m.data[:4]
 
423
        x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
 
424
        m.data = m.data[4:]
 
425
        return x
 
426
}
 
427
 
 
428
func (m *msg) uint64() uint64 {
 
429
        x := uint64(m.uint32()) | uint64(m.uint32())<<32
 
430
        if m.broken {
 
431
                return 0
 
432
        }
 
433
        return x
 
434
}
 
435
 
 
436
func (m *msg) bytes(n int) []byte {
 
437
        if m.broken {
 
438
                return nil
 
439
        }
 
440
        if len(m.data) < n {
 
441
                m.broken = true
 
442
                return nil
 
443
        }
 
444
        x := m.data[0:n]
 
445
        m.data = m.data[n:]
 
446
        return x
 
447
}
 
448
 
 
449
// writing to a msg
 
450
 
 
451
func (m *msg) wuint32(x uint32) {
 
452
        m.data = append(m.data, byte(x), byte(x>>8), byte(x>>16), byte(x>>24))
 
453
}
 
454
 
 
455
func (m *msg) wuint64(x uint64) {
 
456
        lo := uint32(x)
 
457
        hi := uint32(x >> 32)
 
458
        m.data = append(m.data, byte(lo), byte(lo>>8), byte(lo>>16), byte(lo>>24), byte(hi), byte(hi>>8), byte(hi>>16), byte(hi>>24))
 
459
}
 
460
 
 
461
func (m *msg) wbytes(p []byte) {
 
462
        m.data = append(m.data, p...)
 
463
}
 
464
 
 
465
func (m *msg) wstring(s string) {
 
466
        m.data = append(m.data, s...)
 
467
}
 
468
 
 
469
// Parsing of RPC messages.
 
470
//
 
471
// Each message begins with
 
472
//      total_size uint32
 
473
//      total_descs uint32
 
474
//      fragment_size uint32
 
475
//      fragment_descs uint32
 
476
//
 
477
// If fragment_size < total_size or fragment_descs < total_descs, the actual
 
478
// message is broken up in multiple messages; follow-up messages omit
 
479
// the "total" fields and begin with the "fragment" fields.
 
480
// We do not support putting fragmented messages back together.
 
481
// To do this we would need to change the message receiver.
 
482
//
 
483
// After that size information, the message header follows:
 
484
//      protocol uint32
 
485
//      requestID uint32
 
486
//      isRequest uint32
 
487
//      rpcNumber uint32
 
488
//      status uint32
 
489
//      numValue uint32
 
490
//      numTemplate uint32
 
491
//
 
492
// After the header come numTemplate fixed-size arguments,
 
493
// numValue fixed-size arguments, and then the variable-sized
 
494
// part of the values. The templates describe the expected results
 
495
// and have no associated variable sized data in the request.
 
496
//
 
497
// Each fixed-size argument has the form:
 
498
//      tag uint32 // really a char, like 'b' or 'C'
 
499
//      pad uint32 // unused
 
500
//      val1 uint32
 
501
//      val2 uint32
 
502
//
 
503
// The tags are:
 
504
//      'b':    bool; val1 == 0 or 1
 
505
//      'C':    []byte; val1 == len, data in variable-sized section
 
506
//      'd':    float64; (val1, val2) is data
 
507
//      'D':    []float64; val1 == len, data in variable-sized section
 
508
//      'h':    int; val1 == file descriptor
 
509
//      'i':    int32; descriptor in next entry in m.desc
 
510
//      'I':    []int; val1 == len, data in variable-sized section
 
511
//      's':    string; val1 == len, data in variable-sized section
 
512
//
 
513
 
 
514
func (m *msg) pack() error {
 
515
        m.data = m.data[:0]
 
516
        m.desc = m.desc[:0]
 
517
 
 
518
        // sizes, to fill in later
 
519
        m.wuint32(0)
 
520
        m.wuint32(0)
 
521
        m.wuint32(0)
 
522
        m.wuint32(0)
 
523
 
 
524
        // message header
 
525
        m.wuint32(protocol)
 
526
        m.wuint32(m.id)
 
527
        m.wuint32(m.isRequest)
 
528
        m.wuint32(m.rpc)
 
529
        m.wuint32(m.status)
 
530
        m.wuint32(uint32(len(m.value)))
 
531
        m.wuint32(uint32(len(m.template)))
 
532
 
 
533
        // fixed-size templates
 
534
        for i, x := range m.template {
 
535
                var tag, val1, val2 uint32
 
536
                switch x.(type) {
 
537
                default:
 
538
                        return errors.New("unexpected template type")
 
539
                case bool:
 
540
                        tag = 'b'
 
541
                case []byte:
 
542
                        tag = 'C'
 
543
                        val1 = uint32(m.size[i])
 
544
                case float64:
 
545
                        tag = 'd'
 
546
                case []float64:
 
547
                        tag = 'D'
 
548
                        val1 = uint32(m.size[i])
 
549
                case int:
 
550
                        tag = 'h'
 
551
                case int32:
 
552
                        tag = 'i'
 
553
                case []int32:
 
554
                        tag = 'I'
 
555
                        val1 = uint32(m.size[i])
 
556
                case string:
 
557
                        tag = 's'
 
558
                        val1 = uint32(m.size[i])
 
559
                }
 
560
                m.wuint32(tag)
 
561
                m.wuint32(0)
 
562
                m.wuint32(val1)
 
563
                m.wuint32(val2)
 
564
        }
 
565
 
 
566
        // fixed-size values
 
567
        for _, x := range m.value {
 
568
                var tag, val1, val2 uint32
 
569
                switch x := x.(type) {
 
570
                default:
 
571
                        return errors.New("unexpected value type")
 
572
                case bool:
 
573
                        tag = 'b'
 
574
                        if x {
 
575
                                val1 = 1
 
576
                        }
 
577
                case []byte:
 
578
                        tag = 'C'
 
579
                        val1 = uint32(len(x))
 
580
                case float64:
 
581
                        tag = 'd'
 
582
                        v := float64bits(x)
 
583
                        val1 = uint32(v)
 
584
                        val2 = uint32(v >> 32)
 
585
                case []float64:
 
586
                        tag = 'D'
 
587
                        val1 = uint32(len(x))
 
588
                case int32:
 
589
                        tag = 'i'
 
590
                        m.desc = append(m.desc, x)
 
591
                case []int32:
 
592
                        tag = 'I'
 
593
                        val1 = uint32(len(x))
 
594
                case string:
 
595
                        tag = 's'
 
596
                        val1 = uint32(len(x) + 1)
 
597
                }
 
598
                m.wuint32(tag)
 
599
                m.wuint32(0)
 
600
                m.wuint32(val1)
 
601
                m.wuint32(val2)
 
602
        }
 
603
 
 
604
        // variable-length data for values
 
605
        for _, x := range m.value {
 
606
                switch x := x.(type) {
 
607
                case []byte:
 
608
                        m.wbytes(x)
 
609
                case []float64:
 
610
                        for _, f := range x {
 
611
                                m.wuint64(float64bits(f))
 
612
                        }
 
613
                case []int32:
 
614
                        for _, j := range x {
 
615
                                m.wuint32(uint32(j))
 
616
                        }
 
617
                case string:
 
618
                        m.wstring(x)
 
619
                        m.wstring("\x00")
 
620
                }
 
621
        }
 
622
 
 
623
        // fill in sizes
 
624
        data := m.data
 
625
        m.data = m.data[:0]
 
626
        m.wuint32(uint32(len(data)))
 
627
        m.wuint32(uint32(len(m.desc)))
 
628
        m.wuint32(uint32(len(data)))
 
629
        m.wuint32(uint32(len(m.desc)))
 
630
        m.data = data
 
631
 
 
632
        return nil
 
633
}
 
634
 
 
635
func (m *msg) unpack() error {
 
636
        totalSize := m.uint32()
 
637
        totalDesc := m.uint32()
 
638
        fragSize := m.uint32()
 
639
        fragDesc := m.uint32()
 
640
        if totalSize != fragSize || totalDesc != fragDesc {
 
641
                return errors.New("Native Client: fragmented RPC messages not supported")
 
642
        }
 
643
        if m.uint32() != protocol {
 
644
                return errors.New("Native Client: RPC protocol mismatch")
 
645
        }
 
646
 
 
647
        // message header
 
648
        m.id = m.uint32()
 
649
        m.isRequest = m.uint32()
 
650
        m.rpc = m.uint32()
 
651
        m.status = m.uint32()
 
652
        m.value = make([]interface{}, m.uint32())
 
653
        m.template = make([]interface{}, m.uint32())
 
654
        m.size = make([]int, len(m.template))
 
655
        if m.broken {
 
656
                return errors.New("Native Client: malformed message")
 
657
        }
 
658
 
 
659
        // fixed-size templates
 
660
        for i := range m.template {
 
661
                tag := m.uint32()
 
662
                m.uint32() // padding
 
663
                val1 := m.uint32()
 
664
                m.uint32() // val2
 
665
                switch tag {
 
666
                default:
 
667
                        return errors.New("Native Client: unexpected template type " + string(rune(tag)))
 
668
                case 'b':
 
669
                        m.template[i] = false
 
670
                case 'C':
 
671
                        m.template[i] = []byte(nil)
 
672
                        m.size[i] = int(val1)
 
673
                case 'd':
 
674
                        m.template[i] = float64(0)
 
675
                case 'D':
 
676
                        m.template[i] = []float64(nil)
 
677
                        m.size[i] = int(val1)
 
678
                case 'i':
 
679
                        m.template[i] = int32(0)
 
680
                case 'I':
 
681
                        m.template[i] = []int32(nil)
 
682
                        m.size[i] = int(val1)
 
683
                case 'h':
 
684
                        m.template[i] = int(0)
 
685
                case 's':
 
686
                        m.template[i] = ""
 
687
                        m.size[i] = int(val1)
 
688
                }
 
689
        }
 
690
 
 
691
        // fixed-size values
 
692
        var (
 
693
                strsize []uint32
 
694
                d       int
 
695
        )
 
696
        for i := range m.value {
 
697
                tag := m.uint32()
 
698
                m.uint32() // padding
 
699
                val1 := m.uint32()
 
700
                val2 := m.uint32()
 
701
                switch tag {
 
702
                default:
 
703
                        return errors.New("Native Client: unexpected value type " + string(rune(tag)))
 
704
                case 'b':
 
705
                        m.value[i] = val1 > 0
 
706
                case 'C':
 
707
                        m.value[i] = []byte(nil)
 
708
                        strsize = append(strsize, val1)
 
709
                case 'd':
 
710
                        m.value[i] = float64frombits(uint64(val1) | uint64(val2)<<32)
 
711
                case 'D':
 
712
                        m.value[i] = make([]float64, val1)
 
713
                case 'i':
 
714
                        m.value[i] = int32(val1)
 
715
                case 'I':
 
716
                        m.value[i] = make([]int32, val1)
 
717
                case 'h':
 
718
                        m.value[i] = int(m.desc[d])
 
719
                        d++
 
720
                case 's':
 
721
                        m.value[i] = ""
 
722
                        strsize = append(strsize, val1)
 
723
                }
 
724
        }
 
725
 
 
726
        // variable-sized parts of values
 
727
        for i, x := range m.value {
 
728
                switch x := x.(type) {
 
729
                case []byte:
 
730
                        m.value[i] = m.bytes(int(strsize[0]))
 
731
                        strsize = strsize[1:]
 
732
                case []float64:
 
733
                        for i := range x {
 
734
                                x[i] = float64frombits(m.uint64())
 
735
                        }
 
736
                case []int32:
 
737
                        for i := range x {
 
738
                                x[i] = int32(m.uint32())
 
739
                        }
 
740
                case string:
 
741
                        m.value[i] = string(m.bytes(int(strsize[0])))
 
742
                        strsize = strsize[1:]
 
743
                }
 
744
        }
 
745
 
 
746
        if len(m.data) > 0 {
 
747
                return errors.New("Native Client: junk at end of message")
 
748
        }
 
749
        return nil
 
750
}
 
751
 
 
752
func float64bits(x float64) uint64 {
 
753
        return *(*uint64)(unsafe.Pointer(&x))
 
754
}
 
755
 
 
756
func float64frombits(x uint64) float64 {
 
757
        return *(*float64)(unsafe.Pointer(&x))
 
758
}
 
759
 
 
760
// At startup, connect to the name service.
 
761
var nsClient = nsConnect()
 
762
 
 
763
func nsConnect() *srpcClient {
 
764
        var ns int32 = -1
 
765
        _, _, errno := Syscall(sys_nameservice, uintptr(unsafe.Pointer(&ns)), 0, 0)
 
766
        if errno != 0 {
 
767
                println("Native Client nameservice:", errno.Error())
 
768
                return nil
 
769
        }
 
770
 
 
771
        sock, _, errno := Syscall(sys_imc_connect, uintptr(ns), 0, 0)
 
772
        if errno != 0 {
 
773
                println("Native Client nameservice connect:", errno.Error())
 
774
                return nil
 
775
        }
 
776
 
 
777
        c, err := newClient(int(sock))
 
778
        if err != nil {
 
779
                println("Native Client nameservice init:", err.Error())
 
780
                return nil
 
781
        }
 
782
 
 
783
        return c
 
784
}
 
785
 
 
786
const (
 
787
        nsSuccess               = 0
 
788
        nsNameNotFound          = 1
 
789
        nsDuplicateName         = 2
 
790
        nsInsufficientResources = 3
 
791
        nsPermissionDenied      = 4
 
792
        nsInvalidArgument       = 5
 
793
)
 
794
 
 
795
func openNamedService(name string, mode int32) (fd int, err error) {
 
796
        if nsClient == nil {
 
797
                return 0, errors.New("no name service")
 
798
        }
 
799
        ret, err := nsClient.Call("lookup:si:ih", name, int32(mode))
 
800
        if err != nil {
 
801
                return 0, err
 
802
        }
 
803
        status := ret[0].(int32)
 
804
        fd = ret[1].(int)
 
805
        switch status {
 
806
        case nsSuccess:
 
807
                // ok
 
808
        case nsNameNotFound:
 
809
                return -1, ENOENT
 
810
        case nsDuplicateName:
 
811
                return -1, EEXIST
 
812
        case nsInsufficientResources:
 
813
                return -1, EWOULDBLOCK
 
814
        case nsPermissionDenied:
 
815
                return -1, EPERM
 
816
        case nsInvalidArgument:
 
817
                return -1, EINVAL
 
818
        default:
 
819
                return -1, EINVAL
 
820
        }
 
821
        return fd, nil
 
822
}