Skip to content

Commit

Permalink
feat: upgrade回调函数的实现 (#17)
Browse files Browse the repository at this point in the history
* test: test

* sv

* fewngo

* 3223

* chore: 加入commit提交规范

* chore: 优化commit规范

* workflow: 增加ci检测及加入pr模板

* fix: 修复pnpm format引起的ci问题

* fix: 修复pnpm lint引起的ci问题

* fix: 修复pnpm lint引起的ci问题

* feat: 初始化websocket客户端

* fix: 修改eslint规则,优化websocket(#6)

* ci: 去除typescript的ci

* refactor: 重构项目,去除typescript

* feat: 加入ws 开发依赖等(#13)

* fix: 修复无法握手,host=>hostName

* fix: 修复无法握手

* feat: upgrade回调函数的实现
  • Loading branch information
yuhao423 authored Jun 25, 2024
1 parent 32087c3 commit be8eb2a
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ const readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
module.exports = {
protocolVersions,
readyStates,
//这个GUID只能是这个,不能是其他值
GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
};
95 changes: 89 additions & 6 deletions src/websocket.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const http = require("http");
const EventEmitter = require("events");
const { URL } = require("url");
const { randomBytes } = require("crypto");
const { randomBytes, createHash } = require("crypto");

const { protocolVersions, readyStates } = require("./constant");
const { protocolVersions, readyStates, GUID } = require("./constant");

class YuFlux extends EventEmitter {
constructor(address, protocols, options) {
Expand All @@ -13,7 +13,9 @@ class YuFlux extends EventEmitter {
if (address !== undefined) {
this._isServer = false;
this._redirect = 0;

// 加入socket,tcp
this._socket = null;
this._protocol = "";
if (protocols === undefined || null) {
protocols = [];
}
Expand All @@ -23,6 +25,18 @@ class YuFlux extends EventEmitter {
this._isServer = true;
}
}

/**
* @private
*/
emitClose() {}

/**
* @param {Duplex} socket
* @param {Buffer} head
* @param {Object} options
*/
setSocket(socket, head, option) {}
}

module.exports = YuFlux;
Expand Down Expand Up @@ -149,13 +163,72 @@ const initWebSocketClient = (websocket, address, protocols, options) => {
req.on("error", (err) => {
req = websocket._req = null;

emitErrorAndClose();
emitErrorAndClose(websocket, err);
});

//todo respose 重定向

req.on("upgrade", (res, socket, head) => {
websocket.emit("upgrade", res);

if (websocket._readyState !== readyStates[0]) {
return;
}
//http请求回来了,就置空req
req = websocket._req = null;

const upgrade = res.headers.upgrade;
// console.log(res.headers, "res.headers");
//请求头不对
if (upgrade === undefined || upgrade.toLowerCase() !== "websocket") {
abortHandshake(websocket, socket, "不正确的请求头");
return;
}

//解密,使用sha1算法
//定义GUID(全局唯一标识符)摘要,可以是一个固定值或动态生成,从而生成摘要,最终转化成base64
const digest = createHash("sha1")
.update(key + GUID)
.digest("base64");

if (res.headers["sec-websocket-accept"] !== digest) {
abortHandshake(websocket, socket, "不正确的 sec-websocket-key 请求头");
return;
}

//子协议的处理
const serverProtocol = res.headers["sec-websocket-protocol"];
let protocolError;

if (serverProtocol !== undefined) {
//todo 更细的error划分
protocolError = "暂不支持子协议";
}

if (protocolError) {
abortHandshake(websocket, socket, protocolError);
return;
}

if (serverProtocol) websocket._protocol = serverProtocol;

//处理sec-websocket-extensions,扩展
const secWebSocketExtensions = res.headers["sec-websocket-extensions"];
if (secWebSocketExtensions !== undefined) {
//todo 更细的error划分
const message = "暂不支持websocket扩展协议";
abortHandshake(websocket, socket, message);
return;
}

//握手结束,正式tcp连接(socket)
//setSocket
websocket.setSocket(socket, head, {
allowSynchronousEvents: opts.allowSynchronousEvents,
generateMask: opts.generateMask,
maxPayload: opts.maxPayload,
skipUTF8Validation: opts.skipUTF8Validation,
});
});

if (opts.finishRequest) {
Expand All @@ -166,6 +239,16 @@ const initWebSocketClient = (websocket, address, protocols, options) => {
};

//todo 完善 emitErrorAndClose 函数
const emitErrorAndClose = (err) => {
console.error(err, "err");
/**
* @param {websocket} websocket websocket实例
* @param {*} err
*
*/
const emitErrorAndClose = (websocket, err) => {
//1. 改变websocket的状态
websocket._readyState = readyStates[3];
//2. emit error
websocket.emit("error", err);
//3. 真正的emitClose函数
websocket.emitClose();
};

0 comments on commit be8eb2a

Please sign in to comment.