From 7b01a3fc41b8611aa26c7d5d0f5c0f2bcd012ee0 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Sat, 1 Jul 2023 14:46:38 +0700 Subject: lib/websocket: reformat comments and documentation --- lib/websocket/client.go | 75 ++++++++++++++++++++++++---------------------- lib/websocket/closecode.go | 52 ++++++++++++++++---------------- lib/websocket/frame.go | 64 ++++++++++++++++++--------------------- lib/websocket/frames.go | 7 +++-- lib/websocket/rootroute.go | 10 +++---- lib/websocket/server.go | 24 ++++++++++----- 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 -- cgit v1.3