veyron/lib/websocket: Add Nacl implementation of WebsocketConn.

Change-Id: Iccdc8e983fd4e7ac7c1f80aeb6568d2f5ccb851d
diff --git a/lib/websocket/conn_nacl.go b/lib/websocket/conn_nacl.go
new file mode 100644
index 0000000..22d368d
--- /dev/null
+++ b/lib/websocket/conn_nacl.go
@@ -0,0 +1,105 @@
+// +build nacl
+
+package websocket
+
+import (
+	"net"
+	"net/url"
+	"runtime/ppapi"
+	"sync"
+	"time"
+)
+
+// Ppapi instance which must be set before the Dial is called.
+var PpapiInstance ppapi.Instance
+
+func WebsocketConn(address string, ws *ppapi.WebsocketConn) net.Conn {
+	return &wrappedConn{
+		address: address,
+		ws:      ws,
+	}
+}
+
+type wrappedConn struct {
+	address    string
+	ws         *ppapi.WebsocketConn
+	readLock   sync.Mutex
+	writeLock  sync.Mutex
+	currBuffer []byte
+}
+
+func Dial(address string) (net.Conn, error) {
+	inst := PpapiInstance
+	u, err := url.Parse("ws://" + address)
+	if err != nil {
+		return nil, err
+	}
+
+	ws, err := inst.DialWebsocket(u.String())
+	if err != nil {
+		return nil, err
+	}
+	return WebsocketConn(address, ws), nil
+}
+
+func (c *wrappedConn) Read(b []byte) (int, error) {
+	c.readLock.Lock()
+	defer c.readLock.Unlock()
+
+	var err error
+	if len(c.currBuffer) == 0 {
+		c.currBuffer, err = c.ws.ReceiveMessage()
+		if err != nil {
+			return 0, nil
+		}
+	}
+
+	n := copy(b, c.currBuffer)
+	c.currBuffer = c.currBuffer[n:]
+	return n, nil
+}
+
+func (c *wrappedConn) Write(b []byte) (int, error) {
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	if err := c.ws.SendMessage(b); err != nil {
+		return 0, err
+	}
+	return len(b), nil
+}
+
+func (c *wrappedConn) Close() error {
+	return c.ws.Close()
+}
+
+func (c *wrappedConn) LocalAddr() net.Addr {
+	return websocketAddr{s: c.address}
+}
+
+func (c *wrappedConn) RemoteAddr() net.Addr {
+	return websocketAddr{s: c.address}
+}
+
+func (c *wrappedConn) SetDeadline(t time.Time) error {
+	panic("SetDeadline not implemented.")
+}
+
+func (c *wrappedConn) SetReadDeadline(t time.Time) error {
+	panic("SetReadDeadline not implemented.")
+}
+
+func (c *wrappedConn) SetWriteDeadline(t time.Time) error {
+	panic("SetWriteDeadline not implemented.")
+}
+
+type websocketAddr struct {
+	s string
+}
+
+func (websocketAddr) Network() string {
+	return "ws"
+}
+
+func (w websocketAddr) String() string {
+	return w.s
+}