Allow Multiple P2P Connections at once

plugins-allow-selecting-specific-detector
Moe 2024-05-25 13:22:13 -07:00
parent 1944831138
commit c10efb12f4
4 changed files with 115 additions and 84 deletions

View File

@ -8,6 +8,9 @@ let config = workerData.config
let lang = workerData.lang
let sslInfo = config.ssl || {}
let remoteConnectionPort = config.easyRemotePort || (sslInfo && sslInfo.port && (sslInfo.enabled !== false) ? sslInfo.port : config.port || 8080)
const multipleSelected = config.p2pHostMultiSelected instanceof Array && config.p2pHostMultiSelected.length > 0;
const p2pApiKey = config.p2pApiKey;
const p2pServerList = config.p2pServerList;
const net = require("net")
const bson = require('bson')
const WebSocket = require('cws')
@ -36,11 +39,11 @@ parentPort.on('message',(data) => {
break;
}
})
var socketCheckTimer = null
var heartbeatTimer = null
var heartBeatCheckTimout = null
var onClosedTimeout = null
let stayDisconnected = false
var socketCheckTimer = {}
var heartbeatTimer = {}
var heartBeatCheckTimout = {}
var onClosedTimeout = {}
let stayDisconnected = {}
const requestConnections = {}
const requestConnectionsData = {}
function getRequestConnection(requestId){
@ -48,29 +51,28 @@ function getRequestConnection(requestId){
write: () => {}
}
}
function clearAllTimeouts(){
clearInterval(heartbeatTimer)
clearTimeout(heartBeatCheckTimout)
clearTimeout(onClosedTimeout)
function clearAllTimeouts(p2pServerAddress){
clearInterval(heartbeatTimer[p2pServerAddress])
clearTimeout(heartBeatCheckTimout[p2pServerAddress])
clearTimeout(onClosedTimeout[p2pServerAddress])
}
function startConnection(p2pServerAddress,subscriptionId){
let tunnelToP2P
stayDisconnected = false
stayDisconnected[p2pServerAddress] = false
const allMessageHandlers = []
async function startWebsocketConnection(key,callback){
s.debugLog(`startWebsocketConnection EXECUTE`,new Error())
console.log('P2P : Connecting to Konekta P2P Server...')
function createWebsocketConnection(){
clearAllTimeouts()
return new Promise((resolve,reject) => {
try{
stayDisconnected = true
stayDisconnected[p2pServerAddress] = true
if(tunnelToP2P)tunnelToP2P.close()
}catch(err){
console.log(err)
}
tunnelToP2P = new WebSocket(p2pServerAddress);
stayDisconnected = false;
stayDisconnected[p2pServerAddress] = false;
tunnelToP2P.on('open', function(){
resolve(tunnelToP2P)
})
@ -81,7 +83,7 @@ function startConnection(p2pServerAddress,subscriptionId){
})
tunnelToP2P.on('close', () => {
console.log(`P2P Connection Closed!`)
clearAllTimeouts()
clearAllTimeouts(p2pServerAddress)
// onClosedTimeout = setTimeout(() => {
// disconnectedConnection();
// },5000)
@ -95,8 +97,8 @@ function startConnection(p2pServerAddress,subscriptionId){
})
}
clearInterval(socketCheckTimer)
socketCheckTimer = setInterval(() => {
clearInterval(socketCheckTimer[p2pServerAddress])
socketCheckTimer[p2pServerAddress] = setInterval(() => {
// s.debugLog('Tunnel Ready State :',tunnelToP2P.readyState)
if(tunnelToP2P.readyState !== 1){
s.debugLog('Tunnel NOT Ready! Reconnecting...')
@ -106,10 +108,10 @@ function startConnection(p2pServerAddress,subscriptionId){
})
}
function disconnectedConnection(code,reason){
s.debugLog('stayDisconnected',stayDisconnected)
s.debugLog('stayDisconnected',stayDisconnected[p2pServerAddress])
clearAllTimeouts()
s.debugLog('DISCONNECTED!')
if(stayDisconnected)return;
if(stayDisconnected[p2pServerAddress])return;
s.debugLog('RESTARTING!')
setTimeout(() => {
if(tunnelToP2P && tunnelToP2P.readyState !== 1)startWebsocketConnection()
@ -122,8 +124,8 @@ function startConnection(p2pServerAddress,subscriptionId){
subscriptionId: subscriptionId,
restrictedTo: config.p2pRestrictedTo || [],
})
clearInterval(heartbeatTimer)
heartbeatTimer = setInterval(() => {
clearInterval(heartbeatTimer[p2pServerAddress])
heartbeatTimer[p2pServerAddress] = setInterval(() => {
sendDataToTunnel({
f: 'ping',
})
@ -158,7 +160,7 @@ function startConnection(p2pServerAddress,subscriptionId){
// remotesocket.off('close')
// requestConnections[requestId].end()
// }
const responseTunnel = await getResponseTunnel(requestId)
const responseTunnel = await getResponseTunnel(requestId, p2pServerAddress)
let remotesocket = new net.Socket();
remotesocket.on('ready',() => {
remotesocket.write(initData.buffer)
@ -196,8 +198,8 @@ function startConnection(p2pServerAddress,subscriptionId){
}
}
function refreshHeartBeatCheck(){
clearTimeout(heartBeatCheckTimout)
heartBeatCheckTimout = setTimeout(() => {
clearTimeout(heartBeatCheckTimout[p2pServerAddress])
heartBeatCheckTimout[p2pServerAddress] = setTimeout(() => {
startWebsocketConnection()
},1000 * 10 * 1.5)
}
@ -304,15 +306,16 @@ function startConnection(p2pServerAddress,subscriptionId){
onIncomingMessage('disconnect',function(data,requestId){
console.log(`FAILED LICENSE CHECK ON P2P`)
const retryLater = data && data.retryLater;
stayDisconnected = !retryLater
stayDisconnected[p2pServerAddress] = !retryLater
if(retryLater)console.log(`Retrying P2P Later...`)
})
return tunnelToP2P;
}
const responseTunnels = {}
async function getResponseTunnel(originalRequestId){
return responseTunnels[originalRequestId] || await createResponseTunnel(originalRequestId)
async function getResponseTunnel(originalRequestId, p2pServerAddress){
return responseTunnels[originalRequestId] || await createResponseTunnel(originalRequestId, p2pServerAddress)
}
function createResponseTunnel(originalRequestId){
function createResponseTunnel(originalRequestId, p2pServerAddress){
const responseTunnelMessageHandlers = []
function onMessage(key,callback){
responseTunnelMessageHandlers.push({
@ -321,7 +324,7 @@ function createResponseTunnel(originalRequestId){
})
}
return new Promise((resolve,reject) => {
const responseTunnel = new WebSocket(config.selectedHost);
const responseTunnel = new WebSocket(p2pServerAddress);
function sendToResponseTunnel(data){
responseTunnel.send(
bson.serialize(data)
@ -374,10 +377,19 @@ function closeResponseTunnel(originalRequestId){
s.debugLog('closeResponseTunnel',err)
}
}
function initialize(){
const selectedP2PServerId = config.p2pServerList[config.p2pHostSelected] ? config.p2pHostSelected : Object.keys(config.p2pServerList)[0]
const p2pServerDetails = config.p2pServerList[selectedP2PServerId]
function initialize(p2pHostSelected){
const selectedP2PServerId = p2pServerList[p2pHostSelected] ? p2pHostSelected : Object.keys(p2pServerList)[0]
const p2pServerDetails = p2pServerList[selectedP2PServerId]
const selectedHost = `${p2pServerDetails.secure ? `wss` : 'ws'}://` + p2pServerDetails.host + ':' + p2pServerDetails.p2pPort
config.selectedHost = selectedHost
startConnection(selectedHost,config.p2pApiKey)
startConnection(selectedHost,p2pApiKey)
}
if(multipleSelected){
for(aSelection of config.p2pHostMultiSelected){
clearAllTimeouts(aSelection)
initialize(aSelection)
}
}else{
const singleSelection = config.p2pHostSelected;
clearAllTimeouts(singleSelection)
initialize(singleSelection)
}

View File

@ -35,6 +35,12 @@
#easyRemoteAccess .card.active .fa {
color: #6ee068;
}
#easyRemoteAccess .card .remote-dashboard-link {
display: none!important;
}
#easyRemoteAccess .card.active .remote-dashboard-link {
display: block!important;
}
#easyRemoteAccess .card .selected-badge {
display: none;
color: #fff!important;
@ -56,3 +62,7 @@
#p2pServerList .card .d-flex.flex-row:nth-of-type(odd) {
background: rgba(0,0,0,0.1)
}
#easyRemoteAccess .active .activate-remote-selection .fa-check:before {
content: "\f00d"!important;
}

View File

@ -7,7 +7,6 @@ $(document).ready(function(){
var remoteDashboardLinkButton = easyRemoteAccessTab.find('.remote-dashboard-link')
var loadingRegistration = false
var statusConnections = {}
var currentlyRegisteredP2PServer = currentlySelectedP2PServerId ? currentlySelectedP2PServerId + '' : undefined
function copyToClipboard(str) {
const el = document.createElement('textarea');
el.value = str;
@ -72,37 +71,11 @@ $(document).ready(function(){
loadingRegistration = false
easyRemoteAccessTab.find('.remote-dashboard-link').html(`<i class="fa fa-external-link"></i> ` + lang['Open Remote Dashboard'])
easyRemoteAccessTab.find('.remote-dashboard-link-copy').html(`<i class="fa fa-copy"></i> ` + lang['Copy Remote Link'])
displayCurrentlySelectedInternally()
}
function displayCurrentlySelectedInternally(){
var selectedServer = p2pServerList[currentlyRegisteredP2PServer]
if(selectedServer){
var key = selectedServer.key
var cardEl = easyRemoteAccessTab.find(`[drawn-id="${key}"]`)
easyRemoteAccessTab.find(`[drawn-id].selected`).removeClass('selected')
cardEl.addClass('selected')
setCurrentRemoteLink()
}
}
function makeHostLink(selectedServer,apiKey){
var href = `https://${selectedServer.host}:${selectedServer.webPort == 80 ? 443 : selectedServer.webPort}/s/${apiKey}/`
return href
}
function setCurrentRemoteLink(){
var apiKey = easyRemoteAccessForm.find('[name="p2pApiKey"]').val()
var selectedServer = p2pServerList[currentlyRegisteredP2PServer]
console.log(selectedServer,currentlySelectedP2PServerId,p2pServerList)
if(selectedServer && selectedServer.host){
var href = makeHostLink(selectedServer,apiKey)
remoteDashboardLinkButton.attr('href',href)
}else{
new PNotify({
type: 'warning',
title: lang['P2P Server Not Selected'],
text: lang.p2pServerNotSelectedText,
})
}
}
function beginAllStatusConnections(){
$.each(p2pServerList,function(key,server){
server.key = key
@ -127,6 +100,14 @@ $(document).ready(function(){
toggleAffected.hide()
}
}
function getSelectedServers(){
var theArray = [];
$(`[drawn-id].active`).each(function(){
var theKey = $(this).attr('drawn-id')
theArray.push(theKey)
})
return theArray
}
p2pEnabledSwitch.change(setVisibilityForList)
easyRemoteAccessTab.find('.submit').click(function(){
easyRemoteAccessForm.submit()
@ -135,39 +116,51 @@ $(document).ready(function(){
e.preventDefault()
var formValues = $(this).serializeObject()
disableForm()
formValues.p2pHostSelected = currentlySelectedP2PServerId
// formValues.p2pHostSelected = currentlySelectedP2PServerId
formValues.p2pHostMultiSelected = getSelectedServers()
console.log(formValues)
$.post(superApiPrefix + $user.sessionKey + '/p2p/save',{
data: JSON.stringify(formValues)
},function(data){
console.log(data)
if(data.ok){
currentlyRegisteredP2PServer = currentlySelectedP2PServerId + ''
new PNotify({
type: 'success',
title: lang['P2P Settings Applied'],
text: lang.p2pSettingsText1,
})
setCurrentRemoteLink()
setTimeout(enableForm,5000)
}
})
return false
})
easyRemoteAccessForm.on('click','[drawn-id]',function(){
easyRemoteAccessTab.on('click','.activate-remote-selection',function(e){
e.preventDefault()
var el = $(this)
var p2pServerId = el.attr('drawn-id')
easyRemoteAccessForm.find('[drawn-id]').removeClass('active')
el.addClass('active')
currentlySelectedP2PServerId = p2pServerId
var parent = el.parents('[drawn-id]')
var drawnId = parent.attr('drawn-id')
var alreadyActive = parent.hasClass('active')
var selectedServer = p2pServerList[drawnId]
var isWss = selectedServer.p2pPort == 443
console.log(selectedServer)
if(alreadyActive){
parent.removeClass('active')
}else{
parent.addClass('active')
const drawnIdToDisable = isWss ? drawnId.replace('-ssl','') : `${drawnId}-ssl`
console.log(drawnIdToDisable)
easyRemoteAccessTab.find(`[drawn-id="${drawnIdToDisable}"]`).removeClass('active')
}
return false;
})
easyRemoteAccessTab.on('click','.remote-dashboard-link-copy',function(e){
e.preventDefault()
if(!loadingRegistration){
var parent = $(this).parents('[drawn-id]')
var drawnId = parent.attr('drawn-id')
var apiKey = easyRemoteAccessForm.find('[name="p2pApiKey"]').val()
var selectedServer = p2pServerList[currentlyRegisteredP2PServer]
console.log(selectedServer,currentlySelectedP2PServerId,p2pServerList)
if(selectedServer && selectedServer.host){
var selectedServer = p2pServerList[drawnId]
if(parent.hasClass('active') && selectedServer && selectedServer.host){
var href = makeHostLink(selectedServer,apiKey)
copyToClipboard(href)
new PNotify({
@ -183,8 +176,24 @@ $(document).ready(function(){
})
}
}
e.stopPropagation()
return false;
})
easyRemoteAccessTab.on('click','.remote-dashboard-link',function(e){
e.preventDefault()
if(!loadingRegistration){
var parent = $(this).parents('[drawn-id]')
var drawnId = parent.attr('drawn-id')
var apiKey = easyRemoteAccessForm.find('[name="p2pApiKey"]').val()
var selectedServer = p2pServerList[drawnId]
console.log(selectedServer,parent.hasClass('active'),parent.length)
if(parent.hasClass('active') && selectedServer && selectedServer.host){
var href = makeHostLink(selectedServer,apiKey)
window.open(href, '_blank').focus();
}
}
e.stopPropagation()
return false;
})
setVisibilityForList()
displayCurrentlySelectedInternally()
})

View File

@ -1,5 +1,7 @@
<% const p2pServerList = config.p2pServerList || {}
const selectedServer = p2pServerList[config.p2pHostSelected]
<%
const p2pServerList = config.p2pServerList || {}
const selectedServers = config.p2pHostMultiSelected
const multipleSelected = selectedServers instanceof Array && selectedServers.length > 0;
%>
<style>
.epic-text-filter {
@ -19,8 +21,9 @@
</style>
<script>
window.p2pServerList = <%- JSON.stringify(p2pServerList) %>
window.multipleSelected = <%- multipleSelected %>
window.selectedServers = <%- JSON.stringify(selectedServers) %>
window.useBetterP2P = <%- !!config.useBetterP2P %>
window.currentlySelectedP2PServerId = `<%- config.p2pHostSelected %>`
</script>
<link rel="stylesheet" href="<%-window.libURL%>assets/css/super.easyRemoteAccess.css">
<form>
@ -40,12 +43,6 @@
<div class="form-group p2p-toggle-affected">
<input placeholder="<%-lang['P2P API Key']%>" class="form-control btn btn-dark text-left text-white" type="text" name="p2pApiKey" value="<%- config.p2pApiKey %>">
</div>
<div class="form-group p2p-toggle-affected">
<div class="btn-group d-flex flex-row">
<a target="_blank" href="#" class="flex-grow-1 btn btn-default remote-dashboard-link-copy"><i class="fa fa-copy"></i> <%- lang['Copy Remote Link'] %></a>
<a target="_blank" href="#" class="flex-grow-1 btn btn-info remote-dashboard-link" target="_blank"><i class="fa fa-external-link"></i> <%- lang['Open Remote Dashboard'] %></a>
</div>
</div>
<div class="btn-group d-flex flex-row">
<a href="#" class="submit flex-grow-1 btn btn-success"><i class="fa fa-check"></i> <%- lang.Save %></a>
</div>
@ -72,7 +69,7 @@
if(!config.useBetterP2P && details.v2)return;
%>
<div class="col-md-4">
<div class="card bg-dark cursor-pointer text-white mb-4 <% if(config.p2pHostSelected === key){ %>active<% } %>" drawn-id="<%- key %>">
<div class="card bg-dark cursor-pointer text-white mb-4 <% if((!multipleSelected && config.p2pHostSelected === key) || multipleSelected && selectedServers.indexOf(key) > -1){ %>active<% } %>" drawn-id="<%- key %>">
<div class="card-header" style="min-height:auto">
<span class="badge badge-sm badge-danger pull-right selected-badge"><%- lang.Selected %></span>
<span class="badge badge-sm badge-info name-badge"><%- details.name.toUpperCase() %></span>
@ -107,7 +104,11 @@
</div>
</div>
<div class="card-footer" style="min-height:auto">
<a class="btn badge badge-sm badge-warning geo-badge" target="_blank" href="<%- `https://www.google.ca/maps/@${details.location.lat},${details.location.lon},15z` %>"><i class="fa fa-map-marker"></i> <%- details.location.lat %>, <%- details.location.lon %></a>
<div>
<a target="_blank" href="#" class="d-block btn btn-default activate-remote-selection"><i class="fa fa-check"></i> <%- lang['Activate'] %></a>
<a target="_blank" href="#" class="d-block btn btn-default remote-dashboard-link-copy"><i class="fa fa-copy"></i> <%- lang['Copy Remote Link'] %></a>
<a target="_blank" href="#" class="d-block btn btn-info remote-dashboard-link" target="_blank"><i class="fa fa-external-link"></i> <%- lang['Open Remote Dashboard'] %></a>
</div>
</div>
</div>
</div>
@ -115,7 +116,6 @@
</div>
<div class="form-group p2p-toggle-affected">
<div class="btn-group d-flex flex-row">
<a target="_blank" href="#" class="flex-grow-1 btn btn-info remote-dashboard-link" target="_blank"><i class="fa fa-external-link"></i> <%- lang['Open Remote Dashboard'] %></a>
<a href="#" class="submit flex-grow-1 btn btn-success"><i class="fa fa-check"></i> <%- lang.Save %></a>
</div>
</div>