func (c *Client) Call(call interface{}) ([]byte, error) { msg := &message{ Xid: 0xcafebabe, Msgtype: 0, Body: call, } w := new(bytes.Buffer) if err := xdr.Write(w, msg); err != nil { return nil, err } if err := c.send(w.Bytes()); err != nil { return nil, err } buf, err := c.recv() if err != nil { return nil, err } xid, buf := xdr.Uint32(buf) if xid != msg.Xid { return nil, fmt.Errorf("xid did not match, expected: %x, received: %x", msg.Xid, xid) } mtype, buf := xdr.Uint32(buf) if mtype != 1 { return nil, fmt.Errorf("message as not a reply: %d", mtype) } reply_stat, buf := xdr.Uint32(buf) switch reply_stat { case MSG_ACCEPTED: _, buf = xdr.Uint32(buf) opaque_len, buf := xdr.Uint32(buf) _ = buf[0:int(opaque_len)] buf = buf[opaque_len:] accept_stat, buf := xdr.Uint32(buf) switch accept_stat { case SUCCESS: return buf, nil case PROG_UNAVAIL: return nil, fmt.Errorf("PROG_UNAVAIL") case PROG_MISMATCH: // TODO(dfc) decode mismatch_info return nil, fmt.Errorf("rpc: PROG_MISMATCH") default: return nil, fmt.Errorf("rpc: %d", accept_stat) } case MSG_DENIED: rejected_stat, _ := xdr.Uint32(buf) switch rejected_stat { case RPC_MISMATCH: default: return nil, fmt.Errorf("rejected_stat was not valid: %d", rejected_stat) } default: return nil, fmt.Errorf("reply_stat was not valid: %d", reply_stat) } panic("unreachable") }
func (m *Mount) Mount(dirpath string, auth rpc.Auth) (*Volume, error) { type mount struct { rpc.Header Dirpath string } buf, err := m.Call(&mount{ rpc.Header{ Rpcvers: 2, Prog: MOUNT_PROG, Vers: MOUNT_VERS, Proc: MOUNTPROC3_EXPORT, Cred: auth, Verf: rpc.AUTH_NULL, }, dirpath, }) if err != nil { return nil, err } mountstat3, buf := xdr.Uint32(buf) switch mountstat3 { case MNT3_OK: fh, buf := xdr.Opaque(buf) _, buf = xdr.Uint32List(buf) return &Volume{fh}, nil case MNT3ERR_PERM: return nil, &Error{"MNT3ERR_PERM"} case MNT3ERR_NOENT: return nil, &Error{"MNT3ERR_NOENT"} case MNT3ERR_IO: return nil, &Error{"MNT3ERR_IO"} case MNT3ERR_ACCES: return nil, &Error{"MNT3ERR_ACCES"} case MNT3ERR_NOTDIR: return nil, &Error{"MNT3ERR_NOTDIR"} case MNT3ERR_NAMETOOLONG: return nil, &Error{"MNT3ERR_NAMETOOLONG"} } return nil, fmt.Errorf("unknown mount stat: %d", mountstat3) }
func (p *Portmapper) Getport(mapping Mapping) (int, error) { type getport struct { Header Mapping } msg := &getport{ Header{ Rpcvers: 2, Prog: PMAP_PROG, Vers: PMAP_VERS, Proc: PMAPPROC_GETPORT, Cred: AUTH_NULL, Verf: AUTH_NULL, }, mapping, } buf, err := p.Call(msg) if err != nil { return 0, err } port, _ := xdr.Uint32(buf) return int(port), nil }