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.
5
// Native Client SRPC message passing.
6
// This code is needed to invoke SecureRandom, the NaCl equivalent of /dev/random.
16
// An srpcClient represents the client side of an SRPC connection.
17
type srpcClient struct {
21
service map[string]srpcService // services by name
23
outMu sync.Mutex // protects writing to connection
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
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
37
// An srpc represents a single srpc issued by a client.
46
// newClient allocates a new SRPC client using the file descriptor fd.
47
func newClient(fd int) (*srpcClient, error) {
52
c.service = make(map[string]srpcService)
53
c.pending = make(map[uint32]*srpc)
55
// service discovery request
58
template: []interface{}{[]byte(nil)},
59
size: []int{4000}, // max size to accept for returned byte slice
61
if err := m.pack(); err != nil {
62
return nil, errors.New("Native Client SRPC service_discovery: preparing request: " + err.Error())
70
if m.status != uint32(srpcOK) {
71
return nil, errors.New("Native Client SRPC service_discovery: " + srpcErrno(m.status).Error())
73
list := m.value[0].([]byte)
77
i := byteIndex(list, '\n')
79
line, list = list, nil
81
line, list = list[:i], list[i+1:]
83
i = byteIndex(line, ':')
85
c.service[string(line)] = srpcService{n, string(line[i+1:])}
93
func byteIndex(b []byte, c byte) int {
94
for i, bi := range b {
104
func (c *srpcClient) wait(r *srpc) {
106
for rx = range r.Done {
115
func (c *srpcClient) input() {
119
println("Native Client SRPC receive error:", err.Error())
122
if m.unpack(); m.status != uint32(srpcOK) {
123
println("Native Client SRPC receive error: invalid message: ", srpcErrno(m.status).Error())
127
// deliver to intended recipient
129
rpc, ok := c.pending[m.id]
131
delete(c.pending, m.id)
134
// wake a new muxer if there are more RPCs to read
136
for _, rpc := range c.pending {
138
rpc.Done <- &yourTurn
143
println("Native Client: unexpected response for ID", m.id)
150
// Wait blocks until the RPC has finished.
151
func (r *srpc) Wait() {
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{}) {
162
srv, ok := r.c.service[name]
165
r.Err = srpcErrBadRPCNumber
169
r.c.pending[r.id] = r
182
// Fill in the return values and sizes to generate
183
// the right type chars. We'll take most any size.
185
// Skip over input arguments.
186
// We could check them against arg, but the server
187
// will do that anyway.
189
for srv.fmt[i] != ':' {
192
format := srv.fmt[i+1:]
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++ {
200
println("Native Client SRPC: unexpected service type " + string(format[i]))
201
r.Err = srpcErrBadRPCNumber
205
m.template[i] = false
207
m.template[i] = []byte(nil)
210
m.template[i] = float64(0)
212
m.template[i] = []float64(nil)
215
m.template[i] = int(-1)
217
m.template[i] = int32(0)
219
m.template[i] = []int32(nil)
227
if err := m.pack(); err != nil {
228
r.Err = errors.New("Native Client RPC Start " + name + ": preparing request: " + err.Error())
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:
242
// r.Start(name, arg)
244
// return r.Ret, r.Errno
246
func (c *srpcClient) Call(name string, arg ...interface{}) (ret []interface{}, err error) {
253
// NewRPC creates a new RPC on the client connection.
254
func (c *srpcClient) NewRPC(done chan *srpc) *srpc {
256
done = make(chan *srpc, 1)
262
return &srpc{Done: done, c: c, id: id}
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
271
// An srpcErrno is an SRPC status code.
272
type srpcErrno uint32
275
srpcOK srpcErrno = 256 + iota
277
srpcErrMessageTruncated
279
srpcErrProtocolMismatch
284
srpcErrInArgTypeMismatch
285
srpcErrOutArgTypeMismatch
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",
306
func (e srpcErrno) Error() string {
307
if e < srpcOK || int(e-srpcOK) >= len(srpcErrstr) {
308
return "srpcErrno(" + itoa(int(e)) + ")"
310
return srpcErrstr[e-srpcOK]
313
// A msgHdr is the data argument to the imc_recvmsg
314
// and imc_sendmsg system calls.
323
// A single region for I/O.
329
const maxMsgSize = 1<<16 - 4*4
331
// A msgReceiver receives messages from a file descriptor.
332
type msgReceiver struct {
334
data [maxMsgSize]byte
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))
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)
350
println("Native Client imc_recvmsg: ", e.Error())
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.
358
m.data = make([]byte, n)
359
copy(m.data, r.data[0:])
361
// Make a copy of the desc too.
362
// The system call *did* update r.hdr.ndesc.
364
m.desc = make([]int32, r.hdr.ndesc)
365
copy(m.desc, r.desc[:])
371
// A msgSender sends messages on a file descriptor.
372
type msgSender struct {
378
func (s *msgSender) send(m *msg) error {
380
s.iov.base = &m.data[0]
382
s.iov.len = int32(len(m.data))
387
_, _, e := Syscall(sys_imc_sendmsg, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0)
389
println("Native Client imc_sendmsg: ", e.Error())
395
// A msg is the Go representation of an SRPC message.
397
data []byte // message data
398
desc []int32 // message file descriptors
400
// parsed version of message
406
template []interface{}
412
// reading from a msg
414
func (m *msg) uint32() uint32 {
423
x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
428
func (m *msg) uint64() uint64 {
429
x := uint64(m.uint32()) | uint64(m.uint32())<<32
436
func (m *msg) bytes(n int) []byte {
451
func (m *msg) wuint32(x uint32) {
452
m.data = append(m.data, byte(x), byte(x>>8), byte(x>>16), byte(x>>24))
455
func (m *msg) wuint64(x uint64) {
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))
461
func (m *msg) wbytes(p []byte) {
462
m.data = append(m.data, p...)
465
func (m *msg) wstring(s string) {
466
m.data = append(m.data, s...)
469
// Parsing of RPC messages.
471
// Each message begins with
473
// total_descs uint32
474
// fragment_size uint32
475
// fragment_descs uint32
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.
483
// After that size information, the message header follows:
490
// numTemplate uint32
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.
497
// Each fixed-size argument has the form:
498
// tag uint32 // really a char, like 'b' or 'C'
499
// pad uint32 // unused
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
514
func (m *msg) pack() error {
518
// sizes, to fill in later
527
m.wuint32(m.isRequest)
530
m.wuint32(uint32(len(m.value)))
531
m.wuint32(uint32(len(m.template)))
533
// fixed-size templates
534
for i, x := range m.template {
535
var tag, val1, val2 uint32
538
return errors.New("unexpected template type")
543
val1 = uint32(m.size[i])
548
val1 = uint32(m.size[i])
555
val1 = uint32(m.size[i])
558
val1 = uint32(m.size[i])
567
for _, x := range m.value {
568
var tag, val1, val2 uint32
569
switch x := x.(type) {
571
return errors.New("unexpected value type")
579
val1 = uint32(len(x))
584
val2 = uint32(v >> 32)
587
val1 = uint32(len(x))
590
m.desc = append(m.desc, x)
593
val1 = uint32(len(x))
596
val1 = uint32(len(x) + 1)
604
// variable-length data for values
605
for _, x := range m.value {
606
switch x := x.(type) {
610
for _, f := range x {
611
m.wuint64(float64bits(f))
614
for _, j := range x {
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)))
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")
643
if m.uint32() != protocol {
644
return errors.New("Native Client: RPC protocol mismatch")
649
m.isRequest = 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))
656
return errors.New("Native Client: malformed message")
659
// fixed-size templates
660
for i := range m.template {
662
m.uint32() // padding
667
return errors.New("Native Client: unexpected template type " + string(rune(tag)))
669
m.template[i] = false
671
m.template[i] = []byte(nil)
672
m.size[i] = int(val1)
674
m.template[i] = float64(0)
676
m.template[i] = []float64(nil)
677
m.size[i] = int(val1)
679
m.template[i] = int32(0)
681
m.template[i] = []int32(nil)
682
m.size[i] = int(val1)
684
m.template[i] = int(0)
687
m.size[i] = int(val1)
696
for i := range m.value {
698
m.uint32() // padding
703
return errors.New("Native Client: unexpected value type " + string(rune(tag)))
705
m.value[i] = val1 > 0
707
m.value[i] = []byte(nil)
708
strsize = append(strsize, val1)
710
m.value[i] = float64frombits(uint64(val1) | uint64(val2)<<32)
712
m.value[i] = make([]float64, val1)
714
m.value[i] = int32(val1)
716
m.value[i] = make([]int32, val1)
718
m.value[i] = int(m.desc[d])
722
strsize = append(strsize, val1)
726
// variable-sized parts of values
727
for i, x := range m.value {
728
switch x := x.(type) {
730
m.value[i] = m.bytes(int(strsize[0]))
731
strsize = strsize[1:]
734
x[i] = float64frombits(m.uint64())
738
x[i] = int32(m.uint32())
741
m.value[i] = string(m.bytes(int(strsize[0])))
742
strsize = strsize[1:]
747
return errors.New("Native Client: junk at end of message")
752
func float64bits(x float64) uint64 {
753
return *(*uint64)(unsafe.Pointer(&x))
756
func float64frombits(x uint64) float64 {
757
return *(*float64)(unsafe.Pointer(&x))
760
// At startup, connect to the name service.
761
var nsClient = nsConnect()
763
func nsConnect() *srpcClient {
765
_, _, errno := Syscall(sys_nameservice, uintptr(unsafe.Pointer(&ns)), 0, 0)
767
println("Native Client nameservice:", errno.Error())
771
sock, _, errno := Syscall(sys_imc_connect, uintptr(ns), 0, 0)
773
println("Native Client nameservice connect:", errno.Error())
777
c, err := newClient(int(sock))
779
println("Native Client nameservice init:", err.Error())
790
nsInsufficientResources = 3
791
nsPermissionDenied = 4
792
nsInvalidArgument = 5
795
func openNamedService(name string, mode int32) (fd int, err error) {
797
return 0, errors.New("no name service")
799
ret, err := nsClient.Call("lookup:si:ih", name, int32(mode))
803
status := ret[0].(int32)
810
case nsDuplicateName:
812
case nsInsufficientResources:
813
return -1, EWOULDBLOCK
814
case nsPermissionDenied:
816
case nsInvalidArgument: