mac ver
This commit is contained in:
1 parent
f7961b8e70
commit
f8357220fc
9 files changed
+197
-51
No files matched your search
Binary file not shown.
@@ -114,16 +114,10 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
}
|
||||
|
||||
function messageStatusHtml(m) {
|
||||
if (m.sender !== 'me') {
|
||||
return '<span class="chat-msg-status received">Received</span>';
|
||||
if (m.status === 'failed') {
|
||||
return '<span class="chat-msg-status pending">Failed to send</span>';
|
||||
}
|
||||
if (m.deliveredAt) {
|
||||
return '<span class="chat-msg-status delivered">Sent · Received by contact</span>';
|
||||
}
|
||||
if (m.id) {
|
||||
return '<span class="chat-msg-status sent">Sent</span>';
|
||||
}
|
||||
return '<span class="chat-msg-status pending">Sending…</span>';
|
||||
return '';
|
||||
}
|
||||
|
||||
function mergeMessages(peerId, incoming) {
|
||||
@@ -312,6 +306,7 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
if (!body) return;
|
||||
const senderId = selfPeerId() || 'local';
|
||||
const name = selfName();
|
||||
const thread = getThread(selectedPeer.peerId);
|
||||
sendBtn.disabled = true;
|
||||
try {
|
||||
const res = await BackOneAuth.fetchWithAuth(
|
||||
@@ -327,7 +322,7 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
})
|
||||
}
|
||||
);
|
||||
if (!res.ok) return;
|
||||
if (!res.ok) throw new Error(`secure chat send failed: ${res.status}`);
|
||||
const data = await res.json();
|
||||
const now = data.createdAt || Date.now();
|
||||
const msg = {
|
||||
@@ -339,12 +334,25 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
deliveredAt: null,
|
||||
status: 'sent'
|
||||
};
|
||||
getThread(selectedPeer.peerId).push(msg);
|
||||
thread.push(msg);
|
||||
if (msg.at > lastPollSince) lastPollSince = msg.at;
|
||||
persistThread(networkId, selectedPeer.peerId);
|
||||
input.value = '';
|
||||
render();
|
||||
} catch (_) {
|
||||
const now = Date.now();
|
||||
thread.push({
|
||||
id: null,
|
||||
sender: 'me',
|
||||
senderName: name,
|
||||
body,
|
||||
at: now,
|
||||
deliveredAt: null,
|
||||
status: 'failed'
|
||||
});
|
||||
if (now > lastPollSince) lastPollSince = now;
|
||||
persistThread(networkId, selectedPeer.peerId);
|
||||
render();
|
||||
} finally {
|
||||
updateInputs();
|
||||
}
|
||||
|
||||
+19
-11
@@ -114,16 +114,10 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
}
|
||||
|
||||
function messageStatusHtml(m) {
|
||||
if (m.sender !== 'me') {
|
||||
return '<span class="chat-msg-status received">Received</span>';
|
||||
if (m.status === 'failed') {
|
||||
return '<span class="chat-msg-status pending">Failed to send</span>';
|
||||
}
|
||||
if (m.deliveredAt) {
|
||||
return '<span class="chat-msg-status delivered">Sent · Received by contact</span>';
|
||||
}
|
||||
if (m.id) {
|
||||
return '<span class="chat-msg-status sent">Sent</span>';
|
||||
}
|
||||
return '<span class="chat-msg-status pending">Sending…</span>';
|
||||
return '';
|
||||
}
|
||||
|
||||
function mergeMessages(peerId, incoming) {
|
||||
@@ -313,6 +307,7 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
if (!body) return;
|
||||
const senderId = selfPeerId() || 'local';
|
||||
const name = selfName();
|
||||
const thread = getThread(selectedPeer.peerId);
|
||||
sendBtn.disabled = true;
|
||||
try {
|
||||
const res = await BackOneAuth.fetchWithAuth(
|
||||
@@ -328,7 +323,7 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
})
|
||||
}
|
||||
);
|
||||
if (!res.ok) return;
|
||||
if (!res.ok) throw new Error(`secure chat send failed: ${res.status}`);
|
||||
const data = await res.json();
|
||||
const now = data.createdAt || Date.now();
|
||||
const msg = {
|
||||
@@ -340,12 +335,25 @@ window.BackOneAddons['secure-chat'] = function secureChatAddon() {
|
||||
deliveredAt: null,
|
||||
status: 'sent'
|
||||
};
|
||||
getThread(selectedPeer.peerId).push(msg);
|
||||
thread.push(msg);
|
||||
if (msg.at > lastPollSince) lastPollSince = msg.at;
|
||||
persistThread(networkId, selectedPeer.peerId);
|
||||
input.value = '';
|
||||
render();
|
||||
} catch (_) {
|
||||
const now = Date.now();
|
||||
thread.push({
|
||||
id: null,
|
||||
sender: 'me',
|
||||
senderName: name,
|
||||
body,
|
||||
at: now,
|
||||
deliveredAt: null,
|
||||
status: 'failed'
|
||||
});
|
||||
if (now > lastPollSince) lastPollSince = now;
|
||||
persistThread(networkId, selectedPeer.peerId);
|
||||
render();
|
||||
} finally {
|
||||
updateInputs();
|
||||
}
|
||||
|
||||
@@ -6,11 +6,81 @@ set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
BACKONE_REPO="${BACKONE_REPO:-$ROOT/../BackOne}"
|
||||
|
||||
if [[ "$(uname -s)" != "Linux" ]]; then
|
||||
echo "This script is Linux-only." >&2
|
||||
echo "On macOS, edit /Library/Application Support/BackOne/local.conf as valid JSON," >&2
|
||||
echo "then restart the BackOne daemon/app instead of using systemctl." >&2
|
||||
exit 1
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
CONF="/Library/Application Support/BackOne/local.conf"
|
||||
PORT="$(cat "/Library/Application Support/BackOne/backone.port" 2>/dev/null || echo 9993)"
|
||||
echo "macOS secure chat settings"
|
||||
echo ""
|
||||
|
||||
if [[ "${EUID}" -eq 0 ]]; then
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
from pathlib import Path
|
||||
path = Path("/Library/Application Support/BackOne/local.conf")
|
||||
cfg = json.loads(path.read_text())
|
||||
settings = cfg.setdefault("settings", {})
|
||||
settings["webhubBind"] = "overlay"
|
||||
settings["webhubAllowOverlayChat"] = True
|
||||
settings.setdefault("webhubPort", 9993)
|
||||
path.write_text(json.dumps(cfg, indent=2) + "\n")
|
||||
print(f"Updated {path}")
|
||||
print(" webhubBind = overlay")
|
||||
print(" webhubAllowOverlayChat = true")
|
||||
print(" webhubPort =", settings.get("webhubPort", 9993))
|
||||
PY
|
||||
echo ""
|
||||
echo "Restarting backone daemon..."
|
||||
pkill -x backone 2>/dev/null || true
|
||||
sleep 1
|
||||
"/Library/Application Support/BackOne/launch.sh" >/tmp/backone.log 2>&1 &
|
||||
sleep 2
|
||||
else
|
||||
echo "Run with sudo to apply overlay settings automatically:"
|
||||
echo " sudo $0"
|
||||
echo ""
|
||||
echo "Or verify ${CONF} contains:"
|
||||
echo ' "settings": {'
|
||||
echo ' "webhubBind": "overlay",'
|
||||
echo ' "webhubAllowOverlayChat": true'
|
||||
echo ' }'
|
||||
echo ""
|
||||
python3 - <<'PY' 2>/dev/null || true
|
||||
import json
|
||||
from pathlib import Path
|
||||
path = Path("/Library/Application Support/BackOne/local.conf")
|
||||
try:
|
||||
cfg = json.loads(path.read_text())
|
||||
settings = cfg.get("settings") or {}
|
||||
print("Current settings:")
|
||||
print(" webhubBind =", settings.get("webhubBind"))
|
||||
print(" webhubAllowOverlayChat =", settings.get("webhubAllowOverlayChat"))
|
||||
print(" webhubPort =", settings.get("webhubPort", 9993))
|
||||
if settings.get("webhubBind") not in (None, "", "overlay"):
|
||||
print("WARN: webhubBind should be overlay for cross-host chat on macOS")
|
||||
except Exception as exc:
|
||||
print(f"Could not parse {path}: {exc}")
|
||||
PY
|
||||
echo ""
|
||||
echo "Then restart the daemon:"
|
||||
echo ' sudo pkill -x backone'
|
||||
echo ' sudo "/Library/Application Support/BackOne/launch.sh" >/tmp/backone.log 2>&1 &'
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "Verifying listen address (port ${PORT})..."
|
||||
if command -v lsof >/dev/null 2>&1; then
|
||||
lsof -nP -iTCP -sTCP:LISTEN 2>/dev/null | rg ":${PORT} " || echo " WARN: nothing listening on port ${PORT}" >&2
|
||||
fi
|
||||
echo ""
|
||||
echo "Verifying overlay relay (no auth) on 127.0.0.1:${PORT}..."
|
||||
code="$(curl -s -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' \
|
||||
-d '{"networkId":"0000000000000000","senderId":"0000000000","senderName":"t","targetId":"0000000000","body":"t","at":1}' \
|
||||
"http://127.0.0.1:${PORT}/controller/comms/chat/relay")"
|
||||
echo " POST /controller/comms/chat/relay -> HTTP ${code}"
|
||||
if [[ "$code" != "200" ]]; then
|
||||
echo " WARN: relay no-auth check failed — peers may see connection errors" >&2
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${EUID}" -ne 0 ]]; then
|
||||
|
||||
@@ -7,12 +7,21 @@ NETWORK_ID="${1:?network id required (16 hex chars)}"
|
||||
TARGET_ID="${2:?target peer id required (10 hex chars)}"
|
||||
MSG="${3:-ping from send-secure-chat-test.sh}"
|
||||
|
||||
OS="$(uname -s)"
|
||||
if [[ "$OS" == "Darwin" ]]; then
|
||||
SERVICE_HOME="/Library/Application Support/BackOne"
|
||||
DEFAULT_HUB_PORT=9993
|
||||
else
|
||||
SERVICE_HOME="/var/lib/backone"
|
||||
DEFAULT_HUB_PORT=9994
|
||||
fi
|
||||
|
||||
TOKEN="$(
|
||||
cat ~/.backone-local-auth 2>/dev/null \
|
||||
|| cat ~/.backOneAuthToken 2>/dev/null \
|
||||
|| sudo cat /var/lib/backone/authtoken.secret
|
||||
|| sudo cat "${SERVICE_HOME}/authtoken.secret"
|
||||
)"
|
||||
PORT="$(cat /var/lib/backone/backone.port 2>/dev/null || echo 9993)"
|
||||
PORT="$(cat "${SERVICE_HOME}/backone.port" 2>/dev/null || echo 9993)"
|
||||
|
||||
MY_ID="$(
|
||||
curl -sf -H "X-ZT1-Auth: $TOKEN" "http://127.0.0.1:${PORT}/status" \
|
||||
@@ -24,8 +33,12 @@ HUB_PORT="$(
|
||||
| jq -r '.webhubPort // empty' 2>/dev/null || true
|
||||
)"
|
||||
if [[ -z "$HUB_PORT" ]]; then
|
||||
if ss -tln 2>/dev/null | grep -q '127.0.0.1:9994'; then
|
||||
HUB_PORT=9994
|
||||
if [[ "$OS" == "Darwin" ]]; then
|
||||
if nc -z 127.0.0.1 "$DEFAULT_HUB_PORT" 2>/dev/null; then
|
||||
HUB_PORT="$DEFAULT_HUB_PORT"
|
||||
fi
|
||||
elif ss -tln 2>/dev/null | rg -q "127\\.0\\.0\\.1:${DEFAULT_HUB_PORT}"; then
|
||||
HUB_PORT="$DEFAULT_HUB_PORT"
|
||||
else
|
||||
echo "Could not detect webhub port. Is backone-webhub running?" >&2
|
||||
exit 1
|
||||
@@ -52,12 +65,12 @@ else
|
||||
echo "Peer VL1: not in /peer list"
|
||||
fi
|
||||
|
||||
if ! cmp -s /usr/sbin/backone "${BACKONE_REPO:-$HOME/git/BackOne}/backone" 2>/dev/null; then
|
||||
if [[ "$OS" != "Darwin" ]] && ! cmp -s /usr/sbin/backone "${BACKONE_REPO:-$HOME/git/BackOne}/backone" 2>/dev/null; then
|
||||
echo ""
|
||||
echo "WARN: system backone is not the patched build — run:" >&2
|
||||
echo " sudo ./scripts/install-secure-chat-deps.sh" >&2
|
||||
fi
|
||||
if ! cmp -s /usr/lib/backone/addons/webhub/backone-webhub \
|
||||
if [[ "$OS" != "Darwin" ]] && ! cmp -s /usr/lib/backone/addons/webhub/backone-webhub \
|
||||
"${BACKONE_REPO:-$HOME/git/BackOne}/addons/webhub/backone-webhub" 2>/dev/null; then
|
||||
echo "WARN: system webhub is outdated — run install script above" >&2
|
||||
fi
|
||||
@@ -74,7 +87,11 @@ for candidate in /usr/bin/python3 python3; do
|
||||
done
|
||||
if [[ -z "$PYTHON" ]]; then
|
||||
echo "python3-websockets is required. Install with:" >&2
|
||||
echo " sudo apt install python3-websockets" >&2
|
||||
if [[ "$OS" == "Darwin" ]]; then
|
||||
echo " python3 -m pip install websockets" >&2
|
||||
else
|
||||
echo " sudo apt install python3-websockets" >&2
|
||||
fi
|
||||
echo " # or: pip install websockets (outside the BackOneUI venv)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+17
-5
@@ -26,6 +26,10 @@ use crate::serviceclient::ServiceClient;
|
||||
|
||||
const WINDOW_W: c_int = 960;
|
||||
const WINDOW_H: c_int = 640;
|
||||
#[cfg(target_os = "macos")]
|
||||
const DEFAULT_WEBHUB_PORT: u16 = 9993;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
const DEFAULT_WEBHUB_PORT: u16 = 9994;
|
||||
const DEFAULT_BACKONE_PORT: u16 = 9993;
|
||||
|
||||
@@ -235,7 +239,13 @@ unsafe fn send_current_message() -> bool {
|
||||
if !ports.contains(&DEFAULT_BACKONE_PORT) {
|
||||
ports.push(DEFAULT_BACKONE_PORT);
|
||||
}
|
||||
if c.realtime_chat_available {
|
||||
let overlay_contact = cv.contact.ip.starts_with("192.168.") || cv.contact.ip.starts_with("10.");
|
||||
#[cfg(target_os = "macos")]
|
||||
let prefer_relay = overlay_contact;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let prefer_relay = false;
|
||||
|
||||
if c.realtime_chat_available && !prefer_relay {
|
||||
let _ = c.hub_cmd.send(HubCommand::SendChatRemote {
|
||||
host: target_host.clone(),
|
||||
ports,
|
||||
@@ -254,7 +264,7 @@ unsafe fn send_current_message() -> bool {
|
||||
});
|
||||
let empty = CString::new("").unwrap();
|
||||
libui::uiMultilineEntrySetText(compose_entry, empty.as_ptr());
|
||||
if !c.realtime_chat_available {
|
||||
if !c.realtime_chat_available || prefer_relay {
|
||||
let relayed = relay::relay_chat_to_peer_paths(
|
||||
&c.client,
|
||||
&network_id,
|
||||
@@ -1274,11 +1284,13 @@ pub fn secure_chat_main() {
|
||||
}
|
||||
|
||||
let auth_token = client.auth_token().to_string();
|
||||
let hub_host = client.webhub_host();
|
||||
let hub_host = client.webhub_local_host();
|
||||
let hub_port = client.webhub_port();
|
||||
let local_webhub_available = client.local_webhub_reachable();
|
||||
let realtime_chat_available =
|
||||
client.http_get_json("/controller/comms/ping?host=127.0.0.1").is_some();
|
||||
let realtime_chat_available = client
|
||||
.http_get_json("/controller/comms/ping?host=127.0.0.1")
|
||||
.is_some()
|
||||
|| (cfg!(target_os = "macos") && local_webhub_available);
|
||||
let (hub_cmd, hub_events) = if realtime_chat_available {
|
||||
spawn_webhub(auth_token, hub_host, hub_port)
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,12 @@ use super::contacts::{add_contact, SecureContact};
|
||||
|
||||
pub const QR_TYPE: &str = "backone-secure-chat-contact";
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
const DEFAULT_CONTACT_PORT: u16 = 9993;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
const DEFAULT_CONTACT_PORT: u16 = 9994;
|
||||
|
||||
pub fn contacts_qr_path() -> PathBuf {
|
||||
let home = unsafe { crate::APPLICATION_HOME.as_str() };
|
||||
PathBuf::from(home).join("my-secure-chat-qr.png")
|
||||
@@ -76,7 +82,7 @@ pub fn parse_contact_payload(value: &Value) -> Result<SecureContact, String> {
|
||||
let port = value
|
||||
.get("port")
|
||||
.and_then(|v| v.as_u64())
|
||||
.unwrap_or(9994) as u16;
|
||||
.unwrap_or(DEFAULT_CONTACT_PORT as u64) as u16;
|
||||
let network_id = value
|
||||
.get("networkId")
|
||||
.and_then(|v| v.as_str())
|
||||
|
||||
+24
-11
@@ -62,6 +62,28 @@ fn is_loopback_host(host: &str) -> bool {
|
||||
host == "127.0.0.1" || host == "localhost" || host == "::1"
|
||||
}
|
||||
|
||||
fn is_private_host(host: &str) -> bool {
|
||||
let host = host.split('/').next().unwrap_or(host).trim();
|
||||
host.starts_with("10.") || host.starts_with("192.168.")
|
||||
}
|
||||
|
||||
fn ws_needs_auth(host: &str, auth_token: &str) -> bool {
|
||||
!auth_token.is_empty() && (is_loopback_host(host) || is_private_host(host))
|
||||
}
|
||||
|
||||
fn ws_url(host: &str, port: u16, auth_token: &str) -> String {
|
||||
if ws_needs_auth(host, auth_token) {
|
||||
format!(
|
||||
"ws://{}:{}/?auth={}",
|
||||
host,
|
||||
port,
|
||||
encode_query_component(auth_token)
|
||||
)
|
||||
} else {
|
||||
format!("ws://{}:{}/", host, port)
|
||||
}
|
||||
}
|
||||
|
||||
fn send_chat_remote(
|
||||
auth_token: &str,
|
||||
host: &str,
|
||||
@@ -82,16 +104,7 @@ fn send_chat_remote(
|
||||
});
|
||||
|
||||
for port in ports {
|
||||
let url = if is_loopback_host(host) && !auth_token.is_empty() {
|
||||
format!(
|
||||
"ws://{}:{}/?auth={}",
|
||||
host,
|
||||
port,
|
||||
encode_query_component(auth_token)
|
||||
)
|
||||
} else {
|
||||
format!("ws://{}:{}/", host, port)
|
||||
};
|
||||
let url = ws_url(host, *port, auth_token);
|
||||
|
||||
let Ok((mut socket, _)) = connect(&url) else {
|
||||
continue;
|
||||
@@ -99,7 +112,7 @@ fn send_chat_remote(
|
||||
if let MaybeTlsStream::Plain(tcp) = socket.get_ref() {
|
||||
let _ = tcp.set_read_timeout(Some(Duration::from_millis(3000)));
|
||||
}
|
||||
if is_loopback_host(host) && !auth_token.is_empty() {
|
||||
if ws_needs_auth(host, auth_token) {
|
||||
let _ = socket.send(Message::Text(
|
||||
json!({ "type": "auth", "token": auth_token }).to_string(),
|
||||
));
|
||||
|
||||
@@ -519,6 +519,18 @@ impl ServiceClient {
|
||||
Self::webhub_host_from_local_conf().unwrap_or_else(|| String::from("127.0.0.1"))
|
||||
}
|
||||
|
||||
/// Host for the local Secure Chat WebHub client. On macOS the daemon is reached on loopback
|
||||
/// even when webhubBind is set to an overlay address for inbound peers.
|
||||
pub fn webhub_local_host(&self) -> String {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
if self.local_webhub_reachable() {
|
||||
return String::from("127.0.0.1");
|
||||
}
|
||||
}
|
||||
self.webhub_host()
|
||||
}
|
||||
|
||||
fn webhub_port_from_local_conf() -> Option<u16> {
|
||||
for path in [crate::GLOBAL_SERVICE_HOME_V2, crate::GLOBAL_SERVICE_HOME_V1] {
|
||||
let conf_path = Path::new(path).join("local.conf");
|
||||
|
||||
Reference in new issue
Block a user