From 13abf7f0167a3816bf5f571dee06d8bbd93c3723 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Sat, 14 Dec 2019 11:59:18 +1300
Subject: [PATCH] WebSocket and WebSocketServer JSDoc
---
.../script-engine/src/WebSocketClass.cpp | 30 +++++
libraries/script-engine/src/WebSocketClass.h | 113 ++++++++++++++++++
.../script-engine/src/WebSocketServerClass.h | 66 ++++++++++
3 files changed, 209 insertions(+)
diff --git a/libraries/script-engine/src/WebSocketClass.cpp b/libraries/script-engine/src/WebSocketClass.cpp
index 56753f07d1..c02efd8a30 100644
--- a/libraries/script-engine/src/WebSocketClass.cpp
+++ b/libraries/script-engine/src/WebSocketClass.cpp
@@ -68,6 +68,18 @@ void WebSocketClass::close(QWebSocketProtocol::CloseCode closeCode, QString reas
_webSocket->close(closeCode, reason);
}
+/**jsdoc
+ * Called when the connection closes.
+ * @callback WebSocket~onCloseCallback
+ * @param {WebSocket.CloseData} data - Information on the connection closure.
+ */
+/**jsdoc
+ * Information on a connection being closed.
+ * @typedef {object} WebSocket.CloseData
+ * @property {WebSocket.CloseCode} code - The reason why the connection was closed.
+ * @property {string} reason - Description of the reason why the connection was closed.
+ * @property {boolean} wasClean - true
if the connection closed cleanly, false
if it didn't.
+ */
void WebSocketClass::handleOnClose() {
bool hasError = (_webSocket->error() != QAbstractSocket::UnknownSocketError);
if (_onCloseEvent.isFunction()) {
@@ -81,12 +93,26 @@ void WebSocketClass::handleOnClose() {
}
}
+/**jsdoc
+ * Called when an error occurs.
+ * @callback WebSocket~onErrorCallback
+ */
void WebSocketClass::handleOnError(QAbstractSocket::SocketError error) {
if (_onErrorEvent.isFunction()) {
_onErrorEvent.call();
}
}
+/**jsdoc
+ * Triggered when a message is received.
+ * @callback WebSocket~onMessageCallback
+ * @param {WebSocket.MessageData} message - The message received.
+ */
+/**jsdoc
+ * A message received on a WebSocket connection.
+ * @typedef {object} WebSocket.MessageData
+ * @property {string} data - The message content.
+ */
void WebSocketClass::handleOnMessage(const QString& message) {
if (_onMessageEvent.isFunction()) {
QScriptValueList args;
@@ -97,6 +123,10 @@ void WebSocketClass::handleOnMessage(const QString& message) {
}
}
+/**jsdoc
+ * Called when the connection opens.
+ * @callback WebSocket~onOpenCallback
+ */
void WebSocketClass::handleOnOpen() {
if (_onOpenEvent.isFunction()) {
_onOpenEvent.call();
diff --git a/libraries/script-engine/src/WebSocketClass.h b/libraries/script-engine/src/WebSocketClass.h
index dbc9729c61..56fb334152 100644
--- a/libraries/script-engine/src/WebSocketClass.h
+++ b/libraries/script-engine/src/WebSocketClass.h
@@ -16,6 +16,68 @@
#include
#include
+/**jsdoc
+ * Provides a bi-direcctional, event-driven communication session between the script and another WebSocket connection. It is a
+ * near-complete implementation of the WebSocket API described in the Mozilla docs:
+ * https://developer.mozilla.org/en-US/docs/Web/API/WebSocket.
+ *
+ * Constructed by new WebSocket(...)
in Interface, client entity, avatar, and server entity scripts, or the
+ * {@link WebSocketServer} class in server entity and assignment client scripts.
+ *
+ *
Note: Does not support secure, wss:
protocol.
+ *
+ * @class WebSocket
+ * @param {string|WebSocket} urlOrWebSocket - The URL to connect to or an existing {@link WebSocket} to reuse the connection of.
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-avatar
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
+ * @property {string} binaryType="blob" - Not used.
+ * @property {number} bufferedAmount=0 - Not implemented. Read-only.
+ * @property {string} extensions="" - Not implemented. Read-only.
+ *
+ * @property {WebSocket~onOpenCallback} onopen - Function called when the connection opens.
+ * @property {WebSocket~onMessageCallback} onmessage - Function called when a message is received.
+ * @property {WebSocket~onErrorCallback} onerror - Function called when an error occurs.
+ * @property {WebSocket~onCloseCallback} onclose - Function called when the connection closes.
+ *
+ * @property {string} protocol="" - Not implemented. Read-only.
+ * @property {WebSocket.ReadyState} readyState - The state of the connection. Read-only.
+ * @property {string} url - The URL to connect to. Read-only.
+ *
+ * @property {WebSocket.ReadyState} CONNECTING - The connection is opening. Read-only.
+ * @property {WebSocket.ReadyState} OPEN - The connection is open. Read-only.
+ * @property {WebSocket.ReadyState} CLOSING - The connection is closing. Read-only.
+ * @property {WebSocket.ReadyState} CLOSED - The connection is closed. Read-only.
+ *
+ * @example Echo a message off websocket.org.
+ * print("Create WebSocket");
+ * var WEBSOCKET_PING_URL = "ws://echo.websocket.org";
+ * var webSocket = new WebSocket(WEBSOCKET_PING_URL);
+ *
+ * webSocket.onclose = function (data) {
+ * print("WebSocket closed");
+ * print("Ready state =", webSocket.readyState); // 3
+ * };
+ *
+ * webSocket.onmessage = function (data) {
+ * print("Message received:", data.data);
+ *
+ * print("Close WebSocket");
+ * webSocket.close();
+ * };
+ *
+ * webSocket.onopen = function () {
+ * print("WebSocket opened");
+ * print("Ready state =", webSocket.readyState); // 1
+ *
+ * print("Send a test message");
+ * webSocket.send("Test message");
+ * };
+ */
class WebSocketClass : public QObject {
Q_OBJECT
Q_PROPERTY(QString binaryType READ getBinaryType WRITE setBinaryType)
@@ -43,6 +105,21 @@ public:
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
+ /**jsdoc
+ * The state of a WebSocket connection.
+ *
+ *
+ * Value | Name | Description |
+ *
+ *
+ * 0 | CONNECTING | The connection is opening. |
+ * 1 | OPEN | The connection is open. |
+ * 2 | CLOSING | The connection is closing. |
+ * 3 | CLOSED | The connection is closed. |
+ *
+ *
+ * @typedef {number} WebSocket.ReadyState
+ */
enum ReadyState {
CONNECTING = 0,
OPEN,
@@ -100,8 +177,44 @@ public:
QScriptValue getOnOpen() { return _onOpenEvent; }
public slots:
+
+ /**jsdoc
+ * Sends a message on the connection.
+ * @function WebSocket.send
+ * @param {string|object} message - The message to send. If an object, it is converted to a string.
+ */
void send(QScriptValue message);
+ /**jsdoc
+ * Closes the connection.
+ * @function WebSocket.close
+ * @param {WebSocket.CloseCode} [closeCode=1000] - The reason for closing.
+ * @param {string} [reason=""] - A description of the reason for closing.
+ */
+ /**jsdoc
+ * The reason why the connection was closed.
+ *
+ *
+ * Value | Name | Description |
+ *
+ *
+ * 1000 | Normal | Normal closure. |
+ * 1001 | GoingAway | Going away. |
+ * 1002 | ProtocolError | Protocol error. |
+ * 1003 | DatatypeNotSupported | Unsupported data. |
+ * 1004 | Reserved1004 | Reserved. |
+ * 1005 | MissingStatusCode | No status received. |
+ * 1006 | AbnormalDisconnection | abnormal closure. |
+ * 1007 | WrongDatatype | Invalid frame payload data. |
+ * 1008 | PolicyViolated | Policy violation. |
+ * 1009 | TooMuchData | Message too big. |
+ * 1010 | MissingExtension | Mandatory extension missing. |
+ * 1011 | BadOperation | Internal server error. |
+ * 1015 | TlsHandshakeFailed | TLS handshake failed. |
+ *
+ *
+ * @typedef {number} WebSocket.CloseCode
+ */
void close();
void close(QWebSocketProtocol::CloseCode closeCode);
void close(QWebSocketProtocol::CloseCode closeCode, QString reason);
diff --git a/libraries/script-engine/src/WebSocketServerClass.h b/libraries/script-engine/src/WebSocketServerClass.h
index 972bf9c032..dfd277fec1 100644
--- a/libraries/script-engine/src/WebSocketServerClass.h
+++ b/libraries/script-engine/src/WebSocketServerClass.h
@@ -17,6 +17,60 @@
#include
#include "WebSocketClass.h"
+/**jsdoc
+ * Manages {@link WebSocket}s in server entity and assignment client scripts.
+ *
+ * @class WebSocketServer
+ *
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
+ * @property {string} url - The URL that the server is listening on. Read-only.
+ * @property {number} port - The port that the server is listening on. Read-only.
+ * @property {boolean} listening - true
if the server is listening for incoming connections, false
if
+ * it isn't. Read-only.
+ *
+ * @example Echo a message back to sender.
+ * // Server entity script. Echoes received message back to sender.
+ * (function () {
+ * print("Create WebSocketServer");
+ * var webSocketServer = new WebSocketServer();
+ * print("Server url:", webSocketServer.url);
+ *
+ * function onNewConnection(webSocket) {
+ * print("New connection");
+ *
+ * webSocket.onmessage = function (message) {
+ * print("Message received:", message.data);
+ *
+ * var returnMessage = message.data + " back!";
+ * print("Echo a message back:", returnMessage);
+ * webSocket.send(message.data + " back!");
+ * };
+ * }
+ *
+ * webSocketServer.newConnection.connect(onNewConnection);
+ * })
+ *
+ * @example
+ * // Interface script. Bounces message off server entity script.
+ * // Use the server URL reported by the server entity script.
+ * var WEBSOCKET_PING_URL = "ws://127.0.0.1:nnnnn";
+ * var TEST_MESSAGE = "Hello";
+ *
+ * print("Create WebSocket");
+ * var webSocket = new WebSocket(WEBSOCKET_PING_URL);
+ *
+ * webSocket.onmessage = function(data) {
+ * print("Message received:", data.data);
+ * };
+ *
+ * webSocket.onopen = function() {
+ * print("WebSocket opened");
+ * print("Send test message:", TEST_MESSAGE);
+ * webSocket.send(TEST_MESSAGE);
+ * };
+ */
class WebSocketServerClass : public QObject {
Q_OBJECT
Q_PROPERTY(QString url READ getURL)
@@ -34,6 +88,11 @@ public:
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
public slots:
+
+ /**jsdoc
+ * Closes all connections and closes the WebSocketServer.
+ * @function WebSocketServer.close
+ */
void close();
private:
@@ -45,6 +104,13 @@ private slots:
void onNewConnection();
signals:
+
+ /**jsdoc
+ * Triggered when there is a new connection.
+ * @function WebSocketServer.newConnection
+ * @param {WebSocket} webSocket - The {@link WebSocket} for the new connection.
+ * @returns {Signal}
+ */
void newConnection(WebSocketClass* client);
};