Identity fingerprint in profile pop-up & Peer info pop-up
This commit is contained in:
parent
3681626c48
commit
01e593bbc5
@ -58,7 +58,7 @@ input[type="file"] {
|
|||||||
padding: 20px 70px;
|
padding: 20px 70px;
|
||||||
background-color: #2B2F31;
|
background-color: #2B2F31;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
font-size: 1.3em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
.popup_background {
|
.popup_background {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -117,6 +117,15 @@ input[type="file"] {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
.popup .session_info h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.popup .session_info p:first-of-type, .popup .session_info pre {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.popup .session_info p:nth-of-type(2) {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
.button_row {
|
.button_row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
@ -156,6 +165,13 @@ input[type="file"] {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
#me>div:hover p {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
#identity_fingerprint {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
#left_panel ul:last-of-type, #msg_log {
|
#left_panel ul:last-of-type, #msg_log {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
@ -233,6 +249,10 @@ input[type="file"] {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#chat_header>div:hover p {
|
||||||
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
#chat_header>div>p {
|
#chat_header>div>p {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
</main>
|
</main>
|
||||||
<script>
|
<script>
|
||||||
//replaced by web server
|
//replaced by web server
|
||||||
|
let identityFingerprint = "IDENTITY_FINGERPRINT";
|
||||||
let isIdentityProtected = IS_IDENTITY_PROTECTED;
|
let isIdentityProtected = IS_IDENTITY_PROTECTED;
|
||||||
let websocketPort = WEBSOCKET_PORT;
|
let websocketPort = WEBSOCKET_PORT;
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const ENTER_KEY_CODE = 13;
|
const ENTER_KEY_CODE = 13;
|
||||||
let identity_name = undefined;
|
let identityName = undefined;
|
||||||
let socket = null;
|
let socket = null;
|
||||||
let notificationAllowed = false;
|
let notificationAllowed = false;
|
||||||
let currentSessionId = -1;
|
let currentSessionId = -1;
|
||||||
@ -60,7 +60,7 @@ document.getElementById("delete_conversation").onclick = function() {
|
|||||||
}
|
}
|
||||||
document.getElementById("add_contact").onclick = function() {
|
document.getElementById("add_contact").onclick = function() {
|
||||||
socket.send("contact "+currentSessionId+" "+sessionsData.get(currentSessionId).name);
|
socket.send("contact "+currentSessionId+" "+sessionsData.get(currentSessionId).name);
|
||||||
sessionsData.get(currentSessionId).is_contact = true;
|
sessionsData.get(currentSessionId).isContact = true;
|
||||||
displayHeader();
|
displayHeader();
|
||||||
displaySessions();
|
displaySessions();
|
||||||
}
|
}
|
||||||
@ -78,9 +78,9 @@ document.getElementById("remove_contact").onclick = function() {
|
|||||||
button.onclick = function() {
|
button.onclick = function() {
|
||||||
socket.send("uncontact "+currentSessionId);
|
socket.send("uncontact "+currentSessionId);
|
||||||
let session = sessionsData.get(currentSessionId);
|
let session = sessionsData.get(currentSessionId);
|
||||||
session.is_contact = false;
|
session.isContact = false;
|
||||||
session.is_verified = false;
|
session.isVerified = false;
|
||||||
if (!session.is_online) {
|
if (!session.isOnline) {
|
||||||
sessionsData.delete(currentSessionId);
|
sessionsData.delete(currentSessionId);
|
||||||
msgHistory.get(currentSessionId).length = 0;
|
msgHistory.get(currentSessionId).length = 0;
|
||||||
}
|
}
|
||||||
@ -93,7 +93,44 @@ document.getElementById("remove_contact").onclick = function() {
|
|||||||
showPopup(mainDiv);
|
showPopup(mainDiv);
|
||||||
}
|
}
|
||||||
document.getElementById("verify").onclick = function() {
|
document.getElementById("verify").onclick = function() {
|
||||||
socket.send("fingerprints "+currentSessionId);
|
let session = sessionsData.get(currentSessionId);
|
||||||
|
if (typeof session !== "undefined") {
|
||||||
|
let mainDiv = document.createElement("div");
|
||||||
|
mainDiv.appendChild(generatePopupWarningTitle());
|
||||||
|
let instructions = document.createElement("p");
|
||||||
|
instructions.textContent = "Compare the following fingerprints by a trusted way of communication (such as real life) and be sure they match.";
|
||||||
|
mainDiv.appendChild(instructions);
|
||||||
|
let p_local = document.createElement("p");
|
||||||
|
p_local.textContent = "Local fingerprint:";
|
||||||
|
mainDiv.appendChild(p_local);
|
||||||
|
let pre_local = document.createElement("pre");
|
||||||
|
pre_local.textContent = beautifyFingerprint(identityFingerprint);
|
||||||
|
mainDiv.appendChild(pre_local);
|
||||||
|
let p_peer = document.createElement("p");
|
||||||
|
p_peer.textContent = "Peer fingerprint:";
|
||||||
|
mainDiv.appendChild(p_peer);
|
||||||
|
let pre_peer = document.createElement("pre");
|
||||||
|
pre_peer.textContent = beautifyFingerprint(session.fingerprint);
|
||||||
|
mainDiv.appendChild(pre_peer);
|
||||||
|
let buttonRow = document.createElement("div");
|
||||||
|
buttonRow.classList.add("button_row");
|
||||||
|
let verifyButton = document.createElement("button");
|
||||||
|
verifyButton.textContent = "They match";
|
||||||
|
verifyButton.onclick = function() {
|
||||||
|
socket.send("verify "+currentSessionId);
|
||||||
|
sessionsData.get(currentSessionId).isVerified = true;
|
||||||
|
removePopup();
|
||||||
|
displayHeader();
|
||||||
|
displaySessions();
|
||||||
|
};
|
||||||
|
buttonRow.appendChild(verifyButton);
|
||||||
|
let cancelButton = document.createElement("button");
|
||||||
|
cancelButton.textContent = "They don't match";
|
||||||
|
cancelButton.onclick = removePopup;
|
||||||
|
buttonRow.appendChild(cancelButton);
|
||||||
|
mainDiv.appendChild(buttonRow);
|
||||||
|
showPopup(mainDiv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
document.getElementById("logout").onclick = function() {
|
document.getElementById("logout").onclick = function() {
|
||||||
let mainDiv = document.createElement("div");
|
let mainDiv = document.createElement("div");
|
||||||
@ -141,125 +178,9 @@ document.getElementById("attach_file").onchange = function(event) {
|
|||||||
document.getElementById("file_cancel").onclick = function() {
|
document.getElementById("file_cancel").onclick = function() {
|
||||||
socket.send("abort "+currentSessionId);
|
socket.send("abort "+currentSessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//source: https://stackoverflow.com/a/14919494
|
|
||||||
function humanFileSize(bytes, dp=1) {
|
|
||||||
const thresh = 1000;
|
|
||||||
if (Math.abs(bytes) < thresh) {
|
|
||||||
return bytes + ' B';
|
|
||||||
}
|
|
||||||
const units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
||||||
let u = -1;
|
|
||||||
const r = 10**dp;
|
|
||||||
do {
|
|
||||||
bytes /= thresh;
|
|
||||||
++u;
|
|
||||||
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
|
|
||||||
return bytes.toFixed(dp) + ' ' + units[u];
|
|
||||||
}
|
|
||||||
//source: https://www.w3schools.com/js/js_cookies.asp
|
|
||||||
function getCookie(cname) {
|
|
||||||
var name = cname + "=";
|
|
||||||
var decodedCookie = decodeURIComponent(document.cookie);
|
|
||||||
var ca = decodedCookie.split(';');
|
|
||||||
for(var i = 0; i <ca.length; i++) {
|
|
||||||
var c = ca[i];
|
|
||||||
while (c.charAt(0) == ' ') {
|
|
||||||
c = c.substring(1);
|
|
||||||
}
|
|
||||||
if (c.indexOf(name) == 0) {
|
|
||||||
return c.substring(name.length, c.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
socket = new WebSocket("ws://"+location.hostname+":"+websocketPort+"/ws");
|
|
||||||
socket.onopen = function() {
|
|
||||||
console.log("Connected");
|
|
||||||
socket.send(getCookie("aira_auth")); //authenticating websocket connection
|
|
||||||
window.onfocus = function() {
|
|
||||||
if (currentSessionId != -1) {
|
|
||||||
socket.send("set_seen "+currentSessionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Notification.permission === "granted") {
|
|
||||||
notificationAllowed = true;
|
|
||||||
} else if (Notification.permission !== "denied") {
|
|
||||||
Notification.requestPermission().then(function (permission) {
|
|
||||||
if (permission === "granted") {
|
|
||||||
notificationAllowed = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
socket.onmessage = function(msg) {
|
|
||||||
if (typeof msg.data == "string") {
|
|
||||||
console.log("Message: "+msg.data);
|
|
||||||
let args = msg.data.split(" ");
|
|
||||||
switch (args[0]) {
|
|
||||||
case "disconnected":
|
|
||||||
onDisconnected(args[1]);
|
|
||||||
break;
|
|
||||||
case "new_session":
|
|
||||||
onNewSession(args[1], args[2] === "true", msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
|
||||||
break;
|
|
||||||
case "new_message":
|
|
||||||
onNewMessage(args[1], args[2] === "true", msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
|
||||||
break;
|
|
||||||
case "file":
|
|
||||||
onFileReceived(args[1], args[2], msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
|
||||||
break;
|
|
||||||
case "file_transfer":
|
|
||||||
onNewFileTransfer(args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
||||||
break;
|
|
||||||
case "ask_large_file":
|
|
||||||
onAskLargeFile(args[1], args[2], args[3], args[4]);
|
|
||||||
break;
|
|
||||||
case "file_accepted":
|
|
||||||
onFileAccepted(args[1]);
|
|
||||||
break;
|
|
||||||
case "aborted":
|
|
||||||
onFileAborted(args[1]);
|
|
||||||
break;
|
|
||||||
case "inc_file_transfer":
|
|
||||||
onIncFileTransfer(args[1], parseInt(args[2]));
|
|
||||||
break;
|
|
||||||
case "load_sent_msg":
|
|
||||||
onMsgLoad(args[1], args[2] === "true", msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
|
||||||
break;
|
|
||||||
case "load_sent_file":
|
|
||||||
onFileLoad(args[1], args[2] === "true", args[3], msg.data.slice(args[0].length+args[1].length+args[2].length+args[3].length+4));
|
|
||||||
break;
|
|
||||||
case "name_told":
|
|
||||||
onNameTold(args[1], msg.data.slice(args[0].length+args[1].length+2));
|
|
||||||
break;
|
|
||||||
case "is_contact":
|
|
||||||
onIsContact(args[1], args[2] === "true", msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
|
||||||
break;
|
|
||||||
case "not_seen":
|
|
||||||
setNotSeen(msg.data.slice(args[0].length+1));
|
|
||||||
break;
|
|
||||||
case "fingerprints":
|
|
||||||
onFingerprints(args[1], args[2]);
|
|
||||||
break;
|
|
||||||
case "set_name":
|
|
||||||
onNameSet(msg.data.slice(args[0].length+1));
|
|
||||||
break;
|
|
||||||
case "password_changed":
|
|
||||||
onPasswordChanged(args[1] === "true", args[2] === "true");
|
|
||||||
break;
|
|
||||||
case "logout":
|
|
||||||
logout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
socket.onclose = function() {
|
|
||||||
console.log("Disconnected");
|
|
||||||
}
|
|
||||||
let msg_log = document.getElementById("msg_log");
|
let msg_log = document.getElementById("msg_log");
|
||||||
msg_log.onscroll = function() {
|
msg_log.onscroll = function() {
|
||||||
if (sessionsData.get(currentSessionId).is_contact) {
|
if (sessionsData.get(currentSessionId).isContact) {
|
||||||
if (msg_log.scrollTop < 30) {
|
if (msg_log.scrollTop < 30) {
|
||||||
socket.send("load_msgs "+currentSessionId);
|
socket.send("load_msgs "+currentSessionId);
|
||||||
}
|
}
|
||||||
@ -268,14 +189,18 @@ msg_log.onscroll = function() {
|
|||||||
let profile_div = document.querySelector("#me>div");
|
let profile_div = document.querySelector("#me>div");
|
||||||
profile_div.onclick = function() {
|
profile_div.onclick = function() {
|
||||||
let mainDiv = document.createElement("div");
|
let mainDiv = document.createElement("div");
|
||||||
let avatar = generateAvatar(identity_name);
|
let avatar = generateAvatar(identityName);
|
||||||
mainDiv.appendChild(avatar);
|
mainDiv.appendChild(avatar);
|
||||||
|
let fingerprint = document.createElement("pre");
|
||||||
|
fingerprint.id = "identity_fingerprint";
|
||||||
|
fingerprint.textContent = beautifyFingerprint(identityFingerprint);
|
||||||
|
mainDiv.appendChild(fingerprint);
|
||||||
let sectionName = document.createElement("section");
|
let sectionName = document.createElement("section");
|
||||||
sectionName.textContent = "Name:";
|
sectionName.textContent = "Name:";
|
||||||
let inputName = document.createElement("input");
|
let inputName = document.createElement("input");
|
||||||
inputName.id = "new_name";
|
inputName.id = "new_name";
|
||||||
inputName.type = "text";
|
inputName.type = "text";
|
||||||
inputName.value = identity_name;
|
inputName.value = identityName;
|
||||||
sectionName.appendChild(inputName);
|
sectionName.appendChild(inputName);
|
||||||
let saveNameButton = document.createElement("button");
|
let saveNameButton = document.createElement("button");
|
||||||
saveNameButton.textContent = "Save";
|
saveNameButton.textContent = "Save";
|
||||||
@ -370,21 +295,167 @@ profile_div.onclick = function() {
|
|||||||
mainDiv.appendChild(sectionDelete);
|
mainDiv.appendChild(sectionDelete);
|
||||||
showPopup(mainDiv);
|
showPopup(mainDiv);
|
||||||
}
|
}
|
||||||
|
let chatHeader = document.getElementById("chat_header");
|
||||||
|
chatHeader.children[0].onclick = function() {
|
||||||
|
let session = sessionsData.get(currentSessionId);
|
||||||
|
if (typeof session !== "undefined") {
|
||||||
|
let mainDiv = document.createElement("div");
|
||||||
|
mainDiv.classList.add("session_info");
|
||||||
|
mainDiv.appendChild(generateAvatar(session.name));
|
||||||
|
let h2 = document.createElement("h2");
|
||||||
|
h2.textContent = session.name;
|
||||||
|
mainDiv.appendChild(h2);
|
||||||
|
let pFingerprint = document.createElement("p");
|
||||||
|
pFingerprint.textContent = "Fingerprint:";
|
||||||
|
mainDiv.appendChild(pFingerprint);
|
||||||
|
let pre = document.createElement("pre");
|
||||||
|
pre.textContent = ' '+beautifyFingerprint(session.fingerprint);
|
||||||
|
mainDiv.appendChild(pre);
|
||||||
|
if (session.isOnline) {
|
||||||
|
let pIp = document.createElement("p");
|
||||||
|
pIp.textContent = "IP: "+session.ip;
|
||||||
|
mainDiv.appendChild(pIp);
|
||||||
|
let pConnection = document.createElement("p");
|
||||||
|
pConnection.textContent = "Connection: ";
|
||||||
|
if (session.outgoing) {
|
||||||
|
pConnection.textContent += "outgoing";
|
||||||
|
} else {
|
||||||
|
pConnection.textContent += "incomming";
|
||||||
|
}
|
||||||
|
mainDiv.appendChild(pConnection);
|
||||||
|
}
|
||||||
|
showPopup(mainDiv);
|
||||||
|
}
|
||||||
|
}
|
||||||
document.querySelector("#refresher button").onclick = function() {
|
document.querySelector("#refresher button").onclick = function() {
|
||||||
socket.send("refresh");
|
socket.send("refresh");
|
||||||
}
|
}
|
||||||
|
|
||||||
function onNewSession(sessionId, outgoing, name) {
|
//source: https://stackoverflow.com/a/14919494
|
||||||
|
function humanFileSize(bytes, dp=1) {
|
||||||
|
const thresh = 1000;
|
||||||
|
if (Math.abs(bytes) < thresh) {
|
||||||
|
return bytes + ' B';
|
||||||
|
}
|
||||||
|
const units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
let u = -1;
|
||||||
|
const r = 10**dp;
|
||||||
|
do {
|
||||||
|
bytes /= thresh;
|
||||||
|
++u;
|
||||||
|
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
|
||||||
|
return bytes.toFixed(dp) + ' ' + units[u];
|
||||||
|
}
|
||||||
|
//source: https://www.w3schools.com/js/js_cookies.asp
|
||||||
|
function getCookie(cname) {
|
||||||
|
var name = cname + "=";
|
||||||
|
var decodedCookie = decodeURIComponent(document.cookie);
|
||||||
|
var ca = decodedCookie.split(';');
|
||||||
|
for(var i = 0; i <ca.length; i++) {
|
||||||
|
var c = ca[i];
|
||||||
|
while (c.charAt(0) == ' ') {
|
||||||
|
c = c.substring(1);
|
||||||
|
}
|
||||||
|
if (c.indexOf(name) == 0) {
|
||||||
|
return c.substring(name.length, c.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
socket = new WebSocket("ws://"+location.hostname+":"+websocketPort+"/ws");
|
||||||
|
socket.onopen = function() {
|
||||||
|
console.log("Connected");
|
||||||
|
socket.send(getCookie("aira_auth")); //authenticating websocket connection
|
||||||
|
window.onfocus = function() {
|
||||||
|
if (currentSessionId != -1) {
|
||||||
|
socket.send("set_seen "+currentSessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Notification.permission === "granted") {
|
||||||
|
notificationAllowed = true;
|
||||||
|
} else if (Notification.permission !== "denied") {
|
||||||
|
Notification.requestPermission().then(function (permission) {
|
||||||
|
if (permission === "granted") {
|
||||||
|
notificationAllowed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
socket.onmessage = function(msg) {
|
||||||
|
if (typeof msg.data == "string") {
|
||||||
|
console.log("Message: "+msg.data);
|
||||||
|
let args = msg.data.split(" ");
|
||||||
|
switch (args[0]) {
|
||||||
|
case "disconnected":
|
||||||
|
onDisconnected(args[1]);
|
||||||
|
break;
|
||||||
|
case "new_session":
|
||||||
|
onNewSession(args[1], args[2] === "true", args[3], args[4], msg.data.slice(args[0].length+args[1].length+args[2].length+args[3].length+args[4].length+5));
|
||||||
|
break;
|
||||||
|
case "new_message":
|
||||||
|
onNewMessage(args[1], args[2] === "true", msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
||||||
|
break;
|
||||||
|
case "file":
|
||||||
|
onFileReceived(args[1], args[2], msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
||||||
|
break;
|
||||||
|
case "file_transfer":
|
||||||
|
onNewFileTransfer(args[1], args[2], args[3], args[4], args[5], args[6]);
|
||||||
|
break;
|
||||||
|
case "ask_large_file":
|
||||||
|
onAskLargeFile(args[1], args[2], args[3], args[4]);
|
||||||
|
break;
|
||||||
|
case "file_accepted":
|
||||||
|
onFileAccepted(args[1]);
|
||||||
|
break;
|
||||||
|
case "aborted":
|
||||||
|
onFileAborted(args[1]);
|
||||||
|
break;
|
||||||
|
case "inc_file_transfer":
|
||||||
|
onIncFileTransfer(args[1], parseInt(args[2]));
|
||||||
|
break;
|
||||||
|
case "load_sent_msg":
|
||||||
|
onMsgLoad(args[1], args[2] === "true", msg.data.slice(args[0].length+args[1].length+args[2].length+3));
|
||||||
|
break;
|
||||||
|
case "load_sent_file":
|
||||||
|
onFileLoad(args[1], args[2] === "true", args[3], msg.data.slice(args[0].length+args[1].length+args[2].length+args[3].length+4));
|
||||||
|
break;
|
||||||
|
case "name_told":
|
||||||
|
onNameTold(args[1], msg.data.slice(args[0].length+args[1].length+2));
|
||||||
|
break;
|
||||||
|
case "is_contact":
|
||||||
|
onIsContact(args[1], args[2] === "true", args[3], msg.data.slice(args[0].length+args[1].length+args[2].length+args[3].length+4));
|
||||||
|
break;
|
||||||
|
case "not_seen":
|
||||||
|
setNotSeen(msg.data.slice(args[0].length+1));
|
||||||
|
break;
|
||||||
|
case "set_name":
|
||||||
|
onNameSet(msg.data.slice(args[0].length+1));
|
||||||
|
break;
|
||||||
|
case "password_changed":
|
||||||
|
onPasswordChanged(args[1] === "true", args[2] === "true");
|
||||||
|
break;
|
||||||
|
case "logout":
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socket.onclose = function() {
|
||||||
|
console.log("Disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onNewSession(sessionId, outgoing, fingerprint, ip, name) {
|
||||||
if (sessionsData.has(sessionId)) {
|
if (sessionsData.has(sessionId)) {
|
||||||
let session = sessionsData.get(sessionId);
|
let session = sessionsData.get(sessionId);
|
||||||
session.is_online = true;
|
session.isOnline = true;
|
||||||
session.outgoing = outgoing;
|
session.outgoing = outgoing;
|
||||||
|
session.ip = ip;
|
||||||
displaySessions();
|
displaySessions();
|
||||||
if (currentSessionId == sessionId) {
|
if (currentSessionId == sessionId) {
|
||||||
displayChatBottom();
|
displayChatBottom();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addSession(sessionId, name, outgoing, false, false, true);
|
addSession(sessionId, name, outgoing, fingerprint, ip, false, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onNameTold(sessionId, name) {
|
function onNameTold(sessionId, name) {
|
||||||
@ -401,14 +472,14 @@ function setNotSeen(str_sessionIds) {
|
|||||||
}
|
}
|
||||||
displaySessions();
|
displaySessions();
|
||||||
}
|
}
|
||||||
function onIsContact(sessionId, verified, name) {
|
function onIsContact(sessionId, verified, fingerprint, name) {
|
||||||
if (sessionsData.has(sessionId)) {
|
if (sessionsData.has(sessionId)) {
|
||||||
let session = sessionsData.get(sessionId);
|
let session = sessionsData.get(sessionId);
|
||||||
session.is_contact = true;
|
session.isContact = true;
|
||||||
session.is_verified = verified;
|
session.isVerified = verified;
|
||||||
onNameTold(sessionId, name);
|
onNameTold(sessionId, name);
|
||||||
} else {
|
} else {
|
||||||
addSession(sessionId, name, true, true, verified, false);
|
addSession(sessionId, name, undefined, fingerprint, undefined, true, verified, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onMsgOrFileReceived(sessionId, outgoing, body) {
|
function onMsgOrFileReceived(sessionId, outgoing, body) {
|
||||||
@ -556,63 +627,20 @@ function onFileLoad(sessionId, outgoing, uuid, fileName) {
|
|||||||
function onDisconnected(sessionId) {
|
function onDisconnected(sessionId) {
|
||||||
pendingFiles.delete(sessionId);
|
pendingFiles.delete(sessionId);
|
||||||
let session = sessionsData.get(sessionId);
|
let session = sessionsData.get(sessionId);
|
||||||
if (session.is_contact) {
|
if (session.isContact) {
|
||||||
session.is_online = false;
|
session.isOnline = false;
|
||||||
} else {
|
} else {
|
||||||
sessionsData.delete(sessionId);
|
sessionsData.delete(sessionId);
|
||||||
}
|
}
|
||||||
if (currentSessionId == sessionId) {
|
if (currentSessionId == sessionId) {
|
||||||
displayChatBottom();
|
displayChatBottom();
|
||||||
}
|
}
|
||||||
if (currentSessionId == sessionId && !session.is_contact) {
|
if (currentSessionId == sessionId && !session.isContact) {
|
||||||
currentSessionId = -1;
|
currentSessionId = -1;
|
||||||
document.getElementById("chat_header").classList.add("offline");
|
chatHeader.classList.add("offline");
|
||||||
}
|
}
|
||||||
displaySessions();
|
displaySessions();
|
||||||
}
|
}
|
||||||
function onFingerprints(local, peer) {
|
|
||||||
let beautifyFingerprints = function(f) {
|
|
||||||
for (let i=4; i<f.length; i+=5) {
|
|
||||||
f = f.slice(0, i)+" "+f.slice(i);
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
};
|
|
||||||
let mainDiv = document.createElement("div");
|
|
||||||
mainDiv.appendChild(generatePopupWarningTitle());
|
|
||||||
let instructions = document.createElement("p");
|
|
||||||
instructions.textContent = "Compare the following fingerprints by a trusted way of communication (such as real life) and be sure they match.";
|
|
||||||
mainDiv.appendChild(instructions);
|
|
||||||
let p_local = document.createElement("p");
|
|
||||||
p_local.textContent = "Local fingerprint:";
|
|
||||||
mainDiv.appendChild(p_local);
|
|
||||||
let pre_local = document.createElement("pre");
|
|
||||||
pre_local.textContent = beautifyFingerprints(local);
|
|
||||||
mainDiv.appendChild(pre_local);
|
|
||||||
let p_peer = document.createElement("p");
|
|
||||||
p_peer.textContent = "Peer fingerprint:";
|
|
||||||
mainDiv.appendChild(p_peer);
|
|
||||||
let pre_peer = document.createElement("pre");
|
|
||||||
pre_peer.textContent = beautifyFingerprints(peer);
|
|
||||||
mainDiv.appendChild(pre_peer);
|
|
||||||
let buttonRow = document.createElement("div");
|
|
||||||
buttonRow.classList.add("button_row");
|
|
||||||
let verifyButton = document.createElement("button");
|
|
||||||
verifyButton.textContent = "They match";
|
|
||||||
verifyButton.onclick = function() {
|
|
||||||
socket.send("verify "+currentSessionId);
|
|
||||||
sessionsData.get(currentSessionId).is_verified = true;
|
|
||||||
removePopup();
|
|
||||||
displayHeader();
|
|
||||||
displaySessions();
|
|
||||||
};
|
|
||||||
buttonRow.appendChild(verifyButton);
|
|
||||||
let cancelButton = document.createElement("button");
|
|
||||||
cancelButton.textContent = "They don't match";
|
|
||||||
cancelButton.onclick = removePopup;
|
|
||||||
buttonRow.appendChild(cancelButton);
|
|
||||||
mainDiv.appendChild(buttonRow);
|
|
||||||
showPopup(mainDiv);
|
|
||||||
}
|
|
||||||
function onFileReceived(sessionId, uuid, file_name) {
|
function onFileReceived(sessionId, uuid, file_name) {
|
||||||
msgHistory.get(sessionId).push([false, true, [uuid, file_name]]);
|
msgHistory.get(sessionId).push([false, true, [uuid, file_name]]);
|
||||||
onMsgOrFileReceived(sessionId, false, file_name);
|
onMsgOrFileReceived(sessionId, false, file_name);
|
||||||
@ -623,15 +651,15 @@ function onFileSent(sessionId, uuid, file_name) {
|
|||||||
dislayHistory();
|
dislayHistory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onNameSet(new_name) {
|
function onNameSet(newName) {
|
||||||
removePopup();
|
removePopup();
|
||||||
identity_name = new_name;
|
identityName = newName;
|
||||||
displayProfile();
|
displayProfile();
|
||||||
}
|
}
|
||||||
function onPasswordChanged(success, is_protected) {
|
function onPasswordChanged(success, isProtected) {
|
||||||
if (success) {
|
if (success) {
|
||||||
removePopup();
|
removePopup();
|
||||||
isIdentityProtected = is_protected;
|
isIdentityProtected = isProtected;
|
||||||
} else {
|
} else {
|
||||||
let input = document.querySelector("input[type=\"password\"]");
|
let input = document.querySelector("input[type=\"password\"]");
|
||||||
input.value = "";
|
input.value = "";
|
||||||
@ -640,29 +668,37 @@ function onPasswordChanged(success, is_protected) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSession(sessionId, name, outgoing, is_contact, is_verified, is_online) {
|
function beautifyFingerprint(f) {
|
||||||
|
for (let i=4; i<f.length; i+=5) {
|
||||||
|
f = f.slice(0, i)+" "+f.slice(i);
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
function addSession(sessionId, name, outgoing, fingerprint, ip, isContact, isVerified, isOnline) {
|
||||||
sessionsData.set(sessionId, {
|
sessionsData.set(sessionId, {
|
||||||
"name": name,
|
"name": name,
|
||||||
"outgoing": outgoing,
|
"outgoing": outgoing,
|
||||||
"is_contact": is_contact,
|
"fingerprint": fingerprint,
|
||||||
"is_verified": is_verified,
|
"ip": ip,
|
||||||
|
"isContact": isContact,
|
||||||
|
"isVerified": isVerified,
|
||||||
"seen": true,
|
"seen": true,
|
||||||
"is_online": is_online,
|
"isOnline": isOnline,
|
||||||
});
|
});
|
||||||
msgHistory.set(sessionId, []);
|
msgHistory.set(sessionId, []);
|
||||||
displaySessions();
|
displaySessions();
|
||||||
}
|
}
|
||||||
function displaySessions() {
|
function displaySessions() {
|
||||||
let online_sessions = document.getElementById("online_sessions");
|
let onlineSessions = document.getElementById("online_sessions");
|
||||||
online_sessions.innerHTML = "";
|
onlineSessions.innerHTML = "";
|
||||||
let offline_sessions = document.getElementById("offline_sessions");
|
let offlineSessions = document.getElementById("offline_sessions");
|
||||||
offline_sessions.innerHTML = "";
|
offlineSessions.innerHTML = "";
|
||||||
sessionsData.forEach(function (session, sessionId) {
|
sessionsData.forEach(function (session, sessionId) {
|
||||||
let session_element = generateSession(sessionId, session);
|
let sessionElement = generateSession(sessionId, session);
|
||||||
if (session.is_online) {
|
if (session.isOnline) {
|
||||||
online_sessions.appendChild(session_element);
|
onlineSessions.appendChild(sessionElement);
|
||||||
} else {
|
} else {
|
||||||
offline_sessions.appendChild(session_element) ;
|
offlineSessions.appendChild(sessionElement) ;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -671,26 +707,25 @@ function logout() {
|
|||||||
}
|
}
|
||||||
function displayProfile() {
|
function displayProfile() {
|
||||||
profile_div.innerHTML = "";
|
profile_div.innerHTML = "";
|
||||||
profile_div.appendChild(generateAvatar(identity_name));
|
profile_div.appendChild(generateAvatar(identityName));
|
||||||
let p = document.createElement("p");
|
let p = document.createElement("p");
|
||||||
p.textContent = identity_name;
|
p.textContent = identityName;
|
||||||
profile_div.appendChild(p);
|
profile_div.appendChild(p);
|
||||||
}
|
}
|
||||||
function displayHeader() {
|
function displayHeader() {
|
||||||
let chat_header = document.getElementById("chat_header");
|
chatHeader.children[0].innerHTML = "";
|
||||||
chat_header.children[0].innerHTML = "";
|
chatHeader.className = 0;
|
||||||
chat_header.className = 0;
|
|
||||||
let session = sessionsData.get(currentSessionId);
|
let session = sessionsData.get(currentSessionId);
|
||||||
if (typeof session === "undefined") {
|
if (typeof session === "undefined") {
|
||||||
chat_header.style.display = "none";
|
chatHeader.style.display = "none";
|
||||||
} else {
|
} else {
|
||||||
chat_header.children[0].appendChild(generateAvatar(session.name));
|
chatHeader.children[0].appendChild(generateAvatar(session.name));
|
||||||
chat_header.children[0].appendChild(generateName(session.name));
|
chatHeader.children[0].appendChild(generateName(session.name));
|
||||||
chat_header.style.display = "flex";
|
chatHeader.style.display = "flex";
|
||||||
if (session.is_contact) {
|
if (session.isContact) {
|
||||||
chat_header.classList.add("is_contact");
|
chatHeader.classList.add("is_contact");
|
||||||
if (session.is_verified) {
|
if (session.isVerified) {
|
||||||
chat_header.classList.add("is_verified");
|
chatHeader.classList.add("is_verified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -742,10 +777,10 @@ function generateSession(sessionId, session) {
|
|||||||
} else {
|
} else {
|
||||||
li.classList.add("incomming");
|
li.classList.add("incomming");
|
||||||
}
|
}
|
||||||
if (session.is_contact) {
|
if (session.isContact) {
|
||||||
li.classList.add("is_contact");
|
li.classList.add("is_contact");
|
||||||
}
|
}
|
||||||
if (session.is_verified) {
|
if (session.isVerified) {
|
||||||
li.classList.add("is_verified");
|
li.classList.add("is_verified");
|
||||||
}
|
}
|
||||||
if (!session.seen) {
|
if (!session.seen) {
|
||||||
@ -814,7 +849,7 @@ function displayChatBottom(speed = undefined) {
|
|||||||
if (typeof session === "undefined") {
|
if (typeof session === "undefined") {
|
||||||
msgBox.removeAttribute("style");
|
msgBox.removeAttribute("style");
|
||||||
} else {
|
} else {
|
||||||
if (session.is_online) {
|
if (session.isOnline) {
|
||||||
msgBox.style.display = "flex";
|
msgBox.style.display = "flex";
|
||||||
} else {
|
} else {
|
||||||
msgBox.removeAttribute("style");
|
msgBox.removeAttribute("style");
|
||||||
@ -873,7 +908,7 @@ function dislayHistory(scrollToBottom = true) {
|
|||||||
msgHistory.get(currentSessionId).forEach(entry => {
|
msgHistory.get(currentSessionId).forEach(entry => {
|
||||||
let name;
|
let name;
|
||||||
if (entry[0]) { //outgoing msg
|
if (entry[0]) { //outgoing msg
|
||||||
name = identity_name;
|
name = identityName;
|
||||||
} else {
|
} else {
|
||||||
name = sessionsData.get(currentSessionId).name;
|
name = sessionsData.get(currentSessionId).name;
|
||||||
}
|
}
|
||||||
|
30
src/main.rs
30
src/main.rs
@ -93,16 +93,25 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc<RwLo
|
|||||||
let session_manager = global_vars.read().unwrap().session_manager.clone();
|
let session_manager = global_vars.read().unwrap().session_manager.clone();
|
||||||
ui_connection.set_name(&session_manager.get_my_name());
|
ui_connection.set_name(&session_manager.get_my_name());
|
||||||
session_manager.list_contacts().into_iter().for_each(|contact|{
|
session_manager.list_contacts().into_iter().for_each(|contact|{
|
||||||
ui_connection.set_as_contact(contact.0, &contact.1, contact.2);
|
ui_connection.set_as_contact(contact.0, &contact.1, contact.2, &crypto::generate_fingerprint(&contact.3));
|
||||||
session_manager.last_loaded_msg_offsets.write().unwrap().insert(contact.0, 0);
|
session_manager.last_loaded_msg_offsets.write().unwrap().insert(contact.0, 0);
|
||||||
load_msgs(session_manager.clone(), &mut ui_connection, &contact.0);
|
load_msgs(session_manager.clone(), &mut ui_connection, &contact.0);
|
||||||
});
|
});
|
||||||
session_manager.sessions.read().unwrap().iter().for_each(|session| {
|
session_manager.sessions.read().unwrap().iter().for_each(|session| {
|
||||||
ui_connection.on_new_session(session.0, &session.1.name, session.1.outgoing, session.1.file_download.as_ref());
|
ui_connection.on_new_session(
|
||||||
|
session.0,
|
||||||
|
&session.1.name,
|
||||||
|
session.1.outgoing,
|
||||||
|
&crypto::generate_fingerprint(&session.1.peer_public_key),
|
||||||
|
session.1.ip,
|
||||||
|
session.1.file_download.as_ref()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
let not_seen = session_manager.list_not_seen();
|
{
|
||||||
if not_seen.len() > 0 {
|
let not_seen = session_manager.not_seen.read().unwrap();
|
||||||
ui_connection.set_not_seen(not_seen);
|
if not_seen.len() > 0 {
|
||||||
|
ui_connection.set_not_seen(not_seen.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
session_manager.get_saved_msgs().into_iter().for_each(|msgs| {
|
session_manager.get_saved_msgs().into_iter().for_each(|msgs| {
|
||||||
ui_connection.load_msgs(&msgs.0, &msgs.1);
|
ui_connection.load_msgs(&msgs.0, &msgs.1);
|
||||||
@ -181,13 +190,6 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc<RwLo
|
|||||||
Err(e) => print_error!(e)
|
Err(e) => print_error!(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"fingerprints" => {
|
|
||||||
let session_id: usize = args[1].parse().unwrap();
|
|
||||||
let (local, peer) = session_manager.get_public_keys(&session_id);
|
|
||||||
let local = crypto::generate_fingerprint(&local);
|
|
||||||
let peer = crypto::generate_fingerprint(&peer);
|
|
||||||
ui_connection.fingerprints(&local, &peer);
|
|
||||||
}
|
|
||||||
"verify" => {
|
"verify" => {
|
||||||
let session_id: usize = args[1].parse().unwrap();
|
let session_id: usize = args[1].parse().unwrap();
|
||||||
match session_manager.set_verified(&session_id) {
|
match session_manager.set_verified(&session_id) {
|
||||||
@ -509,9 +511,11 @@ fn index_not_logged_in(global_vars: &Arc<RwLock<GlobalVars>>) -> HttpResponse {
|
|||||||
async fn handle_index(req: HttpRequest) -> HttpResponse {
|
async fn handle_index(req: HttpRequest) -> HttpResponse {
|
||||||
let global_vars = req.app_data::<Data<Arc<RwLock<GlobalVars>>>>().unwrap();
|
let global_vars = req.app_data::<Data<Arc<RwLock<GlobalVars>>>>().unwrap();
|
||||||
if is_authenticated(&req) {
|
if is_authenticated(&req) {
|
||||||
|
let global_vars_read = global_vars.read().unwrap();
|
||||||
HttpResponse::Ok().body(
|
HttpResponse::Ok().body(
|
||||||
include_str!("frontend/index.html")
|
include_str!("frontend/index.html")
|
||||||
.replace("WEBSOCKET_PORT", &global_vars.read().unwrap().websocket_port.to_string())
|
.replace("IDENTITY_FINGERPRINT", &crypto::generate_fingerprint(&global_vars_read.session_manager.get_my_public_key()))
|
||||||
|
.replace("WEBSOCKET_PORT", &global_vars_read.websocket_port.to_string())
|
||||||
.replace("IS_IDENTITY_PROTECTED", &Identity::is_protected().unwrap().to_string())
|
.replace("IS_IDENTITY_PROTECTED", &Identity::is_protected().unwrap().to_string())
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,7 +9,7 @@ use session::Session;
|
|||||||
use ed25519_dalek::PUBLIC_KEY_LENGTH;
|
use ed25519_dalek::PUBLIC_KEY_LENGTH;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use platform_dirs::UserDirs;
|
use platform_dirs::UserDirs;
|
||||||
use crate::{constants, discovery, identity::{Contact, Identity}, utils::{get_unix_timestamp, get_not_used_path}, print_error};
|
use crate::{constants, crypto, discovery, identity::{Contact, Identity}, print_error, utils::{get_unix_timestamp, get_not_used_path}};
|
||||||
use crate::ui_interface::UiConnection;
|
use crate::ui_interface::UiConnection;
|
||||||
|
|
||||||
#[derive(Display, Debug, PartialEq, Eq)]
|
#[derive(Display, Debug, PartialEq, Eq)]
|
||||||
@ -19,7 +19,7 @@ pub enum SessionError {
|
|||||||
TransmissionCorrupted,
|
TransmissionCorrupted,
|
||||||
BufferTooLarge,
|
BufferTooLarge,
|
||||||
InvalidSessionId,
|
InvalidSessionId,
|
||||||
Unknown
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SessionCommand {
|
enum SessionCommand {
|
||||||
@ -55,7 +55,8 @@ pub struct LargeFileDownload {
|
|||||||
pub struct SessionData {
|
pub struct SessionData {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub outgoing: bool,
|
pub outgoing: bool,
|
||||||
peer_public_key: [u8; PUBLIC_KEY_LENGTH],
|
pub peer_public_key: [u8; PUBLIC_KEY_LENGTH],
|
||||||
|
pub ip: IpAddr,
|
||||||
sender: Sender<SessionCommand>,
|
sender: Sender<SessionCommand>,
|
||||||
pub file_download: Option<LargeFileDownload>,
|
pub file_download: Option<LargeFileDownload>,
|
||||||
}
|
}
|
||||||
@ -68,7 +69,7 @@ pub struct SessionManager {
|
|||||||
loaded_contacts: RwLock<HashMap<usize, Contact>>,
|
loaded_contacts: RwLock<HashMap<usize, Contact>>,
|
||||||
pub last_loaded_msg_offsets: RwLock<HashMap<usize, usize>>,
|
pub last_loaded_msg_offsets: RwLock<HashMap<usize, usize>>,
|
||||||
pub saved_msgs: Mutex<HashMap<usize, Vec<(bool, Vec<u8>)>>>,
|
pub saved_msgs: Mutex<HashMap<usize, Vec<(bool, Vec<u8>)>>>,
|
||||||
not_seen: RwLock<Vec<usize>>,
|
pub not_seen: RwLock<Vec<usize>>,
|
||||||
mdns_service: Mutex<Option<Service>>,
|
mdns_service: Mutex<Option<Service>>,
|
||||||
listener_stop_signal: Mutex<Option<Sender<()>>>,
|
listener_stop_signal: Mutex<Option<Sender<()>>>,
|
||||||
}
|
}
|
||||||
@ -480,6 +481,7 @@ impl SessionManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(mut session) = session {
|
if let Some(mut session) = session {
|
||||||
|
let ip = session.get_ip();
|
||||||
let mut is_contact = false;
|
let mut is_contact = false;
|
||||||
let session_data = {
|
let session_data = {
|
||||||
let mut sessions = session_manager.sessions.write().unwrap();
|
let mut sessions = session_manager.sessions.write().unwrap();
|
||||||
@ -493,9 +495,10 @@ impl SessionManager {
|
|||||||
if is_new_session && session_manager.is_identity_loaded() { //check if we didn't logged out during the handshake
|
if is_new_session && session_manager.is_identity_loaded() { //check if we didn't logged out during the handshake
|
||||||
let (sender, receiver) = mpsc::channel(32);
|
let (sender, receiver) = mpsc::channel(32);
|
||||||
let session_data = SessionData{
|
let session_data = SessionData{
|
||||||
name: session.get_ip(),
|
name: ip.to_string(),
|
||||||
outgoing,
|
outgoing,
|
||||||
peer_public_key,
|
peer_public_key,
|
||||||
|
ip,
|
||||||
sender: sender,
|
sender: sender,
|
||||||
file_download: None,
|
file_download: None,
|
||||||
};
|
};
|
||||||
@ -524,7 +527,7 @@ impl SessionManager {
|
|||||||
if let Some(session_data) = session_data {
|
if let Some(session_data) = session_data {
|
||||||
let (session_id, receiver) = session_data;
|
let (session_id, receiver) = session_data;
|
||||||
session_manager.with_ui_connection(|ui_connection| {
|
session_manager.with_ui_connection(|ui_connection| {
|
||||||
ui_connection.on_new_session(&session_id, &session.get_ip(), outgoing, None);
|
ui_connection.on_new_session(&session_id, &ip.to_string(), outgoing, &crypto::generate_fingerprint(&peer_public_key), ip, None);
|
||||||
});
|
});
|
||||||
if !is_contact {
|
if !is_contact {
|
||||||
match session.encrypt_and_send(&protocol::ask_name()).await {
|
match session.encrypt_and_send(&protocol::ask_name()).await {
|
||||||
@ -567,24 +570,14 @@ impl SessionManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_contacts(&self) -> Vec<(usize, String, bool)> {
|
pub fn list_contacts(&self) -> Vec<(usize, String, bool, [u8; PUBLIC_KEY_LENGTH])> {
|
||||||
self.loaded_contacts.read().unwrap().iter().map(|c| (*c.0, c.1.name.clone(), c.1.verified)).collect()
|
self.loaded_contacts.read().unwrap().iter().map(|c| (*c.0, c.1.name.clone(), c.1.verified, c.1.public_key)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_saved_msgs(&self) -> HashMap<usize, Vec<(bool, Vec<u8>)>> {
|
pub fn get_saved_msgs(&self) -> HashMap<usize, Vec<(bool, Vec<u8>)>> {
|
||||||
self.saved_msgs.lock().unwrap().clone()
|
self.saved_msgs.lock().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_peer_public_key(&self, session_id: &usize) -> Option<[u8; PUBLIC_KEY_LENGTH]> {
|
|
||||||
let sessions = self.sessions.read().unwrap();
|
|
||||||
let session = sessions.get(session_id)?;
|
|
||||||
Some(session.peer_public_key)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_not_seen(&self) -> Vec<usize> {
|
|
||||||
self.not_seen.read().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_seen(&self, session_id: usize, seen: bool) {
|
pub fn set_seen(&self, session_id: usize, seen: bool) {
|
||||||
let mut not_seen = self.not_seen.write().unwrap();
|
let mut not_seen = self.not_seen.write().unwrap();
|
||||||
if seen {
|
if seen {
|
||||||
@ -608,7 +601,7 @@ impl SessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_contact(&self, session_id: usize, name: String) -> Result<(), rusqlite::Error> {
|
pub fn add_contact(&self, session_id: usize, name: String) -> Result<(), rusqlite::Error> {
|
||||||
let contact = self.identity.read().unwrap().as_ref().unwrap().add_contact(name, self.get_peer_public_key(&session_id).unwrap())?;
|
let contact = self.identity.read().unwrap().as_ref().unwrap().add_contact(name, self.sessions.read().unwrap().get(&session_id).unwrap().peer_public_key)?;
|
||||||
self.loaded_contacts.write().unwrap().insert(session_id, contact);
|
self.loaded_contacts.write().unwrap().insert(session_id, contact);
|
||||||
self.last_loaded_msg_offsets.write().unwrap().insert(session_id, 0);
|
self.last_loaded_msg_offsets.write().unwrap().insert(session_id, 0);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -671,8 +664,8 @@ impl SessionManager {
|
|||||||
msgs
|
msgs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_public_keys(&self, session_id: &usize) -> ([u8; PUBLIC_KEY_LENGTH], [u8; PUBLIC_KEY_LENGTH]) {
|
pub fn get_my_public_key(&self) -> [u8; PUBLIC_KEY_LENGTH] {
|
||||||
(self.identity.read().unwrap().as_ref().unwrap().get_public_key(), self.loaded_contacts.read().unwrap().get(session_id).unwrap().public_key)
|
self.identity.read().unwrap().as_ref().unwrap().get_public_key()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_my_name(&self) -> String {
|
pub fn get_my_name(&self) -> String {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{io::ErrorKind, convert::TryInto};
|
use std::{convert::TryInto, io::ErrorKind, net::IpAddr};
|
||||||
use tokio::{net::TcpStream, io::{AsyncReadExt, AsyncWriteExt}};
|
use tokio::{net::TcpStream, io::{AsyncReadExt, AsyncWriteExt}};
|
||||||
use ed25519_dalek;
|
use ed25519_dalek;
|
||||||
use ed25519_dalek::{ed25519::signature::Signature, Verifier, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH};
|
use ed25519_dalek::{ed25519::signature::Signature, Verifier, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH};
|
||||||
@ -48,8 +48,8 @@ impl Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ip(&self) -> String {
|
pub fn get_ip(&self) -> IpAddr {
|
||||||
self.stream.peer_addr().unwrap().ip().to_string()
|
self.stream.peer_addr().unwrap().ip()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn socket_read(&mut self, buff: &mut [u8]) -> Result<usize, SessionError> {
|
async fn socket_read(&mut self, buff: &mut [u8]) -> Result<usize, SessionError> {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::net::TcpStream;
|
use std::net::{IpAddr, TcpStream};
|
||||||
use tungstenite::{WebSocket, protocol::Role, Message};
|
use tungstenite::{WebSocket, protocol::Role, Message};
|
||||||
use crate::{protocol, session_manager::LargeFileDownload};
|
use crate::{protocol, session_manager::LargeFileDownload};
|
||||||
|
|
||||||
mod ui_messages {
|
mod ui_messages {
|
||||||
use std::{iter::FromIterator, str::from_utf8};
|
use std::{iter::FromIterator, net::IpAddr, str::from_utf8};
|
||||||
use tungstenite::Message;
|
use tungstenite::Message;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use crate::{print_error, session_manager::{protocol, LargeFileDownload, FileState}, utils::to_uuid_bytes};
|
use crate::{print_error, session_manager::{protocol, LargeFileDownload, FileState}, utils::to_uuid_bytes};
|
||||||
@ -27,8 +27,8 @@ mod ui_messages {
|
|||||||
pub fn on_disconnected(session_id: &usize) -> Message {
|
pub fn on_disconnected(session_id: &usize) -> Message {
|
||||||
simple_event("disconnected", session_id)
|
simple_event("disconnected", session_id)
|
||||||
}
|
}
|
||||||
pub fn on_new_session(session_id: &usize, name: &str, outgoing: bool) -> Message {
|
pub fn on_new_session(session_id: &usize, name: &str, outgoing: bool, fingerprint: &str, ip: IpAddr) -> Message {
|
||||||
Message::from(format!("new_session {} {} {}", session_id, outgoing, name))
|
Message::from(format!("new_session {} {} {} {} {}", session_id, outgoing, fingerprint, ip, name))
|
||||||
}
|
}
|
||||||
pub fn on_file_received(session_id: &usize, buffer: &[u8]) -> Option<Message> {
|
pub fn on_file_received(session_id: &usize, buffer: &[u8]) -> Option<Message> {
|
||||||
let uuid = Uuid::from_bytes(to_uuid_bytes(&buffer[1..17])?);
|
let uuid = Uuid::from_bytes(to_uuid_bytes(&buffer[1..17])?);
|
||||||
@ -98,11 +98,8 @@ mod ui_messages {
|
|||||||
pub fn on_name_told(session_id: &usize, name: &str) -> Message {
|
pub fn on_name_told(session_id: &usize, name: &str) -> Message {
|
||||||
Message::from(format!("name_told {} {}", session_id, name))
|
Message::from(format!("name_told {} {}", session_id, name))
|
||||||
}
|
}
|
||||||
pub fn set_as_contact(session_id: usize, name: &str, verified: bool) -> Message {
|
pub fn set_as_contact(session_id: usize, name: &str, verified: bool, fingerprint: &str) -> Message {
|
||||||
Message::from(format!("is_contact {} {} {}", session_id, verified, name))
|
Message::from(format!("is_contact {} {} {} {}", session_id, verified, fingerprint, name))
|
||||||
}
|
|
||||||
pub fn fingerprints(local: &str, peer: &str) -> Message {
|
|
||||||
Message::from(format!("fingerprints {} {}", local, peer))
|
|
||||||
}
|
}
|
||||||
pub fn set_name(new_name: &str) -> Message {
|
pub fn set_name(new_name: &str) -> Message {
|
||||||
Message::from(format!("set_name {}", new_name))
|
Message::from(format!("set_name {}", new_name))
|
||||||
@ -156,8 +153,8 @@ impl UiConnection {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn on_new_session(&mut self, session_id: &usize, name: &str, outgoing: bool, file_transfer: Option<&LargeFileDownload>) {
|
pub fn on_new_session(&mut self, session_id: &usize, name: &str, outgoing: bool, fingerprint: &str, ip: IpAddr, file_transfer: Option<&LargeFileDownload>) {
|
||||||
self.write_message(ui_messages::on_new_session(session_id, name, outgoing));
|
self.write_message(ui_messages::on_new_session(session_id, name, outgoing, fingerprint, ip));
|
||||||
if let Some(file_transfer) = file_transfer {
|
if let Some(file_transfer) = file_transfer {
|
||||||
self.write_message(ui_messages::new_file_transfer(session_id, file_transfer));
|
self.write_message(ui_messages::new_file_transfer(session_id, file_transfer));
|
||||||
}
|
}
|
||||||
@ -172,8 +169,8 @@ impl UiConnection {
|
|||||||
pub fn inc_file_transfer(&mut self, session_id: &usize, chunk_size: u64) {
|
pub fn inc_file_transfer(&mut self, session_id: &usize, chunk_size: u64) {
|
||||||
self.write_message(ui_messages::inc_file_transfer(session_id, chunk_size));
|
self.write_message(ui_messages::inc_file_transfer(session_id, chunk_size));
|
||||||
}
|
}
|
||||||
pub fn set_as_contact(&mut self, session_id: usize, name: &str, verified: bool) {
|
pub fn set_as_contact(&mut self, session_id: usize, name: &str, verified: bool, fingerprint: &str) {
|
||||||
self.write_message(ui_messages::set_as_contact(session_id, name, verified));
|
self.write_message(ui_messages::set_as_contact(session_id, name, verified, fingerprint));
|
||||||
}
|
}
|
||||||
pub fn load_msgs(&mut self, session_id: &usize, msgs: &Vec<(bool, Vec<u8>)>) {
|
pub fn load_msgs(&mut self, session_id: &usize, msgs: &Vec<(bool, Vec<u8>)>) {
|
||||||
msgs.into_iter().rev().for_each(|msg| {
|
msgs.into_iter().rev().for_each(|msg| {
|
||||||
@ -186,9 +183,6 @@ impl UiConnection {
|
|||||||
pub fn set_not_seen(&mut self, session_ids: Vec<usize>) {
|
pub fn set_not_seen(&mut self, session_ids: Vec<usize>) {
|
||||||
self.write_message(ui_messages::set_not_seen(session_ids));
|
self.write_message(ui_messages::set_not_seen(session_ids));
|
||||||
}
|
}
|
||||||
pub fn fingerprints(&mut self, local: &str, peer: &str) {
|
|
||||||
self.write_message(ui_messages::fingerprints(local, peer));
|
|
||||||
}
|
|
||||||
pub fn set_name(&mut self, new_name: &str) {
|
pub fn set_name(&mut self, new_name: &str) {
|
||||||
self.write_message(ui_messages::set_name(new_name));
|
self.write_message(ui_messages::set_name(new_name));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user