diff options
Diffstat (limited to 'libgo/go/exp/nacl/srpc/msg.go')
-rw-r--r-- | libgo/go/exp/nacl/srpc/msg.go | 522 |
1 files changed, 0 insertions, 522 deletions
diff --git a/libgo/go/exp/nacl/srpc/msg.go b/libgo/go/exp/nacl/srpc/msg.go deleted file mode 100644 index 92601ed3730..00000000000 --- a/libgo/go/exp/nacl/srpc/msg.go +++ /dev/null @@ -1,522 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// SRPC constants, data structures, and parsing. - -package srpc - -import ( - "math" - "os" - "strconv" - "syscall" - "unsafe" -) - -// An Errno is an SRPC status code. -type Errno uint32 - -const ( - OK Errno = 256 + iota - ErrBreak - ErrMessageTruncated - ErrNoMemory - ErrProtocolMismatch - ErrBadRPCNumber - ErrBadArgType - ErrTooFewArgs - ErrTooManyArgs - ErrInArgTypeMismatch - ErrOutArgTypeMismatch - ErrInternalError - ErrAppError -) - -var errstr = [...]string{ - OK - OK: "ok", - ErrBreak - OK: "break", - ErrMessageTruncated - OK: "message truncated", - ErrNoMemory - OK: "out of memory", - ErrProtocolMismatch - OK: "protocol mismatch", - ErrBadRPCNumber - OK: "invalid RPC method number", - ErrBadArgType - OK: "unexpected argument type", - ErrTooFewArgs - OK: "too few arguments", - ErrTooManyArgs - OK: "too many arguments", - ErrInArgTypeMismatch - OK: "input argument type mismatch", - ErrOutArgTypeMismatch - OK: "output argument type mismatch", - ErrInternalError - OK: "internal error", - ErrAppError - OK: "application error", -} - -func (e Errno) String() string { - if e < OK || int(e-OK) >= len(errstr) { - return "Errno(" + strconv.Itoa64(int64(e)) + ")" - } - return errstr[e-OK] -} - -// A *msgHdr is the data argument to the imc_recvmsg -// and imc_sendmsg system calls. Because it contains unchecked -// counts trusted by the system calls, the data structure is unsafe -// to expose to package clients. -type msgHdr struct { - iov *iov - niov int32 - desc *int32 - ndesc int32 - flags uint32 -} - -// A single region for I/O. Just as unsafe as msgHdr. -type iov struct { - base *byte - len int32 -} - -// A msg is the Go representation of a message. -type msg struct { - rdata []byte // data being consumed during message parsing - rdesc []int32 // file descriptors being consumed during message parsing - wdata []byte // data being generated when replying - - // parsed version of message - protocol uint32 - requestId uint64 - isReq bool - rpcNumber uint32 - gotHeader bool - status Errno // error code sent in response - Arg []interface{} // method arguments - Ret []interface{} // method results - Size []int // max sizes for arrays in method results - fmt string // accumulated format string of arg+":"+ret -} - -// A msgReceiver receives messages from a file descriptor. -type msgReceiver struct { - fd int - data [128 * 1024]byte - desc [8]int32 - hdr msgHdr - iov iov -} - -func (r *msgReceiver) recv() (*msg, os.Error) { - // Init pointers to buffers where syscall recvmsg can write. - r.iov.base = &r.data[0] - r.iov.len = int32(len(r.data)) - r.hdr.iov = &r.iov - r.hdr.niov = 1 - r.hdr.desc = &r.desc[0] - r.hdr.ndesc = int32(len(r.desc)) - n, _, e := syscall.Syscall(syscall.SYS_IMC_RECVMSG, uintptr(r.fd), uintptr(unsafe.Pointer(&r.hdr)), 0) - if e != 0 { - return nil, os.NewSyscallError("imc_recvmsg", int(e)) - } - - // Make a copy of the data so that the next recvmsg doesn't - // smash it. The system call did not update r.iov.len. Instead it - // returned the total byte count as n. - m := new(msg) - m.rdata = make([]byte, n) - copy(m.rdata, r.data[0:]) - - // Make a copy of the desc too. - // The system call *did* update r.hdr.ndesc. - if r.hdr.ndesc > 0 { - m.rdesc = make([]int32, r.hdr.ndesc) - copy(m.rdesc, r.desc) - } - - return m, nil -} - -// A msgSender sends messages on a file descriptor. -type msgSender struct { - fd int - hdr msgHdr - iov iov -} - -func (s *msgSender) send(m *msg) os.Error { - if len(m.wdata) > 0 { - s.iov.base = &m.wdata[0] - } - s.iov.len = int32(len(m.wdata)) - s.hdr.iov = &s.iov - s.hdr.niov = 1 - s.hdr.desc = nil - s.hdr.ndesc = 0 - _, _, e := syscall.Syscall(syscall.SYS_IMC_SENDMSG, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0) - if e != 0 { - return os.NewSyscallError("imc_sendmsg", int(e)) - } - return nil -} - -// Reading from msg.rdata. -func (m *msg) uint8() uint8 { - if m.status != OK { - return 0 - } - if len(m.rdata) < 1 { - m.status = ErrMessageTruncated - return 0 - } - x := m.rdata[0] - m.rdata = m.rdata[1:] - return x -} - -func (m *msg) uint32() uint32 { - if m.status != OK { - return 0 - } - if len(m.rdata) < 4 { - m.status = ErrMessageTruncated - return 0 - } - b := m.rdata[0:4] - x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 - m.rdata = m.rdata[4:] - return x -} - -func (m *msg) uint64() uint64 { - if m.status != OK { - return 0 - } - if len(m.rdata) < 8 { - m.status = ErrMessageTruncated - return 0 - } - b := m.rdata[0:8] - x := uint64(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) - x |= uint64(uint32(b[4])|uint32(b[5])<<8|uint32(b[6])<<16|uint32(b[7])<<24) << 32 - m.rdata = m.rdata[8:] - return x -} - -func (m *msg) bytes(n int) []byte { - if m.status != OK { - return nil - } - if len(m.rdata) < n { - m.status = ErrMessageTruncated - return nil - } - x := m.rdata[0:n] - m.rdata = m.rdata[n:] - return x -} - -// Writing to msg.wdata. -func (m *msg) grow(n int) []byte { - i := len(m.wdata) - if i+n > cap(m.wdata) { - a := make([]byte, i, (i+n)*2) - copy(a, m.wdata) - m.wdata = a - } - m.wdata = m.wdata[0 : i+n] - return m.wdata[i : i+n] -} - -func (m *msg) wuint8(x uint8) { m.grow(1)[0] = x } - -func (m *msg) wuint32(x uint32) { - b := m.grow(4) - b[0] = byte(x) - b[1] = byte(x >> 8) - b[2] = byte(x >> 16) - b[3] = byte(x >> 24) -} - -func (m *msg) wuint64(x uint64) { - b := m.grow(8) - lo := uint32(x) - b[0] = byte(lo) - b[1] = byte(lo >> 8) - b[2] = byte(lo >> 16) - b[3] = byte(lo >> 24) - hi := uint32(x >> 32) - b[4] = byte(hi) - b[5] = byte(hi >> 8) - b[6] = byte(hi >> 16) - b[7] = byte(hi >> 24) -} - -func (m *msg) wbytes(p []byte) { copy(m.grow(len(p)), p) } - -func (m *msg) wstring(s string) { - b := m.grow(len(s)) - copy(b, s) -} - -// Parsing of RPC header and arguments. -// -// The header format is: -// protocol uint32; -// requestId uint64; -// isReq bool; -// rpcNumber uint32; -// status uint32; // only for response -// -// Then a sequence of values follow, preceded by the length: -// nvalue uint32; -// -// Each value begins with a one-byte type followed by -// type-specific data. -// -// type uint8; -// 'b': x bool; -// 'C': len uint32; x [len]byte; -// 'd': x float64; -// 'D': len uint32; x [len]float64; -// 'h': x int; // handle aka file descriptor -// 'i': x int32; -// 'I': len uint32; x [len]int32; -// 's': len uint32; x [len]byte; -// -// If this is a request, a sequence of pseudo-values follows, -// preceded by its length (nvalue uint32). -// -// Each pseudo-value is a one-byte type as above, -// followed by a maximum length (len uint32) -// for the 'C', 'D', 'I', and 's' types. -// -// In the Go msg, we represent each argument by -// an empty interface containing the type of x in the -// corresponding case. - -// The current protocol number. -const protocol = 0xc0da0002 - -func (m *msg) unpackHeader() { - m.protocol = m.uint32() - m.requestId = m.uint64() - m.isReq = m.uint8() != 0 - m.rpcNumber = m.uint32() - m.gotHeader = m.status == OK // signal that header parsed successfully - if m.gotHeader && !m.isReq { - status := Errno(m.uint32()) - m.gotHeader = m.status == OK // still ok? - if m.gotHeader { - m.status = status - } - } -} - -func (m *msg) packHeader() { - m.wuint32(m.protocol) - m.wuint64(m.requestId) - if m.isReq { - m.wuint8(1) - } else { - m.wuint8(0) - } - m.wuint32(m.rpcNumber) - if !m.isReq { - m.wuint32(uint32(m.status)) - } -} - -func (m *msg) unpackValues(v []interface{}) { - for i := range v { - t := m.uint8() - m.fmt += string(t) - switch t { - default: - if m.status == OK { - m.status = ErrBadArgType - } - return - case 'b': // bool[1] - v[i] = m.uint8() > 0 - case 'C': // char array - v[i] = m.bytes(int(m.uint32())) - case 'd': // double - v[i] = math.Float64frombits(m.uint64()) - case 'D': // double array - a := make([]float64, int(m.uint32())) - for j := range a { - a[j] = math.Float64frombits(m.uint64()) - } - v[i] = a - case 'h': // file descriptor (handle) - if len(m.rdesc) == 0 { - if m.status == OK { - m.status = ErrBadArgType - } - return - } - v[i] = int(m.rdesc[0]) - m.rdesc = m.rdesc[1:] - case 'i': // int - v[i] = int32(m.uint32()) - case 'I': // int array - a := make([]int32, int(m.uint32())) - for j := range a { - a[j] = int32(m.uint32()) - } - v[i] = a - case 's': // string - v[i] = string(m.bytes(int(m.uint32()))) - } - } -} - -func (m *msg) packValues(v []interface{}) { - for i := range v { - switch x := v[i].(type) { - default: - if m.status == OK { - m.status = ErrInternalError - } - return - case bool: - m.wuint8('b') - if x { - m.wuint8(1) - } else { - m.wuint8(0) - } - case []byte: - m.wuint8('C') - m.wuint32(uint32(len(x))) - m.wbytes(x) - case float64: - m.wuint8('d') - m.wuint64(math.Float64bits(x)) - case []float64: - m.wuint8('D') - m.wuint32(uint32(len(x))) - for _, f := range x { - m.wuint64(math.Float64bits(f)) - } - case int32: - m.wuint8('i') - m.wuint32(uint32(x)) - case []int32: - m.wuint8('I') - m.wuint32(uint32(len(x))) - for _, i := range x { - m.wuint32(uint32(i)) - } - case string: - m.wuint8('s') - m.wuint32(uint32(len(x))) - m.wstring(x) - } - } -} - -func (m *msg) unpackRequest() { - m.status = OK - if m.unpackHeader(); m.status != OK { - return - } - if m.protocol != protocol || !m.isReq { - m.status = ErrProtocolMismatch - return - } - - // type-tagged argument values - m.Arg = make([]interface{}, m.uint32()) - m.unpackValues(m.Arg) - if m.status != OK { - return - } - - // type-tagged expected return sizes. - // fill in zero values for each return value - // and save sizes. - m.fmt += ":" - m.Ret = make([]interface{}, m.uint32()) - m.Size = make([]int, len(m.Ret)) - for i := range m.Ret { - t := m.uint8() - m.fmt += string(t) - switch t { - default: - if m.status == OK { - m.status = ErrBadArgType - } - return - case 'b': // bool[1] - m.Ret[i] = false - case 'C': // char array - m.Size[i] = int(m.uint32()) - m.Ret[i] = []byte(nil) - case 'd': // double - m.Ret[i] = float64(0) - case 'D': // double array - m.Size[i] = int(m.uint32()) - m.Ret[i] = []float64(nil) - case 'h': // file descriptor (handle) - m.Ret[i] = int(-1) - case 'i': // int - m.Ret[i] = int32(0) - case 'I': // int array - m.Size[i] = int(m.uint32()) - m.Ret[i] = []int32(nil) - case 's': // string - m.Size[i] = int(m.uint32()) - m.Ret[i] = "" - } - } -} - -func (m *msg) packRequest() { - m.packHeader() - m.wuint32(uint32(len(m.Arg))) - m.packValues(m.Arg) - m.wuint32(uint32(len(m.Ret))) - for i, v := range m.Ret { - switch x := v.(type) { - case bool: - m.wuint8('b') - case []byte: - m.wuint8('C') - m.wuint32(uint32(m.Size[i])) - case float64: - m.wuint8('d') - case []float64: - m.wuint8('D') - m.wuint32(uint32(m.Size[i])) - case int: - m.wuint8('h') - case int32: - m.wuint8('i') - case []int32: - m.wuint8('I') - m.wuint32(uint32(m.Size[i])) - case string: - m.wuint8('s') - m.wuint32(uint32(m.Size[i])) - } - } -} - -func (m *msg) unpackResponse() { - m.status = OK - if m.unpackHeader(); m.status != OK { - return - } - if m.protocol != protocol || m.isReq { - m.status = ErrProtocolMismatch - return - } - - // type-tagged return values - m.fmt = "" - m.Ret = make([]interface{}, m.uint32()) - m.unpackValues(m.Ret) -} - -func (m *msg) packResponse() { - m.packHeader() - m.wuint32(uint32(len(m.Ret))) - m.packValues(m.Ret) -} |