Merge pull request #30 from RiV-chain/ie11

IE11 support, markup fixes, caching fixes
This commit is contained in:
Vadym Vikulin 2022-12-20 14:09:51 +02:00 committed by GitHub
commit eeae07c59b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 1609 additions and 51 deletions

View file

@ -24,6 +24,8 @@ build_script:
- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi.sh x86"
- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi-gui.sh x64"
- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi-gui.sh x86"
- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi-ie.sh x64"
- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi-ie.sh x86"
test: off

View file

@ -67,8 +67,8 @@ go-winres simply --file-version $PKGVERSION --file-description "RiV-mesh (c) CLI
cp *.syso cmd/meshctl
# Build Mesh!
[ "${PKGARCH}" == "x64" ] && GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ ./build
[ "${PKGARCH}" == "x86" ] && GOOS=windows GOARCH=386 CGO_ENABLED=1 CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ ./build
[ "${PKGARCH}" == "x64" ] && GOOS=windows GOARCH=amd64 CGO_ENABLED=0 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ ./build
[ "${PKGARCH}" == "x86" ] && GOOS=windows GOARCH=386 CGO_ENABLED=0 CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ ./build
[ "${PKGARCH}" == "arm" ] && GOOS=windows GOARCH=arm CGO_ENABLED=0 ./build
# Create the postinstall script
@ -95,12 +95,8 @@ then
fi
if [ $PKGARCH = "x64" ]; then
PKGWINTUNDLL=wintun/bin/amd64/wintun.dll
PKGWEBVIEWFILE=contrib/ui/mesh-ui/dll/x64/webview.dll
PKGWEBVIEWFILELOADER=contrib/ui/mesh-ui/dll/x64/WebView2Loader.dll
elif [ $PKGARCH = "x86" ]; then
PKGWINTUNDLL=wintun/bin/x86/wintun.dll
PKGWEBVIEWFILE=contrib/ui/mesh-ui/dll/x86/webview.dll
PKGWEBVIEWFILELOADER=contrib/ui/mesh-ui/dll/x86/WebView2Loader.dll
elif [ $PKGARCH = "arm" ]; then
PKGWINTUNDLL=wintun/bin/arm/wintun.dll
#elif [ $PKGARCH = "arm64" ]; then
@ -209,18 +205,6 @@ cat > wix.xml << EOF
DiskId="1"
Source="mesh-ui.exe"
KeyPath="yes" />
<File
Id="WebViewDllFile"
Name="webview.dll"
DiskId="1"
Source="${PKGWEBVIEWFILE}" />
<File
Id="WebViewLoaderFile"
Name="WebView2Loader.dll"
DiskId="1"
Source="${PKGWEBVIEWFILELOADER}" />
<File
Id="UiAssets"
Name="ui.zip"
@ -237,8 +221,7 @@ cat > wix.xml << EOF
DiskId="1"
Source="updateconfig.bat"
KeyPath="yes"/>
</Component>
</Component>
</Directory>
</Directory>
</Directory>
@ -272,7 +255,7 @@ cat > wix.xml << EOF
<CustomAction Id="LaunchApplication"
FileKey="MeshUI"
Impersonate="yes"
ExeCommand=""
ExeCommand=""
Return="asyncNoWait" />
<!-- Step 3: Include the custom action -->

321
contrib/msi/build-msi-ie.sh Normal file
View file

@ -0,0 +1,321 @@
#!/bin/sh
# This script generates an MSI file for Mesh for a given architecture. It
# needs to run on Windows within MSYS2 and Go 1.13 or later must be installed on
# the system and within the PATH. This is ran currently by Appveyor or GitHub Actions (see
# appveyor.yml in the repository root) for both x86 and x64.
#
# Author: Vadym Vikulin <vadym.vikulin@rivchain.org>
# Get arch from command line if given
PKGARCH=$1
if [ "${PKGARCH}" == "" ];
then
echo "tell me the architecture: x86, x64, arm or arm64"
exit 1
fi
# Get the rest of the repository history. This is needed within Appveyor because
# otherwise we don't get all of the branch histories and therefore the semver
# scripts don't work properly.
if [ "${APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH}" != "" ];
then
git fetch --all
git checkout ${APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH}
elif [ "${APPVEYOR_REPO_BRANCH}" != "" ];
then
git fetch --all
git checkout ${APPVEYOR_REPO_BRANCH}
fi
# Install prerequisites within MSYS2
pacman -S --needed --noconfirm unzip git curl
# Download the wix tools!
if [ ! -d wixbin ];
then
curl -LO https://wixtoolset.org/downloads/v3.14.0.6526/wix314-binaries.zip
if [ `md5sum wix314-binaries.zip | cut -f 1 -d " "` != "aecd655bb56238d48ef5254cd4dc958e" ];
then
echo "wix package didn't match expected checksum"
exit 1
fi
mkdir -p wixbin
unzip -o wix314-binaries.zip -d wixbin || (
echo "failed to unzip WiX"
exit 1
)
fi
# Build Mesh!
[ "${PKGARCH}" == "x64" ] && GOOS=windows GOARCH=amd64 CGO_ENABLED=0 ./build
[ "${PKGARCH}" == "x86" ] && GOOS=windows GOARCH=386 CGO_ENABLED=0 ./build
[ "${PKGARCH}" == "arm" ] && GOOS=windows GOARCH=arm CGO_ENABLED=0 ./build
[ "${PKGARCH}" == "arm64" ] && GOOS=windows GOARCH=arm64 CGO_ENABLED=0 ./build
# Create the postinstall script
cat > updateconfig.bat << EOF
if not exist %ALLUSERSPROFILE%\\RiV-mesh (
mkdir %ALLUSERSPROFILE%\\RiV-mesh
)
if not exist %ALLUSERSPROFILE%\\RiV-mesh\\mesh.conf (
if exist mesh.exe (
mesh.exe -genconf > %ALLUSERSPROFILE%\\RiV-mesh\\mesh.conf
)
)
EOF
# Work out metadata for the package info
PKGNAME=$(sh contrib/semver/name.sh)
PKGVERSION=$(sh contrib/msi/msversion.sh --bare)
PKGVERSIONMS=$(echo $PKGVERSION | tr - .)
PKGUIFOLDER=contrib/ui/mesh-ui/ui/
[ "${PKGARCH}" == "x64" ] && \
PKGGUID="5bcfdddd-66a7-4eb7-b5f7-4a7500dcc65d" PKGINSTFOLDER="ProgramFiles64Folder" || \
PKGGUID="cbf6ffa1-219e-4bb2-a0e5-74dbf1b58a45" PKGINSTFOLDER="ProgramFilesFolder"
PKGLICENSEFILE=LICENSE.rtf
# Download the Wintun driver
if [ ! -d wintun ];
then
curl -o wintun.zip https://www.wintun.net/builds/wintun-0.14.1.zip
unzip wintun.zip
fi
PKG_UI_ASSETS_ZIP=$(pwd)/ui.zip
( cd "$PKGUIFOLDER" && 7z a "$PKG_UI_ASSETS_ZIP" * )
PKG_UI_ASSETS_ZIP=ui.zip
if [ $PKGARCH = "x64" ]; then
PKGWINTUNDLL=wintun/bin/amd64/wintun.dll
elif [ $PKGARCH = "x86" ]; then
PKGWINTUNDLL=wintun/bin/x86/wintun.dll
elif [ $PKGARCH = "arm" ]; then
PKGWINTUNDLL=wintun/bin/arm/wintun.dll
elif [ $PKGARCH = "arm64" ]; then
PKGWINTUNDLL=wintun/bin/arm64/wintun.dll
else
echo "wasn't sure which architecture to get wintun for"
exit 1
fi
if [ $PKGNAME != "master" ]; then
PKGDISPLAYNAME="RiV-mesh Network (${PKGNAME} branch)"
else
PKGDISPLAYNAME="RiV-mesh Network"
fi
cat > mesh-ui-ie.js << EOF
var ie = new ActiveXObject("InternetExplorer.Application");
ie.AddressBar = false;
ie.MenuBar = false;
ie.ToolBar = false;
ie.height = 960
ie.width = 706
ie.resizable = false
ie.Visible = true;
ie.Navigate("http://localhost:19019");
EOF
# Generate the wix.xml file
cat > wix.xml << EOF
<?xml version="1.0" encoding="windows-1252"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product
Name="${PKGDISPLAYNAME}"
Id="*"
UpgradeCode="${PKGGUID}"
Language="1033"
Codepage="1252"
Version="${PKGVERSIONMS}"
Manufacturer="RiV-chain">
<Package
Id="*"
Keywords="Installer"
Description="RiV-mesh Network Installer"
Comments="RiV-mesh Network standalone router for Windows."
Manufacturer="RiV-chain"
InstallerVersion="200"
InstallScope="perMachine"
Languages="1033"
Compressed="yes"
SummaryCodepage="1252"/>
<MajorUpgrade
AllowDowngrades="yes" />
<Media
Id="1"
Cabinet="Media.cab"
EmbedCab="yes"
CompressionLevel="high" />
<Icon Id="RiVIcon" SourceFile="riv.ico"/>
<Property Id="ARPPRODUCTICON" Value="RiVIcon" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="${PKGINSTFOLDER}" Name="PFiles">
<Directory Id="MeshInstallFolder" Name="RiV-mesh">
<Component Id="MainExecutable" Guid="c2119231-2aa3-4962-867a-9759c87beb24">
<File
Id="Mesh"
Name="mesh.exe"
DiskId="1"
Source="mesh.exe"
KeyPath="yes" />
<File
Id="IE_JS"
Name="mesh-ui-ie.js"
DiskId="1"
Source="mesh-ui-ie.js" />
<File
Id="Wintun"
Name="wintun.dll"
DiskId="1"
Source="${PKGWINTUNDLL}" />
<ServiceInstall
Id="ServiceInstaller"
Account="LocalSystem"
Description="RiV-mesh Network router process"
DisplayName="RiV-mesh Service"
ErrorControl="normal"
LoadOrderGroup="NetworkProvider"
Name="Mesh"
Start="auto"
Type="ownProcess"
Arguments='-useconffile "%ALLUSERSPROFILE%\\RiV-mesh\\mesh.conf" -logto "%ALLUSERSPROFILE%\\RiV-mesh\\mesh.log" -httpaddress "http://localhost:19019" -wwwroot "[MeshInstallFolder]ui.zip"'
Vital="yes" />
<ServiceControl
Id="MeshServiceControl"
Name="Mesh"
Start="install"
Stop="both"
Remove="uninstall" />
</Component>
<Component Id="CtrlExecutable" Guid="a916b730-974d-42a1-b687-d9d504cbb86a">
<File
Id="Meshctl"
Name="meshctl.exe"
DiskId="1"
Source="meshctl.exe"
KeyPath="yes"/>
</Component>
<Component Id="UIExecutable" Guid="ef9f30e0-8274-4526-835b-51bc09b5b1b7">
<File
Id="UiAssets"
Name="ui.zip"
DiskId="1"
Source="${PKG_UI_ASSETS_ZIP}" />
</Component>
<Component Id="ConfigScript" Guid="64a3733b-c98a-4732-85f3-20cd7da1a785">
<File
Id="Configbat"
Name="updateconfig.bat"
DiskId="1"
Source="updateconfig.bat"
KeyPath="yes"/>
</Component>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="RiV-mesh"/>
<Directory Id="DesktopFolder" Name="Desktop"/>
<Directory Id="StartupFolder" Name="Startup"/>
</Directory>
</Directory>
<CustomAction
Id="UpdateGenerateConfig"
Directory="MeshInstallFolder"
ExeCommand="cmd.exe /c updateconfig.bat"
Execute="deferred"
Return="check"
Impersonate="yes" />
<!-- Step 2: Add UI to your installer / Step 4: Trigger the custom action -->
<UI>
<UIRef Id="WixUI_Minimal" />
<Publish Dialog="ExitDialog"
Control="Finish"
Event="DoAction"
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
</UI>
<WixVariable Id="WixUILicenseRtf" Value="${PKGLICENSEFILE}" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch RiV-mesh" />
<CustomAction Id="LaunchApplication"
Directory="MeshInstallFolder"
ExeCommand="cscript.exe mesh-ui-ie.js"
Execute="immediate"
Return="asyncNoWait"
Impersonate="yes"/>
<!-- Step 3: Include the custom action -->
<Property Id="ASSISTANCE_START_VIA_REGISTRY">1</Property>
<InstallExecuteSequence>
<Custom
Action="UpdateGenerateConfig"
Before="StartServices">
NOT Installed AND NOT REMOVE
</Custom>
</InstallExecuteSequence>
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="ApplicationShortcut" Guid="e32e4d07-abf8-4c37-a2c3-1ca4b4f98adc" >
<Shortcut Id="ApplicationStartMenuShortcut"
Name="RiV-mesh"
Description="RiV-mesh is IoT E2E encrypted network"
Target="[%WINDIR]\System32\cscript.exe"
Arguments='"[MeshInstallFolder]mesh-ui-ie.js"'
WorkingDirectory="MeshInstallFolder"
Icon="RiVIcon"/>
<Shortcut Id="DesktopShortcut"
Name="RiV-mesh"
Description="RiV-mesh is IoT E2E encrypted network"
Directory="DesktopFolder"
Target="[%WINDIR]\System32\cscript.exe"
Arguments='"[MeshInstallFolder]mesh-ui-ie.js"'
WorkingDirectory="MeshInstallFolder"
Icon="RiVIcon"/>
<RemoveFolder Id="MeshInstallFolder" On="uninstall"/>
<RegistryValue Root="HKCU"
Key="Software\RiV-chain\RiV-mesh"
Name="installed"
Type="integer"
Value="1"
KeyPath="yes" />
<RegistryValue Id="MerAs.rst" Root="HKCU" Action="write"
Key="Software\Microsoft\Windows\CurrentVersion\Run"
Name="RiV-mesh client"
Type="string"
Value='"cscript.exe" "[MeshInstallFolder]mesh-ui-ie.js"' />
<Condition>ASSISTANCE_START_VIA_REGISTRY</Condition>
</Component>
</DirectoryRef>
<Feature Id="MeshFeature" Title="Mesh" Level="1">
<ComponentRef Id="MainExecutable" />
<ComponentRef Id="UIExecutable" />
<ComponentRef Id="CtrlExecutable" />
<ComponentRef Id="ApplicationShortcut" />
<ComponentRef Id="ConfigScript" />
</Feature>
</Product>
</Wix>
EOF
# Generate the MSI
CANDLEFLAGS="-nologo"
LIGHTFLAGS="-nologo -spdb -sice:ICE71 -sice:ICE61"
wixbin/candle $CANDLEFLAGS -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj -arch ${PKGARCH} wix.xml && \
wixbin/light $LIGHTFLAGS -ext WixUIExtension -ext WixUtilExtension.dll -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}-win7-ie.msi ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj

View file

@ -137,7 +137,7 @@ cat > wix.xml << EOF
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="${PKGINSTFOLDER}" Name="PFiles">
<Directory Id="MeshInstallFolder" Name="Mesh">
<Directory Id="MeshInstallFolder" Name="RiV-mesh">
<Component Id="MainExecutable" Guid="c2119231-2aa3-4962-867a-9759c87beb24">
<File

View file

@ -0,0 +1,420 @@
"use strict";
var $ = function $(id) {
return document.getElementById(id);
};
var $$ = function $$(clazz) {
return document.getElementsByClassName(clazz);
};
function setPingValue(peer, value) {
var cellText;
var peerCell = $(peer);
if (!peerCell) return;
var peerTable = $("peer_list");
if (value === "-1") {
var peerAddress = $("label_" + peer);
peerAddress.style.color = "rgba(250,250,250,.5)";
} else {
cellText = document.createTextNode(value);
peerCell.appendChild(cellText);
var peerCellTime = $("time_" + peer);
var cellTextTime = document.createTextNode("ms");
peerCellTime.appendChild(cellTextTime);
}
peerCell.parentNode.classList.remove("is-hidden");
//sort table
moveRowToOrderPos(peerTable, 2, peerCell.parentNode);
}
function cmpTime(a, b) {
return a.textContent.trim() === "" ? 1 : a.textContent.trim() // using `.textContent.trim()` for test
.localeCompare(b.textContent.trim(), 'en', { numeric: true });
}
function moveRowToOrderPos(table, col, row) {
var tb = table.tBodies[0],
tr = tb.rows;
var i = 0;
for (; i < tr.length && cmpTime(row.cells[col], tr[i].cells[col]) >= 0; ++i) {}
if (i < tr.length && i != row.rowIndex) {
tb.deleteRow(row.rowIndex);
tb.insertBefore(row, tr[i]);
}
}
function openTab(element, tabName) {
// Declare all variables
var i, tabContent, tabLinks;
// Get all elements with class="content" and hide them
tabContent = $$("tab here");
for (i = 0; i < tabContent.length; i++) {
tabContent[i].className = "tab here is-hidden";
}
// Get all elements with class="tab" and remove the class "is-active"
tabLinks = $$("tab is-active");
for (i = 0; i < tabLinks.length; i++) {
tabLinks[i].className = "tab";
}
// Show the current tab, and add an "is-active" class to the button that opened the tab
$(tabName).className = "tab here";
element.parentElement.className = "tab is-active";
//refreshRecordsList();
}
function copy2clipboard(text) {
var textArea = document.createElement("textarea");
textArea.style.position = 'fixed';
textArea.style.top = 0;
textArea.style.left = 0;
// Ensure it has a small width and height. Setting to 1px / 1em
// doesn't work as this gives a negative w/h on some browsers.
textArea.style.width = '2em';
textArea.style.height = '2em';
// We don't need padding, reducing the size if it does flash render.
textArea.style.padding = 0;
// Clean up any borders.
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';
// Avoid flash of the white box if rendered for any reason.
textArea.style.background = 'transparent';
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild(textArea);
showInfo('value copied successfully!');
}
function showInfo(text) {
var info = $("notification_info");
var message = $("info_text");
message.innerHTML = text;
info.className = "notification is-primary";
var button = $("info_close");
button.onclick = function () {
message.value = "";
info.className = "notification is-primary is-hidden";
};
setTimeout(button.onclick, 2000);
}
function showWindow(text) {
var info = $("notification_window");
var message = $("info_window");
message.innerHTML = text;
info.classList.remove("is-hidden");
var button_info_close = $("info_win_close");
button_info_close.onclick = function () {
message.value = "";
info.classList.add("is-hidden");
$("peer_list").remove();
};
var button_window_close = $("window_close");
button_window_close.onclick = function () {
message.value = "";
info.classList.add("is-hidden");
$("peer_list").remove();
};
var button_window_save = $("window_save");
button_window_save.onclick = function () {
message.value = "";
info.classList.add("is-hidden");
//todo save peers
var peers = document.querySelectorAll('*[id^="peer-"]');
var peer_list = [];
for (i = 0; i < peers.length; ++i) {
var p = peers[i];
if (p.checked) {
var peerURL = p.parentElement.parentElement.children[1].innerText;
peer_list.push(peerURL);
}
}
fetch('api/peers', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Riv-Save-Config': 'true'
},
body: JSON.stringify(peer_list)
}).catch(function (error) {
console.error('Error:', error);
});
$("peer_list").remove();
};
}
function add_table(peerList) {
var peers = [];
//const countries = Object.keys(peerList);
// get the reference for the body
var body = document.createElement("div");
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
tbl.setAttribute('id', "peer_list");
//tbl.setAttribute('cellpadding', '10');
var tblBody = document.createElement("tbody");
// creating all cells
for (var c in peerList) {
var counter = 1;
for (var peer in peerList[c]) {
peers.push(peer);
// creates a table row
var row = document.createElement("tr");
row.className = "is-hidden";
var imgElement = document.createElement("td");
imgElement.className = "big-flag fi fi-" + ui.lookupCountryCodeByAddress(peer);
var peerAddress = document.createElement("td");
var cellText = document.createTextNode(peer);
peerAddress.appendChild(cellText);
peerAddress.setAttribute('id', "label_" + peer);
var peerPing = document.createElement("td");
peerPing.setAttribute('id', peer);
var peerPingTime = document.createElement("td");
peerPingTime.setAttribute('id', "time_" + peer);
var peerSelect = document.createElement("td");
var chk = document.createElement('input');
chk.setAttribute('type', 'checkbox');
chk.setAttribute('id', "peer-" + counter);
peerSelect.appendChild(chk);
row.appendChild(imgElement);
row.appendChild(peerAddress);
row.appendChild(peerPing);
row.appendChild(peerPingTime);
row.appendChild(peerSelect);
tblBody.appendChild(row);
}
}
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
//tbl.setAttribute("border", "0");
showWindow(body.innerHTML);
return peers;
}
function togglePrivKeyVisibility() {
if (this.classList.contains("fa-eye")) {
this.classList.remove("fa-eye");
this.classList.add("fa-eye-slash");
$("priv_key_visible").innerHTML = $("priv_key").innerHTML;
} else {
this.classList.remove("fa-eye-slash");
this.classList.add("fa-eye");
$("priv_key_visible").innerHTML = "••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••";
}
}
function humanReadableSpeed(speed) {
var i = speed == 0 ? 0 : Math.floor(Math.log(speed) / Math.log(1024));
return (speed / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['Bps', 'kBps', 'MBps', 'GBps', 'TBps'][i];
}
var ui = ui || {
countries: []
};
ui.getAllPeers = function () {
if (!("_allPeersPromise" in ui)) {
ui._allPeersPromise = new Promise(function (resolve, reject) {
if ("_allPeers" in ui) resolve(ui._allPeers);else fetch('https://map.rivchain.org/rest/peers.json').then(function (response) {
return response.json();
}).then(function (data) {
var _loop = function _loop() {
var country = c.slice(0, -3);
var filtered = ui.countries.find(function (entry) {
return entry.name.toLowerCase() == country;
});
//let flagFile = filtered ? filtered["flag_4x3"] : "";
var flagCode = filtered ? filtered["code"] : "";
for (var peer in data[c]) {
data[c][peer].countryCode = flagCode;
}
};
// add country code to each peer
for (var c in data) {
_loop();
}
ui._allPeers = data;
resolve(ui._allPeers);
}).catch(reject);
}).finally(function () {
return delete ui._allPeersPromise;
});
}
return ui._allPeersPromise;
};
ui.showAllPeers = function () {
return ui.getAllPeers().then(function (peerList) {
var peers = add_table(peerList);
//start peers test
fetch('api/ping', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(peers)
}).catch(function (error) {
console.error('Error:', error);
});
}).catch(function (error) {
console.error(error);
});
};
ui.getConnectedPeers = function () {
return fetch('api/peers').then(function (response) {
return response.json();
});
};
var regexMulticast = /:\/\/\[fe80::/;
ui.updateConnectedPeersHandler = function (peers) {
$("peers").innerText = "";
var regexStrip = /%[^\]]*/gm;
var sorted = peers.map(function (peer) {
return { "url": peer["remote"], "isMulticast": peer["remote"].match(regexMulticast) };
}).sort(function (a, b) {
return a.isMulticast > b.isMulticast;
});
sorted.forEach(function (peer) {
var row = $("peers").appendChild(document.createElement('div'));
row.className = "overflow-ellipsis";
var flag = row.appendChild(document.createElement("span"));
if (peer.isMulticast) flag.className = "fa fa-thin fa-share-nodes peer-connected-fl";else flag.className = "fi fi-" + ui.lookupCountryCodeByAddress(peer.url) + " peer-connected-fl";
row.append(peer.url.replace(regexStrip, ""));
});
};
ui.updateStatus = function (peers) {
var status = "st-error";
if (peers) {
if (peers.length) {
var isNonMulticastExists = peers.filter(function (peer) {
return !peer["remote"].match(regexMulticast);
}).length;
status = isNonMulticastExists ? "st-multicast" : "st-connected";
} else {
status = "st-connecting";
}
}
Array.from($$("status")).forEach(function (node) {
return node.classList.add("is-hidden");
});
$(status).classList.remove("is-hidden");
};
ui.updateSpeed = function (peers) {
if (peers) {
var rsbytes = { "bytes_recvd": peers.reduce(function (acc, peer) {
return acc + peer.bytes_recvd;
}, 0),
"bytes_sent": peers.reduce(function (acc, peer) {
return acc + peer.bytes_sent;
}, 0),
"timestamp": Date.now() };
if ("_rsbytes" in ui) {
$("dn_speed").innerText = humanReadableSpeed((rsbytes.bytes_recvd - ui._rsbytes.bytes_recvd) * 1000 / (rsbytes.timestamp - ui._rsbytes.timestamp));
$("up_speed").innerText = humanReadableSpeed((rsbytes.bytes_sent - ui._rsbytes.bytes_sent) * 1000 / (rsbytes.timestamp - ui._rsbytes.timestamp));
}
ui._rsbytes = rsbytes;
} else {
delete ui._rsbytes;
$("dn_speed").innerText = "? Bs";
$("up_speed").innerText = "? Bs";
}
};
ui.updateConnectedPeers = function () {
return ui.getConnectedPeers().then(function (peers) {
ui.updateConnectedPeersHandler(peers);
ui.updateStatus(peers);
ui.updateSpeed(peers);
}).catch(function (error) {
$("peers").innerText = error.message;
ui.updateStatus();
ui.updateSpeed();
});
};
ui.lookupCountryCodeByAddress = function (address) {
for (var c in ui._allPeers) {
for (var peer in ui._allPeers[c]) {
if (peer == address) return ui._allPeers[c][peer].countryCode;
}
}
};
ui.getSelfInfo = function () {
return fetch('api/self').then(function (response) {
return response.json();
});
};
ui.updateSelfInfo = function () {
return ui.getSelfInfo().then(function (info) {
$("ipv6").innerText = info.address;
$("subnet").innerText = info.subnet;
$("pub_key").innerText = info.key;
$("priv_key").innerText = info.private_key;
$("ipv6").innerText = info.address;
$("version").innerText = info.build_version;
}).catch(function (error) {
$("ipv6").innerText = error.message;
});
};
ui.sse = new EventSource('/api/sse');
function main() {
window.addEventListener("load", function () {
$("showAllPeersBtn").addEventListener("click", ui.showAllPeers);
ui.getAllPeers().then(function () {
return ui.updateConnectedPeers();
});
setInterval(ui.updateConnectedPeers, 5000);
ui.updateSelfInfo();
//setInterval(ui.updateSelfInfo, 5000);
ui.sse.addEventListener("ping", function (e) {
var data = JSON.parse(e.data);
setPingValue(data.peer, data.value);
});
ui.sse.addEventListener("peers", function (e) {
ui.updateConnectedPeersHandler(JSON.parse(e.data));
});
});
}
main();

View file

@ -68,12 +68,9 @@ img {
display: block;
}
html, body {
height: 100vh;
}
body {
max-width: 690px;
min-width: 690px;
margin: auto;
}
@ -86,6 +83,13 @@ td.fi {
background-position: 0;
}
footer {
position:fixed;
bottom:0;
max-width: 690px;
margin-top: auto;
}
#footer-row td {
padding: 10px;
white-space: nowrap;

View file

@ -229,7 +229,7 @@ function humanReadableSpeed(speed) {
return (speed / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['Bps', 'kBps', 'MBps', 'GBps', 'TBps'][i];
}
var ui = {
var ui = ui || {
countries: []
};
@ -372,10 +372,6 @@ ui.sse = new EventSource('/api/sse');
function main() {
fetch('country.json')
.then((response) => response.json())
.then((data) => { ui.countries = data });
window.addEventListener("load", () => {
$("showAllPeersBtn").addEventListener("click", ui.showAllPeers);

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,6 @@
[
var ui = ui || {};
ui.countries = [
{
"capital": "Georgetown",
"code": "ac",

View file

@ -11,11 +11,27 @@
<link rel="stylesheet" href="assets/bulmaswatch.min.css" type="text/css">
<link rel="stylesheet" href="assets/flag-icons.css" type="text/css">
<link rel="stylesheet" href="assets/mesh-ui.css" type="text/css">
<script type="application/javascript" src="assets/mesh-ui.js"></script>
<script type="application/javascript" src="country.json"></script>
<!--script type="application/javascript" src="assets/mesh-ui.js"></script-->
<script>
var script = document.createElement('script');
//load polyfills + EC5 for IE or usual for rest
if (window.document.documentMode) {
script.src = "assets/polyfills.js";
script.onload = function () {
var ec5 = document.createElement('script');
ec5.src = "assets/mesh-ui-es5.js";
document.head.appendChild(ec5);
};
} else {
script.src = "assets/mesh-ui.js";
}
document.head.appendChild(script);
</script>
</head>
<body>
<div class="container hero is-fullheight">
<body class="hero is-fullheight">
<div>
<div class="box is-hidden" id="notification_window">
<div style="z-index: 9;" class="notification is-primary">
<button class="delete" id="info_win_close"></button>
@ -53,7 +69,7 @@
preserveAspectRatio="xMidYMid meet" viewBox="0 0 42 42">
<path
d="M18.5 35.5l-8 2c-.48.04-1 .52-1 1v1c0 .5.47 1 1 1h20c.43 0 1-.41 1-1v-1c-.02-.52-.55-.98-1-1l-8-2h-4zm19-1c2.59 0 3-.529 3-3v-26c0-2.391-.55-3-3-3h-34c-2.43 0-3 .54-3 3v26c0 2.51.529 3 3 3h34zm-2-27v22h-30v-22h30z"
fill="white" />
fill="white" ></path>
</svg>
</span>
<span>My Node</span>
@ -67,8 +83,8 @@
style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);"
preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32">
<g fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M5 15v15h22V15zm4 0C9 9 9 5 16 5s7 4 7 10m-7 5v3" />
<circle cx="16" cy="24" r="1" />
<path d="M5 15v15h22V15zm4 0C9 9 9 5 16 5s7 4 7 10m-7 5v3" ></path>
<circle cx="16" cy="24" r="1" ></circle>
</g>
</svg>
</span>
@ -82,10 +98,10 @@
focusable="false" width="1em" height="1em"
style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);"
preserveAspectRatio="xMidYMid meet" viewBox="0 0 48 48">
<path fill="#2196F3" d="M37 40H11l-6 6V12c0-3.3 2.7-6 6-6h26c3.3 0 6 2.7 6 6v22c0 3.3-2.7 6-6 6z" />
<path fill="#2196F3" d="M37 40H11l-6 6V12c0-3.3 2.7-6 6-6h26c3.3 0 6 2.7 6 6v22c0 3.3-2.7 6-6 6z" ></path>
<g fill="#fff">
<path d="M22 20h4v11h-4z" />
<circle cx="24" cy="15" r="2" />
<path d="M22 20h4v11h-4z" ></path>
<circle cx="24" cy="15" r="2" ></circle>
</g>
</svg>
</span>
@ -165,7 +181,8 @@
</div>
</div>
<footer class="is-flex-align-items-flex-end" style="margin-top: auto">
</div>
<footer>
<hr style="margin: 0px;background-color: #5d656d;">
<table class="content"><tr id="footer-row">
<td id="version">v123456</td>
@ -181,6 +198,4 @@
</tr></table>
</footer>
</div>
</html>

View file

@ -5,7 +5,7 @@ import (
"os"
"github.com/RiV-chain/RiV-mesh/src/defaults"
"github.com/webview/webview"
"github.com/jchv/go-webview-selector"
"github.com/docopt/docopt-go"
)

7
go.mod
View file

@ -23,6 +23,12 @@ require (
require gerace.dev/zipfs v0.2.0
require (
github.com/jchv/go-webview-selector v0.0.0-20220126075917-13df59bce3cf // indirect
github.com/jchv/go-webview2 v0.0.0-20220126073738-2ea27096a5eb // indirect
github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 // indirect
)
require (
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/dustin/go-humanize v1.0.0 // indirect
@ -39,7 +45,6 @@ require (
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/webview/webview v0.0.0-20210330151455-f540d88dde4e
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.1 // indirect

10
go.sum
View file

@ -47,6 +47,12 @@ github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwM
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hjson/hjson-go v3.1.0+incompatible h1:DY/9yE8ey8Zv22bY+mHV1uk2yRy0h8tKhZ77hEdi0Aw=
github.com/hjson/hjson-go v3.1.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
github.com/jchv/go-webview-selector v0.0.0-20220126075917-13df59bce3cf h1:LfCNdIjo0pYj7ChAEkRZKPW/GKOzQLGqz/8CbDTxBvE=
github.com/jchv/go-webview-selector v0.0.0-20220126075917-13df59bce3cf/go.mod h1:RfUO9QcPUZ27qVS+rq9SYhhjsVNiolWwaIQdNjqFUsQ=
github.com/jchv/go-webview2 v0.0.0-20220126073738-2ea27096a5eb h1:oKKhiqJVbFqiPo+cj7zmY/R8AaOxgLQixUAOP/bKuRM=
github.com/jchv/go-webview2 v0.0.0-20220126073738-2ea27096a5eb/go.mod h1:/BNVc0Sw3Wj6Sz9uSxPwhCEUhhWs92hPde75K2YV24A=
github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 h1:pdFFlHXY9tZXmJz+tRSm1DzYEH4ebha7cffmm607bMU=
github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/kardianos/minwinsvc v1.0.2 h1:JmZKFJQrmTGa/WiW+vkJXKmfzdjabuEW4Tirj5lLdR0=
github.com/kardianos/minwinsvc v1.0.2/go.mod h1:LUZNYhNmxujx2tR7FbdxqYJ9XDDoCd3MQcl1o//FWl4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -93,8 +99,6 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/webview/webview v0.0.0-20210330151455-f540d88dde4e h1:z780M7mCrdt6KiICeW9SGirvQjxDlrVU+n99FO93nbI=
github.com/webview/webview v0.0.0-20210330151455-f540d88dde4e/go.mod h1:rpXAuuHgyEJb6kXcXldlkOjU6y4x+YcASKKXJNUhh0Y=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@ -136,8 +140,10 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210218145245-beda7e5e158e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View file

@ -254,10 +254,16 @@ func (a *AdminSocket) StartHttpServer(configFn string, nc *config.NodeConfig) {
a.log.Errorln("An error occurred parsing http address:", err)
return
}
addNoCacheHeaders := func(w http.ResponseWriter) {
w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Add("Pragma", "no-cache")
w.Header().Add("Expires", "0")
}
http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Following methods are allowed: getself, getpeers. litening"+u.Host)
})
http.HandleFunc("/api/self", func(w http.ResponseWriter, r *http.Request) {
addNoCacheHeaders(w)
switch r.Method {
case "GET":
w.Header().Add("Content-Type", "application/json")
@ -316,6 +322,7 @@ func (a *AdminSocket) StartHttpServer(configFn string, nc *config.NodeConfig) {
return nil
}
addNoCacheHeaders(w)
switch r.Method {
case "GET":
w.Header().Add("Content-Type", "application/json")
@ -365,6 +372,7 @@ func (a *AdminSocket) StartHttpServer(configFn string, nc *config.NodeConfig) {
})
http.HandleFunc("/api/sse", func(w http.ResponseWriter, r *http.Request) {
addNoCacheHeaders(w)
switch r.Method {
case "GET":
w.Header().Add("Content-Type", "text/event-stream")
@ -399,9 +407,7 @@ func (a *AdminSocket) StartHttpServer(configFn string, nc *config.NodeConfig) {
if docFs == "" {
var nocache = func(fs http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Add("Pragma", "no-cache")
w.Header().Add("Expires", "0")
addNoCacheHeaders(w)
fs.ServeHTTP(w, r)
}
}