summaryrefslogtreecommitdiff
path: root/usr/rsc
diff options
context:
space:
mode:
Diffstat (limited to 'usr/rsc')
-rw-r--r--usr/rsc/nacl/av/Makefile13
-rw-r--r--usr/rsc/nacl/av/av.go311
-rw-r--r--usr/rsc/nacl/av/event.go471
-rw-r--r--usr/rsc/nacl/av/image.go95
-rw-r--r--usr/rsc/nacl/srpc/Makefile13
-rw-r--r--usr/rsc/nacl/srpc/client.go210
-rw-r--r--usr/rsc/nacl/srpc/msg.go532
-rw-r--r--usr/rsc/nacl/srpc/server.go204
8 files changed, 0 insertions, 1849 deletions
diff --git a/usr/rsc/nacl/av/Makefile b/usr/rsc/nacl/av/Makefile
deleted file mode 100644
index 523a9fff1..000000000
--- a/usr/rsc/nacl/av/Makefile
+++ /dev/null
@@ -1,13 +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.
-
-include $(GOROOT)/src/Make.$(GOARCH)
-
-TARG=nacl/av
-GOFILES=\
- av.go\
- event.go\
- image.go\
-
-include $(GOROOT)/src/Make.pkg
diff --git a/usr/rsc/nacl/av/av.go b/usr/rsc/nacl/av/av.go
deleted file mode 100644
index 0accf4612..000000000
--- a/usr/rsc/nacl/av/av.go
+++ /dev/null
@@ -1,311 +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.
-
-// Native Client audio/video
-
-// Package av implements audio and video access for Native Client
-// binaries running standalone or embedded in a web browser window.
-//
-// The C version of the API is documented at
-// http://nativeclient.googlecode.com/svn/data/docs_tarball/nacl/googleclient/native_client/scons-out/doc/html/group__audio__video.html
-package av
-
-import (
- "bytes";
- "draw";
- "log";
- "nacl/srpc";
- "os";
- "syscall";
- "unsafe";
-)
-
-var srpcEnabled = srpc.Enabled();
-
-// native_client/src/trusted/service_runtime/include/sys/audio_video.h
-
-// Subsystem values for Init.
-const (
- SubsystemVideo = 1<<iota;
- SubsystemAudio;
- SubsystemEmbed;
-)
-// SubsystemRawEvents;
-
-// Audio formats.
-const (
- AudioFormatStereo44K = iota;
- AudioFormatStereo48K;
-)
-
-// A Window represents a connection to the Native Client window.
-// It implements draw.Context.
-type Window struct {
- Embedded bool; // running as part of a web page?
- *Image; // screen image
-
- mousec chan draw.Mouse;
- kbdc chan int;
- quitc chan bool;
- resizec chan bool;
-}
-
-// *Window implements draw.Context
-var _ draw.Context = (*Window)(nil)
-
-func (w *Window) KeyboardChan() <-chan int {
- return w.kbdc;
-}
-
-func (w *Window) MouseChan() <-chan draw.Mouse {
- return w.mousec;
-}
-
-func (w *Window) QuitChan() <-chan bool {
- return w.quitc;
-}
-
-func (w *Window) ResizeChan() <-chan bool {
- return w.resizec;
-}
-
-func (w *Window) Screen() draw.Image {
- return w.Image;
-}
-
-// Init initializes the Native Client subsystems specified by subsys.
-// Init must be called before using any of the other functions
-// in this package, and it must be called only once.
-//
-// If the SubsystemVideo flag is set, Init requests a window of size dx×dy.
-// When embedded in a web page, the web page's window specification
-// overrides the parameters to Init, so the returned Window may have
-// a different size than requested.
-//
-// If the SubsystemAudio flag is set, Init requests a connection to the
-// audio device carrying 44 kHz 16-bit stereo PCM audio samples.
-func Init(subsys int, dx, dy int) (*Window, os.Error) {
- xsubsys := subsys;
- if srpcEnabled {
- waitBridge();
- xsubsys &^= SubsystemVideo|SubsystemEmbed;
- }
-
- if xsubsys & SubsystemEmbed != 0 {
- return nil, os.NewError("not embedded");
- }
-
- w := new(Window);
- err := multimediaInit(xsubsys);
- if err != nil {
- return nil, err;
- }
-
- if subsys&SubsystemVideo != 0 {
- if dx, dy, err = videoInit(dx, dy); err != nil {
- return nil, err;
- }
- w.Image = newImage(dx, dy, bridge.pixel);
- w.resizec = make(chan bool, 64);
- w.kbdc = make(chan int, 64);
- w.mousec = make(chan draw.Mouse, 64);
- w.quitc = make(chan bool);
- }
-
- if subsys&SubsystemAudio != 0 {
- var n int;
- if n, err = audioInit(AudioFormatStereo44K, 2048); err != nil {
- return nil, err;
- }
- println("audio", n);
- }
-
- if subsys&SubsystemVideo != 0 {
- go w.readEvents();
- }
-
- return w, nil;
-}
-
-func (w *Window) FlushImage() {
- if w.Image == nil {
- return;
- }
- videoUpdate(w.Image.Linear);
-}
-
-func multimediaInit(subsys int) (err os.Error) {
- return os.NewSyscallError("multimedia_init", syscall.MultimediaInit(subsys));
-}
-
-func videoInit(dx, dy int) (ndx, ndy int, err os.Error) {
- if srpcEnabled {
- bridge.share.ready = 1;
- return int(bridge.share.width), int(bridge.share.height), nil;
- }
- if e := syscall.VideoInit(dx, dy); e != 0 {
- return 0, 0, os.NewSyscallError("video_init", int(e));
- }
- return dx, dy, nil;
-}
-
-func videoUpdate(data []Color) (err os.Error) {
- if srpcEnabled {
- bridge.flushRPC.Call("upcall", nil);
- return;
- }
- return os.NewSyscallError("video_update", syscall.VideoUpdate((*uint32)(&data[0])));
-}
-
-var noEvents = os.NewError("no events");
-
-func videoPollEvent(ev []byte) (err os.Error) {
- if srpcEnabled {
- r := bridge.share.eq.ri;
- if r == bridge.share.eq.wi {
- return noEvents;
- }
- bytes.Copy(ev, &bridge.share.eq.event[r]);
- bridge.share.eq.ri = (r+1) % eqsize;
- return nil;
- }
- return os.NewSyscallError("video_poll_event", syscall.VideoPollEvent(&ev[0]));
-}
-
-func audioInit(fmt int, want int) (got int, err os.Error) {
- var x int;
- e := syscall.AudioInit(fmt, want, &x);
- if e == 0 {
- return x, nil;
- }
- return 0, os.NewSyscallError("audio_init", e);
-}
-
-var audioSize uintptr
-
-// AudioStream provides access to the audio device.
-// Each call to AudioStream writes the given data,
-// which should be a slice of 16-bit stereo PCM audio samples,
-// and returns the number of samples required by the next
-// call to AudioStream.
-//
-// To find out the initial number of samples to write, call AudioStream(nil).
-//
-func AudioStream(data []uint16) (nextSize int, err os.Error) {
- if audioSize == 0 {
- e := os.NewSyscallError("audio_stream", syscall.AudioStream(nil, &audioSize));
- return int(audioSize), e;
- }
- if data == nil {
- return int(audioSize), nil;
- }
- if uintptr(len(data))*2 != audioSize {
- log.Stdoutf("invalid audio size want %d got %d", audioSize, len(data));
- }
- e := os.NewSyscallError("audio_stream", syscall.AudioStream(&data[0], &audioSize));
- return int(audioSize), e;
-}
-
-// Synchronization structure to wait for bridge to become ready.
-var bridge struct {
- c chan bool;
- displayFd int;
- rpcFd int;
- share *videoShare;
- pixel []Color;
- client *srpc.Client;
- flushRPC *srpc.RPC;
-}
-
-// Wait for bridge to become ready.
-// When chan is first created, there is nothing in it,
-// so this blocks. Once the bridge is ready, multimediaBridge.Run
-// will drop a value into the channel. Then any calls
-// to waitBridge will finish, taking the value out and immediately putting it back.
-func waitBridge() {
- bridge.c <- <-bridge.c;
-}
-
-const eqsize = 64;
-
-// Data structure shared with host via mmap.
-type videoShare struct {
- revision int32; // definition below is rev 100 unless noted
- mapSize int32;
-
- // event queue
- eq struct {
- ri uint32; // read index [0,eqsize)
- wi uint32; // write index [0,eqsize)
- eof int32;
- event [eqsize][64]byte;
- };
-
- // now unused
- _, _, _, _ int32;
-
- // video backing store information
- width, height, _, size int32;
- ready int32; // rev 0x101
-}
-
-// The frame buffer data is videoShareSize bytes after
-// the videoShare begins.
-const videoShareSize = 16*1024
-
-type multimediaBridge struct{}
-
-// If using SRPC, the runtime will call this method to pass in two file descriptors,
-// one to mmap to get the display memory, and another to use for SRPCs back
-// to the main process.
-func (multimediaBridge) Run(arg, ret []interface{}, size []int) srpc.Errno {
- bridge.displayFd = arg[0].(int);
- bridge.rpcFd = arg[1].(int);
-
- var st syscall.Stat_t;
- if errno := syscall.Fstat(bridge.displayFd, &st); errno != 0 {
- log.Exitf("mmbridge stat display: %s", os.Errno(errno));
- }
-
- addr, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
- 0,
- uintptr(st.Size),
- syscall.PROT_READ|syscall.PROT_WRITE,
- syscall.MAP_SHARED,
- uintptr(bridge.displayFd),
- 0);
- if errno != 0 {
- log.Exitf("mmap display: %s", os.Errno(errno));
- }
-
- bridge.share = (*videoShare)(unsafe.Pointer(addr));
-
- // Overestimate frame buffer size
- // (must use a compile-time constant)
- // and then reslice. 256 megapixels (1 GB) should be enough.
- fb := (*[256*1024*1024]Color)(unsafe.Pointer(addr+videoShareSize));
- bridge.pixel = fb[0:(st.Size - videoShareSize)/4];
-
- // Configure RPC connection back to client.
- var err os.Error;
- bridge.client, err = srpc.NewClient(bridge.rpcFd);
- if err != nil {
- log.Exitf("NewClient: %s", err);
- }
- bridge.flushRPC = bridge.client.NewRPC(nil);
-
- // Notify waiters that the bridge is ready.
- println("bridged", bridge.share.revision);
- bridge.c <- true;
-
- return srpc.OK;
-}
-
-func init() {
- bridge.c = make(chan bool, 1);
- if srpcEnabled {
- srpc.Add("nacl_multimedia_bridge", "hh:", multimediaBridge{});
- }
-}
-
diff --git a/usr/rsc/nacl/av/event.go b/usr/rsc/nacl/av/event.go
deleted file mode 100644
index 62ecbc6e6..000000000
--- a/usr/rsc/nacl/av/event.go
+++ /dev/null
@@ -1,471 +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.
-
-// NaCl GUI events.
-// Clients do not have raw access to the event stream
-// (only filtered through the lens of package draw)
-// but perhaps they will.
-
-package av
-
-import (
- "bytes";
- "debug/binary";
- "draw";
- "log";
- "os";
- "time";
-)
-
-// An eventType identifies the type of a Native Client Event.
-type eventType uint8;
-const (
- eventActive = 1+iota;
- eventExpose;
- eventKeyDown;
- eventKeyUp;
- eventMouseMotion;
- eventMouseButtonDown;
- eventMouseButtonUp;
- eventQuit;
- eventUnsupported;
-)
-
-// A key represents a key on a keyboard.
-type key uint16
-const (
- keyUnknown = 0;
- keyFirst = 0;
- keyBackspace = 8;
- keyTab = 9;
- keyClear = 12;
- keyReturn = 13;
- keyPause = 19;
- keyEscape = 27;
- keySpace = 32;
- keyExclaim = 33;
- keyQuotedbl = 34;
- keyHash = 35;
- keyDollar = 36;
- keyAmpersand = 38;
- keyQuote = 39;
- keyLeftparen = 40;
- keyRightparen = 41;
- keyAsterisk = 42;
- keyPlus = 43;
- keyComma = 44;
- keyMinus = 45;
- keyPeriod = 46;
- keySlash = 47;
- key0 = 48;
- key1 = 49;
- key2 = 50;
- key3 = 51;
- key4 = 52;
- key5 = 53;
- key6 = 54;
- key7 = 55;
- key8 = 56;
- key9 = 57;
- keyColon = 58;
- keySemicolon = 59;
- keyLess = 60;
- keyEquals = 61;
- keyGreater = 62;
- keyQuestion = 63;
- keyAt = 64;
- keyLeftbracket = 91;
- keyBackslash = 92;
- keyRightbracket = 93;
- keyCaret = 94;
- keyUnderscore = 95;
- keyBackquote = 96;
- keyA = 97;
- keyB = 98;
- keyC = 99;
- keyD = 100;
- keyE = 101;
- keyF = 102;
- keyG = 103;
- keyH = 104;
- keyI = 105;
- keyJ = 106;
- keyK = 107;
- keyL = 108;
- keyM = 109;
- keyN = 110;
- keyO = 111;
- keyP = 112;
- keyQ = 113;
- keyR = 114;
- keyS = 115;
- keyT = 116;
- keyU = 117;
- keyV = 118;
- keyW = 119;
- keyX = 120;
- keyY = 121;
- keyZ = 122;
- keyDelete = 127;
- keyWorld0 = 160;
- keyWorld1 = 161;
- keyWorld2 = 162;
- keyWorld3 = 163;
- keyWorld4 = 164;
- keyWorld5 = 165;
- keyWorld6 = 166;
- keyWorld7 = 167;
- keyWorld8 = 168;
- keyWorld9 = 169;
- keyWorld10 = 170;
- keyWorld11 = 171;
- keyWorld12 = 172;
- keyWorld13 = 173;
- keyWorld14 = 174;
- keyWorld15 = 175;
- keyWorld16 = 176;
- keyWorld17 = 177;
- keyWorld18 = 178;
- keyWorld19 = 179;
- keyWorld20 = 180;
- keyWorld21 = 181;
- keyWorld22 = 182;
- keyWorld23 = 183;
- keyWorld24 = 184;
- keyWorld25 = 185;
- keyWorld26 = 186;
- keyWorld27 = 187;
- keyWorld28 = 188;
- keyWorld29 = 189;
- keyWorld30 = 190;
- keyWorld31 = 191;
- keyWorld32 = 192;
- keyWorld33 = 193;
- keyWorld34 = 194;
- keyWorld35 = 195;
- keyWorld36 = 196;
- keyWorld37 = 197;
- keyWorld38 = 198;
- keyWorld39 = 199;
- keyWorld40 = 200;
- keyWorld41 = 201;
- keyWorld42 = 202;
- keyWorld43 = 203;
- keyWorld44 = 204;
- keyWorld45 = 205;
- keyWorld46 = 206;
- keyWorld47 = 207;
- keyWorld48 = 208;
- keyWorld49 = 209;
- keyWorld50 = 210;
- keyWorld51 = 211;
- keyWorld52 = 212;
- keyWorld53 = 213;
- keyWorld54 = 214;
- keyWorld55 = 215;
- keyWorld56 = 216;
- keyWorld57 = 217;
- keyWorld58 = 218;
- keyWorld59 = 219;
- keyWorld60 = 220;
- keyWorld61 = 221;
- keyWorld62 = 222;
- keyWorld63 = 223;
- keyWorld64 = 224;
- keyWorld65 = 225;
- keyWorld66 = 226;
- keyWorld67 = 227;
- keyWorld68 = 228;
- keyWorld69 = 229;
- keyWorld70 = 230;
- keyWorld71 = 231;
- keyWorld72 = 232;
- keyWorld73 = 233;
- keyWorld74 = 234;
- keyWorld75 = 235;
- keyWorld76 = 236;
- keyWorld77 = 237;
- keyWorld78 = 238;
- keyWorld79 = 239;
- keyWorld80 = 240;
- keyWorld81 = 241;
- keyWorld82 = 242;
- keyWorld83 = 243;
- keyWorld84 = 244;
- keyWorld85 = 245;
- keyWorld86 = 246;
- keyWorld87 = 247;
- keyWorld88 = 248;
- keyWorld89 = 249;
- keyWorld90 = 250;
- keyWorld91 = 251;
- keyWorld92 = 252;
- keyWorld93 = 253;
- keyWorld94 = 254;
- keyWorld95 = 255;
-
- // Numeric keypad
- keyKp0 = 256;
- keyKp1 = 257;
- keyKp2 = 258;
- keyKp3 = 259;
- keyKp4 = 260;
- keyKp5 = 261;
- keyKp6 = 262;
- keyKp7 = 263;
- keyKp8 = 264;
- keyKp9 = 265;
- keyKpPeriod = 266;
- keyKpDivide = 267;
- keyKpMultiply = 268;
- keyKpMinus = 269;
- keyKpPlus = 270;
- keyKpEnter = 271;
- keyKpEquals = 272;
-
- // Arrow & insert/delete pad
- keyUp = 273;
- keyDown = 274;
- keyRight = 275;
- keyLeft = 276;
- keyInsert = 277;
- keyHome = 278;
- keyEnd = 279;
- keyPageup = 280;
- keyPagedown = 281;
-
- // Function keys
- keyF1 = 282;
- keyF2 = 283;
- keyF3 = 284;
- keyF4 = 285;
- keyF5 = 286;
- keyF6 = 287;
- keyF7 = 288;
- keyF8 = 289;
- keyF9 = 290;
- keyF10 = 291;
- keyF11 = 292;
- keyF12 = 293;
- keyF13 = 294;
- keyF14 = 295;
- keyF15 = 296;
-
- // Modifier keys
- keyNumlock = 300;
- keyCapslock = 301;
- keyScrollock = 302;
- keyRshift = 303;
- keyLshift = 304;
- keyRctrl = 305;
- keyLctrl = 306;
- keyRalt = 307;
- keyLalt = 308;
- keyRmeta = 309;
- keyLmeta = 310;
- keyLsuper = 311;
- keyRsuper = 312;
- keyMode = 313;
- keyCompose = 314;
-
- // Misc keys
- keyHelp = 315;
- keyPrint = 316;
- keySysreq = 317;
- keyBreak = 318;
- keyMenu = 319;
- keyPower = 320;
- keyEuro = 321;
- keyUndo = 322;
-
- // Add any other keys here
- keyLast
-)
-
-// A keymod is a set of bit flags
-type keymod uint16
-const (
- keymodNone = 0x0000;
- keymodLshift= 0x0001;
- keymodRshift= 0x0002;
- keymodLctrl = 0x0040;
- keymodRctrl = 0x0080;
- keymodLalt = 0x0100;
- keymodRalt = 0x0200;
- keymodLmeta = 0x0400;
- keymodRmeta = 0x0800;
- keymodNum = 0x1000;
- keymodCaps = 0x2000;
- keymodMode = 0x4000;
- keymodReserved = 0x8000
-)
-
-const (
- mouseButtonLeft = 1;
- mouseButtonMiddle = 2;
- mouseButtonRight = 3;
- mouseScrollUp = 4;
- mouseScrollDown = 5
-)
-
-const (
- mouseStateLeftButtonPressed = 1;
- mouseStateMiddleButtonPressed = 2;
- mouseStateRightButtonPressed = 4
-)
-
-const (
- activeMouse = 1; // mouse leaving/entering
- activeInputFocus = 2; // input focus lost/restored
- activeApplication = 4 // application minimized/restored
-)
-
-const maxEventBytes = 64
-
-type activeEvent struct {
- EventType eventType;
- Gain uint8;
- State uint8;
-}
-
-type exposeEvent struct {
- EventType eventType;
-}
-
-type keyboardEvent struct {
- EventType eventType;
- Device uint8;
- State uint8;
- Pad uint8;
- ScanCode uint8;
- Pad1 uint8;
- Key key;
- Mod keymod;
- Unicode uint16;
-}
-
-type mouseMotionEvent struct {
- EventType eventType;
- Device uint8;
- Buttons uint8;
- Pad uint8;
- X uint16;
- Y uint16;
- Xrel int16;
- Yrel int16;
-}
-
-type mouseButtonEvent struct {
- EventType eventType;
- Device uint8;
- Button uint8;
- State uint8;
- X uint16;
- Y uint16;
-}
-
-type quitEvent struct {
- EventType eventType;
-}
-
-type syncEvent struct {
-}
-
-type event interface {
-}
-
-type reader []byte
-func (r *reader) Read(p []byte) (n int, err os.Error) {
- b := *r;
- if len(b) == 0 && len(p) > 0 {
- return 0, os.EOF;
- }
- n = bytes.Copy(p, b);
- *r = b[n:len(b)];
- return;
-}
-
-func (w *Window) readEvents() {
- buf := make([]byte, maxEventBytes);
- clean := false;
- var (
- ea *activeEvent;
- ee *exposeEvent;
- ke *keyboardEvent;
- mme *mouseMotionEvent;
- mbe *mouseButtonEvent;
- qe *quitEvent;
- )
- var m draw.Mouse;
- for {
- if err := videoPollEvent(buf); err != nil {
- if !clean {
- clean = w.resizec <- false;
- }
- time.Sleep(10e6); // 10ms
- continue;
- }
- clean = false;
- var e event;
- switch buf[0] {
- default:
- log.Stdout("unsupported event type", buf[0]);
- continue;
- case eventActive:
- ea = new(activeEvent);
- e = ea;
- case eventExpose:
- ee = new(exposeEvent);
- e = ee;
- case eventKeyDown, eventKeyUp:
- ke = new(keyboardEvent);
- e = ke;
- case eventMouseMotion:
- mme = new(mouseMotionEvent);
- e = mme;
- case eventMouseButtonDown, eventMouseButtonUp:
- mbe = new(mouseButtonEvent);
- e = mbe;
- case eventQuit:
- qe = new(quitEvent);
- e = qe;
- }
- r := reader(buf);
- if err := binary.Read(&r, binary.LittleEndian, e); err != nil {
- log.Stdout("unpacking %T event: %s", e, err);
- continue;
- }
- // log.Stdoutf("%#v\n", e);
- switch buf[0] {
- case eventExpose:
- w.resizec <- true
- case eventKeyDown:
- w.kbdc <- int(ke.Key);
- case eventKeyUp:
- w.kbdc <- -int(ke.Key);
- case eventMouseMotion:
- m.X = int(mme.X);
- m.Y = int(mme.Y);
- m.Buttons = int(mme.Buttons);
- m.Nsec = time.Nanoseconds();
- _ = w.mousec <- m;
- case eventMouseButtonDown:
- m.X = int(mbe.X);
- m.Y = int(mbe.Y);
- // TODO(rsc): Remove uint cast once 8g bug is fixed.
- m.Buttons |= 1<<uint(mbe.Button-1);
- m.Nsec = time.Nanoseconds();
- _ = w.mousec <- m;
- case eventMouseButtonUp:
- m.X = int(mbe.X);
- m.Y = int(mbe.Y);
- // TODO(rsc): Remove uint cast once 8g bug is fixed.
- m.Buttons &^= 1<<uint(mbe.Button-1);
- m.Nsec = time.Nanoseconds();
- _ = w.mousec <- m;
- case eventQuit:
- w.quitc <- true;
- }
- }
-}
diff --git a/usr/rsc/nacl/av/image.go b/usr/rsc/nacl/av/image.go
deleted file mode 100644
index 3aee3cad0..000000000
--- a/usr/rsc/nacl/av/image.go
+++ /dev/null
@@ -1,95 +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.
-
-package av
-
-import (
- "image";
-)
-
-// Native Client image format:
-// a single linear array of 32-bit ARGB as packed uint32s.
-
-// An Image represents a Native Client frame buffer.
-// The pixels in the image can be accessed as a single
-// linear slice or as a two-dimensional slice of slices.
-// Image implements image.Image.
-type Image struct {
- Linear []Color;
- Pixel [][]Color;
-}
-
-var _ image.Image = (*Image)(nil);
-
-func (m *Image) ColorModel() image.ColorModel {
- return ColorModel;
-}
-
-func (m *Image) Width() int {
- if len(m.Pixel) == 0 {
- return 0;
- }
- return len(m.Pixel[0]);
-}
-
-func (m *Image) Height() int {
- return len(m.Pixel);
-}
-
-func (m *Image) At(x, y int) image.Color {
- return m.Pixel[y][x];
-}
-
-func (m *Image) Set(x, y int, color image.Color) {
- if c, ok := color.(Color); ok {
- m.Pixel[y][x] = c;
- }
- m.Pixel[y][x] = makeColor(color.RGBA());
-}
-
-func newImage(dx, dy int, linear []Color) *Image {
- if linear == nil {
- linear = make([]Color, dx*dy);
- }
- pix := make([][]Color, dy);
- for i := range pix {
- pix[i] = linear[dx*i : dx*(i+1)];
- }
- return &Image{linear, pix};
-}
-
-// A Color represents a Native Client color value,
-// a 32-bit R, G, B, A value packed as 0xAARRGGBB.
-type Color uint32
-func (p Color) RGBA() (r, g, b, a uint32) {
- x := uint32(p);
- a = x>>24;
- a |= a<<8;
- a |= a<<16;
- r = (x>>16) & 0xFF;
- r |= r<<8;
- r |= r<<16;
- g = (x>>8) & 0xFF;
- g |= g<<8;
- g |= g<<16;
- b = x & 0xFF;
- b |= b<<8;
- b |= b<<16;
- return;
-}
-
-func makeColor(r, g, b, a uint32) Color {
- return Color(a>>24<<24 | r>>24<<16 | g>>24<<8 | b>>24);
-}
-
-func toColor(color image.Color) image.Color {
- if c, ok := color.(Color); ok {
- return c;
- }
- return makeColor(color.RGBA());
-}
-
-// ColorModel is the color model corresponding to the Native Client Color.
-var ColorModel = image.ColorModelFunc(toColor);
-
diff --git a/usr/rsc/nacl/srpc/Makefile b/usr/rsc/nacl/srpc/Makefile
deleted file mode 100644
index 9014d2c3a..000000000
--- a/usr/rsc/nacl/srpc/Makefile
+++ /dev/null
@@ -1,13 +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.
-
-include $(GOROOT)/src/Make.$(GOARCH)
-
-TARG=nacl/srpc
-GOFILES=\
- client.go\
- msg.go\
- server.go\
-
-include $(GOROOT)/src/Make.pkg
diff --git a/usr/rsc/nacl/srpc/client.go b/usr/rsc/nacl/srpc/client.go
deleted file mode 100644
index 4c375fe2a..000000000
--- a/usr/rsc/nacl/srpc/client.go
+++ /dev/null
@@ -1,210 +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.
-
-// This package implements Native Client's simple RPC (SRPC).
-package srpc
-
-import (
- "bytes";
- "log";
- "os";
- "sync";
-)
-
-// A Client represents the client side of an SRPC connection.
-type Client struct {
- fd int; // fd to server
- r msgReceiver;
- s msgSender;
- service map[string]srv; // services by name
- out chan *msg; // send to out to write to connection
-
- mu sync.Mutex; // protects pending, idGen
- pending map[uint64]*RPC;
- idGen uint64; // generator for request IDs
-}
-
-// A srv is a single method that the server offers.
-type srv struct {
- num uint32; // method number
- fmt string; // argument format
-}
-
-// An RPC represents a single RPC issued by a client.
-type RPC struct {
- Ret []interface{}; // Return values
- Done chan *RPC; // Channel where notification of done arrives
- Errno Errno; // Status code
- c *Client;
- id uint64; // request id
-}
-
-// NewClient allocates a new client using the file descriptor fd.
-func NewClient(fd int) (c *Client, err os.Error) {
- c = new(Client);
- c.fd = fd;
- c.r.fd = fd;
- c.s.fd = fd;
- c.service = make(map[string]srv);
- c.pending = make(map[uint64]*RPC);
-
- // service discovery request
- m := &msg{
- protocol: protocol,
- isReq: true,
- Ret: []interface{}{ []byte(nil) },
- Size: []int{ 4000 },
- };
- m.packRequest();
- c.s.send(m);
- m, err = c.r.recv();
- if err != nil {
- return nil, err;
- }
- m.unpackResponse();
- if m.status != OK {
- log.Stderrf("NewClient service_discovery: %s", m.status);
- return nil, m.status;
- }
- for n, line := range bytes.Split(m.Ret[0].([]byte), []byte{'\n'}, 0) {
- i := bytes.Index(line, []byte{':'});
- if i < 0 {
- continue;
- }
- c.service[string(line[0:i])] = srv{uint32(n), string(line[i+1:len(line)])};
- }
-
- c.out = make(chan *msg);
- go c.input();
- go c.output();
- return c, nil;
-}
-
-func (c *Client) input() {
- for {
- m, err := c.r.recv();
- if err != nil {
- log.Exitf("client recv: %s", err);
- }
- if m.unpackResponse(); m.status != OK {
- log.Stderrf("invalid message: %s", m.status);
- continue;
- }
- c.mu.Lock();
- rpc, ok := c.pending[m.requestId];
- if ok {
- c.pending[m.requestId] = nil, false;
- }
- c.mu.Unlock();
- if !ok {
- log.Stderrf("unexpected response");
- continue;
- }
- rpc.Ret = m.Ret;
- rpc.Done <- rpc;
- }
-}
-
-func (c *Client) output() {
- for m := range c.out {
- c.s.send(m);
- }
-}
-
-// NewRPC creates a new RPC on the client connection.
-func (c *Client) NewRPC(done chan *RPC) *RPC {
- if done == nil {
- done = make(chan *RPC);
- }
- c.mu.Lock();
- id := c.idGen;
- c.idGen++;
- c.mu.Unlock();
- return &RPC{nil, done, OK, c, id};
-}
-
-// Start issues an RPC request for method name with the given arguments.
-// The RPC r must not be in use for another pending request.
-// To wait for the RPC to finish, receive from r.Done and then
-// inspect r.Ret and r.Errno.
-func (r *RPC) Start(name string, arg []interface{}) {
- var m msg;
-
- r.Errno = OK;
- r.c.mu.Lock();
- srv, ok := r.c.service[name];
- if !ok {
- r.c.mu.Unlock();
- r.Errno = ErrBadRPCNumber;
- r.Done <- r;
- return;
- }
- r.c.pending[r.id] = r;
- r.c.mu.Unlock();
-
- m.protocol = protocol;
- m.requestId = r.id;
- m.isReq = true;
- m.rpcNumber = srv.num;
- m.Arg = arg;
-
- // Fill in the return values and sizes to generate
- // the right type chars. We'll take most any size.
-
- // Skip over input arguments.
- // We could check them against arg, but the server
- // will do that anyway.
- i := 0;
- for srv.fmt[i] != ':' {
- i++;
- }
- fmt := srv.fmt[i+1:len(srv.fmt)];
-
- // Now the return prototypes.
- m.Ret = make([]interface{}, len(fmt) - i);
- m.Size = make([]int, len(fmt) - i);
- for i := 0; i < len(fmt); i++ {
- switch fmt[i] {
- default:
- log.Exitf("unexpected service type %c", fmt[i]);
- case 'b':
- m.Ret[i] = false;
- case 'C':
- m.Ret[i] = []byte(nil);
- m.Size[i] = 1<<30;
- case 'd':
- m.Ret[i] = float64(0);
- case 'D':
- m.Ret[i] = []float64(nil);
- m.Size[i] = 1<<30;
- case 'h':
- m.Ret[i] = int(-1);
- case 'i':
- m.Ret[i] = int32(0);
- case 'I':
- m.Ret[i] = []int32(nil);
- m.Size[i] = 1<<30;
- case 's':
- m.Ret[i] = "";
- m.Size[i] = 1<<30;
- }
- }
-
- m.packRequest();
- r.c.out <- &m;
-}
-
-// Call is a convenient wrapper that starts the RPC request,
-// waits for it to finish, and then returns the results.
-// Its implementation is:
-//
-// r.Start(name, arg);
-// <-r.Done;
-// return r.Ret, r.Errno;
-//
-func (r *RPC) Call(name string, arg []interface{}) (ret []interface{}, err Errno) {
- r.Start(name, arg);
- <-r.Done;
- return r.Ret, r.Errno;
-}
diff --git a/usr/rsc/nacl/srpc/msg.go b/usr/rsc/nacl/srpc/msg.go
deleted file mode 100644
index 27fe7212f..000000000
--- a/usr/rsc/nacl/srpc/msg.go
+++ /dev/null
@@ -1,532 +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 (
- "bytes";
- "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);
- bytes.Copy(m.rdata, &r.data);
-
- // 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);
- for i := range m.rdesc {
- m.rdesc[i] = r.desc[i];
- }
- }
-
- 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:len(m.rdata)];
- 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:len(m.rdata)];
- 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:len(m.rdata)];
- 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:len(m.rdata)];
- 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);
- bytes.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) {
- bytes.Copy(m.grow(len(p)), p);
-}
-
-func (m *msg) wstring(s string) {
- b := m.grow(len(s));
- for i := range b {
- b[i] = s[i];
- }
-}
-
-// 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:len(m.rdesc)];
- 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);
-}
-
diff --git a/usr/rsc/nacl/srpc/server.go b/usr/rsc/nacl/srpc/server.go
deleted file mode 100644
index c4dc0a6c7..000000000
--- a/usr/rsc/nacl/srpc/server.go
+++ /dev/null
@@ -1,204 +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 server
-
-package srpc
-
-import (
- "bytes";
- "log";
- "os";
- "syscall";
-)
-
-// TODO(rsc): I'd prefer to make this
-// type Handler func(m *msg) Errno
-// but NaCl can't use closures.
-// The explicit interface is a way to attach state.
-
-// A Handler is a handler for an SRPC method.
-// It reads arguments from arg, checks size for array limits,
-// writes return values to ret, and returns an Errno status code.
-type Handler interface {
- Run(arg, ret []interface{}, size []int) Errno
-}
-
-type method struct {
- name string;
- fmt string;
- handler Handler;
-}
-
-var rpcMethod []method
-
-// BUG(rsc): Add's format string should be replaced by analyzing the
-// type of an arbitrary func passed in an interface{} using reflection.
-
-// Add registers a handler for the named method.
-// Fmt is a Native Client format string, a sequence of
-// alphabetic characters representing the types of the parameter values,
-// a colon, and then a sequence of alphabetic characters
-// representing the types of the returned values.
-// The format characters and corresponding dynamic types are:
-//
-// b bool
-// C []byte
-// d float64
-// D []float64
-// h int // a file descriptor (aka handle)
-// i int32
-// I []int32
-// s string
-//
-func Add(name, fmt string, handler Handler) {
- n := len(rpcMethod);
- if n >= cap(rpcMethod) {
- a := make([]method, n, (n+4)*2);
- for i := range a {
- a[i] = rpcMethod[i];
- }
- rpcMethod = a;
- }
- rpcMethod = rpcMethod[0:n+1];
- rpcMethod[n] = method{name, fmt, handler};
-}
-
-// Serve accepts new SRPC connections from the file descriptor fd
-// and answers RPCs issued on those connections.
-// It closes fd and returns an error if the imc_accept system call fails.
-func Serve(fd int) os.Error {
- defer syscall.Close(fd);
-
- for {
- cfd, _, e := syscall.Syscall(syscall.SYS_IMC_ACCEPT, uintptr(fd), 0, 0);
- if e != 0 {
- return os.NewSyscallError("imc_accept", int(e));
- }
- go serveLoop(int(cfd));
- }
- panic("unreachable");
-}
-
-func serveLoop(fd int) {
- c := make(chan *msg);
- go sendLoop(fd, c);
-
- var r msgReceiver;
- r.fd = fd;
- for {
- m, err := r.recv();
- if err != nil {
- break;
- }
- m.unpackRequest();
- if !m.gotHeader {
- log.Stderrf("cannot unpack header: %s", m.status);
- continue;
- }
- // log.Stdoutf("<- %#v", m);
- m.isReq = false; // set up for response
- go serveMsg(m, c);
- }
- close(c);
-}
-
-func sendLoop(fd int, c <-chan *msg) {
- var s msgSender;
- s.fd = fd;
- for m := range c {
- // log.Stdoutf("-> %#v", m);
- m.packResponse();
- s.send(m);
- }
- syscall.Close(fd);
-}
-
-func serveMsg(m *msg, c chan<- *msg) {
- if m.status != OK {
- c <- m;
- return;
- }
- if m.rpcNumber >= uint32(len(rpcMethod)) {
- m.status = ErrBadRPCNumber;
- c <- m;
- return;
- }
-
- meth := &rpcMethod[m.rpcNumber];
- if meth.fmt != m.fmt {
- switch {
- case len(m.fmt) < len(meth.fmt):
- m.status = ErrTooFewArgs;
- case len(m.fmt) > len(meth.fmt):
- m.status = ErrTooManyArgs;
- default:
- // There's a type mismatch.
- // It's an in-arg mismatch if the mismatch happens
- // before the colon; otherwise it's an out-arg mismatch.
- m.status = ErrInArgTypeMismatch;
- for i := 0; i < len(m.fmt) && m.fmt[i] == meth.fmt[i]; i++ {
- if m.fmt[i] == ':' {
- m.status = ErrOutArgTypeMismatch;
- break;
- }
- }
- }
- c <- m;
- return;
- }
-
- m.status = meth.handler.Run(m.Arg, m.Ret, m.Size);
- c <- m;
-}
-
-// ServeRuntime serves RPCs issued by the Native Client embedded runtime.
-// This should be called by main once all methods have been registered using Add.
-func ServeRuntime() os.Error {
- // Call getFd to check that we are running embedded.
- if _, err := getFd(); err != nil {
- return err;
- }
-
- // We are running embedded.
- // The fd returned by getFd is a red herring.
- // Accept connections on magic fd 3.
- return Serve(3);
-}
-
-// getFd runs the srpc_get_fd system call.
-func getFd() (fd int, err os.Error) {
- r1, _, e := syscall.Syscall(syscall.SYS_SRPC_GET_FD, 0, 0, 0);
- return int(r1), os.NewSyscallError("srpc_get_fd", int(e));
-}
-
-// Enabled returns true if SRPC is enabled in the Native Client runtime.
-func Enabled() bool {
- _, err:= getFd();
- return err == nil;
-}
-
-// Service #0, service_discovery, returns a list of the other services
-// and their argument formats.
-type serviceDiscovery struct{}
-
-func (serviceDiscovery) Run(arg, ret []interface{}, size []int) Errno {
- var b bytes.Buffer;
- for _, m := range rpcMethod {
- b.WriteString(m.name);
- b.WriteByte(':');
- b.WriteString(m.fmt);
- b.WriteByte('\n');
- }
- if b.Len() > size[0] {
- return ErrNoMemory;
- }
- ret[0] = b.Bytes();
- return OK;
-}
-
-func init() {
- Add("service_discovery", ":C", serviceDiscovery{});
-}
-