summaryrefslogtreecommitdiff
path: root/libgo/go/exp/nacl/srpc/msg.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/exp/nacl/srpc/msg.go')
-rw-r--r--libgo/go/exp/nacl/srpc/msg.go522
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)
-}