[tor-commits] [flashproxy/master] readFrame.
dcf at torproject.org
dcf at torproject.org
Wed Jan 30 05:11:38 UTC 2013
commit 2021b406a3d5249502b0752415cc0f4db1e333d2
Author: David Fifield <david at bamsoftware.com>
Date: Sun Nov 25 23:48:53 2012 -0800
readFrame.
---
websocket-transport/websocket-server.go | 1 +
websocket-transport/websocket.go | 93 +++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+), 0 deletions(-)
diff --git a/websocket-transport/websocket-server.go b/websocket-transport/websocket-server.go
index a2f3652..3874ea9 100644
--- a/websocket-transport/websocket-server.go
+++ b/websocket-transport/websocket-server.go
@@ -30,6 +30,7 @@ func startListener(addr *net.TCPAddr) (*net.TCPListener, error) {
go func() {
var config websocketConfig
config.Subprotocols = []string{"base64"}
+ config.MaxMessageSize = 1500
http.Handle("/", config.Handler(websocketHandler))
err = http.Serve(ln, nil)
if err != nil {
diff --git a/websocket-transport/websocket.go b/websocket-transport/websocket.go
index 9ac9754..fa0de7e 100644
--- a/websocket-transport/websocket.go
+++ b/websocket-transport/websocket.go
@@ -4,7 +4,10 @@ import (
"bufio"
"crypto/sha1"
"encoding/base64"
+ "encoding/binary"
+ "errors"
"fmt"
+ "io"
"net"
"net/http"
"strings"
@@ -12,6 +15,14 @@ import (
type websocketConfig struct {
Subprotocols []string
+ MaxMessageSize uint64
+}
+
+func (config *websocketConfig) maxMessageSize() uint64 {
+ if config.MaxMessageSize == 0 {
+ return 64000
+ }
+ return config.MaxMessageSize
}
type websocket struct {
@@ -19,9 +30,90 @@ type websocket struct {
Bufrw *bufio.ReadWriter
// Whether we are a client or a server implications for masking.
IsClient bool
+ MaxMessageSize uint64
Subprotocol string
}
+type websocketFrame struct {
+ Fin bool
+ Opcode byte
+ Payload []byte
+}
+
+func (frame *websocketFrame) IsControl() bool {
+ return (frame.Opcode & 0x08) != 0
+}
+
+func applyMask(payload []byte, maskKey [4]byte) {
+ for i, _ := range payload {
+ payload[i] = payload[i] ^ maskKey[i % 4]
+ }
+}
+
+func (ws *websocket) ReadFrame() (frame websocketFrame, err error) {
+ var b byte
+ err = binary.Read(ws.Bufrw, binary.BigEndian, &b)
+ if err != nil {
+ return
+ }
+ frame.Fin = (b & 0x80) != 0
+ frame.Opcode = b & 0x0f
+ err = binary.Read(ws.Bufrw, binary.BigEndian, &b)
+ if err != nil {
+ return
+ }
+ masked := (b & 0x80) != 0
+
+ payloadLen := uint64(b & 0x7f)
+ if payloadLen == 126 {
+ var short uint16
+ err = binary.Read(ws.Bufrw, binary.BigEndian, &short)
+ if err != nil {
+ return
+ }
+ payloadLen = uint64(short)
+ } else if payloadLen == 127 {
+ var long uint64
+ err = binary.Read(ws.Bufrw, binary.BigEndian, &long)
+ if err != nil {
+ return
+ }
+ payloadLen = long
+ }
+ if payloadLen > ws.MaxMessageSize {
+ err = errors.New(fmt.Sprintf("frame payload length of %d exceeds maximum of %d", payloadLen, ws.MaxMessageSize))
+ return
+ }
+
+ maskKey := [4]byte{}
+ if masked {
+ if ws.IsClient {
+ err = errors.New("client got masked frame")
+ return
+ }
+ err = binary.Read(ws.Bufrw, binary.BigEndian, &maskKey)
+ if err != nil {
+ return
+ }
+ } else {
+ if !ws.IsClient {
+ err = errors.New("server got unmasked frame")
+ return
+ }
+ }
+
+ frame.Payload = make([]byte, payloadLen)
+ _, err = io.ReadFull(ws.Bufrw, frame.Payload)
+ if err != nil {
+ return
+ }
+ if masked {
+ applyMask(frame.Payload, maskKey)
+ }
+
+ return frame, nil
+}
+
func commaSplit(s string) []string {
var result []string
if strings.TrimSpace(s) == "" {
@@ -129,6 +221,7 @@ func (handler *WebSocketHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.
ws.Conn = conn
ws.Bufrw = bufrw
ws.IsClient = false
+ ws.MaxMessageSize = handler.config.MaxMessageSize
// See RFC 6455 section 4.2.2, item 5 for these steps.
More information about the tor-commits
mailing list