* Parses control frames. * @param {Buffer} body
(body)
| 432 | * @param {Buffer} body |
| 433 | */ |
| 434 | parseControlFrame (body) { |
| 435 | const { opcode, payloadLength } = this.#info |
| 436 | |
| 437 | if (opcode === opcodes.CLOSE) { |
| 438 | if (payloadLength === 1) { |
| 439 | failWebsocketConnection(this.#handler, 1002, 'Received close frame with a 1-byte body.') |
| 440 | return false |
| 441 | } |
| 442 | |
| 443 | this.#info.closeInfo = this.parseCloseBody(body) |
| 444 | |
| 445 | if (this.#info.closeInfo.error) { |
| 446 | const { code, reason } = this.#info.closeInfo |
| 447 | |
| 448 | failWebsocketConnection(this.#handler, code, reason) |
| 449 | return false |
| 450 | } |
| 451 | |
| 452 | // Upon receiving such a frame, the other peer sends a |
| 453 | // Close frame in response, if it hasn't already sent one. |
| 454 | if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { |
| 455 | // If an endpoint receives a Close frame and did not previously send a |
| 456 | // Close frame, the endpoint MUST send a Close frame in response. (When |
| 457 | // sending a Close frame in response, the endpoint typically echos the |
| 458 | // status code it received.) |
| 459 | let body = emptyBuffer |
| 460 | if (this.#info.closeInfo.code) { |
| 461 | body = Buffer.allocUnsafe(2) |
| 462 | body.writeUInt16BE(this.#info.closeInfo.code, 0) |
| 463 | } |
| 464 | const closeFrame = new WebsocketFrameSend(body) |
| 465 | |
| 466 | this.#handler.socket.write(closeFrame.createFrame(opcodes.CLOSE)) |
| 467 | this.#handler.closeState.add(sentCloseFrameState.SENT) |
| 468 | } |
| 469 | |
| 470 | // Upon either sending or receiving a Close control frame, it is said |
| 471 | // that _The WebSocket Closing Handshake is Started_ and that the |
| 472 | // WebSocket connection is in the CLOSING state. |
| 473 | this.#handler.readyState = states.CLOSING |
| 474 | this.#handler.closeState.add(sentCloseFrameState.RECEIVED) |
| 475 | |
| 476 | return false |
| 477 | } else if (opcode === opcodes.PING) { |
| 478 | // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in |
| 479 | // response, unless it already received a Close frame. |
| 480 | // A Pong frame sent in response to a Ping frame must have identical |
| 481 | // "Application data" |
| 482 | |
| 483 | if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { |
| 484 | const frame = new WebsocketFrameSend(body) |
| 485 | |
| 486 | this.#handler.socket.write(frame.createFrame(opcodes.PONG)) |
| 487 | |
| 488 | this.#handler.onPing(body) |
| 489 | } |
| 490 | } else if (opcode === opcodes.PONG) { |
| 491 | // A Pong frame MAY be sent unsolicited. This serves as a |
no test coverage detected