brainclouds2s
Advanced tools
| let S2S = require('./brainclouds2s.js'); | ||
| var socket = null | ||
| var connectionState = { | ||
| CONNECTED: "Connected", | ||
| DISCONNECTED: "Disconnected", | ||
| CONNECTING: "Connecting", | ||
| DISCONNECTING: "Disconnecting" | ||
| } | ||
| var connectionStatus = connectionState.DISCONNECTED | ||
| var connectCallback = null | ||
| var DEFAULT_HEARTBEAT // Seconds | ||
| var heartbeatId = null | ||
| var disconnectedWithReason = false | ||
| var disconnectMessage = null | ||
| var rttAuth = {} | ||
| var rttCallback = null | ||
| var debugEnabled = true | ||
| var appId = null | ||
| var sessionId = null | ||
| /** | ||
| * Sends a request to establish an RTT system connection. | ||
| * @param {*} context object containing session data (appId, serverName, etc.) | ||
| * @param {*} callback function to be invoked after request is sent | ||
| */ | ||
| function requestClientConnection(context, callback) { | ||
| let requestJSON = { | ||
| service: "rttRegistration", | ||
| operation: "REQUEST_SYSTEM_CONNECTION", | ||
| data: {} | ||
| } | ||
| S2S.request(context, requestJSON, callback) | ||
| } | ||
| /** | ||
| * Creates a WebSocket connection. | ||
| * @param {*} host endpoint URL | ||
| * @param {*} port port number | ||
| * @param {*} auth appId and secret | ||
| * @param {*} ssl is ssl enabled | ||
| */ | ||
| function connect(host, port, auth, ssl) { | ||
| connectionStatus = connectionState.CONNECTING; | ||
| rttAuth = auth | ||
| // build url with auth as arguments | ||
| var uri = (ssl ? "wss://" : "ws://") + host + ":" + port; | ||
| if (rttAuth) { | ||
| uri += "?"; | ||
| var count = 0; | ||
| for (var key in rttAuth) { | ||
| if (count > 0) { | ||
| uri += "&"; | ||
| } | ||
| uri += key + "=" + rttAuth[key]; | ||
| ++count; | ||
| } | ||
| } | ||
| connectionStatus = connectionState.CONNECTED | ||
| socket = new WebSocket(uri); | ||
| socket.addEventListener('error', onSocketError); | ||
| socket.addEventListener('close', onSocketClose); | ||
| socket.addEventListener('open', onSocketOpen); | ||
| socket.addEventListener('message', onSocketMessage); | ||
| } | ||
| /** | ||
| * Sends an RTT CONNECT request through the opened WebSocket connection. | ||
| */ | ||
| function onSocketOpen() { | ||
| if (exports.rttIsEnabled()) { // This should always be true, but just in case user called disabled and we end up receiving the event anyway | ||
| // Send a connect request | ||
| var request = { | ||
| operation: "CONNECT", | ||
| service: "rtt", | ||
| data: { | ||
| appId: appId, | ||
| profileId: "s", | ||
| sessionId: sessionId, | ||
| system: { | ||
| protocol: "ws", | ||
| platform: "WEB" | ||
| } | ||
| } | ||
| }; | ||
| var browserName = getBrowserName(); | ||
| if (browserName) { | ||
| request.data.system.browser = browserName; | ||
| } | ||
| request.data.auth = rttAuth; | ||
| if (debugEnabled) { | ||
| console.log("WS SEND: " + JSON.stringify(request)); | ||
| } | ||
| socket.send(JSON.stringify(request)); | ||
| } | ||
| } | ||
| /** | ||
| * Disables RTT and- if the user had not manually disabled RTT- returns a callback failure. | ||
| */ | ||
| function onSocketClose() { | ||
| if (exports.rttIsEnabled()) { // Don't spam errors if we get multiple ones | ||
| connectCallback.failure("close"); | ||
| } | ||
| exports.disableRTT(); | ||
| if (disconnectedWithReason == true) { | ||
| console.log("RTT:Disconnect" + JSON.stringify(disconnectMessage)); | ||
| } | ||
| } | ||
| /** | ||
| * Disables RTT and- if the user had not manually disabled RTT- returns a callback failure. | ||
| */ | ||
| function onSocketError() { | ||
| if (exports.rttIsEnabled()) { // Don't spam errors if we get multiple ones | ||
| connectCallback.failure("error"); | ||
| } | ||
| exports.disableRTT(); | ||
| } | ||
| /** | ||
| * Processes data received from the WebSocket connection and starts RTT heartbeat to keep connection alive. | ||
| * @param {*} e event data | ||
| */ | ||
| function onSocketMessage(e) { | ||
| if (exports.rttIsEnabled()) { // This should always be true, but just in case user called disabled and we end up receiving the even anyway | ||
| var processResult = function (result) { | ||
| if (result.service == "rtt") { | ||
| if (debugEnabled) { | ||
| console.log("WS RECV: " + JSON.stringify(result)); | ||
| } | ||
| if (result.operation == "CONNECT") { | ||
| DEFAULT_HEARTBEAT = result.data.heartbeatSeconds; //make default heartbeat match the heartbeat the server gives us | ||
| startHeartbeat(); | ||
| connectCallback.success(result); | ||
| } | ||
| else if (result.operation == "DISCONNECT") { | ||
| disconnectedWithReason = true; | ||
| disconnectMessage = | ||
| { | ||
| severity: "ERROR", | ||
| reason: result.data.reason, | ||
| reasonCode: result.data.reasonCode, | ||
| data: null | ||
| }; | ||
| } | ||
| } | ||
| else { | ||
| onRecv(result); | ||
| } | ||
| }; | ||
| if (typeof e.data === "string") { | ||
| processResult(e.data); | ||
| } else if (typeof FileReader !== 'undefined') { | ||
| // Web Browser | ||
| var reader = new FileReader(); | ||
| reader.onload = function () { | ||
| var parsed = {}; | ||
| try { | ||
| parsed = JSON.parse(reader.result); | ||
| } | ||
| catch (e) { | ||
| console.log("WS RECV: " + reader.result); | ||
| parsed = JSON.parse(reader.result); // Trigger the error again and let it fail | ||
| } | ||
| processResult(parsed); | ||
| } | ||
| reader.readAsText(e.data); | ||
| } else { | ||
| // Node.js | ||
| var parsed = {}; | ||
| try { | ||
| parsed = JSON.parse(e.data); | ||
| } | ||
| catch (e) { | ||
| console.log("WS RECV: " + e.data); | ||
| parsed = JSON.parse(e.data); // Trigger the error again and let it fail | ||
| } | ||
| processResult(parsed); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Invokes rttCallback with data received through WebSocket message event | ||
| * @param {*} recv message event data | ||
| */ | ||
| function onRecv(recv) { | ||
| if (debugEnabled) { | ||
| console.log("WS RECV: " + JSON.stringify(recv)); | ||
| } | ||
| if (rttCallback) { | ||
| rttCallback(recv); | ||
| } | ||
| } | ||
| /** | ||
| * Gets the name of the browser being used. | ||
| * @returns name of browser | ||
| */ | ||
| function getBrowserName() { | ||
| // Opera 8.0+ | ||
| var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || (typeof navigator !== 'undefined' && navigator.userAgent.indexOf(' OPR/') >= 0); | ||
| // Firefox 1.0+ | ||
| var isFirefox = typeof InstallTrigger !== 'undefined'; | ||
| // Safari 3.0+ "[object HTMLElementConstructor]" | ||
| var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification)); | ||
| // Internet Explorer 6-11 | ||
| var isIE = (typeof document !== 'undefined' && !!document.documentMode); | ||
| // Edge 20+ | ||
| var isEdge = !isIE && !!window.StyleMedia; | ||
| // Chrome 1+ | ||
| var isChrome = !!window.chrome && !!window.chrome.webstore; | ||
| // Blink engine detection | ||
| var isBlink = (isChrome || isOpera) && !!window.CSS; | ||
| if (isOpera) return "opera"; | ||
| if (isFirefox) return "firefox"; | ||
| if (isSafari) return "safari"; | ||
| if (isIE) return "ie"; | ||
| if (isEdge) return "edge"; | ||
| if (isChrome) return "chrome"; | ||
| if (isBlink) return "blink"; | ||
| return null; | ||
| } | ||
| /** | ||
| * Sends heartbeat request at a defined interval to maintain the WebSocket connection. | ||
| */ | ||
| function startHeartbeat() { | ||
| if (!heartbeatId) { | ||
| heartbeatId = setInterval(function () { | ||
| // Send a heartbeat request | ||
| var request = { | ||
| operation: "HEARTBEAT", | ||
| service: "rtt", | ||
| data: null | ||
| }; | ||
| if (debugEnabled) { | ||
| console.log("WS SEND: " + JSON.stringify(request)); | ||
| } | ||
| socket.send(JSON.stringify(request)); | ||
| }, 1000 * DEFAULT_HEARTBEAT); | ||
| } | ||
| } | ||
| /** | ||
| * Attempts to establish an RTT connection to the brainCloud servers. | ||
| * @param {*} context object containing session data (appId, serverName, etc.) | ||
| * @param {*} success function to be invoked when an RTT connection has been established | ||
| * @param {*} failure function to be invoked if an RTT connection is not established | ||
| * @returns if RTT is already enabled | ||
| */ | ||
| exports.enableRTT = (context, success, failure) => { | ||
| disconnectedWithReason = false | ||
| if(exports.rttIsEnabled() || connectionStatus == connectionState.CONNECTING){ | ||
| console.log("RTT is already connected/connecting") | ||
| return; | ||
| } | ||
| else{ | ||
| connectCallback = { | ||
| success: success, | ||
| failure: failure | ||
| } | ||
| connectionStatus = connectionState.CONNECTING | ||
| requestClientConnection(context, (context, result) => { | ||
| if (context.logEnabled) { | ||
| console.log(JSON.stringify(result)) | ||
| } | ||
| if (result.status == 200) { | ||
| for (var i = 0; i < result.data.endpoints.length; ++i) { | ||
| var endpoint = result.data.endpoints[i]; | ||
| if (endpoint.protocol === "ws") { | ||
| appId = context.appId | ||
| sessionId = context.sessionId | ||
| connect(endpoint.host, endpoint.port, result.data.auth, endpoint.ssl); | ||
| return; | ||
| } | ||
| } | ||
| // We didn't find websocket endpoint | ||
| result.status = 0; | ||
| result.status_message = "WebSocket endpoint missing"; | ||
| connectionStatus = connectionState.DISCONNECTED; | ||
| connectCallback.failure(result); | ||
| } | ||
| else { | ||
| connectionStatus = connectionState.DISCONNECTED; | ||
| connectCallback.failure(result); | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| /** | ||
| * Disables the RTT connection. | ||
| * @returns if RTT is not enabled | ||
| */ | ||
| exports.disableRTT = () => { | ||
| if(!(exports.rttIsEnabled()) || connectionStatus == connectionState.DISCONNECTING){ | ||
| console.log("RTT is not enabled") | ||
| return; | ||
| } | ||
| else{ | ||
| connectionStatus = connectionState.DISCONNECTING | ||
| if(heartbeatId){ | ||
| clearInterval(heartbeatId) | ||
| heartbeatId = null | ||
| } | ||
| if (socket) { | ||
| socket.removeEventListener('error', onSocketError); | ||
| socket.removeEventListener('close', onSocketClose); | ||
| socket.removeEventListener('open', onSocketOpen); | ||
| socket.removeEventListener('message', onSocketMessage); | ||
| socket.close() | ||
| socket = null | ||
| } | ||
| connectionStatus = connectionState.DISCONNECTED | ||
| } | ||
| } | ||
| /** | ||
| * Returns whether or not RTT is enabled. | ||
| * @returns True if RTT is enabled | ||
| */ | ||
| exports.rttIsEnabled = () => { | ||
| return connectionStatus == connectionState.CONNECTED | ||
| } | ||
| /** | ||
| * Registers a callback for all RTT services | ||
| * @param {*} callback function to be invoked when receiving RTT updates | ||
| */ | ||
| exports.registerRTTRawCallback = (callback) => { | ||
| rttCallback = callback | ||
| } | ||
| /** | ||
| * Deregisters the RTT callback. | ||
| */ | ||
| exports.deregisterRTTRawCallback = () => { | ||
| rttCallback = null | ||
| } |
+53
-10
| var https = require('https') | ||
| var util = require('util') | ||
| RTT = require('./brainclouds2s-rtt') | ||
| // Constants | ||
@@ -52,3 +54,3 @@ const SERVER_SESSION_EXPIRED = 40365 // Error code for expired session | ||
| } | ||
| callCallback(callback, context, responseData) | ||
| callCallback(context, responseData, callback) | ||
| }) | ||
@@ -59,3 +61,3 @@ }).on("error", err => { | ||
| } | ||
| callCallback(callback, context, null) | ||
| callCallback(context, null, callback) | ||
| }) | ||
@@ -127,3 +129,3 @@ | ||
| callCallback(callback, context, message) | ||
| callCallback(context, message, callback) | ||
| } | ||
@@ -133,3 +135,3 @@ else { | ||
| exports.disconnect(context) | ||
| callCallback(callback, context, null) | ||
| callCallback(context, null, callback) | ||
| } | ||
@@ -169,3 +171,3 @@ }) | ||
| if (request.callback) { | ||
| callCallback(request.callback, context, message); | ||
| callCallback(context, message, request.callback); | ||
| } | ||
@@ -196,8 +198,7 @@ } | ||
| if (data && data.messageResponses && data.messageResponses.length > 0) { | ||
| callCallback(callback, context, data.messageResponses[0]) | ||
| callCallback(context, data.messageResponses[0], callback) | ||
| } | ||
| else { | ||
| // Error that has no packets | ||
| callCallback(callback, context, data) | ||
| callCallback(context, data, callback) | ||
| } | ||
@@ -219,7 +220,7 @@ | ||
| * Invoke a given callback. | ||
| * @param callback Function to be executed | ||
| * @param context S2S context object | ||
| * @param data Content object to be sent | ||
| * @param callback Function to be executed | ||
| */ | ||
| function callCallback(callback, context, data) { | ||
| function callCallback(context, data, callback) { | ||
| if (callback != null) { | ||
@@ -325,1 +326,43 @@ try { | ||
| } | ||
| /** | ||
| * Attempts to establish an RTT connection to the brainCloud servers. | ||
| * @param {*} context object containing session data (appId, serverName, etc.) | ||
| * @param {*} success function to be invoked when an RTT connection has been established | ||
| * @param {*} failure function to be invoked if an RTT connection is not established | ||
| * @returns if RTT is already enabled | ||
| */ | ||
| exports.enableRTT = (context, success, failure) => { | ||
| RTT.enableRTT(context, success, failure) | ||
| } | ||
| /** | ||
| * Disables the RTT connection. | ||
| * @returns if RTT is not enabled | ||
| */ | ||
| exports.disableRTT = () => { | ||
| RTT.disableRTT() | ||
| } | ||
| /** | ||
| * Returns whether or not RTT is enabled. | ||
| * @returns True if RTT is enabled | ||
| */ | ||
| exports.rttIsEnabled = () => { | ||
| return RTT.rttIsEnabled() | ||
| } | ||
| /** | ||
| * Registers a callback for all RTT services | ||
| * @param {*} callback function to be invoked when receiving RTT updates | ||
| */ | ||
| exports.registerRTTRawCallback = (callback) => { | ||
| RTT.registerRTTRawCallback(callback) | ||
| } | ||
| /** | ||
| * Deregisters the RTT callback. | ||
| */ | ||
| exports.deregisterRTTRawCallback = () => { | ||
| RTT.deregisterRTTRawCallback() | ||
| } |
+6
-2
| { | ||
| "name": "brainclouds2s", | ||
| "version": "5.1.0", | ||
| "version": "5.2.0", | ||
| "description": "brianCloud S2S module", | ||
@@ -22,3 +22,7 @@ "main": "brainclouds2s.js", | ||
| }, | ||
| "homepage": "https://github.com/bitHeads/brainclouds2s-node#readme" | ||
| "homepage": "https://github.com/bitHeads/brainclouds2s-node#readme", | ||
| "dependencies": { | ||
| "ws": "^8.14.2", | ||
| "xmlhttprequest": "^1.8.0" | ||
| } | ||
| } |
+92
-1
| const fs = require('fs') | ||
| let S2S = require('./brainclouds2s.js') | ||
| let S2S = require('./brainclouds2s.js'); | ||
| /** | ||
| * Tests are running within NodeJS not a browser. | ||
| * | ||
| * As a result, we need to set up the global 'window' object and | ||
| * initialize the XMLHttpRequest, WebSocket and LocalStorage facilities. | ||
| */ | ||
| // Set up XMLHttpRequest. | ||
| XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; | ||
| window = { | ||
| XMLHttpRequest: XMLHttpRequest | ||
| }; | ||
| XMLHttpRequest.UNSENT = 0; | ||
| XMLHttpRequest.OPENED = 1; | ||
| XMLHttpRequest.HEADERS_RECEIVED = 2; | ||
| XMLHttpRequest.LOADING = 3; | ||
| XMLHttpRequest.DONE = 4; | ||
| // Set up WebSocket. | ||
| WebSocket = require('ws'); | ||
| var fail_log = []; | ||
@@ -433,2 +454,72 @@ var filters = process.argv[2]; | ||
| }) | ||
| await asyncTest("RTT", 4, () => { | ||
| let s2s = S2S.init(GAME_ID, SERVER_NAME, SERVER_SECRET, S2S_URL, false) | ||
| let channelID = GAME_ID + ":sy:mysyschannel" | ||
| let postChatJSON = { | ||
| service: "chat", | ||
| operation: "SYS_POST_CHAT_MESSAGE", | ||
| data: { | ||
| channelId: channelID, | ||
| content: { | ||
| text: "Hello World", | ||
| custom: { | ||
| somethingCustom: "wow" | ||
| } | ||
| }, | ||
| recordInHistory: false, | ||
| from: { | ||
| name: "Homer", | ||
| pic: "http://www.simpsons.test/homer.jpg" | ||
| } | ||
| } | ||
| } | ||
| let channelConnectJSON = { | ||
| service: "chat", | ||
| operation: "SYS_CHANNEL_CONNECT", | ||
| data: { | ||
| channelId: channelID, | ||
| maxReturn: 10 | ||
| } | ||
| } | ||
| let msgReceived = false | ||
| S2S.setLogEnabled(s2s, true) | ||
| S2S.authenticate(s2s, (s2s, result) => { | ||
| equal(result && result.status, 200, "Authenticate: " + JSON.stringify(result)) | ||
| S2S.enableRTT(s2s, onRTTEnabled, (error) => { | ||
| console.log("enable RTT failed " + JSON.stringify(error)) | ||
| resolve_test() | ||
| }) | ||
| }) | ||
| function onRTTEnabled() { | ||
| equal(S2S.rttIsEnabled(), true, "RTT enabled") | ||
| S2S.registerRTTRawCallback(onRTTCallbackReceived) | ||
| S2S.request(s2s, channelConnectJSON, onChannelConnectRequestSuccess) | ||
| } | ||
| function onChannelConnectRequestSuccess() { | ||
| S2S.request(s2s, postChatJSON, (s2s, result) => { | ||
| console.log("Post Chat Msg Req success") | ||
| }) | ||
| } | ||
| function onRTTCallbackReceived(message) { | ||
| if (message.service === "chat" && message.operation === "INCOMING") { | ||
| msgReceived = true | ||
| } | ||
| equal(msgReceived, true, "Received chat message - " + JSON.stringify(message)) | ||
| S2S.disableRTT() | ||
| equal(S2S.rttIsEnabled(), false, "RTT disabled") | ||
| resolve_test() | ||
| } | ||
| }) | ||
| } | ||
@@ -435,0 +526,0 @@ } |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
51113
43.62%6
20%1115
64.94%2
Infinity%+ Added
+ Added
+ Added
+ Added