From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libgo/go/websocket/websocket.go | 189 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 libgo/go/websocket/websocket.go (limited to 'libgo/go/websocket/websocket.go') diff --git a/libgo/go/websocket/websocket.go b/libgo/go/websocket/websocket.go new file mode 100644 index 000000000..d5996abe1 --- /dev/null +++ b/libgo/go/websocket/websocket.go @@ -0,0 +1,189 @@ +// 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 a client and server for the Web Socket protocol. +// The protocol is defined at http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol +package websocket + +// TODO(ukai): +// better logging. + +import ( + "bufio" + "crypto/md5" + "encoding/binary" + "io" + "net" + "os" +) + +// WebSocketAddr is an implementation of net.Addr for Web Sockets. +type WebSocketAddr string + +// Network returns the network type for a Web Socket, "websocket". +func (addr WebSocketAddr) Network() string { return "websocket" } + +// String returns the network address for a Web Socket. +func (addr WebSocketAddr) String() string { return string(addr) } + +const ( + stateFrameByte = iota + stateFrameLength + stateFrameData + stateFrameTextData +) + +// Conn is a channel to communicate to a Web Socket. +// It implements the net.Conn interface. +type Conn struct { + // The origin URI for the Web Socket. + Origin string + // The location URI for the Web Socket. + Location string + // The subprotocol for the Web Socket. + Protocol string + + buf *bufio.ReadWriter + rwc io.ReadWriteCloser + + // It holds text data in previous Read() that failed with small buffer. + data []byte + reading bool +} + +// 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: origin, Location: location, Protocol: protocol, buf: buf, rwc: rwc} + return ws +} + +// Read implements the io.Reader interface for a Conn. +func (ws *Conn) Read(msg []byte) (n int, err os.Error) { +Frame: + for !ws.reading && len(ws.data) == 0 { + // Beginning of frame, possibly. + b, err := ws.buf.ReadByte() + if err != nil { + return 0, err + } + if b&0x80 == 0x80 { + // Skip length frame. + length := 0 + for { + c, err := ws.buf.ReadByte() + if err != nil { + return 0, err + } + length = length*128 + int(c&0x7f) + if c&0x80 == 0 { + break + } + } + for length > 0 { + _, err := ws.buf.ReadByte() + if err != nil { + return 0, err + } + } + continue Frame + } + // In text mode + if b != 0 { + // Skip this frame + for { + c, err := ws.buf.ReadByte() + if err != nil { + return 0, err + } + if c == '\xff' { + break + } + } + continue Frame + } + ws.reading = true + } + if len(ws.data) == 0 { + ws.data, err = ws.buf.ReadSlice('\xff') + if err == nil { + ws.reading = false + ws.data = ws.data[:len(ws.data)-1] // trim \xff + } + } + n = copy(msg, ws.data) + ws.data = ws.data[n:] + return n, err +} + +// Write implements the io.Writer interface for a Conn. +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 +} + +// Close implements the io.Closer interface for a Conn. +func (ws *Conn) Close() os.Error { return ws.rwc.Close() } + +// LocalAddr returns the WebSocket Origin for the connection. +func (ws *Conn) LocalAddr() net.Addr { return WebSocketAddr(ws.Origin) } + +// RemoteAddr returns the WebSocket locations for the connection. +func (ws *Conn) RemoteAddr() net.Addr { return WebSocketAddr(ws.Location) } + +// SetTimeout sets the connection's network timeout in nanoseconds. +func (ws *Conn) SetTimeout(nsec int64) os.Error { + if conn, ok := ws.rwc.(net.Conn); ok { + return conn.SetTimeout(nsec) + } + return os.EINVAL +} + +// SetReadTimeout sets the connection's network read timeout in nanoseconds. +func (ws *Conn) SetReadTimeout(nsec int64) os.Error { + if conn, ok := ws.rwc.(net.Conn); ok { + return conn.SetReadTimeout(nsec) + } + return os.EINVAL +} + +// SetWritetTimeout sets the connection's network write timeout in nanoseconds. +func (ws *Conn) SetWriteTimeout(nsec int64) os.Error { + if conn, ok := ws.rwc.(net.Conn); ok { + return conn.SetWriteTimeout(nsec) + } + return os.EINVAL +} + +// getChallengeResponse computes the expected response from the +// challenge as described in section 5.1 Opening Handshake steps 42 to +// 43 of http://www.whatwg.org/specs/web-socket-protocol/ +func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err os.Error) { + // 41. Let /challenge/ be the concatenation of /number_1/, expressed + // a big-endian 32 bit integer, /number_2/, expressed in a big- + // endian 32 bit integer, and the eight bytes of /key_3/ in the + // order they were sent to the wire. + challenge := make([]byte, 16) + binary.BigEndian.PutUint32(challenge[0:], number1) + binary.BigEndian.PutUint32(challenge[4:], number2) + copy(challenge[8:], key3) + + // 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big- + // endian 128 bit string. + h := md5.New() + if _, err = h.Write(challenge); err != nil { + return + } + expected = h.Sum() + return +} + +var _ net.Conn = (*Conn)(nil) // compile-time check that *Conn implements net.Conn. -- cgit v1.2.3