summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-07-01 14:46:38 +0700
committerShulhan <ms@kilabit.info>2023-07-01 17:25:15 +0700
commit7b01a3fc41b8611aa26c7d5d0f5c0f2bcd012ee0 (patch)
tree65634cbf100878c060e0a88bcd84406f9b8deb3a
parentb9f69e549f1ecde42f34cc2dab6437bb62c42fe6 (diff)
downloadpakakeh.go-7b01a3fc41b8611aa26c7d5d0f5c0f2bcd012ee0.tar.xz
lib/websocket: reformat comments and documentation
-rw-r--r--lib/websocket/client.go75
-rw-r--r--lib/websocket/closecode.go52
-rw-r--r--lib/websocket/frame.go64
-rw-r--r--lib/websocket/frames.go7
-rw-r--r--lib/websocket/rootroute.go10
-rw-r--r--lib/websocket/server.go24
6 files changed, 120 insertions, 112 deletions
diff --git a/lib/websocket/client.go b/lib/websocket/client.go
index a646d1d6..382d808b 100644
--- a/lib/websocket/client.go
+++ b/lib/websocket/client.go
@@ -34,18 +34,16 @@ const (
defPort = "80"
)
-var (
- // ErrConnClosed define an error if client is not connected and try to
- // send a message.
- ErrConnClosed = errors.New(`client is not connected`)
-)
+// ErrConnClosed define an error if client is not connected and try to
+// send a message.
+var ErrConnClosed = errors.New(`client is not connected`)
// Client for WebSocket protocol.
//
// Unlike HTTP client or other most commmon TCP oriented client, the WebSocket
-// client is actually asynchronous or passive-active instead of synchronous.
+// client is asynchronous or passive-active instead of synchronous.
// At any time client connection is open to server, client can receive a
-// message broadcast from server.
+// message broadcasted from server.
//
// Case examples: if client send "A" to server, and expect that server
// response with "A+", server may send message "B" before sending "A+".
@@ -61,7 +59,7 @@ var (
// from request or broadcast from server,
//
// cl := &Client{
-// Endpoint: "ws://127.0.0.1:9001",
+// Endpoint: `ws://127.0.0.1:9001`,
// HandleText: func(cl *Client, frame *Frame) error {
// // Process response from request or broadcast from
// // server.
@@ -71,18 +69,18 @@ var (
//
// err := cl.Connect()
// if err != nil {
-// log.Fatal(err.Error())
+// log.Fatal(err)
// }
//
// err = cl.SendText([]byte("Hello from client"))
// if err != nil {
-// log.Fatal(err.Error())
+// log.Fatal(err)
// }
//
-// At any time, server may send PING or CLOSE the connection. For this
-// messages, client already handled it by sending PONG message or by closing
-// underlying connection automatically.
-// Implementor can check closed connection from error returned from Send
+// At any time, server may send PING or CLOSE the connection.
+// For this messages, client already handled it by sending PONG message or by
+// closing underlying connection automatically.
+// Implementor can check a closed connection from error returned from Send
// methods to match with ErrConnClosed.
type Client struct {
conn net.Conn
@@ -110,18 +108,21 @@ type Client struct {
HandleBin ClientHandler
// handleClose function that will be called when client receive
- // control CLOSE frame from server. Default handle is to response
- // with control CLOSE frame with the same payload.
+ // control CLOSE frame from server.
+ // Default handle is to response with control CLOSE frame with the
+ // same payload.
// This field is not exported, and only defined to allow testing.
handleClose ClientHandler
// handlePing function that will be called when client receive control
- // PING frame from server. Default handler is to response with PONG.
+ // PING frame from server.
+ // Default handler is to response with PONG.
// This field is not exported, and only defined to allow testing.
handlePing ClientHandler
// handlePong a function that will be called when client receive
- // control PONG frame from server. Default is nil.
+ // control PONG frame from server.
+ // Default is nil.
handlePong ClientHandler
// HandleQuit function that will be called when client connection is
@@ -442,36 +443,44 @@ func clientOnClose(cl *Client, frame *Frame) (err error) {
switch {
case frame.closeCode == 0:
frame.closeCode = StatusBadRequest
+
case frame.closeCode < StatusNormal:
frame.closeCode = StatusBadRequest
+
case frame.closeCode == 1004:
- // Reserved. The specific meaning might be defined in the future.
+ // Reserved.
+ // The specific meaning might be defined in the future.
frame.closeCode = StatusBadRequest
+
case frame.closeCode == 1005:
// 1005 is a reserved value and MUST NOT be set as a status
- // code in a Close control frame by an endpoint. It is
- // designated for use in applications expecting a status code
- // to indicate that no status code was actually present.
+ // code in a Close control frame by an endpoint.
+ // It is designated for use in applications expecting a status
+ // code to indicate that no status code was actually present.
frame.closeCode = StatusBadRequest
+
case frame.closeCode == 1006:
// 1006 is a reserved value and MUST NOT be set as a status
- // code in a Close control frame by an endpoint. It is
- // designated for use in applications expecting a status code
- // to indicate that the connection was closed abnormally,
+ // code in a Close control frame by an endpoint.
+ // It is designated for use in applications expecting a status
+ // code to indicate that the connection was closed abnormally,
// e.g., without sending or receiving a Close control frame.
frame.closeCode = StatusBadRequest
+
case frame.closeCode >= 1015 && frame.closeCode <= 2999:
frame.closeCode = StatusBadRequest
+
case frame.closeCode >= 3000 && frame.closeCode <= 3999:
// Status codes in the range 3000-3999 are reserved for use by
- // libraries, frameworks, and applications. These status
- // codes are registered directly with IANA. The
- // interpretation of these codes is undefined by this
+ // libraries, frameworks, and applications.
+ // These status codes are registered directly with IANA.
+ // The interpretation of these codes is undefined by this
// protocol.
case frame.closeCode >= 4000 && frame.closeCode <= 4999:
// Status codes in the range 4000-4999 are reserved for
- // private use and thus can't be registered. Such codes can
- // be used by prior agreements between WebSocket applications.
+ // private use and thus can't be registered.
+ // Such codes can be used by prior agreements between
+ // WebSocket applications.
// The interpretation of these codes is undefined by this
// protocol.
}
@@ -483,20 +492,16 @@ func clientOnClose(cl *Client, frame *Frame) (err error) {
}
var (
- logp = `clientOnClose`
packet []byte = NewFrameClose(true, frame.closeCode, frame.payload)
)
cl.Lock()
err = cl.send(packet)
cl.Unlock()
- if err != nil {
- log.Printf(`%s: %s`, logp, err)
- }
cl.Quit()
- return nil
+ return err
}
// handleFragment will handle continuation frame (fragmentation).
diff --git a/lib/websocket/closecode.go b/lib/websocket/closecode.go
index 6bae2201..15236c18 100644
--- a/lib/websocket/closecode.go
+++ b/lib/websocket/closecode.go
@@ -18,55 +18,55 @@ type CloseCode uint16
//
// See RFC6455 7.4.1-P45 for more information.
const (
- // StatusNormal (1000) indicates a normal closure, meaning that the
- // purpose for which the connection was established has been
- // fulfilled.
+ // StatusNormal indicates a normal closure, meaning that the purpose
+ // for which the connection was established has been fulfilled.
StatusNormal CloseCode = 1000
- // StatusGone (1001) indicates that an endpoint is "going away", such
- // as a server going down or a browser having navigated away from a
- // page.
+ // StatusGone indicates that an endpoint is "going away", such as a
+ // server going down or a browser having navigated away from a page.
StatusGone = 1001
- // StatusBadRequest (1002) indicates that an endpoint is terminating
- // the connection due to a protocol error.
+ // StatusBadRequest indicates that an endpoint is terminating the
+ // connection due to a protocol error.
StatusBadRequest = 1002
- // StatusUnsupportedType (1003) indicates that an endpoint is
- // terminating the connection because it has received a type of data
- // it cannot accept (e.g., an endpoint that understands only text data
- // MAY send this if it receives a binary message).
+ // StatusUnsupportedType indicates that an endpoint is terminating the
+ // connection because it has received a type of data it cannot accept
+ // (e.g., an endpoint that understands only text data MAY send this if
+ // it receives a binary message).
StatusUnsupportedType = 1003
- // StatusInvalidData (1007) indicates that an endpoint is terminating
+ // StatusInvalidData indicates that an endpoint is terminating
// the connection because it has received data within a message that
// was not consistent with the type of the message (e.g., non-UTF-8
// [RFC3629] data within a text message).
StatusInvalidData = 1007
- // StatusForbidden (1008) indicates that an endpoint is terminating
- // the connection because it has received a message that violates its
- // policy. This is a generic status code that can be returned when
- // there is no other more suitable status code (e.g., 1003 or 1009) or
- // if there is a need to hide specific details about the policy.
+ // StatusForbidden indicates that an endpoint is terminating the
+ // connection because it has received a message that violates its
+ // policy.
+ // This is a generic status code that can be returned when there is no
+ // other more suitable status code (e.g., 1003 or 1009) or if there is
+ // a need to hide specific details about the policy.
StatusForbidden = 1008
- // StatusRequestEntityTooLarge (1009) indicates that an endpoint is
+ // StatusRequestEntityTooLarge indicates that an endpoint is
// terminating the connection because it has received a message that
// is too big for it to process.
StatusRequestEntityTooLarge = 1009
- // StatusBadGateway (1010) indicates that an endpoint (client) is
+ // StatusBadGateway indicates that an endpoint (client) is
// terminating the connection because it has expected the server to
// negotiate one or more extension, but the server didn't return them
- // in the response message of the WebSocket handshake. The list of
- // extensions that are needed SHOULD appear in the /reason/ part of
- // the Close frame. Note that this status code is not used by the
- // server, because it can fail the WebSocket handshake instead.
+ // in the response message of the WebSocket handshake.
+ // The list of extensions that are needed SHOULD appear in the
+ // "reason" part of the Close frame.
+ // Note that this status code is not used by the server, because it
+ // can fail the WebSocket handshake instead.
StatusBadGateway = 1010
- // StatusInternalError or 1011 indicates that a server is terminating
- // the connection because it encountered an unexpected condition that
+ // StatusInternalError indicates that a server is terminating the
+ // connection because it encountered an unexpected condition that
// prevented it from fulfilling the request.
StatusInternalError = 1011
)
diff --git a/lib/websocket/frame.go b/lib/websocket/frame.go
index 24858584..bfb2fdea 100644
--- a/lib/websocket/frame.go
+++ b/lib/websocket/frame.go
@@ -12,18 +12,16 @@ import (
// Frame represent a WebSocket data protocol.
type Frame struct {
- //
// maskKey size is 0 or 4 bytes.
//
// All frames sent from the client to the server are masked by a
- // 32-bit value that is contained within the frame. This field is
- // present if the mask bit is set to 1 and is absent if the mask bit
- // is set to 0. See Section 5.3 for further information on client-
- // to-server masking.
- //
+ // 32-bit value that is contained within the frame.
+ // This field is present if the mask bit is set to 1 and is absent if
+ // the mask bit is set to 0.
+ // See Section 5.3 for further information on client-to-server
+ // masking.
maskKey []byte
- //
// Payload data: (x+y) bytes
//
// The "Payload data" is defined as "Extension data" concatenated
@@ -32,44 +30,42 @@ type Frame struct {
// Extension data: x bytes
//
// The "Extension data" is 0 bytes unless an extension has been
- // negotiated. Any extension MUST specify the length of the
- // "Extension data", or how that length may be calculated, and how
- // the extension use MUST be negotiated during the opening handshake.
+ // negotiated.
+ // Any extension MUST specify the length of the "Extension data", or
+ // how that length may be calculated, and how the extension use MUST
+ // be negotiated during the opening handshake.
// If present, the "Extension data" is included in the total payload
// length.
//
// Application data: y bytes
//
// Arbitrary "Application data", taking up the remainder of the frame
- // after any "Extension data". The length of the "Application data"
- // is equal to the payload length minus the length of the "Extension
- // data".
- //
+ // after any "Extension data".
+ // The length of the "Application data" is equal to the payload length
+ // minus the length of the "Extension data".
payload []byte
- //
// chopped contains the unfinished frame, excluding mask keys and
// payload.
- //
chopped []byte
- //
// len represent Payload length: 7 bits, 7+16 bits, or 7+64 bits
//
// The length of the "Payload data", in bytes: if 0-125, that is the
- // payload length. If 126, the following 2 bytes interpreted as a
- // 16-bit unsigned integer are the payload length. If 127, the
- // following 8 bytes interpreted as a 64-bit unsigned integer (the
- // most significant bit MUST be 0) are the payload length. Multibyte
- // length quantities are expressed in network byte order. Note that
- // in all cases, the minimal number of bytes MUST be used to encode
- // the length, for example, the length of a 124-byte-long string
- // can't be encoded as the sequence 126, 0, 124. The payload length
- // is the length of the "Extension data" + the length of the
- // "Application data". The length of the "Extension data" may be
- // zero, in which case the payload length is the length of the
- // "Application data".
- //
+ // payload length.
+ // If 126, the following 2 bytes interpreted as a 16-bit unsigned
+ // integer are the payload length.
+ // If 127, the following 8 bytes interpreted as a 64-bit unsigned
+ // integer (the most significant bit MUST be 0) are the payload
+ // length.
+ // Multibyte length quantities are expressed in network byte order.
+ // Note that in all cases, the minimal number of bytes MUST be used to
+ // encode the length, for example, the length of a 124-byte-long
+ // string can't be encoded as the sequence 126, 0, 124.
+ // The payload length is the length of the "Extension data" + the
+ // length of the "Application data".
+ // The length of the "Extension data" may be zero, in which case the
+ // payload length is the length of the "Application data".
len uint64
// closeCode represent the status of control frame close request.
@@ -77,15 +73,13 @@ type Frame struct {
// opcode (4 bits) defines the interpretation of the "Payload data".
// If an unknown opcode is received, the receiving endpoint MUST _Fail
- // the WebSocket Connection_. The following values are defined.
+ // the WebSocket Connection_.
opcode Opcode
- //
// masked (1 bit) defines whether the "Payload data" is masked.
// If set to 1, a masking key is present in masking-key, and this is
- // used to unmask the "Payload data" as per Section 5.3. All frames
- // sent from client to server have this bit set to 1.
- //
+ // used to unmask the "Payload data" as per Section 5.3.
+ // All frames sent from client to server have this bit set to 1.
masked byte
// fin Indicates that this is the final fragment in a message.
diff --git a/lib/websocket/frames.go b/lib/websocket/frames.go
index b6143f45..018c0b89 100644
--- a/lib/websocket/frames.go
+++ b/lib/websocket/frames.go
@@ -17,9 +17,10 @@ type Frames struct {
// Unpack websocket data protocol from raw bytes to one or more frames.
//
// When receiving packet from client, the underlying protocol or operating
-// system may buffered the packet. Client may send a single frame one at
-// time, but server may receive one or more frame in one packet; and vice
-// versa. That's the reason why the Unpack return multiple frame instead of
+// system may buffered the packet.
+// Client may send a single frame one at time, but server may receive one or
+// more frame in one packet; and vice versa.
+// That's the reason why the Unpack return multiple frame instead of
// single frame.
//
// On success it will return one or more frames.
diff --git a/lib/websocket/rootroute.go b/lib/websocket/rootroute.go
index 7ca11da8..8ef49303 100644
--- a/lib/websocket/rootroute.go
+++ b/lib/websocket/rootroute.go
@@ -85,11 +85,11 @@ func (root *rootRoute) getParent(method string) *route {
// add new route handler by method and target.
//
-// method is one of HTTP method that is allowed: DELETE, GET, PATCH, POST, or
-// PUT.
-// target is absolute path, MUST start with slash "/", and can contains
-// parameter by prefixing it with colon ":". For example, "/book/:id", will
-// be parsed into,
+// The method parameter is one of HTTP method that is allowed: DELETE, GET,
+// PATCH, POST, or PUT.
+// The target parameter is absolute path, MUST start with slash "/", and can
+// contains parameter by prefixing it with colon ":". For example,
+// "/book/:id", will be parsed into,
//
// {
// name:"book",
diff --git a/lib/websocket/server.go b/lib/websocket/server.go
index 30985268..586de037 100644
--- a/lib/websocket/server.go
+++ b/lib/websocket/server.go
@@ -346,17 +346,18 @@ func (serv *Server) upgrader() {
// A fragmented message consists of a single frame with the FIN bit
// clear and an opcode other than 0, followed by zero or more frames
// with the FIN bit clear and the opcode set to 0, and terminated by
-// a single frame with the FIN bit set and an opcode of 0. A
-// fragmented message is conceptually equivalent to a single larger
+// a single frame with the FIN bit set and an opcode of 0.
+// A/ fragmented message is conceptually equivalent to a single larger
// message whose payload is equal to the concatenation of the
// payloads of the fragments in order; however, in the presence of
// extensions, this may not hold true as the extension defines the
-// interpretation of the "Extension data" present. For instance,
-// "Extension data" may only be present at the beginning of the first
-// fragment and apply to subsequent fragments, or there may be
-// "Extension data" present in each of the fragments that applies
-// only to that particular fragment. In the absence of "Extension
-// data", the following example demonstrates how fragmentation works.
+// interpretation of the "Extension data" present.
+// For instance, "Extension data" may only be present at the beginning of the
+// first fragment and apply to subsequent fragments, or there may be
+// "Extension data" present in each of the fragments that applies only to that
+// particular fragment.
+// In the absence of "Extension data", the following example demonstrates how
+// fragmentation works.
//
// EXAMPLE: For a text message sent as three fragments, the first
// fragment would have an opcode of 0x1 and a FIN bit clear, the
@@ -565,17 +566,21 @@ func (serv *Server) handleClose(conn int, req *Frame) {
switch {
case req.closeCode == 0:
req.closeCode = StatusBadRequest
+
case req.closeCode < StatusNormal:
req.closeCode = StatusBadRequest
+
case req.closeCode == 1004:
// Reserved. The specific meaning might be defined in the future.
req.closeCode = StatusBadRequest
+
case req.closeCode == 1005:
// 1005 is a reserved value and MUST NOT be set as a status
// code in a Close control frame by an endpoint. It is
// designated for use in applications expecting a status code
// to indicate that no status code was actually present.
req.closeCode = StatusBadRequest
+
case req.closeCode == 1006:
// 1006 is a reserved value and MUST NOT be set as a status
// code in a Close control frame by an endpoint. It is
@@ -583,14 +588,17 @@ func (serv *Server) handleClose(conn int, req *Frame) {
// to indicate that the connection was closed abnormally,
// e.g., without sending or receiving a Close control frame.
req.closeCode = StatusBadRequest
+
case req.closeCode >= 1015 && req.closeCode <= 2999:
req.closeCode = StatusBadRequest
+
case req.closeCode >= 3000 && req.closeCode <= 3999:
// Status codes in the range 3000-3999 are reserved for use by
// libraries, frameworks, and applications. These status
// codes are registered directly with IANA. The
// interpretation of these codes is undefined by this
// protocol.
+
case req.closeCode >= 4000 && req.closeCode <= 4999:
// Status codes in the range 4000-4999 are reserved for
// private use and thus can't be registered. Such codes can