aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2019-03-15 21:53:54 +0700
committerShulhan <ms@kilabit.info>2019-03-17 02:12:43 +0700
commitcc9990d30eb9863e56cdb52197de3610d1853d40 (patch)
tree0288c1dc2c11e6725838bc1dfe8a70b9a50664bd
parentd4a58da2becbb4ae46d2bbe57aa8bc2c99a0845e (diff)
downloadpakakeh.go-cc9990d30eb9863e56cdb52197de3610d1853d40.tar.xz
websocket: move isValidFrame as method of Frame
This is to minimize duplicate code on client and server.
-rw-r--r--lib/websocket/client.go36
-rw-r--r--lib/websocket/frame.go45
-rw-r--r--lib/websocket/server.go36
3 files changed, 47 insertions, 70 deletions
diff --git a/lib/websocket/client.go b/lib/websocket/client.go
index 50856c18..0cc1e85a 100644
--- a/lib/websocket/client.go
+++ b/lib/websocket/client.go
@@ -452,7 +452,7 @@ func (cl *Client) handleFragment(frame *Frame) (isInvalid bool) {
// handleFrame handle a single frame from client.
//
func (cl *Client) handleFrame(frame *Frame) (isClosing bool) {
- if !cl.isValidFrame(frame) {
+ if !frame.isValid(false, cl.allowRsv1, cl.allowRsv2, cl.allowRsv3) {
cl.handleBadRequest()
return true
}
@@ -528,40 +528,6 @@ func (cl *Client) handleInvalidData() {
}
//
-// isValidFrame will return true if a frame from server is valid:
-// it's not masked, the reserved bits is not set (unless negotiated with
-// server), and if its control frame the fin should be set and payload must be
-// less than 125.
-//
-func (cl *Client) isValidFrame(frame *Frame) bool {
- if frame.masked == frameIsMasked {
- return false
- }
- if frame.rsv1 > 0 && !cl.allowRsv1 {
- return false
- }
- if frame.rsv2 > 0 && !cl.allowRsv2 {
- return false
- }
- if frame.rsv3 > 0 && !cl.allowRsv3 {
- return false
- }
-
- if frame.opcode == OpcodeClose || frame.opcode == OpcodePing || frame.opcode == OpcodePong {
- if frame.fin == 0 {
- // Control frame must set the fin.
- return false
- }
- // Control frame payload must not larger than 125.
- if frame.len > frameSmallPayload {
- return false
- }
- }
-
- return true
-}
-
-//
// SendBin send data frame as binary to server.
// If handler is nil, no response will be read from server.
//
diff --git a/lib/websocket/frame.go b/lib/websocket/frame.go
index 1b9c8690..c0e0d6ce 100644
--- a/lib/websocket/frame.go
+++ b/lib/websocket/frame.go
@@ -192,6 +192,51 @@ func (f *Frame) IsData() bool {
}
//
+// isValid will return true if a frame is valid.
+// If isMasked is true, the frame masked MUST be set, otherwise it will return
+// false; and vice versa.
+// Parameter allowRsv1, allowRsv2, and allowRsv3 are to allow one or more
+// frame reserved bits to be set, in order.
+// If reserved bit 1 is set but parameter allowRsv1 is false, it will return
+// false; and so on.
+// If its control frame the fin field should be set and payload must be less
+// than 125.
+//
+func (f *Frame) isValid(isMasked, allowRsv1, allowRsv2, allowRsv3 bool) bool {
+ if isMasked {
+ if f.masked != frameIsMasked {
+ return false
+ }
+ } else {
+ if f.masked == frameIsMasked {
+ return false
+ }
+ }
+ if f.rsv1 > 0 && !allowRsv1 {
+ return false
+ }
+ if f.rsv2 > 0 && !allowRsv2 {
+ return false
+ }
+ if f.rsv3 > 0 && !allowRsv3 {
+ return false
+ }
+
+ if f.opcode >= OpcodeClose {
+ if f.fin == 0 {
+ // Control frame must set the fin.
+ return false
+ }
+ // Control frame payload must not larger than 125.
+ if f.len > frameSmallPayload {
+ return false
+ }
+ }
+
+ return true
+}
+
+//
// Opcode return the frame operation code.
//
func (f *Frame) Opcode() Opcode {
diff --git a/lib/websocket/server.go b/lib/websocket/server.go
index e20fb1dc..b3609e3e 100644
--- a/lib/websocket/server.go
+++ b/lib/websocket/server.go
@@ -398,7 +398,7 @@ func (serv *Server) handleFragment(conn int, req *Frame) (isInvalid bool) {
// handleFrame handle a single frame from client.
//
func (serv *Server) handleFrame(conn int, frame *Frame) (isClosing bool) {
- if !serv.isValidFrame(frame) {
+ if !frame.isValid(true, serv.allowRsv1, serv.allowRsv2, serv.allowRsv3) {
serv.handleBadRequest(conn)
return true
}
@@ -628,40 +628,6 @@ func (serv *Server) handlePing(conn int, req *Frame) {
}
//
-// isValidFrame will return true if a frame from client is valid:
-// it's masked, the reserved bits is not set (unless allowed by server), and
-// if its control frame the fin should be set and payload must be less than
-// 125.
-//
-func (serv *Server) isValidFrame(frame *Frame) bool {
- if frame.masked != frameIsMasked {
- return false
- }
- if frame.rsv1 > 0 && !serv.allowRsv1 {
- return false
- }
- if frame.rsv2 > 0 && !serv.allowRsv2 {
- return false
- }
- if frame.rsv3 > 0 && !serv.allowRsv3 {
- return false
- }
-
- if frame.opcode == OpcodeClose || frame.opcode == OpcodePing || frame.opcode == OpcodePong {
- if frame.fin == 0 {
- // Control frame must set the fin.
- return false
- }
- // Control frame payload must not larger than 125.
- if frame.len > frameSmallPayload {
- return false
- }
- }
-
- return true
-}
-
-//
// reader read request from client.
//
// To avoid confusing network intermediaries (such as intercepting proxies)