summaryrefslogtreecommitdiff
path: root/src/pkg/websocket/websocket.go
diff options
context:
space:
mode:
authorFumitoshi Ukai <ukai@google.com>2009-11-29 14:22:44 -0800
committerFumitoshi Ukai <ukai@google.com>2009-11-29 14:22:44 -0800
commit44b0d5999a8b20630701fda866a5ee416e9fe862 (patch)
tree4d591b2d0afc51c45cbc88d8731ce936f5e58fb7 /src/pkg/websocket/websocket.go
parent72695b377fe6061eef5dfc26ea52d43732c7e972 (diff)
downloadgolang-44b0d5999a8b20630701fda866a5ee416e9fe862.tar.gz
Add WebSocket server framework hooked into http.
R=r, rsc http://codereview.appspot.com/156071 Committer: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/pkg/websocket/websocket.go')
-rw-r--r--src/pkg/websocket/websocket.go138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/pkg/websocket/websocket.go b/src/pkg/websocket/websocket.go
new file mode 100644
index 000000000..0fd32cd4c
--- /dev/null
+++ b/src/pkg/websocket/websocket.go
@@ -0,0 +1,138 @@
+// 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.
+
+// The websocket package implements Web Socket protocol server.
+package websocket
+
+// References:
+// The Web Socket protocol: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
+
+// TODO(ukai):
+// better logging.
+
+import (
+ "bufio";
+ "io";
+ "net";
+ "os";
+)
+
+type WebSocketAddr string
+
+func (addr WebSocketAddr) Network() string { return "websocket" }
+
+func (addr WebSocketAddr) String() string { return string(addr) }
+
+// Conn is an channels to communicate over Web Socket.
+type Conn struct {
+ // An origin URI of the Web Socket.
+ Origin string;
+ // A location URI of the Web Socket.
+ Location string;
+ // A subprotocol of the Web Socket.
+ Protocol string;
+
+ buf *bufio.ReadWriter;
+ rwc io.ReadWriteCloser;
+}
+
+// newConn creates a new Web Socket.
+func newConn(origin, location, protocol string, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
+ if buf == nil {
+ br := bufio.NewReader(rwc);
+ bw := bufio.NewWriter(rwc);
+ buf = bufio.NewReadWriter(br, bw);
+ }
+ ws := &Conn{origin, location, protocol, buf, rwc};
+ return ws;
+}
+
+func (ws *Conn) Read(msg []byte) (n int, err os.Error) {
+ for {
+ frameByte, err := ws.buf.ReadByte();
+ if err != nil {
+ return
+ }
+ if (frameByte & 0x80) == 0x80 {
+ length := 0;
+ for {
+ c, err := ws.buf.ReadByte();
+ if err != nil {
+ return
+ }
+ if (c & 0x80) == 0x80 {
+ length = length*128 + int(c&0x7f)
+ } else {
+ break
+ }
+ }
+ for length > 0 {
+ _, err := ws.buf.ReadByte();
+ if err != nil {
+ return
+ }
+ length--;
+ }
+ } else {
+ for {
+ c, err := ws.buf.ReadByte();
+ if err != nil {
+ return
+ }
+ if c == '\xff' {
+ return
+ }
+ if frameByte == 0 {
+ if n+1 <= cap(msg) {
+ msg = msg[0 : n+1]
+ }
+ msg[n] = c;
+ n++;
+ }
+ if n >= cap(msg) {
+ err = os.E2BIG;
+ return;
+ }
+ }
+ }
+ }
+ return;
+}
+
+func (ws *Conn) Write(msg []byte) (n int, err os.Error) {
+ ws.buf.WriteByte(0);
+ ws.buf.Write(msg);
+ ws.buf.WriteByte(0xff);
+ err = ws.buf.Flush();
+ return len(msg), err;
+}
+
+func (ws *Conn) Close() os.Error { return ws.rwc.Close() }
+
+func (ws *Conn) LocalAddr() net.Addr { return WebSocketAddr(ws.Origin) }
+
+func (ws *Conn) RemoteAddr() net.Addr { return WebSocketAddr(ws.Location) }
+
+func (ws *Conn) SetTimeout(nsec int64) os.Error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetTimeout(nsec)
+ }
+ return os.EINVAL;
+}
+
+func (ws *Conn) SetReadTimeout(nsec int64) os.Error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetReadTimeout(nsec)
+ }
+ return os.EINVAL;
+}
+
+func (ws *Conn) SetWriteTimeout(nsec int64) os.Error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetWriteTimeout(nsec)
+ }
+ return os.EINVAL;
+}
+
+var _ net.Conn = (*Conn)(nil) // compile-time check that *Conn implements net.Conn.