diff options
author | Russ Cox <rsc@golang.org> | 2009-10-02 13:25:26 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-10-02 13:25:26 -0700 |
commit | 09d2e093423fbcfd50d96c8eb349a753be680974 (patch) | |
tree | ae56c31bba336b3f0abd684b7bd282babc24506a | |
parent | 055cef87d04ba14aefbe72269e055eac9d7ba4f1 (diff) | |
download | golang-09d2e093423fbcfd50d96c8eb349a753be680974.tar.gz |
final Native Client package - av
R=r
DELTA=894 (887 added, 0 deleted, 7 changed)
OCL=35115
CL=35286
-rw-r--r-- | usr/rsc/nacl/av/Makefile | 13 | ||||
-rw-r--r-- | usr/rsc/nacl/av/av.go | 308 | ||||
-rw-r--r-- | usr/rsc/nacl/av/event.go | 471 | ||||
-rw-r--r-- | usr/rsc/nacl/av/image.go | 95 | ||||
-rw-r--r-- | usr/rsc/nacl/srpc/server.go | 14 |
5 files changed, 894 insertions, 7 deletions
diff --git a/usr/rsc/nacl/av/Makefile b/usr/rsc/nacl/av/Makefile new file mode 100644 index 000000000..523a9fff1 --- /dev/null +++ b/usr/rsc/nacl/av/Makefile @@ -0,0 +1,13 @@ +# 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 new file mode 100644 index 000000000..8433cda54 --- /dev/null +++ b/usr/rsc/nacl/av/av.go @@ -0,0 +1,308 @@ +// 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. +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 new file mode 100644 index 000000000..62ecbc6e6 --- /dev/null +++ b/usr/rsc/nacl/av/event.go @@ -0,0 +1,471 @@ +// 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 new file mode 100644 index 000000000..3aee3cad0 --- /dev/null +++ b/usr/rsc/nacl/av/image.go @@ -0,0 +1,95 @@ +// 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/server.go b/usr/rsc/nacl/srpc/server.go index 4fd778d63..c4dc0a6c7 100644 --- a/usr/rsc/nacl/srpc/server.go +++ b/usr/rsc/nacl/srpc/server.go @@ -19,10 +19,10 @@ import ( // The explicit interface is a way to attach state. // A Handler is a handler for an SRPC method. -// It reads arguments from m.Arg, checks m.Size for array limits, -// writes return values to m.Ret, and returns an Errno status code. +// 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(m *msg) Errno + Run(arg, ret []interface{}, size []int) Errno } type method struct { @@ -149,7 +149,7 @@ func serveMsg(m *msg, c chan<- *msg) { return; } - m.status = meth.handler.Run(m); + m.status = meth.handler.Run(m.Arg, m.Ret, m.Size); c <- m; } @@ -183,7 +183,7 @@ func Enabled() bool { // and their argument formats. type serviceDiscovery struct{} -func (serviceDiscovery) Run(m *msg) Errno { +func (serviceDiscovery) Run(arg, ret []interface{}, size []int) Errno { var b bytes.Buffer; for _, m := range rpcMethod { b.WriteString(m.name); @@ -191,10 +191,10 @@ func (serviceDiscovery) Run(m *msg) Errno { b.WriteString(m.fmt); b.WriteByte('\n'); } - if b.Len() > m.Size[0] { + if b.Len() > size[0] { return ErrNoMemory; } - m.Ret[0] = b.Bytes(); + ret[0] = b.Bytes(); return OK; } |