Compare commits
8 Commits
v0.0.32
...
052663efbe
Author | SHA1 | Date | |
---|---|---|---|
052663efbe | |||
8f84ff2611 | |||
37e1c5d97b | |||
cef526bcf3 | |||
6af36cafa9 | |||
fca859d93d | |||
2178300d8d | |||
636bdcce6b |
@ -16,9 +16,9 @@ MAKEFLAGS += --no-builtin-rules
|
|||||||
## LD := Linker.
|
## LD := Linker.
|
||||||
## ANDROID_SDK := Path to the Android SDK.
|
## ANDROID_SDK := Path to the Android SDK.
|
||||||
|
|
||||||
VERSION_CODE := 38
|
VERSION_CODE := 39
|
||||||
VERSION_CODE_IOS := 14
|
VERSION_CODE_IOS := 15
|
||||||
VERSION_NUMBER := 0.0.32
|
VERSION_NUMBER := 0.0.33-wip
|
||||||
VERSION_NAME := This program kills fascists.
|
VERSION_NAME := This program kills fascists.
|
||||||
|
|
||||||
IPHONEOS_VERSION_MIN=14.0
|
IPHONEOS_VERSION_MIN=14.0
|
||||||
@ -650,6 +650,7 @@ SODIUM_SOURCES := \
|
|||||||
deps/libsodium/src/libsodium/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c \
|
deps/libsodium/src/libsodium/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c \
|
||||||
deps/libsodium/src/libsodium/crypto_core/salsa/ref/core_salsa_ref.c \
|
deps/libsodium/src/libsodium/crypto_core/salsa/ref/core_salsa_ref.c \
|
||||||
deps/libsodium/src/libsodium/crypto_core/softaes/softaes.c \
|
deps/libsodium/src/libsodium/crypto_core/softaes/softaes.c \
|
||||||
|
deps/libsodium/src/libsodium/crypto_generichash/crypto_generichash.c \
|
||||||
deps/libsodium/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-ref.c \
|
deps/libsodium/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-ref.c \
|
||||||
deps/libsodium/src/libsodium/crypto_generichash/blake2b/ref/blake2b-ref.c \
|
deps/libsodium/src/libsodium/crypto_generichash/blake2b/ref/blake2b-ref.c \
|
||||||
deps/libsodium/src/libsodium/crypto_generichash/blake2b/ref/generichash_blake2b.c \
|
deps/libsodium/src/libsodium/crypto_generichash/blake2b/ref/generichash_blake2b.c \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🦀",
|
"emoji": "🦀",
|
||||||
"previous": "&Rn4Eg5ev5qhrYRnwxPB0DiEwO7VdGMDGp7tL/W7bRZo=.sha256"
|
"previous": "&lOCyez82jwCUs8R/Ynx2nBK598+qDZ7RhGnWOaNQO9U=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ class TfElement extends LitElement {
|
|||||||
url: {type: String},
|
url: {type: String},
|
||||||
private_messages: {type: Array},
|
private_messages: {type: Array},
|
||||||
recent_reactions: {type: Array},
|
recent_reactions: {type: Array},
|
||||||
|
is_administrator: {type: Boolean},
|
||||||
|
stay_connected: {type: Boolean},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +75,10 @@ class TfElement extends LitElement {
|
|||||||
async initial_load() {
|
async initial_load() {
|
||||||
let whoami = await tfrpc.rpc.getActiveIdentity();
|
let whoami = await tfrpc.rpc.getActiveIdentity();
|
||||||
let ids = (await tfrpc.rpc.getIdentities()) || [];
|
let ids = (await tfrpc.rpc.getIdentities()) || [];
|
||||||
|
this.is_administrator = await tfrpc.rpc.isAdministrator();
|
||||||
|
this.stay_connected =
|
||||||
|
this.is_administrator &&
|
||||||
|
(await tfrpc.rpc.globalSettingsGet('stay_connected'));
|
||||||
this.url = await tfrpc.rpc.url();
|
this.url = await tfrpc.rpc.url();
|
||||||
this.whoami = whoami ?? (ids.length ? ids[0] : undefined);
|
this.whoami = whoami ?? (ids.length ? ids[0] : undefined);
|
||||||
this.guest = !this.whoami?.length;
|
this.guest = !this.whoami?.length;
|
||||||
@ -131,8 +137,8 @@ class TfElement extends LitElement {
|
|||||||
let channel_names = [
|
let channel_names = [
|
||||||
'',
|
'',
|
||||||
'@',
|
'@',
|
||||||
'🔐',
|
|
||||||
'👍',
|
'👍',
|
||||||
|
'🔐',
|
||||||
...this.channels.map((x) => '#' + x),
|
...this.channels.map((x) => '#' + x),
|
||||||
];
|
];
|
||||||
let index = channel_names.indexOf(this.hash.substring(1));
|
let index = channel_names.indexOf(this.hash.substring(1));
|
||||||
@ -658,6 +664,18 @@ class TfElement extends LitElement {
|
|||||||
tfrpc.rpc.sync();
|
tfrpc.rpc.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toggle_stay_connected() {
|
||||||
|
let stay_connected = await tfrpc.rpc.globalSettingsGet('stay_connected');
|
||||||
|
let new_stay_connected = !this.stay_connected;
|
||||||
|
try {
|
||||||
|
if (new_stay_connected != stay_connected) {
|
||||||
|
await tfrpc.rpc.globalSettingsSet('stay_connected', new_stay_connected);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.stay_connected = await tfrpc.rpc.globalSettingsGet('stay_connected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
@ -680,14 +698,26 @@ class TfElement extends LitElement {
|
|||||||
class="w3-bar w3-theme-l1"
|
class="w3-bar w3-theme-l1"
|
||||||
style="position: static; top: 0; z-index: 10"
|
style="position: static; top: 0; z-index: 10"
|
||||||
>
|
>
|
||||||
<button
|
${this.is_administrator
|
||||||
class=${'w3-bar-item w3-button w3-circle w3-ripple' +
|
? html`
|
||||||
(this.connections?.some((x) => x.flags.one_shot) ? ' w3-spin' : '')}
|
<button
|
||||||
style="width: 1.5em; height: 1.5em; padding: 8px"
|
class=${'w3-bar-item w3-button w3-circle w3-ripple' +
|
||||||
@click=${this.refresh}
|
(this.connections?.some((x) => x.flags.one_shot)
|
||||||
>
|
? ' w3-spin'
|
||||||
↻
|
: '')}
|
||||||
</button>
|
style="width: 1.5em; height: 1.5em; padding: 8px"
|
||||||
|
@click=${this.refresh}
|
||||||
|
>
|
||||||
|
↻
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="w3-bar-item w3-button w3-ripple"
|
||||||
|
@click=${this.toggle_stay_connected}
|
||||||
|
>
|
||||||
|
${this.stay_connected ? '🔗' : '⛓️💥'}
|
||||||
|
</button>
|
||||||
|
`
|
||||||
|
: undefined}
|
||||||
${Object.entries(k_tabs).map(
|
${Object.entries(k_tabs).map(
|
||||||
([k, v]) => html`
|
([k, v]) => html`
|
||||||
<button
|
<button
|
||||||
|
@ -686,7 +686,11 @@ class TfMessageElement extends LitElement {
|
|||||||
${x.action}
|
${x.action}
|
||||||
${x.users.map(
|
${x.users.map(
|
||||||
(y) => html`
|
(y) => html`
|
||||||
<tf-user id=${y} .users=${this.users}></tf-user>
|
<tf-user
|
||||||
|
id=${y}
|
||||||
|
.users=${this.users}
|
||||||
|
icon_only="true"
|
||||||
|
></tf-user>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,6 +7,7 @@ class TfUserElement extends LitElement {
|
|||||||
return {
|
return {
|
||||||
id: {type: String},
|
id: {type: String},
|
||||||
fallback_name: {type: String},
|
fallback_name: {type: String},
|
||||||
|
icon_only: {type: Boolean},
|
||||||
users: {type: Object},
|
users: {type: Object},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -17,6 +18,7 @@ class TfUserElement extends LitElement {
|
|||||||
super();
|
super();
|
||||||
this.id = null;
|
this.id = null;
|
||||||
this.fallback_name = null;
|
this.fallback_name = null;
|
||||||
|
this.icon_only = false;
|
||||||
this.users = {};
|
this.users = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,9 +34,11 @@ class TfUserElement extends LitElement {
|
|||||||
>😎</span
|
>😎</span
|
||||||
>`;
|
>`;
|
||||||
let name = this.users?.[this.id]?.name;
|
let name = this.users?.[this.id]?.name;
|
||||||
name = html`<a target="_top" href=${'#' + this.id}
|
name = this.icon_only
|
||||||
>${name ?? this.fallback_name ?? this.id}</a
|
? undefined
|
||||||
>`;
|
: html`<a target="_top" href=${'#' + this.id}
|
||||||
|
>${name ?? this.fallback_name ?? this.id}</a
|
||||||
|
>`;
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
let image_link = user.image;
|
let image_link = user.image;
|
||||||
@ -48,6 +52,7 @@ class TfUserElement extends LitElement {
|
|||||||
class=${'w3-theme-l4 ' + shape}
|
class=${'w3-theme-l4 ' + shape}
|
||||||
style="width: 2em; height: 2em; vertical-align: middle; object-fit: cover"
|
style="width: 2em; height: 2em; vertical-align: middle; object-fit: cover"
|
||||||
src="/${image_link}/view"
|
src="/${image_link}/view"
|
||||||
|
alt=${name ?? this.fallback_name ?? this.id}
|
||||||
/>`;
|
/>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "👋",
|
"emoji": "👋",
|
||||||
"previous": "&fY3YUKPuH/wqOgKPVNJu1vWEHCXf5fToL2qiVXMRmxc=.sha256"
|
"previous": "&3puDxDNnf6C+YXpFysYLgxFMAy54/AO9V7Xpja6qO/k=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,8 @@
|
|||||||
<h2>First-time user checklist:</h2>
|
<h2>First-time user checklist:</h2>
|
||||||
<ol type="1" style="text-align: left">
|
<ol type="1" style="text-align: left">
|
||||||
<li>
|
<li>
|
||||||
<a href="https://dev.tildefriends.net/cory/tildefriends/releases"
|
<a
|
||||||
|
href="https://dev.tildefriends.net/cory/tildefriends/releases/latest"
|
||||||
>Download</a
|
>Download</a
|
||||||
>
|
>
|
||||||
Tilde Friends or use
|
Tilde Friends or use
|
||||||
@ -84,7 +85,7 @@
|
|||||||
>https://www.tildefriends.net/</a
|
>https://www.tildefriends.net/</a
|
||||||
>.
|
>.
|
||||||
<div class="w3-cell-row">
|
<div class="w3-cell-row">
|
||||||
<div class="w3-container w3-cell">
|
<div class="w3-container w3-cell w3-mobile">
|
||||||
<h3>Mobile</h3>
|
<h3>Mobile</h3>
|
||||||
<p>
|
<p>
|
||||||
<a
|
<a
|
||||||
@ -113,7 +114,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>Just launch the app.</p>
|
<p>Just launch the app.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w3-container w3-cell">
|
<div class="w3-container w3-cell w3-mobile">
|
||||||
<h3>Web</h3>
|
<h3>Web</h3>
|
||||||
<p>
|
<p>
|
||||||
<a
|
<a
|
||||||
@ -128,8 +129,19 @@
|
|||||||
>
|
>
|
||||||
to take it for a spin right away.
|
to take it for a spin right away.
|
||||||
</p>
|
</p>
|
||||||
|
<h3>PeachCloud</h3>
|
||||||
|
<p>
|
||||||
|
Tilde Friends is also a part of 🍑☁️<a
|
||||||
|
href="https://peach-docs.commoninternet.net/"
|
||||||
|
>PeachCloud</a
|
||||||
|
>, which is available on
|
||||||
|
<a href="https://apps.yunohost.org/app/peachpub"
|
||||||
|
>YunoHost</a
|
||||||
|
>
|
||||||
|
for accessible self-hosting.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w3-container w3-cell">
|
<div class="w3-container w3-cell w3-mobile">
|
||||||
<h3>Desktop</h3>
|
<h3>Desktop</h3>
|
||||||
<p>
|
<p>
|
||||||
<a
|
<a
|
||||||
|
@ -25,14 +25,14 @@
|
|||||||
}:
|
}:
|
||||||
pkgs.stdenv.mkDerivation rec {
|
pkgs.stdenv.mkDerivation rec {
|
||||||
pname = "tildefriends";
|
pname = "tildefriends";
|
||||||
version = "0.0.31";
|
version = "0.0.32";
|
||||||
|
|
||||||
src = pkgs.fetchFromGitea {
|
src = pkgs.fetchFromGitea {
|
||||||
domain = "dev.tildefriends.net";
|
domain = "dev.tildefriends.net";
|
||||||
owner = "cory";
|
owner = "cory";
|
||||||
repo = "tildefriends";
|
repo = "tildefriends";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
hash = "sha256-c2ZKVNikI5jN5GQuvp7S53qqnRZniSrJMF1FUZdVNPI=";
|
hash = "sha256-Dk0NOEQIg2LeENySK0+MgpZEtfsClGq6dZL+eOOpE0U=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ options:
|
|||||||
autologin (default: false): Whether mobile autologin is supported.
|
autologin (default: false): Whether mobile autologin is supported.
|
||||||
broadcast (default: true): Send network discovery broadcasts.
|
broadcast (default: true): Send network discovery broadcasts.
|
||||||
discovery (default: true): Receive network discovery broadcasts.
|
discovery (default: true): Receive network discovery broadcasts.
|
||||||
|
stay_connected (default: false): Whether to attempt to keep several peer connections open.
|
||||||
-o, --one-proc Run everything in one process (unsafely!).
|
-o, --one-proc Run everything in one process (unsafely!).
|
||||||
-z, --zip path Zip archive from which to load files.
|
-z, --zip path Zip archive from which to load files.
|
||||||
-v, --verbose Log raw messages.
|
-v, --verbose Log raw messages.
|
||||||
|
8
flake.lock
generated
8
flake.lock
generated
@ -20,16 +20,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1748037224,
|
"lastModified": 1750622754,
|
||||||
"narHash": "sha256-92vihpZr6dwEMV6g98M5kHZIttrWahb9iRPBm1atcPk=",
|
"narHash": "sha256-kMhs+YzV4vPGfuTpD3mwzibWUE6jotw5Al2wczI0Pv8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "f09dede81861f3a83f7f06641ead34f02f37597f",
|
"rev": "c7ab75210cb8cb16ddd8f290755d9558edde7ee1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-24.11",
|
"ref": "nixos-25.05",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
description = "Tilde Friends is a platform for making, running, and sharing web applications.";
|
description = "Tilde Friends is a platform for making, running, and sharing web applications.";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.unprompted.tildefriends"
|
package="com.unprompted.tildefriends"
|
||||||
android:versionCode="38"
|
android:versionCode="39"
|
||||||
android:versionName="0.0.32">
|
android:versionName="0.0.33-wip">
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
|
@ -13,13 +13,13 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.0.32</string>
|
<string>0.0.33</string>
|
||||||
<key>CFBundleSupportedPlatforms</key>
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
<array>
|
<array>
|
||||||
<string>iPhoneOS</string>
|
<string>iPhoneOS</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>14</string>
|
<string>15</string>
|
||||||
<key>DTPlatformName</key>
|
<key>DTPlatformName</key>
|
||||||
<string>iphoneos</string>
|
<string>iphoneos</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "util.js.h"
|
#include "util.js.h"
|
||||||
|
|
||||||
#include "quickjs.h"
|
#include "quickjs.h"
|
||||||
|
#include "sodium/crypto_generichash.h"
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
|
|
||||||
@ -154,11 +155,11 @@ static void _tf_mem_summarize(void* ptr, size_t size, int frames_count, void* co
|
|||||||
{
|
{
|
||||||
summary_t* summary = user_data;
|
summary_t* summary = user_data;
|
||||||
tf_mem_allocation_t allocation = {
|
tf_mem_allocation_t allocation = {
|
||||||
.stack_hash = tf_util_fnv32a(frames, sizeof(void*) * frames_count, 0),
|
|
||||||
.count = 1,
|
.count = 1,
|
||||||
.size = size,
|
.size = size,
|
||||||
.frames_count = frames_count,
|
.frames_count = frames_count,
|
||||||
};
|
};
|
||||||
|
crypto_generichash((void*)&allocation.stack_hash, sizeof(allocation.stack_hash), (const void*)frames, sizeof(void*) * frames_count, NULL, 0);
|
||||||
memcpy(allocation.frames, frames, sizeof(void*) * frames_count);
|
memcpy(allocation.frames, frames, sizeof(void*) * frames_count);
|
||||||
|
|
||||||
int index = tf_util_insert_index(&allocation, summary->allocations, summary->count, sizeof(tf_mem_allocation_t), _tf_mem_hash_stack_compare);
|
int index = tf_util_insert_index(&allocation, summary->allocations, summary->count, sizeof(tf_mem_allocation_t), _tf_mem_hash_stack_compare);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
#include "ssb.db.h"
|
||||||
#include "ssb.h"
|
#include "ssb.h"
|
||||||
#include "util.js.h"
|
#include "util.js.h"
|
||||||
|
|
||||||
@ -51,15 +52,19 @@ static void _tf_ssb_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_change_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _tf_ssb_connections_get_next_connection(tf_ssb_connections_t* connections, char* host, size_t host_size, int* port, char* key, size_t key_size)
|
static bool _tf_ssb_connections_get_next_connection(
|
||||||
|
tf_ssb_connections_t* connections, char* host, size_t host_size, int* port, char* key, size_t key_size, bool* out_stay_connected)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
sqlite3_stmt* statement;
|
sqlite3_stmt* statement;
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(connections->ssb);
|
sqlite3* db = tf_ssb_acquire_db_reader(connections->ssb);
|
||||||
|
|
||||||
|
tf_ssb_db_get_global_setting_bool(db, "stay_connected", out_stay_connected);
|
||||||
|
|
||||||
if (sqlite3_prepare_v2(db, "SELECT host, port, key FROM connections WHERE last_attempt IS NULL OR (strftime('%s', 'now') - last_attempt > ?1) ORDER BY last_attempt LIMIT 1",
|
if (sqlite3_prepare_v2(db, "SELECT host, port, key FROM connections WHERE last_attempt IS NULL OR (strftime('%s', 'now') - last_attempt > ?1) ORDER BY last_attempt LIMIT 1",
|
||||||
-1, &statement, NULL) == SQLITE_OK)
|
-1, &statement, NULL) == SQLITE_OK)
|
||||||
{
|
{
|
||||||
if (sqlite3_bind_int(statement, 1, 60000) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
|
if (sqlite3_bind_int(statement, 1, *out_stay_connected ? 15 : 60000) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
|
||||||
{
|
{
|
||||||
tf_string_set(host, host_size, (const char*)sqlite3_column_text(statement, 0));
|
tf_string_set(host, host_size, (const char*)sqlite3_column_text(statement, 0));
|
||||||
*port = sqlite3_column_int(statement, 1);
|
*port = sqlite3_column_int(statement, 1);
|
||||||
@ -80,6 +85,8 @@ typedef struct _tf_ssb_connections_get_next_t
|
|||||||
{
|
{
|
||||||
tf_ssb_connections_t* connections;
|
tf_ssb_connections_t* connections;
|
||||||
bool ready;
|
bool ready;
|
||||||
|
bool stay_connected;
|
||||||
|
bool full;
|
||||||
char host[256];
|
char host[256];
|
||||||
int port;
|
int port;
|
||||||
char key[k_id_base64_len];
|
char key[k_id_base64_len];
|
||||||
@ -92,7 +99,7 @@ static void _tf_ssb_connections_get_next_work(tf_ssb_t* ssb, void* user_data)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
next->ready = _tf_ssb_connections_get_next_connection(next->connections, next->host, sizeof(next->host), &next->port, next->key, sizeof(next->key));
|
next->ready = _tf_ssb_connections_get_next_connection(next->connections, next->host, sizeof(next->host), &next->port, next->key, sizeof(next->key), &next->stay_connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _tf_ssb_connections_get_next_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
static void _tf_ssb_connections_get_next_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||||
@ -100,12 +107,20 @@ static void _tf_ssb_connections_get_next_after_work(tf_ssb_t* ssb, int status, v
|
|||||||
tf_ssb_connections_get_next_t* next = user_data;
|
tf_ssb_connections_get_next_t* next = user_data;
|
||||||
if (next->ready)
|
if (next->ready)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
** Might be a duplicate connection or otherwise discarded by
|
||||||
|
** tf_ssb_connect() before we otherwise set attempted, so do it
|
||||||
|
** here.
|
||||||
|
*/
|
||||||
|
tf_ssb_connections_set_attempted(next->connections, next->host, next->port, next->key);
|
||||||
|
|
||||||
uint8_t key_bin[k_id_bin_len];
|
uint8_t key_bin[k_id_bin_len];
|
||||||
if (tf_ssb_id_str_to_bin(key_bin, next->key))
|
if (tf_ssb_id_str_to_bin(key_bin, next->key))
|
||||||
{
|
{
|
||||||
tf_ssb_connect(ssb, next->host, next->port, key_bin, k_tf_ssb_connect_flag_do_not_store, NULL, NULL);
|
tf_ssb_connect(ssb, next->host, next->port, key_bin, k_tf_ssb_connect_flag_do_not_store, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
uv_timer_set_repeat(&next->connections->timer, next->stay_connected ? (next->full ? 2000 : 200) : (next->full ? 10000 : 2000));
|
||||||
tf_free(next);
|
tf_free(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +139,7 @@ static void _tf_ssb_connections_timer(uv_timer_t* timer)
|
|||||||
tf_ssb_connections_get_next_t* next = tf_malloc(sizeof(tf_ssb_connections_get_next_t));
|
tf_ssb_connections_get_next_t* next = tf_malloc(sizeof(tf_ssb_connections_get_next_t));
|
||||||
*next = (tf_ssb_connections_get_next_t) {
|
*next = (tf_ssb_connections_get_next_t) {
|
||||||
.connections = connections,
|
.connections = connections,
|
||||||
|
.full = count + 1 == tf_countof(active),
|
||||||
};
|
};
|
||||||
tf_ssb_run_work(connections->ssb, _tf_ssb_connections_get_next_work, _tf_ssb_connections_get_next_after_work, next);
|
tf_ssb_run_work(connections->ssb, _tf_ssb_connections_get_next_work, _tf_ssb_connections_get_next_after_work, next);
|
||||||
}
|
}
|
||||||
|
@ -332,8 +332,6 @@ static void _tf_ssb_rpc_tunnel_callback(tf_ssb_connection_t* connection, uint8_t
|
|||||||
|
|
||||||
JS_FreeValue(context, stack_val);
|
JS_FreeValue(context, stack_val);
|
||||||
JS_FreeValue(context, message_val);
|
JS_FreeValue(context, message_val);
|
||||||
|
|
||||||
tf_ssb_connection_close(tun->connection, buffer);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "ares.h"
|
#include "ares.h"
|
||||||
#include "backtrace.h"
|
#include "backtrace.h"
|
||||||
#include "quickjs.h"
|
#include "quickjs.h"
|
||||||
|
#include "sodium/crypto_generichash.h"
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
#include "unzip.h"
|
#include "unzip.h"
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
@ -1255,6 +1256,8 @@ static void _tf_task_free_promise(tf_task_t* task, promiseid_t id)
|
|||||||
JSValue tf_task_allocate_promise(tf_task_t* task, promiseid_t* out_promise)
|
JSValue tf_task_allocate_promise(tf_task_t* task, promiseid_t* out_promise)
|
||||||
{
|
{
|
||||||
uint32_t stack_hash = 0;
|
uint32_t stack_hash = 0;
|
||||||
|
crypto_generichash_state state;
|
||||||
|
crypto_generichash_init(&state, NULL, 0, sizeof(stack_hash));
|
||||||
if (task->_promise_stack_debug)
|
if (task->_promise_stack_debug)
|
||||||
{
|
{
|
||||||
JSValue error = JS_ThrowInternalError(task->_context, "promise callstack");
|
JSValue error = JS_ThrowInternalError(task->_context, "promise callstack");
|
||||||
@ -1262,16 +1265,17 @@ JSValue tf_task_allocate_promise(tf_task_t* task, promiseid_t* out_promise)
|
|||||||
JSValue stack_value = JS_GetPropertyStr(task->_context, exception, "stack");
|
JSValue stack_value = JS_GetPropertyStr(task->_context, exception, "stack");
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
const char* stack = JS_ToCStringLen(task->_context, &length, stack_value);
|
const char* stack = JS_ToCStringLen(task->_context, &length, stack_value);
|
||||||
stack_hash = tf_util_fnv32a((const void*)stack, (int)length, 0);
|
crypto_generichash_update(&state, (const void*)stack, (int)length);
|
||||||
void* buffer[31];
|
void* buffer[31];
|
||||||
int count = tf_util_backtrace(buffer, sizeof(buffer) / sizeof(*buffer));
|
int count = tf_util_backtrace(buffer, sizeof(buffer) / sizeof(*buffer));
|
||||||
stack_hash = tf_util_fnv32a((const void*)buffer, sizeof(void*) * count, stack_hash);
|
crypto_generichash_update(&state, (const void*)buffer, sizeof(void*) * count);
|
||||||
_add_promise_stack(task, stack_hash, stack, buffer, count);
|
_add_promise_stack(task, stack_hash, stack, buffer, count);
|
||||||
JS_FreeCString(task->_context, stack);
|
JS_FreeCString(task->_context, stack);
|
||||||
JS_FreeValue(task->_context, stack_value);
|
JS_FreeValue(task->_context, stack_value);
|
||||||
JS_FreeValue(task->_context, exception);
|
JS_FreeValue(task->_context, exception);
|
||||||
JS_FreeValue(task->_context, error);
|
JS_FreeValue(task->_context, error);
|
||||||
}
|
}
|
||||||
|
crypto_generichash_final(&state, (void*)&stack_hash, sizeof(stack_hash));
|
||||||
|
|
||||||
promiseid_t promise_id;
|
promiseid_t promise_id;
|
||||||
do
|
do
|
||||||
|
@ -400,6 +400,10 @@ static const setting_t k_settings[] = {
|
|||||||
{ .name = "autologin", .type = "boolean", .description = "Whether mobile autologin is supported.", .default_value = { .kind = k_kind_bool, .bool_value = TF_IS_MOBILE != 0 } },
|
{ .name = "autologin", .type = "boolean", .description = "Whether mobile autologin is supported.", .default_value = { .kind = k_kind_bool, .bool_value = TF_IS_MOBILE != 0 } },
|
||||||
{ .name = "broadcast", .type = "boolean", .description = "Send network discovery broadcasts.", .default_value = { .kind = k_kind_bool, .bool_value = true } },
|
{ .name = "broadcast", .type = "boolean", .description = "Send network discovery broadcasts.", .default_value = { .kind = k_kind_bool, .bool_value = true } },
|
||||||
{ .name = "discovery", .type = "boolean", .description = "Receive network discovery broadcasts.", .default_value = { .kind = k_kind_bool, .bool_value = true } },
|
{ .name = "discovery", .type = "boolean", .description = "Receive network discovery broadcasts.", .default_value = { .kind = k_kind_bool, .bool_value = true } },
|
||||||
|
{ .name = "stay_connected",
|
||||||
|
.type = "boolean",
|
||||||
|
.description = "Whether to attempt to keep several peer connections open.",
|
||||||
|
.default_value = { .kind = k_kind_bool, .bool_value = false } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const setting_t* _util_get_setting(const char* name, tf_setting_kind_t kind)
|
static const setting_t* _util_get_setting(const char* name, tf_setting_kind_t kind)
|
||||||
@ -691,17 +695,6 @@ bool tf_util_is_mobile()
|
|||||||
return TF_IS_MOBILE != 0;
|
return TF_IS_MOBILE != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tf_util_fnv32a(const void* buffer, int length, uint32_t start)
|
|
||||||
{
|
|
||||||
uint32_t result = 0x811c9dc5;
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
result ^= ((const uint8_t*)buffer)[i];
|
|
||||||
result += (result << 1) + (result << 4) + (result << 7) + (result << 8) + (result << 24);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tf_string_set(char* buffer, size_t size, const char* string)
|
size_t tf_string_set(char* buffer, size_t size, const char* string)
|
||||||
{
|
{
|
||||||
size_t length = string ? strlen(string) : 0;
|
size_t length = string ? strlen(string) : 0;
|
||||||
|
@ -224,15 +224,6 @@ void tf_util_document_settings(const char* line_prefix);
|
|||||||
*/
|
*/
|
||||||
bool tf_util_is_mobile();
|
bool tf_util_is_mobile();
|
||||||
|
|
||||||
/**
|
|
||||||
** Compute a 32-bit hash of a buffer.
|
|
||||||
** @param buffer The data.
|
|
||||||
** @param length The size of the buffer in bytes.
|
|
||||||
** @param start The hash seed.
|
|
||||||
** @return The computed hash.
|
|
||||||
*/
|
|
||||||
uint32_t tf_util_fnv32a(const void* buffer, int length, uint32_t start);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Populate a string buffer, truncating if necessary.
|
** Populate a string buffer, truncating if necessary.
|
||||||
** @param buffer The buffer.
|
** @param buffer The buffer.
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#define VERSION_NUMBER "0.0.32"
|
#define VERSION_NUMBER "0.0.33-wip"
|
||||||
#define VERSION_NAME "This program kills fascists."
|
#define VERSION_NAME "This program kills fascists."
|
||||||
|
Reference in New Issue
Block a user