mirror of
https://git.hmsn.ink/kospo/helptalk/user.git
synced 2026-03-20 03:02:17 +09:00
first
This commit is contained in:
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
BIN
public/img/icon-192.e97f0a99.jpg
Normal file
BIN
public/img/icon-192.e97f0a99.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
BIN
public/img/icon.jpg
Normal file
BIN
public/img/icon.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
public/img/icon.png
Normal file
BIN
public/img/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
23
public/index.html
Normal file
23
public/index.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<link rel="manifest" href="<%= BASE_URL %>manifest.json" crossorigin="anonymous">
|
||||
<!-- <link href="../node_modules/simplebar/dist/simplebar.min.css" rel="stylesheet" type="text/css"> -->
|
||||
<title>KOSPO 헬프톡</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
|
||||
Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
22
public/js/shared-worker.js
Normal file
22
public/js/shared-worker.js
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
const clients = [];
|
||||
|
||||
self.onconnect = function(e) {
|
||||
console.log(1)
|
||||
const port = e.ports[0];
|
||||
clients.push(port)
|
||||
|
||||
port.onmessage = function(e) {
|
||||
const message = e.data;
|
||||
|
||||
clients.forEach(client => client.postMessage(message))
|
||||
}
|
||||
|
||||
port.isMaster = function() {
|
||||
clients.forEach(client => client.postMessage({tabId: port.tabId}))
|
||||
}
|
||||
|
||||
port.setMaster = function(tabId) {
|
||||
port.tabId = tabId;
|
||||
}
|
||||
}
|
||||
5232
public/js/sockjs.js
Normal file
5232
public/js/sockjs.js
Normal file
File diff suppressed because it is too large
Load Diff
492
public/js/stomp.js
Normal file
492
public/js/stomp.js
Normal file
@@ -0,0 +1,492 @@
|
||||
// Generated by CoffeeScript 1.7.1
|
||||
|
||||
/*
|
||||
Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0
|
||||
|
||||
Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/)
|
||||
Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
var Byte, Client, Frame, Stomp,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__slice = [].slice;
|
||||
|
||||
Byte = {
|
||||
LF: '\x0A',
|
||||
NULL: '\x00'
|
||||
};
|
||||
|
||||
Frame = (function () {
|
||||
var unmarshallSingle;
|
||||
|
||||
function Frame(command, headers, body) {
|
||||
this.command = command;
|
||||
this.headers = headers != null ? headers : {};
|
||||
this.body = body != null ? body : '';
|
||||
}
|
||||
|
||||
Frame.prototype.toString = function () {
|
||||
var lines, name, skipContentLength, value, _ref;
|
||||
lines = [this.command];
|
||||
skipContentLength = this.headers['content-length'] === false ? true : false;
|
||||
if (skipContentLength) {
|
||||
delete this.headers['content-length'];
|
||||
}
|
||||
_ref = this.headers;
|
||||
for (name in _ref) {
|
||||
if (!__hasProp.call(_ref, name)) continue;
|
||||
value = _ref[name];
|
||||
lines.push("" + name + ":" + value);
|
||||
}
|
||||
if (this.body && !skipContentLength) {
|
||||
lines.push("content-length:" + (Frame.sizeOfUTF8(this.body)));
|
||||
}
|
||||
lines.push(Byte.LF + this.body);
|
||||
return lines.join(Byte.LF);
|
||||
};
|
||||
|
||||
Frame.sizeOfUTF8 = function (s) {
|
||||
if (s) {
|
||||
return encodeURI(s).match(/%..|./g).length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
unmarshallSingle = function (data) {
|
||||
var body, chr, command, divider, headerLines, headers, i, idx, len, line, start, trim, _i, _j, _len, _ref,
|
||||
_ref1;
|
||||
divider = data.search(RegExp("" + Byte.LF + Byte.LF));
|
||||
headerLines = data.substring(0, divider).split(Byte.LF);
|
||||
command = headerLines.shift();
|
||||
headers = {};
|
||||
trim = function (str) {
|
||||
return str.replace(/^\s+|\s+$/g, '');
|
||||
};
|
||||
_ref = headerLines.reverse();
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
line = _ref[_i];
|
||||
idx = line.indexOf(':');
|
||||
headers[trim(line.substring(0, idx))] = trim(line.substring(idx + 1));
|
||||
}
|
||||
body = '';
|
||||
start = divider + 2;
|
||||
if (headers['content-length']) {
|
||||
len = parseInt(headers['content-length']);
|
||||
body = ('' + data).substring(start, start + len);
|
||||
} else {
|
||||
chr = null;
|
||||
for (i = _j = start, _ref1 = data.length; start <= _ref1 ? _j < _ref1 : _j > _ref1; i = start <= _ref1 ? ++_j : --_j) {
|
||||
chr = data.charAt(i);
|
||||
if (chr === Byte.NULL) {
|
||||
break;
|
||||
}
|
||||
body += chr;
|
||||
}
|
||||
}
|
||||
return new Frame(command, headers, body);
|
||||
};
|
||||
|
||||
Frame.unmarshall = function (datas) {
|
||||
var data;
|
||||
return (function () {
|
||||
var _i, _len, _ref, _results;
|
||||
_ref = datas.split(RegExp("" + Byte.NULL + Byte.LF + "*"));
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
data = _ref[_i];
|
||||
if ((data != null ? data.length : void 0) > 0) {
|
||||
_results.push(unmarshallSingle(data));
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
};
|
||||
|
||||
Frame.marshall = function (command, headers, body) {
|
||||
var frame;
|
||||
frame = new Frame(command, headers, body);
|
||||
return frame.toString() + Byte.NULL;
|
||||
};
|
||||
|
||||
return Frame;
|
||||
|
||||
})();
|
||||
|
||||
Client = (function () {
|
||||
var now;
|
||||
|
||||
function Client(ws) {
|
||||
this.ws = ws;
|
||||
this.ws.binaryType = "arraybuffer";
|
||||
this.counter = 0;
|
||||
this.connected = false;
|
||||
this.heartbeat = {
|
||||
outgoing: 10000,
|
||||
incoming: 10000
|
||||
};
|
||||
this.maxWebSocketFrameSize = 16 * 1024;
|
||||
this.subscriptions = {};
|
||||
}
|
||||
|
||||
Client.prototype.debug = function (message) {
|
||||
var _ref;
|
||||
return typeof window !== "undefined" && window !== null ? (_ref = window.console) != null ? _ref.log(message) : void 0 : void 0;
|
||||
};
|
||||
|
||||
now = function () {
|
||||
if (Date.now) {
|
||||
return Date.now();
|
||||
} else {
|
||||
return new Date().valueOf;
|
||||
}
|
||||
};
|
||||
|
||||
Client.prototype._transmit = function (command, headers, body) {
|
||||
var out;
|
||||
out = Frame.marshall(command, headers, body);
|
||||
if (typeof this.debug === "function") {
|
||||
this.debug(">>> " + out);
|
||||
}
|
||||
while (true) {
|
||||
if (out.length > this.maxWebSocketFrameSize) {
|
||||
this.ws.send(out.substring(0, this.maxWebSocketFrameSize));
|
||||
out = out.substring(this.maxWebSocketFrameSize);
|
||||
if (typeof this.debug === "function") {
|
||||
this.debug("remaining = " + out.length);
|
||||
}
|
||||
} else {
|
||||
return this.ws.send(out);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Client.prototype._setupHeartbeat = function (headers) {
|
||||
var serverIncoming, serverOutgoing, ttl, v, _ref, _ref1;
|
||||
if ((_ref = headers.version) !== Stomp.VERSIONS.V1_1 && _ref !== Stomp.VERSIONS.V1_2) {
|
||||
return;
|
||||
}
|
||||
_ref1 = (function () {
|
||||
var _i, _len, _ref1, _results;
|
||||
_ref1 = headers['heart-beat'].split(",");
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
_results.push(parseInt(v));
|
||||
}
|
||||
return _results;
|
||||
})(), serverOutgoing = _ref1[0], serverIncoming = _ref1[1];
|
||||
if (!(this.heartbeat.outgoing === 0 || serverIncoming === 0)) {
|
||||
ttl = Math.max(this.heartbeat.outgoing, serverIncoming);
|
||||
if (typeof this.debug === "function") {
|
||||
this.debug("send PING every " + ttl + "ms");
|
||||
}
|
||||
this.pinger = Stomp.setInterval(ttl, (function (_this) {
|
||||
return function () {
|
||||
_this.ws.send(Byte.LF);
|
||||
return typeof _this.debug === "function" ? _this.debug(">>> PING") : void 0;
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
if (!(this.heartbeat.incoming === 0 || serverOutgoing === 0)) {
|
||||
ttl = Math.max(this.heartbeat.incoming, serverOutgoing);
|
||||
if (typeof this.debug === "function") {
|
||||
this.debug("check PONG every " + ttl + "ms");
|
||||
}
|
||||
return this.ponger = Stomp.setInterval(ttl, (function (_this) {
|
||||
return function () {
|
||||
var delta;
|
||||
delta = now() - _this.serverActivity;
|
||||
if (delta > ttl * 2) {
|
||||
if (typeof _this.debug === "function") {
|
||||
_this.debug("did not receive server activity for the last " + delta + "ms");
|
||||
}
|
||||
return _this.ws.close();
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
};
|
||||
|
||||
Client.prototype._parseConnect = function () {
|
||||
var args, connectCallback, errorCallback, headers;
|
||||
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
||||
headers = {};
|
||||
switch (args.length) {
|
||||
case 2:
|
||||
headers = args[0], connectCallback = args[1];
|
||||
break;
|
||||
case 3:
|
||||
if (args[1] instanceof Function) {
|
||||
headers = args[0], connectCallback = args[1], errorCallback = args[2];
|
||||
} else {
|
||||
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3];
|
||||
break;
|
||||
default:
|
||||
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3], headers.host = args[4];
|
||||
}
|
||||
return [headers, connectCallback, errorCallback];
|
||||
};
|
||||
|
||||
Client.prototype.connect = function () {
|
||||
var args, errorCallback, headers, out;
|
||||
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
||||
out = this._parseConnect.apply(this, args);
|
||||
headers = out[0], this.connectCallback = out[1], errorCallback = out[2];
|
||||
if (typeof this.debug === "function") {
|
||||
this.debug("Opening Web Socket...");
|
||||
}
|
||||
this.ws.onmessage = (function (_this) {
|
||||
return function (evt) {
|
||||
var arr, c, client, data, frame, messageID, onreceive, subscription, _i, _len, _ref, _results;
|
||||
data = typeof ArrayBuffer !== 'undefined' && evt.data instanceof ArrayBuffer ? (arr = new Uint8Array(evt.data), typeof _this.debug === "function" ? _this.debug("--- got data length: " + arr.length) : void 0, ((function () {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = arr.length; _i < _len; _i++) {
|
||||
c = arr[_i];
|
||||
_results.push(String.fromCharCode(c));
|
||||
}
|
||||
return _results;
|
||||
})()).join('')) : evt.data;
|
||||
_this.serverActivity = now();
|
||||
if (data === Byte.LF) {
|
||||
if (typeof _this.debug === "function") {
|
||||
_this.debug("<<< PONG");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (typeof _this.debug === "function") {
|
||||
_this.debug("<<< " + data);
|
||||
}
|
||||
_ref = Frame.unmarshall(data);
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
frame = _ref[_i];
|
||||
switch (frame.command) {
|
||||
case "CONNECTED":
|
||||
if (typeof _this.debug === "function") {
|
||||
_this.debug("connected to server " + frame.headers.server);
|
||||
}
|
||||
_this.connected = true;
|
||||
_this._setupHeartbeat(frame.headers);
|
||||
_results.push(typeof _this.connectCallback === "function" ? _this.connectCallback(frame) : void 0);
|
||||
break;
|
||||
case "MESSAGE":
|
||||
subscription = frame.headers.subscription;
|
||||
onreceive = _this.subscriptions[subscription] || _this.onreceive;
|
||||
if (onreceive) {
|
||||
client = _this;
|
||||
messageID = frame.headers["message-id"];
|
||||
frame.ack = function (headers) {
|
||||
if (headers == null) {
|
||||
headers = {};
|
||||
}
|
||||
return client.ack(messageID, subscription, headers);
|
||||
};
|
||||
frame.nack = function (headers) {
|
||||
if (headers == null) {
|
||||
headers = {};
|
||||
}
|
||||
return client.nack(messageID, subscription, headers);
|
||||
};
|
||||
_results.push(onreceive(frame));
|
||||
} else {
|
||||
_results.push(typeof _this.debug === "function" ? _this.debug("Unhandled received MESSAGE: " + frame) : void 0);
|
||||
}
|
||||
break;
|
||||
case "RECEIPT":
|
||||
_results.push(typeof _this.onreceipt === "function" ? _this.onreceipt(frame) : void 0);
|
||||
break;
|
||||
case "ERROR":
|
||||
_results.push(typeof errorCallback === "function" ? errorCallback(frame) : void 0);
|
||||
break;
|
||||
default:
|
||||
_results.push(typeof _this.debug === "function" ? _this.debug("Unhandled frame: " + frame) : void 0);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
})(this);
|
||||
this.ws.onclose = (function (_this) {
|
||||
return function () {
|
||||
var msg;
|
||||
msg = "Whoops! Lost connection to " + _this.ws.url;
|
||||
if (typeof _this.debug === "function") {
|
||||
_this.debug(msg);
|
||||
}
|
||||
_this._cleanUp();
|
||||
return typeof errorCallback === "function" ? errorCallback(msg) : void 0;
|
||||
};
|
||||
})(this);
|
||||
return this.ws.onopen = (function (_this) {
|
||||
return function () {
|
||||
if (typeof _this.debug === "function") {
|
||||
_this.debug('Web Socket Opened...');
|
||||
}
|
||||
headers["accept-version"] = Stomp.VERSIONS.supportedVersions();
|
||||
headers["heart-beat"] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(',');
|
||||
return _this._transmit("CONNECT", headers);
|
||||
};
|
||||
})(this);
|
||||
};
|
||||
|
||||
Client.prototype.disconnect = function (disconnectCallback, headers) {
|
||||
if (headers == null) {
|
||||
headers = {};
|
||||
}
|
||||
this._transmit("DISCONNECT", headers);
|
||||
this.ws.onclose = null;
|
||||
this.ws.close();
|
||||
this._cleanUp();
|
||||
return typeof disconnectCallback === "function" ? disconnectCallback() : void 0;
|
||||
};
|
||||
|
||||
Client.prototype._cleanUp = function () {
|
||||
this.connected = false;
|
||||
if (this.pinger) {
|
||||
Stomp.clearInterval(this.pinger);
|
||||
}
|
||||
if (this.ponger) {
|
||||
return Stomp.clearInterval(this.ponger);
|
||||
}
|
||||
};
|
||||
|
||||
Client.prototype.send = function (destination, headers, body) {
|
||||
if (headers == null) {
|
||||
headers = {};
|
||||
}
|
||||
if (body == null) {
|
||||
body = '';
|
||||
}
|
||||
headers.destination = destination;
|
||||
return this._transmit("SEND", headers, body);
|
||||
};
|
||||
|
||||
Client.prototype.subscribe = function (destination, callback, headers) {
|
||||
var client;
|
||||
if (headers == null) {
|
||||
headers = {};
|
||||
}
|
||||
if (!headers.id) {
|
||||
headers.id = "sub-" + this.counter++;
|
||||
}
|
||||
headers.destination = destination;
|
||||
this.subscriptions[headers.id] = callback;
|
||||
this._transmit("SUBSCRIBE", headers);
|
||||
client = this;
|
||||
return {
|
||||
id: headers.id,
|
||||
unsubscribe: function () {
|
||||
return client.unsubscribe(headers.id);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Client.prototype.unsubscribe = function (id) {
|
||||
delete this.subscriptions[id];
|
||||
return this._transmit("UNSUBSCRIBE", {
|
||||
id: id
|
||||
});
|
||||
};
|
||||
|
||||
Client.prototype.begin = function (transaction) {
|
||||
var client, txid;
|
||||
txid = transaction || "tx-" + this.counter++;
|
||||
this._transmit("BEGIN", {
|
||||
transaction: txid
|
||||
});
|
||||
client = this;
|
||||
return {
|
||||
id: txid,
|
||||
commit: function () {
|
||||
return client.commit(txid);
|
||||
},
|
||||
abort: function () {
|
||||
return client.abort(txid);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Client.prototype.commit = function (transaction) {
|
||||
return this._transmit("COMMIT", {
|
||||
transaction: transaction
|
||||
});
|
||||
};
|
||||
|
||||
Client.prototype.abort = function (transaction) {
|
||||
return this._transmit("ABORT", {
|
||||
transaction: transaction
|
||||
});
|
||||
};
|
||||
|
||||
Client.prototype.ack = function (messageID, subscription, headers) {
|
||||
if (headers == null) {
|
||||
headers = {};
|
||||
}
|
||||
headers["message-id"] = messageID;
|
||||
headers.subscription = subscription;
|
||||
return this._transmit("ACK", headers);
|
||||
};
|
||||
|
||||
Client.prototype.nack = function (messageID, subscription, headers) {
|
||||
if (headers == null) {
|
||||
headers = {};
|
||||
}
|
||||
headers["message-id"] = messageID;
|
||||
headers.subscription = subscription;
|
||||
return this._transmit("NACK", headers);
|
||||
};
|
||||
|
||||
return Client;
|
||||
|
||||
})();
|
||||
|
||||
Stomp = {
|
||||
VERSIONS: {
|
||||
V1_0: '1.0',
|
||||
V1_1: '1.1',
|
||||
V1_2: '1.2',
|
||||
supportedVersions: function () {
|
||||
return '1.1,1.0';
|
||||
}
|
||||
},
|
||||
client: function (url, protocols) {
|
||||
var klass, ws;
|
||||
if (protocols == null) {
|
||||
protocols = ['v10.stomp', 'v11.stomp'];
|
||||
}
|
||||
klass = Stomp.WebSocketClass || WebSocket;
|
||||
ws = new klass(url, protocols);
|
||||
return new Client(ws);
|
||||
},
|
||||
over: function (ws) {
|
||||
return new Client(ws);
|
||||
},
|
||||
Frame: Frame
|
||||
};
|
||||
|
||||
if (typeof window !== "undefined" && window !== null) {
|
||||
Stomp.setInterval = function (interval, f) {
|
||||
return window.setInterval(f, interval);
|
||||
};
|
||||
|
||||
Stomp.clearInterval = function (id) {
|
||||
return window.clearInterval(id);
|
||||
};
|
||||
window.Stomp = Stomp;
|
||||
} else {
|
||||
Stomp.setInterval = function (interval, f) {
|
||||
return setInterval(f, interval);
|
||||
}
|
||||
Stomp.clearInterval = function (id) {
|
||||
return clearInterval(id);
|
||||
};
|
||||
self.Stomp = Stomp;
|
||||
}
|
||||
|
||||
}).call(this);
|
||||
26
public/manifest.json
Normal file
26
public/manifest.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "KOSPO 헬프톡",
|
||||
"id" : "helptalk",
|
||||
"start_url": "/",
|
||||
"display": "fullscreen",
|
||||
"display_override": ["window-controls-overlay"],
|
||||
"theme-color": "#FF0000",
|
||||
"protocol_handlers" : [
|
||||
{
|
||||
"protocol" : "web+helptalk",
|
||||
"url" : "/%s"
|
||||
}
|
||||
],
|
||||
"icons": [
|
||||
{
|
||||
"src": "/img/icon.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "/img/icon.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
]
|
||||
}
|
||||
202
public/service-worker.js
Normal file
202
public/service-worker.js
Normal file
@@ -0,0 +1,202 @@
|
||||
// eslint-disable-next-line no-undef
|
||||
importScripts(`/js/stomp.js`)
|
||||
// eslint-disable-next-line no-undef
|
||||
importScripts(`/js/sockjs.js`)
|
||||
|
||||
let sockJS;
|
||||
let stompClient;
|
||||
let reConnectAttempts = 0
|
||||
let maxReconnectAttempts = 3
|
||||
let messageList = []
|
||||
let connectLock = false;
|
||||
let lastHeartbeat = null;
|
||||
/*재귀 함수 변수*/
|
||||
let sendPing= null;
|
||||
/*소켓 연결 변수*/
|
||||
let subscribe = null;
|
||||
// 클라이언트 에게 메시지 전달
|
||||
async function hubToClients(message) {
|
||||
const allClients = await clients.matchAll({
|
||||
includeUncontrolled: true,
|
||||
type: 'window',
|
||||
});
|
||||
|
||||
allClients.forEach(client => {
|
||||
client.postMessage(message);
|
||||
});
|
||||
}
|
||||
|
||||
// 브라우저 종료시 소켓 연결 해지
|
||||
async function disConnectWebSocket(message) {
|
||||
console.log('disConnect', message)
|
||||
try {subscribe.unsubscribe()} catch (e) {}
|
||||
try {stompClient.disconnect()} catch (e) {}
|
||||
try {sockJS.close()} catch (e) {}
|
||||
sockJS = null
|
||||
stompClient = null
|
||||
|
||||
// 모든 클라이언트가 종료시 서비스워커 heartbeat 제거
|
||||
const allClients = await clients.matchAll({
|
||||
includeUncontrolled: true,
|
||||
type: 'window',
|
||||
});
|
||||
|
||||
if(allClients.length === 1) {
|
||||
clearInterval(sendPing)
|
||||
sendPing = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 브라우저 종료시 소켓 연결 해지
|
||||
async function kill() {
|
||||
console.log('service worker stompClient', stompClient)
|
||||
console.log('service worker sockJS', sockJS)
|
||||
clearInterval(sendPing)
|
||||
sendPing = null
|
||||
try {subscribe.unsubscribe()} catch (e) {}
|
||||
try {stompClient.disconnect()} catch (e) {}
|
||||
try {sockJS.close()} catch (e) {}
|
||||
stompClient = null;
|
||||
sockJS = null;
|
||||
}
|
||||
|
||||
// 웹소켓 연결 관리
|
||||
function connectWebSocket(message) {
|
||||
lastHeartbeat = Date.now();
|
||||
console.log('sockJSConn',typeof (sockJS))
|
||||
console.log('sockJSInfo',sockJS)
|
||||
if (sockJS === null || sockJS === undefined) {
|
||||
if(sockJS !== null && sockJS !== undefined) {
|
||||
if(sockJS.readyState && sockJS.readyState === WebSocket.OPEN) {
|
||||
try{subscribe.unsubscribe()} catch(e) {}
|
||||
try{stompClient.disconnect();} catch(e) {}
|
||||
try{sockJS.close();} catch(e) {}
|
||||
stompClient = null;
|
||||
sockJS = null;
|
||||
}
|
||||
}
|
||||
|
||||
sockJS = new WebSocket(`${message.url}/stomp/ws`);
|
||||
if (sockJS !== WebSocket.CLOSED && sockJS !== WebSocket.CLOSING) {
|
||||
stompClient = Stomp.over(sockJS);
|
||||
stompClient.heartbeat.outgoing = 20000;
|
||||
stompClient.heartbeat.incoming = 20000;
|
||||
stompClient.debug = (e) => {
|
||||
if (e.includes('ERROR') || e.includes('Exception') || e.includes('failed')) {
|
||||
console.error('STOMP error:', e, new Date().toString());
|
||||
}
|
||||
};
|
||||
|
||||
stompClient.connect({location: 'SW'}, function (frame) {
|
||||
console.log('message.sabun', message.sabun, stompClient)
|
||||
subscribe = stompClient.subscribe(`/exchange/user.exchange/user.${message.sabun}`, async (content) => {
|
||||
const payload = JSON.parse(content.body);
|
||||
console.log('servicew-usersubcribe', payload)
|
||||
|
||||
})
|
||||
console.log('hub connect()')
|
||||
if (sendPing == null) {
|
||||
sendPing = setInterval(() => {
|
||||
hubToClients({type: "PING"})
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
reConnectAttempts = 0;
|
||||
})
|
||||
}
|
||||
|
||||
const baseDelay = 500
|
||||
sockJS.onclose = (e) => {
|
||||
console.error('sockjs onclose', e);
|
||||
if (e.code !== 1000) {
|
||||
const delay = Math.min(baseDelay * Math.pow(2, reConnectAttempts), 5000)
|
||||
setTimeout(() => {
|
||||
hubReconnect()
|
||||
if (reConnectAttempts < maxReconnectAttempts) {
|
||||
reConnectAttempts++;
|
||||
} else {
|
||||
console.log('[Service Worker Hub] Max Reconnect attempts reached.')
|
||||
}
|
||||
}, delay)
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
console.log('socket is connected')
|
||||
}
|
||||
}
|
||||
|
||||
const hubReconnect = () => {
|
||||
try {subscribe.unsubscribe()} catch (e) {}
|
||||
try {stompClient.disconnect()} catch (e) {}
|
||||
try {sockJS.close()} catch (e) {}
|
||||
stompClient = null
|
||||
sockJS = null
|
||||
clearInterval(sendPing)
|
||||
sendPing = null;
|
||||
hubToClients({type:'RECONNECT'});
|
||||
lastHeartbeat = Date.now();
|
||||
}
|
||||
|
||||
// 서비스워커 설치
|
||||
self.addEventListener('install', (event) => {
|
||||
console.log('SW: Installing...');
|
||||
event.waitUntil(
|
||||
self.skipWaiting()
|
||||
);
|
||||
});
|
||||
|
||||
// 서비스워커 활성화
|
||||
this.addEventListener('activate', function activator(event) {
|
||||
console.log('activate!');
|
||||
event.waitUntil(
|
||||
self.clients.claim()
|
||||
);
|
||||
})
|
||||
|
||||
// 클라이언트로부터의 메시지 처리
|
||||
self.addEventListener('message', async (event) => {
|
||||
const message = event.data;
|
||||
switch (message.type) {
|
||||
case 'CONNECT':
|
||||
connectWebSocket(message);
|
||||
break;
|
||||
case 'CLOSE':
|
||||
disConnectWebSocket(message);
|
||||
break;
|
||||
case "KILL" :
|
||||
kill();
|
||||
break;
|
||||
case 'PONG' :
|
||||
if(typeof (stompClient) === "undefined") {
|
||||
hubReconnect()
|
||||
}
|
||||
break;
|
||||
case "WAKEUP" :
|
||||
if(typeof (stompClient) === "undefined") {
|
||||
if(!connectLock) {
|
||||
connectLock = true;
|
||||
hubReconnect()
|
||||
}
|
||||
} else {
|
||||
if(!connectLock) {
|
||||
hubToClients({type:"GETUP"})
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'RECONNECT_SUCCESS' :
|
||||
let suc = true;
|
||||
while (suc) {
|
||||
if (stompClient.connected) {
|
||||
connectLock = false;
|
||||
suc = false;
|
||||
}
|
||||
await sleep(100)
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
const sleep = (delay) => {
|
||||
return new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
Reference in New Issue
Block a user