From 1ee56bae77f496e64c99490c1a46bc0c730977b4 Mon Sep 17 00:00:00 2001 From: Jeongho Nam Date: Mon, 6 May 2024 23:27:08 +0900 Subject: [PATCH] Refactor names of WebSockeet related classes. Changed class names of WebSocket related for clarity. - `WebServer` -> `WebSocketServer` - `WebAcceptor` -> `WebSocketAcceptor` - `WebConnector` -> `WebSocketConnector` - `WebError` -> `WebSocketError` --- README.md | 12 +-- package.json | 2 +- src/components/Communicator.ts | 2 +- src/protocols/internal/IHeaderWrapper.ts | 4 +- src/protocols/internal/once.ts | 2 +- .../{WebAcceptor.ts => WebSocketAcceptor.ts} | 58 ++++++------ ...{WebConnector.ts => WebSocketConnector.ts} | 85 +++++++++--------- .../web/{WebError.ts => WebSocketError.ts} | 10 ++- .../web/{WebServer.ts => WebSocketServer.ts} | 89 +++++++++++-------- src/protocols/web/index.ts | 25 +++++- ...municator.ts => IWebSocketCommunicator.ts} | 4 +- .../web/internal/WebSocketPolyfill.ts | 3 + src/utils/internal/NodeModule.ts | 6 ++ src/utils/internal/serializeError.ts | 3 + test/browser/web-client.ts | 8 +- test/browser/web-server.ts | 5 +- test/node/components/test_security.ts | 9 +- .../node/protocols/web/test_web_calculator.ts | 13 +-- test/node/protocols/web/test_web_chat.ts | 10 +-- test/node/protocols/web/test_web_header.ts | 10 +-- test/node/protocols/web/test_web_mutex.ts | 10 +-- test/node/protocols/web/test_web_reject.ts | 10 +-- .../protocols/web/test_web_server_close.ts | 10 +-- 23 files changed, 217 insertions(+), 173 deletions(-) rename src/protocols/web/{WebAcceptor.ts => WebSocketAcceptor.ts} (75%) rename src/protocols/web/{WebConnector.ts => WebSocketConnector.ts} (70%) rename src/protocols/web/{WebError.ts => WebSocketError.ts} (66%) rename src/protocols/web/{WebServer.ts => WebSocketServer.ts} (68%) rename src/protocols/web/internal/{IWebCommunicator.ts => IWebSocketCommunicator.ts} (82%) diff --git a/README.md b/README.md index 1fea35b..3177a74 100644 --- a/README.md +++ b/README.md @@ -49,12 +49,12 @@ However, whatever [Grid Computing](#12-grid-computing) and *Remote Function Call #### [`composite-calculator/server.ts`](https://github.com/samchon/tgrid.examples/blob/master/src/projects/composite-calculator/server.ts) ```typescript -import { WebServer } from "tgrid/protocols/web"; +import { WebSocketServer } from "tgrid/protocols/web"; import { CompositeCalculator } from "../../providers/Calculator"; async function main(): Promise { - const server: WebServer = new WebServer(); + const server: WebSocketServer = new WebSocketServer(); await server.open(10102, async acceptor => { await acceptor.accept(new CompositeCalculator()); @@ -65,7 +65,7 @@ main(); #### [`composite-calculator/client.ts`](https://github.com/samchon/tgrid.examples/blob/master/src/projects/composite-calculator/client.ts) ```typescript -import { WebConnector } from "tgrid/protocols/web/WebConnector"; +import { WebSocketConnector } from "tgrid/protocols/web/WebSocketConnector"; import { Driver } from "tgrid/components/Driver"; import { ICalculator } from "../../controllers/ICalculator"; @@ -75,7 +75,7 @@ async function main(): Promise //---- // CONNECTION //---- - const connector: WebConnector = new WebConnector(null, null); + const connector: WebSocketConnector = new WebSocketConnector(null, null); await connector.connect("ws://127.0.0.1:10102"); //---- @@ -166,7 +166,7 @@ Let's assume a situation; There's a distributed processing system build by tradi Thus, with **TGrid** and [Remote Function Call](#13-remote-function-call), you can adapt compilation and type checking on the network system. It helps you to develop a network system safely and conveniently. Let's close this chapter with an example of *Safey Implementation*. ```typescript -import { WebConnector } from "tgrid/protocols/web/WebConnector" +import { WebSocketConnector } from "tgrid/protocols/web/WebSocketConnector" import { Driver } from "tgrid/components/Driver"; interface ICalculator @@ -184,7 +184,7 @@ async function main(): Promise //---- // CONNECTION //---- - const connector: WebConnector = new WebConnector(null, null); + const connector: WebSocketConnector = new WebSocketConnector(null, null); await connector.connect("ws://127.0.0.1:10101"); //---- diff --git a/package.json b/package.json index 3900e34..5557201 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tgrid", - "version": "0.11.0", + "version": "1.0.0-dev.20240506", "main": "lib/index.js", "typings": "lib/index.d.ts", "exports": { diff --git a/src/components/Communicator.ts b/src/components/Communicator.ts index 0601338..c1a4cfb 100644 --- a/src/components/Communicator.ts +++ b/src/components/Communicator.ts @@ -14,7 +14,7 @@ import { Invoke } from "./Invoke"; * The basic communicator. * * The `Communicator` is an abstract class taking full charge of network communication. - * Protocolized communicators like {@link WebConnector} are realized by extending this + * Protocolized communicators like {@link WebSocketConnector} are realized by extending this * `Communicator` class. * * You want to make your own communicator using special protocol, extends this `Communicator` diff --git a/src/protocols/internal/IHeaderWrapper.ts b/src/protocols/internal/IHeaderWrapper.ts index 46a04f8..c71b08d 100644 --- a/src/protocols/internal/IHeaderWrapper.ts +++ b/src/protocols/internal/IHeaderWrapper.ts @@ -1,12 +1,12 @@ /** - * @hidden + * @internal */ export interface IHeaderWrapper { header: Headers; } /** - * @hidden + * @internal */ export namespace IHeaderWrapper { export function wrap
(header: Header): IHeaderWrapper
{ diff --git a/src/protocols/internal/once.ts b/src/protocols/internal/once.ts index 4d38a59..e33d3d2 100644 --- a/src/protocols/internal/once.ts +++ b/src/protocols/internal/once.ts @@ -1,5 +1,5 @@ /** - * @hidden + * @internal */ export function once(handler: Func): Func { let called: boolean = false; diff --git a/src/protocols/web/WebAcceptor.ts b/src/protocols/web/WebSocketAcceptor.ts similarity index 75% rename from src/protocols/web/WebAcceptor.ts rename to src/protocols/web/WebSocketAcceptor.ts index 8387786..e5e813b 100644 --- a/src/protocols/web/WebAcceptor.ts +++ b/src/protocols/web/WebSocketAcceptor.ts @@ -5,17 +5,17 @@ import type WebSocket from "ws"; import { Invoke } from "../../components/Invoke"; import { AcceptorBase } from "../internal/AcceptorBase"; import { IHeaderWrapper } from "../internal/IHeaderWrapper"; -import { WebError } from "./WebError"; -import { IWebCommunicator } from "./internal/IWebCommunicator"; +import { WebSocketError } from "./WebSocketError"; +import { IWebSocketCommunicator } from "./internal/IWebSocketCommunicator"; /** * Web Socket Acceptor. * * - available only in the NodeJS. * - * The `WebAcceptor` is a communicator class interacting with the remote (web socket) client using + * The `WebSocketAcceptor` is a communicator class interacting with the remote (web socket) client using * [RFC](https://github.com/samchon/tgrid#13-remote-function-call) (Remote Function Call). The - * `WebAcceptor` objects are always created by the {@link WebServer} class whenever a remote client + * `WebSocketAcceptor` objects are always created by the {@link WebSocketServer} class whenever a remote client * connects to its server. * * To accept connection and start interaction with the remote client, call the {@link accept} @@ -23,7 +23,7 @@ import { IWebCommunicator } from "./internal/IWebCommunicator"; * connection after your busines has been completed. Otherwise, you don't want to accept but reject * the connection, call the {@link reject} method. * - * Also, when declaring this {@link WebAcceptor} type, you've to define two template arguments, + * Also, when declaring this {@link WebSocketAcceptor} type, you've to define two template arguments, * *Header* and *Provider*. The *Header* type repersents an initial data gotten from the remote * client after the connection. I hope you and client not to omit it and utilize it as an * activation tool to enhance security. @@ -37,13 +37,13 @@ import { IWebCommunicator } from "./internal/IWebCommunicator"; * @template Remote Type of features supported by remote system, used for {@link getDriver} function. * @author Jeongho Nam - https://github.com/samchon */ -export class WebAcceptor< +export class WebSocketAcceptor< Header, Provider extends object | null, Remote extends object | null, > extends AcceptorBase - implements IWebCommunicator + implements IWebSocketCommunicator { /** * @hidden @@ -65,7 +65,9 @@ export class WebAcceptor< >( request: http.IncomingMessage, socket: WebSocket, - handler?: (acceptor: WebAcceptor) => Promise, + handler?: ( + acceptor: WebSocketAcceptor, + ) => Promise, ): void { socket.once("message", async (data: WebSocket.Data) => { // @todo: custom code is required @@ -73,8 +75,8 @@ export class WebAcceptor< else try { const wrapper: IHeaderWrapper
= JSON.parse(data as string); - const acceptor: WebAcceptor = - new WebAcceptor(request, socket, wrapper.header); + const acceptor: WebSocketAcceptor = + new WebSocketAcceptor(request, socket, wrapper.header); if (handler !== undefined) await handler(acceptor); } catch (exp) { socket.close(); @@ -111,7 +113,7 @@ export class WebAcceptor< const ret: Promise = this.join(); // DO CLOSE - this.state_ = WebAcceptor.State.CLOSING; + this.state_ = WebSocketAcceptor.State.CLOSING; if (code === 1000) this.socket_!.close(); else this.socket_!.close(code!, reason!); @@ -124,7 +126,7 @@ export class WebAcceptor< */ protected async destructor(error?: Error): Promise { await super.destructor(error); - this.state_ = WebAcceptor.State.CLOSED; + this.state_ = WebSocketAcceptor.State.CLOSED; } /* ---------------------------------------------------------------- @@ -151,14 +153,14 @@ export class WebAcceptor< * * List of values are such like below: * - * - `REJECTING`: The {@link WebAcceptor.reject} method is on running. - * - `NONE`: The {@link WebAcceptor} instance is newly created, but did nothing yet. - * - `ACCEPTING`: The {@link WebAcceptor.accept} method is on running. + * - `REJECTING`: The {@link WebSocketAcceptor.reject} method is on running. + * - `NONE`: The {@link WebSocketAcceptor} instance is newly created, but did nothing yet. + * - `ACCEPTING`: The {@link WebSocketAcceptor.accept} method is on running. * - `OPEN`: The connection is online. - * - `CLOSING`: The {@link WebAcceptor.close} method is on running. + * - `CLOSING`: The {@link WebSocketAcceptor.close} method is on running. * - `CLOSED`: The connection is offline. */ - public get state(): WebAcceptor.State { + public get state(): WebSocketAcceptor.State { return this.state_; } @@ -170,22 +172,22 @@ export class WebAcceptor< */ public async accept(provider: Provider): Promise { // VALIDATION - if (this.state_ !== WebAcceptor.State.NONE) + if (this.state_ !== WebSocketAcceptor.State.NONE) throw new DomainError( - "Error on WebAcceptor.accept(): you've already accepted (or rejected) the connection.", + "Error on WebSocketAcceptor.accept(): you've already accepted (or rejected) the connection.", ); // PREPARE ASSETS - this.state_ = WebAcceptor.State.ACCEPTING; + this.state_ = WebSocketAcceptor.State.ACCEPTING; this.provider_ = provider; // REGISTER EVENTS this.socket_.on("message", this._Handle_message.bind(this)); this.socket_.on("close", this._Handle_close.bind(this)); - this.socket_.send(WebAcceptor.State.OPEN.toString()); + this.socket_.send(WebSocketAcceptor.State.OPEN.toString()); // FINISHED - this.state_ = WebAcceptor.State.OPEN; + this.state_ = WebSocketAcceptor.State.OPEN; } /** @@ -198,13 +200,13 @@ export class WebAcceptor< */ public async reject(status?: number, reason?: string): Promise { // VALIDATION - if (this.state_ !== WebAcceptor.State.NONE) + if (this.state_ !== WebSocketAcceptor.State.NONE) throw new DomainError( "You've already accepted (or rejected) the connection.", ); // SEND CLOSING FRAME - this.state_ = WebAcceptor.State.REJECTING; + this.state_ = WebSocketAcceptor.State.REJECTING; this.socket_.close(status, reason); // FINALIZATION @@ -235,8 +237,8 @@ export class WebAcceptor< * @hidden */ private async _Handle_close(code: number, reason: string): Promise { - const error: WebError | undefined = - code !== 100 ? new WebError(code, reason) : undefined; + const error: WebSocketError | undefined = + code !== 100 ? new WebSocketError(code, reason) : undefined; await this.destructor(error); } @@ -245,9 +247,9 @@ export class WebAcceptor< /** * */ -export namespace WebAcceptor { +export namespace WebSocketAcceptor { /** - * Current state of the {@link WebAcceptor}. + * Current state of the {@link WebSocketAcceptor}. */ export import State = AcceptorBase.State; } diff --git a/src/protocols/web/WebConnector.ts b/src/protocols/web/WebSocketConnector.ts similarity index 70% rename from src/protocols/web/WebConnector.ts rename to src/protocols/web/WebSocketConnector.ts index b5dfbd3..ced43a3 100644 --- a/src/protocols/web/WebConnector.ts +++ b/src/protocols/web/WebSocketConnector.ts @@ -4,25 +4,25 @@ import { Invoke } from "../../components/Invoke"; import { ConnectorBase } from "../internal/ConnectorBase"; import { IHeaderWrapper } from "../internal/IHeaderWrapper"; import { once } from "../internal/once"; -import { WebError } from "./WebError"; -import { IWebCommunicator } from "./internal/IWebCommunicator"; +import { WebSocketError } from "./WebSocketError"; +import { IWebSocketCommunicator } from "./internal/IWebSocketCommunicator"; import { WebSocketPolyfill } from "./internal/WebSocketPolyfill"; /** * Web Socket Connector. * - * The `WebConnector` is a communicator class who can connect to websocket server and + * The `WebSocketConnector` is a communicator class who can connect to websocket server and * interact with it using RFC (Remote Function Call). * * You can connect to the websocket server using {@link connect}() method. The interaction - * would be started if the server is opened by {@link WebServer.open}() and the server - * accepts your connection by {@link WebAcceptor.accept}(). + * would be started if the server is opened by {@link WebSocketServer.open}() and the server + * accepts your connection by {@link WebSocketAcceptor.accept}(). * * Note that, after you business has been completed, please close the connection using - * {@link close}() or let the server to {@link WebAcceptor.close close itself}. If you don't + * {@link close}() or let the server to {@link WebSocketAcceptor.close close itself}. If you don't * close the connection in time, it may waste vulnerable resources of the server. * - * Also, when declaring this {@link WebConnector} type, you've to define two template arguments, + * Also, when declaring this {@link WebSocketConnector} type, you've to define two template arguments, * *Header* and *Provider*. The *Header* type repersents an initial data gotten from the remote * client after the connection. I hope you and client not to omit it and utilize it as an * activation tool to enhance security. @@ -36,13 +36,13 @@ import { WebSocketPolyfill } from "./internal/WebSocketPolyfill"; * @template Remote Type of features supported by remote system, used for {@link getDriver} function. * @author Jeongho Nam - https://github.com/samchon */ -export class WebConnector< +export class WebSocketConnector< Header, Provider extends object | null, Remote extends object | null, > extends ConnectorBase - implements IWebCommunicator + implements IWebSocketCommunicator { /** * @hidden @@ -57,7 +57,7 @@ export class WebConnector< * * Try connection to the remote websocket server with its address and waiting for the * server to accept the trial. If the server rejects your connection, then exception - * would be thrown (in *Promise.catch*, as `WebError`). + * would be thrown (in *Promise.catch*, as `WebSocketError`). * * After the connection and your business has been completed, don't forget to closing the * connection in time to prevent waste of the server resource. @@ -67,28 +67,28 @@ export class WebConnector< */ public async connect( url: string, - options: Partial = {}, + options: Partial = {}, ): Promise { // TEST CONDITION - if (this.socket_ && this.state !== WebConnector.State.CLOSED) - if (this.socket_.readyState === WebConnector.State.CONNECTING) + if (this.socket_ && this.state !== WebSocketConnector.State.CLOSED) + if (this.socket_.readyState === WebSocketConnector.State.CONNECTING) throw new DomainError( - "Error on WebConnector.connect(): already connecting.", + "Error on WebSocketConnector.connect(): already connecting.", ); - else if (this.socket_.readyState === WebConnector.State.OPEN) + else if (this.socket_.readyState === WebSocketConnector.State.OPEN) throw new DomainError( - "Error on WebConnector.connect(): already connected.", + "Error on WebSocketConnector.connect(): already connected.", ); else throw new DomainError( - "Error on WebConnector.connect(): already closing.", + "Error on WebSocketConnector.connect(): already closing.", ); //---- // CONNECTION //---- // PREPARE ASSETS - this.state_ = WebConnector.State.CONNECTING; + this.state_ = WebSocketConnector.State.CONNECTING; try { // DO CONNNECT @@ -104,23 +104,26 @@ export class WebConnector< // PROMISED HANDSHAKE if ( (await this._Handshake(options.timeout)) !== - WebConnector.State.OPEN.toString() + WebSocketConnector.State.OPEN.toString() ) - throw new WebError( + throw new WebSocketError( 1008, - "Error on WebConnector.connect(): target server may not be opened by TGrid. It's not following the TGrid's own handshake rule.", + "Error on WebSocketConnector.connect(): target server may not be opened by TGrid. It's not following the TGrid's own handshake rule.", ); // SUCCESS - this.state_ = WebConnector.State.OPEN; + this.state_ = WebSocketConnector.State.OPEN; { this.socket_!.onmessage = this._Handle_message.bind(this); this.socket_!.onclose = this._Handle_close.bind(this); this.socket_!.onerror = () => {}; } } catch (exp) { - this.state_ = WebConnector.State.NONE; - if (this.socket_ && this.socket_.readyState === WebConnector.State.OPEN) { + this.state_ = WebSocketConnector.State.NONE; + if ( + this.socket_ && + this.socket_.readyState === WebSocketConnector.State.OPEN + ) { this.socket_.onclose = () => {}; this.socket_.close(); } @@ -135,10 +138,10 @@ export class WebConnector< return new Promise((resolve, reject) => { this.socket_!.onopen = () => resolve(this.socket_!); this.socket_!.onclose = once((evt) => { - reject(new WebError(evt.code, evt.reason)); + reject(new WebSocketError(evt.code, evt.reason)); }); this.socket_!.onerror = once(() => { - reject(new WebError(1006, "Connection refused.")); + reject(new WebSocketError(1006, "Connection refused.")); }); }); } @@ -158,7 +161,7 @@ export class WebConnector< const ret: Promise = this.join(); // DO CLOSE - this.state_ = WebConnector.State.CLOSING; + this.state_ = WebSocketConnector.State.CLOSING; this.socket_!.close(code, reason); // LAZY RETURN @@ -181,9 +184,9 @@ export class WebConnector< sleep_for(timeout).then(() => { if (completed === false) { reject( - new WebError( + new WebSocketError( 1008, - `Error on WebConnector.connect(): target server is not sending handshake data over ${timeout} milliseconds.`, + `Error on WebSocketConnector.connect(): target server is not sending handshake data over ${timeout} milliseconds.`, ), ); expired = true; @@ -200,13 +203,13 @@ export class WebConnector< this.socket_!.onclose = once((evt) => { if (expired === false) { completed = true; - reject(new WebError(evt.code, evt.reason)); + reject(new WebSocketError(evt.code, evt.reason)); } }); this.socket_!.onerror = once(() => { if (expired === false) { completed = true; - reject(new WebError(1006, "Connection refused.")); + reject(new WebSocketError(1006, "Connection refused.")); } }); }); @@ -229,13 +232,13 @@ export class WebConnector< * * List of values are such like below: * - * - `NONE`: The {@link WebConnector} instance is newly created, but did nothing yet. - * - `CONNECTING`: The {@link WebConnector.connect} method is on running. + * - `NONE`: The {@link WebSocketConnector} instance is newly created, but did nothing yet. + * - `CONNECTING`: The {@link WebSocketConnector.connect} method is on running. * - `OPEN`: The connection is online. - * - `CLOSING`: The {@link WebConnector.close} method is on running. + * - `CLOSING`: The {@link WebSocketConnector.close} method is on running. * - `CLOSED`: The connection is offline. */ - public get state(): WebConnector.State { + public get state(): WebSocketConnector.State { return this.state_; } @@ -263,12 +266,12 @@ export class WebConnector< * @hidden */ private async _Handle_close(event: CloseEvent): Promise { - const error: WebError | undefined = + const error: WebSocketError | undefined = !event.code || event.code !== 1000 - ? new WebError(event.code, event.reason) + ? new WebSocketError(event.code, event.reason) : undefined; - this.state_ = WebConnector.State.CLOSED; + this.state_ = WebSocketConnector.State.CLOSED; await this.destructor(error); } } @@ -276,14 +279,14 @@ export class WebConnector< /** * */ -export namespace WebConnector { +export namespace WebSocketConnector { /** - * Current state of the {@link WebConnector}. + * Current state of the {@link WebSocketConnector}. */ export import State = ConnectorBase.State; /** - * Connection options for the {@link WebConnector.connect}. + * Connection options for the {@link WebSocketConnector.connect}. */ export interface IConnectOptions { /** diff --git a/src/protocols/web/WebError.ts b/src/protocols/web/WebSocketError.ts similarity index 66% rename from src/protocols/web/WebError.ts rename to src/protocols/web/WebSocketError.ts index e55870d..8442108 100644 --- a/src/protocols/web/WebError.ts +++ b/src/protocols/web/WebSocketError.ts @@ -1,12 +1,10 @@ -import { DomainError } from "tstl"; - /** * Web Socket Error. * * @reference https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent * @author Jeongho Nam - https://github.com/samchon */ -export class WebError extends DomainError { +export class WebSocketError extends Error { public readonly status: number; /** @@ -17,6 +15,12 @@ export class WebError extends DomainError { */ public constructor(status: number, message: string) { super(message); + + // INHERITANCE POLYFILL + const proto = new.target.prototype; + if (Object.setPrototypeOf) Object.setPrototypeOf(this, proto); + else (this as any).__proto__ = proto; + this.status = status; } } diff --git a/src/protocols/web/WebServer.ts b/src/protocols/web/WebSocketServer.ts similarity index 68% rename from src/protocols/web/WebServer.ts rename to src/protocols/web/WebSocketServer.ts index 208b240..6a7378a 100644 --- a/src/protocols/web/WebServer.ts +++ b/src/protocols/web/WebSocketServer.ts @@ -6,21 +6,21 @@ import type WebSocket from "ws"; import { NodeModule } from "../../utils/internal/NodeModule"; import { IServer } from "../internal/IServer"; -import { WebAcceptor } from "./WebAcceptor"; +import { WebSocketAcceptor } from "./WebSocketAcceptor"; /** * Web Socket Server. * * - available only in the NodeJS. * - * The `WebServer` is a class who can open an websocket server. Clients connecting to the - * `WebServer` would communicate with this server through {@link WebAcceptor} objects using + * The `WebSocketServer` is a class who can open an websocket server. Clients connecting to the + * `WebSocketServer` would communicate with this server through {@link WebSocketAcceptor} objects using * RFC (Remote Function Call). * * To open the websocket server, call the {@link open}() method with your callback function which - * would be called whenever a {@link WebAcceptor} has been newly created ay a client's connection. + * would be called whenever a {@link WebSocketAcceptor} has been newly created ay a client's connection. * - * Also, when declaring this {@link WebServer} type, you've to define two template arguments, + * Also, when declaring this {@link WebSocketServer} type, you've to define two template arguments, * *Header* and *Provider*. The *Header* type repersents an initial data gotten from the remote * client after the connection. I hope you and client not to omit it and utilize it as an * activation tool to enhance security. @@ -34,16 +34,16 @@ import { WebAcceptor } from "./WebAcceptor"; * @template Remote Type of features supported by remote system, used for {@link getDriver} function. * @author Jeongho Nam - https://github.com/samchon */ -export class WebServer< +export class WebSocketServer< Header, Provider extends object | null, Remote extends object | null, -> implements IServer +> implements IServer { /** * @hidden */ - private state_: WebServer.State; + private state_: WebSocketServer.State; /** * @hidden @@ -83,14 +83,14 @@ export class WebServer< public constructor(key?: string, cert?: string) { if (is_node() === false) throw new DomainError( - "Error on WebServer.constructor(): only available in NodeJS.", + "Error on WebSocketServer.constructor(): only available in NodeJS.", ); // PREPARE SREVER INSTANCE this.options_ = !!key && !!cert ? { key, cert } : null; // INITIALIZE STATUS & PROTOCOL - this.state_ = WebServer.State.NONE; + this.state_ = WebSocketServer.State.NONE; this.server_ = null; this.protocol_ = null; } @@ -100,37 +100,44 @@ export class WebServer< * * Open a server through the web-socket protocol, with its *port* number and *handler* * function determining whether to accept the client's connection or not. After the server has - * been opened, clients can connect to that websocket server by using the {@link WebConnector} + * been opened, clients can connect to that websocket server by using the {@link WebSocketConnector} * class. * - * When implementing the *handler* function with the {@link WebAcceptor} instance, calls the - * {@link WebAcceptor.accept} method if you want to accept the new client's connection. + * When implementing the *handler* function with the {@link WebSocketAcceptor} instance, calls the + * {@link WebSocketAcceptor.accept} method if you want to accept the new client's connection. * Otherwise you dont't want to accept the client and reject its connection, just calls the - * {@link WebAcceptor.reject} instead. + * {@link WebSocketAcceptor.reject} instead. * * @param port Port number to listen. * @param handler Callback function for client connection. */ public async open( port: number, - handler: (acceptor: WebAcceptor) => Promise, + handler: ( + acceptor: WebSocketAcceptor, + ) => Promise, ): Promise { //---- // PRELIMINARIES //---- // POSSIBLE TO OPEN? - if (this.state_ === WebServer.State.OPEN) + if (this.state_ === WebSocketServer.State.OPEN) throw new DomainError( - "Error on WebServer.open(): it has already been opened.", + "Error on WebSocketServer.open(): it has already been opened.", ); - else if (this.state_ === WebServer.State.OPENING) + else if (this.state_ === WebSocketServer.State.OPENING) throw new DomainError( - "Error on WebServer.open(): it's on opening, wait for a second.", + "Error on WebSocketServer.open(): it's on opening, wait for a second.", + ); + else if (this.state_ === WebSocketServer.State.CLOSING) + throw new RuntimeError( + "Error on WebSocketServer.open(): it's on closing.", ); - else if (this.state_ === WebServer.State.CLOSING) - throw new RuntimeError("Error on WebServer.open(): it's on closing."); // DO OPEN - else if (this.server_ === null || this.state_ === WebServer.State.CLOSED) + else if ( + this.server_ === null || + this.state_ === WebSocketServer.State.CLOSED + ) this.server_ = this.options_ !== null ? (await NodeModule.https.get()).createServer(this.options_!) @@ -140,7 +147,7 @@ export class WebServer< }); // SET STATE - this.state_ = WebServer.State.OPENING; + this.state_ = WebSocketServer.State.OPENING; //---- // OPEN SERVER @@ -154,19 +161,23 @@ export class WebServer< header: Buffer, ) => { this.protocol_!.handleUpgrade(request, netSocket, header, (socket) => - WebAcceptor.upgrade(request, socket, handler), + WebSocketAcceptor.upgrade(request, socket, handler), ); }, ); // FINALIZATION - await WebServer._Open(this.server_, port, (state) => (this.state_ = state)); + await WebSocketServer._Open( + this.server_, + port, + (state) => (this.state_ = state), + ); } /** * Close server. * - * Close all connections between its remote clients ({@link WebConnector}s). + * Close all connections between its remote clients ({@link WebSocketConnector}s). * * It destories all RFCs (remote function calls) between this server and remote clients * (through `Driver`) that are not returned (completed) yet. The destruction @@ -174,15 +185,15 @@ export class WebServer< */ public async close(): Promise { // VALIDATION - if (this.state_ !== WebServer.State.OPEN) + if (this.state_ !== WebSocketServer.State.OPEN) throw new DomainError( - "Error on WebServer.close(): server is not opened.", + "Error on WebSocketServer.close(): server is not opened.", ); // DO CLOSE - this.state_ = WebServer.State.CLOSING; + this.state_ = WebSocketServer.State.CLOSING; await this._Close(); - this.state_ = WebServer.State.CLOSED; + this.state_ = WebSocketServer.State.CLOSED; } /** @@ -191,17 +202,17 @@ export class WebServer< private static _Open( server: http.Server | https.Server, port: number, - setState: (state: WebServer.State) => void, + setState: (state: WebSocketServer.State) => void, ): Promise { return new Promise((resolve, reject) => { // PREPARE RETURNS server.on("listening", () => { - setState(WebServer.State.OPEN); + setState(WebSocketServer.State.OPEN); server.on("error", () => {}); resolve(); }); server.on("error", (error) => { - setState(WebServer.State.NONE); + setState(WebSocketServer.State.NONE); reject(error); }); @@ -233,13 +244,13 @@ export class WebServer< * * List of values are such like below: * - * - `NONE`: The `{@link WebServer} instance is newly created, but did nothing yet. - * - `OPENING`: The {@link WebServer.open} method is on running. + * - `NONE`: The `{@link WebSocketServer} instance is newly created, but did nothing yet. + * - `OPENING`: The {@link WebSocketServer.open} method is on running. * - `OPEN`: The websocket server is online. - * - `CLOSING`: The {@link WebServer.close} method is on running. + * - `CLOSING`: The {@link WebSocketServer.close} method is on running. * - `CLOSED`: The websocket server is offline. */ - public get state(): WebServer.State { + public get state(): WebSocketServer.State { return this.state_; } } @@ -247,9 +258,9 @@ export class WebServer< /** * */ -export namespace WebServer { +export namespace WebSocketServer { /** - * Current state of the {@link WebServer}. + * Current state of the {@link WebSocketServer}. */ export import State = IServer.State; } diff --git a/src/protocols/web/index.ts b/src/protocols/web/index.ts index 931283c..d29f0c2 100644 --- a/src/protocols/web/index.ts +++ b/src/protocols/web/index.ts @@ -1,4 +1,21 @@ -export * from "./WebServer"; -export * from "./WebAcceptor"; -export * from "./WebConnector"; -export * from "./WebError"; +import { WebSocketAcceptor } from "./WebSocketAcceptor"; +import { WebSocketConnector } from "./WebSocketConnector"; +import { WebSocketError } from "./WebSocketError"; +import { WebSocketServer } from "./WebSocketServer"; + +export { + WebSocketServer, + WebSocketAcceptor, + WebSocketConnector, + WebSocketError, +}; + +/** + * @internal + */ +export { + WebSocketAcceptor as WebAcceptor, + WebSocketConnector as WebConnector, + WebSocketError as WebError, + WebSocketServer as WebServer, +}; diff --git a/src/protocols/web/internal/IWebCommunicator.ts b/src/protocols/web/internal/IWebSocketCommunicator.ts similarity index 82% rename from src/protocols/web/internal/IWebCommunicator.ts rename to src/protocols/web/internal/IWebSocketCommunicator.ts index 4ce373c..3977621 100644 --- a/src/protocols/web/internal/IWebCommunicator.ts +++ b/src/protocols/web/internal/IWebSocketCommunicator.ts @@ -3,7 +3,7 @@ * * @author Jeongho Nam - https://github.com/samchon */ -export interface IWebCommunicator { +export interface IWebSocketCommunicator { /** * Close connection. * @@ -14,7 +14,7 @@ export interface IWebCommunicator { * causes all incompleted RFCs to throw exceptions. * * If parametric *code* and *reason* are specified, it means the disconnection is - * abnormal and it would throw special exceptions (`WebError`) to the incompleted RFCs. + * abnormal and it would throw special exceptions (`WebSocketError`) to the incompleted RFCs. * * @param code Closing code. * @param reason Reason why. diff --git a/src/protocols/web/internal/WebSocketPolyfill.ts b/src/protocols/web/internal/WebSocketPolyfill.ts index 4e3931e..ebf06ed 100644 --- a/src/protocols/web/internal/WebSocketPolyfill.ts +++ b/src/protocols/web/internal/WebSocketPolyfill.ts @@ -1,5 +1,8 @@ import { NodeModule } from "../../../utils/internal/NodeModule"; +/** + * @internal + */ export async function WebSocketPolyfill() { const modulo = await NodeModule.ws.get(); return modulo.default; diff --git a/src/utils/internal/NodeModule.ts b/src/utils/internal/NodeModule.ts index 93434c6..d0c1953 100644 --- a/src/utils/internal/NodeModule.ts +++ b/src/utils/internal/NodeModule.ts @@ -9,6 +9,9 @@ import { Singleton, is_node } from "tstl"; import type * as __thread from "worker_threads"; import type * as __ws from "ws"; +/** + * @internal + */ export namespace NodeModule { export const cp: Singleton> = new Singleton(() => import2("child_process"), @@ -37,4 +40,7 @@ export namespace NodeModule { }; } +/** + * @internal + */ const __global = is_node() ? global : undefined; diff --git a/src/utils/internal/serializeError.ts b/src/utils/internal/serializeError.ts index c2a9f2d..00072c6 100644 --- a/src/utils/internal/serializeError.ts +++ b/src/utils/internal/serializeError.ts @@ -1,3 +1,6 @@ +/** + * @internal + */ export const serializeError = (error: any) => { if ( typeof error === "object" && diff --git a/test/browser/web-client.ts b/test/browser/web-client.ts index e3454cc..697971d 100644 --- a/test/browser/web-client.ts +++ b/test/browser/web-client.ts @@ -1,4 +1,4 @@ -import { Driver, WebConnector } from "tgrid"; +import { Driver, WebSocketConnector } from "tgrid"; import { InvalidArgument } from "tstl"; import { ICalculator } from "../controllers/ICalculator"; @@ -6,10 +6,8 @@ import { complete } from "./internal"; window.onload = async () => { for (let i: number = 0; i < 5; ++i) { - const connector: WebConnector = new WebConnector( - null, - null, - ); + const connector: WebSocketConnector = + new WebSocketConnector(null, null); await connector.connect("ws://127.0.0.1:10489"); const driver: Driver = connector.getDriver(); diff --git a/test/browser/web-server.ts b/test/browser/web-server.ts index d4f9147..b7188dd 100644 --- a/test/browser/web-server.ts +++ b/test/browser/web-server.ts @@ -1,9 +1,10 @@ -import { WebServer } from "tgrid"; +import { WebSocketServer } from "tgrid"; import { Calculator } from "../providers/Calculator"; async function main(): Promise { - const server: WebServer = new WebServer(); + const server: WebSocketServer = + new WebSocketServer(); let index: number = 0; await server.open(10489, async (acceptor) => { diff --git a/test/node/components/test_security.ts b/test/node/components/test_security.ts index 22cb6da..6e283a8 100644 --- a/test/node/components/test_security.ts +++ b/test/node/components/test_security.ts @@ -1,4 +1,4 @@ -import { Driver, WebConnector, WebServer } from "tgrid"; +import { Driver, WebSocketConnector, WebSocketServer } from "tgrid"; import { Calculator, Scientific } from "../../providers/Calculator"; @@ -24,13 +24,14 @@ async function must_be_error( } export async function test_security(): Promise { - const server: WebServer = new WebServer(); + const server: WebSocketServer = + new WebSocketServer(); await server.open(10101, async (acceptor) => { await acceptor.accept(new CustomCalculator()); }); - const connector: WebConnector = - new WebConnector(null, null); + const connector: WebSocketConnector = + new WebSocketConnector(null, null); await connector.connect("ws://127.0.0.1:10101"); const calc: Driver = connector.getDriver(); diff --git a/test/node/protocols/web/test_web_calculator.ts b/test/node/protocols/web/test_web_calculator.ts index bfbc71b..3781671 100644 --- a/test/node/protocols/web/test_web_calculator.ts +++ b/test/node/protocols/web/test_web_calculator.ts @@ -1,4 +1,4 @@ -import { Driver, WebConnector, WebServer } from "tgrid"; +import { Driver, WebSocketConnector, WebSocketServer } from "tgrid"; import { Vector } from "tstl"; import { ICalculator } from "../../../controllers/ICalculator"; @@ -11,8 +11,8 @@ export async function test_web_calculator(): Promise { //---- // SERVER //---- - const server: WebServer, null> = - new WebServer(); + const server: WebSocketServer, null> = + new WebSocketServer(); await server.open(PORT, async (acceptor) => { // SPEICFY PROVIDER const provider = /calculator/.test(acceptor.path) @@ -26,8 +26,11 @@ export async function test_web_calculator(): Promise { //---- // CLIENTS //---- - const connector: WebConnector> = - new WebConnector(null, null); + const connector: WebSocketConnector< + null, + null, + ICalculator | IVector + > = new WebSocketConnector(null, null); // const RE-USABILITY for (const path of ["calculator", "vector"]) diff --git a/test/node/protocols/web/test_web_chat.ts b/test/node/protocols/web/test_web_chat.ts index ba69753..7c4c390 100644 --- a/test/node/protocols/web/test_web_chat.ts +++ b/test/node/protocols/web/test_web_chat.ts @@ -1,4 +1,4 @@ -import { Driver, WebConnector, WebServer } from "tgrid"; +import { Driver, WebSocketConnector, WebSocketServer } from "tgrid"; import { sleep_for } from "tstl"; import { IChatPrinter } from "../../../controllers/IChatPrinter"; @@ -13,7 +13,7 @@ CLIENT ---------------------------------------------------------------- */ class Client { private name_!: string; - private connector_!: WebConnector; + private connector_!: WebSocketConnector; private scripts_!: IScript[]; private service_!: Driver; @@ -21,7 +21,7 @@ class Client { public async participate(name: string): Promise { // ASSIGN MEMBERS this.name_ = name; - this.connector_ = new WebConnector(null, { + this.connector_ = new WebSocketConnector(null, { print: (name: string, message: string): void => { this.scripts_.push({ name: name, message: message }); }, @@ -51,11 +51,11 @@ class Client { SERVER ---------------------------------------------------------------- */ class Server { - private server_!: WebServer; + private server_!: WebSocketServer; private scripts_!: IScript[]; public async open(): Promise { - this.server_ = new WebServer(); + this.server_ = new WebSocketServer(); this.scripts_ = []; await this.server_.open(PORT, async (acceptor) => { diff --git a/test/node/protocols/web/test_web_header.ts b/test/node/protocols/web/test_web_header.ts index e743747..383f37a 100644 --- a/test/node/protocols/web/test_web_header.ts +++ b/test/node/protocols/web/test_web_header.ts @@ -1,4 +1,4 @@ -import { WebConnector, WebServer } from "tgrid"; +import { WebSocketConnector, WebSocketServer } from "tgrid"; const PORT = 10101; const TOKEN = "asdfawe4fasdfchswrtgadfg"; @@ -8,16 +8,14 @@ interface IHeaders { } export async function test_web_header(): Promise { - const server: WebServer = new WebServer(); + const server: WebSocketServer = new WebSocketServer(); await server.open(PORT, async (acceptor) => { if (acceptor.header.token !== TOKEN) await acceptor.reject(); else await acceptor.accept(null); }); - const connector: WebConnector = new WebConnector( - { token: TOKEN }, - null, - ); + const connector: WebSocketConnector = + new WebSocketConnector({ token: TOKEN }, null); await connector.connect(`ws://127.0.0.1:${PORT}`); await connector.close(); diff --git a/test/node/protocols/web/test_web_mutex.ts b/test/node/protocols/web/test_web_mutex.ts index ab9ef1a..4d3d8b8 100644 --- a/test/node/protocols/web/test_web_mutex.ts +++ b/test/node/protocols/web/test_web_mutex.ts @@ -1,4 +1,4 @@ -import { Driver, WebConnector, WebServer } from "tgrid"; +import { Driver, WebSocketConnector, WebSocketServer } from "tgrid"; import { DomainError, Mutex, @@ -29,10 +29,8 @@ class Provider { } async function _Test_client(): Promise { - const connector: WebConnector = new WebConnector( - null, - null, - ); + const connector: WebSocketConnector = + new WebSocketConnector(null, null); await connector.connect(`ws://127.0.0.1:${PORT}`); const driver: Driver = connector.getDriver(); @@ -53,7 +51,7 @@ export async function test_web_mutex(): Promise { // PREPARES //---- // OPEN SERVER - const server: WebServer = new WebServer(); + const server: WebSocketServer = new WebSocketServer(); const mutex: Mutex = new Mutex(); const vector: Vector = new Vector(); let index: number = 0; diff --git a/test/node/protocols/web/test_web_reject.ts b/test/node/protocols/web/test_web_reject.ts index 3d59017..68038f6 100644 --- a/test/node/protocols/web/test_web_reject.ts +++ b/test/node/protocols/web/test_web_reject.ts @@ -1,9 +1,9 @@ -import { WebConnector, WebServer } from "tgrid"; +import { WebSocketConnector, WebSocketServer } from "tgrid"; const PORT = 10101; export async function test_web_reject(): Promise { - const server: WebServer = new WebServer(); + const server: WebSocketServer = new WebSocketServer(); // TEST RE-USABILITY TOO for (let i: number = 0; i < 5; ++i) { @@ -11,10 +11,8 @@ export async function test_web_reject(): Promise { await acceptor.reject(1001, "Rejected by test automation program."); }); - const connector: WebConnector = new WebConnector( - null, - null, - ); + const connector: WebSocketConnector = + new WebSocketConnector(null, null); let error: Error | null = null; try { diff --git a/test/node/protocols/web/test_web_server_close.ts b/test/node/protocols/web/test_web_server_close.ts index ade05aa..4793860 100644 --- a/test/node/protocols/web/test_web_server_close.ts +++ b/test/node/protocols/web/test_web_server_close.ts @@ -1,16 +1,14 @@ -import { WebConnector, WebServer } from "tgrid"; +import { WebSocketConnector, WebSocketServer } from "tgrid"; const PORT = 10101; export async function test_web_server_close(): Promise { - const server: WebServer = new WebServer(); + const server: WebSocketServer = new WebSocketServer(); await server.open(PORT, (acceptor) => acceptor.accept(null)); for (let i: number = 0; i < 100; ++i) { - const connector: WebConnector = new WebConnector( - null, - null, - ); + const connector: WebSocketConnector = + new WebSocketConnector(null, null); await connector.connect(`ws://127.0.0.1:${PORT}`); } await server.close();