summaryrefslogtreecommitdiffstats
path: root/nym_sender.php
diff options
context:
space:
mode:
authorGab <24553253+gabrix73@users.noreply.github.com>2026-08-14 20:39:22 +0200
committerGab <24553253+gabrix73@users.noreply.github.com>2026-08-14 20:39:22 +0200
commit43fbddf016f94f4ba006d82c9a67dca61b5852a1 (patch)
tree70054d5fa8a34bb094b8c3ef8ddc9c1fcea3b3d5 /nym_sender.php
parent994071243fc80990cf09e820b671006e9bd31c76 (diff)
downloadyamnweb-43fbddf016f94f4ba006d82c9a67dca61b5852a1.tar.gz
yamnweb-43fbddf016f94f4ba006d82c9a67dca61b5852a1.tar.xz
yamnweb-43fbddf016f94f4ba006d82c9a67dca61b5852a1.zip
Complete Nym and YAMN transport integration
Diffstat (limited to 'nym_sender.php')
-rw-r--r--nym_sender.php101
1 files changed, 43 insertions, 58 deletions
diff --git a/nym_sender.php b/nym_sender.php
index 221de17..e1798a1 100644
--- a/nym_sender.php
+++ b/nym_sender.php
@@ -4,12 +4,11 @@ declare(strict_types=1);
require_once __DIR__ . '/yamn_config.php';
/**
- * Send an already encrypted YAMN envelope through the local Rust Nym sender.
+ * Queue an already encrypted YAMN envelope with the local Rust Nym sender.
*
- * The handoff callback runs after the complete request has been written to
- * the sender's stdin, but before waiting for the sender's bounded flush grace
- * period. This lets the HTTP layer finish a FastCGI response while the lock
- * remains held until the sender exits.
+ * The handoff callback runs only after the persistent sender has accepted the
+ * envelope into its bounded in-memory queue. The daemon is the sole owner of
+ * the Nym client storage and never writes queued envelopes to disk.
*/
function sendNymEnvelope(
string $payload,
@@ -18,17 +17,15 @@ function sendNymEnvelope(
?callable $onHandoff = null
): array
{
- $sender = yamnConfig('YAMN_NYM_SENDER', '/usr/local/bin/yamn-nym-submit');
- $recipient = yamnConfig('YAMN_NYM_RECIPIENT');
- $storage = yamnConfig('YAMN_NYM_STORAGE', '/var/lib/yamnweb/nym-client');
- $lockPath = yamnConfig('YAMN_NYM_LOCK', '/var/lib/yamnweb/nym-submit.lock');
+ $socketPath = yamnConfig('YAMN_NYM_SOCKET', '/run/yamnweb/nym-sender.sock');
$entryAddress = $selectedEntryAddress ?? yamnConfig('YAMN_ENTRY_ADDRESS');
- if (!is_executable($sender)) {
- return ['success' => false, 'error' => 'Nym sender is not available'];
- }
- if ($recipient === '' || strlen($recipient) > 512 || preg_match('/\s/', $recipient)) {
- return ['success' => false, 'error' => 'Nym recipient is not configured'];
+ if (
+ dirname($socketPath) !== '/run/yamnweb'
+ || basename($socketPath) === ''
+ || str_contains($socketPath, "\0")
+ ) {
+ return ['success' => false, 'error' => 'Nym sender socket is not configured correctly'];
}
if ($entryAddress === '' || strlen($entryAddress) > 320 || preg_match('/[\r\n\0\s]/', $entryAddress)) {
return ['success' => false, 'error' => 'YAMN entry address is not configured'];
@@ -49,66 +46,54 @@ function sendNymEnvelope(
return ['success' => false, 'error' => 'Unable to encode Nym request'];
}
- $lock = @fopen($lockPath, 'c');
- if ($lock === false) {
- return ['success' => false, 'error' => 'Nym sender lock is not available'];
- }
- if (!flock($lock, LOCK_EX | LOCK_NB)) {
- fclose($lock);
- return ['success' => false, 'error' => 'Nym sender is busy, please retry later'];
- }
-
- $descriptors = [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
- $environment = $_ENV;
- $environment['YAMN_NYM_RECIPIENT'] = $recipient;
- $environment['YAMN_NYM_STORAGE'] = $storage;
- $process = proc_open([$sender], $descriptors, $pipes, null, $environment);
- if (!is_resource($process)) {
- flock($lock, LOCK_UN);
- fclose($lock);
- return ['success' => false, 'error' => 'Unable to start Nym sender'];
+ $errno = 0;
+ $error = '';
+ $socket = @stream_socket_client(
+ 'unix://' . $socketPath,
+ $errno,
+ $error,
+ 3,
+ STREAM_CLIENT_CONNECT
+ );
+ if (!is_resource($socket)) {
+ return ['success' => false, 'error' => 'Nym sender is not available'];
}
+ stream_set_timeout($socket, 5);
$inputLength = strlen($input);
$offset = 0;
while ($offset < $inputLength) {
- $written = fwrite($pipes[0], substr($input, $offset));
+ $written = fwrite($socket, substr($input, $offset));
if ($written === false || $written === 0) {
break;
}
$offset += $written;
}
if ($offset !== $inputLength) {
- fclose($pipes[0]);
- proc_terminate($process);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($process);
- flock($lock, LOCK_UN);
- fclose($lock);
- return ['success' => false, 'error' => 'Unable to hand envelope to Nym sender'];
+ fclose($socket);
+ return ['success' => false, 'error' => 'Unable to queue envelope with Nym sender'];
}
- fclose($pipes[0]);
-
- if ($onHandoff !== null) {
- $onHandoff();
+ if (!stream_socket_shutdown($socket, STREAM_SHUT_WR)) {
+ fclose($socket);
+ return ['success' => false, 'error' => 'Unable to finish Nym queue request'];
}
- $stdout = stream_get_contents($pipes[1]);
- fclose($pipes[1]);
- $stderr = stream_get_contents($pipes[2]);
- fclose($pipes[2]);
- $status = proc_close($process);
- flock($lock, LOCK_UN);
- fclose($lock);
-
- if ($status !== 0) {
- return ['success' => false, 'error' => 'Nym submission failed'];
+ $responseText = stream_get_contents($socket, 4096);
+ $metadata = stream_get_meta_data($socket);
+ fclose($socket);
+ if (($metadata['timed_out'] ?? false) === true || !is_string($responseText)) {
+ return ['success' => false, 'error' => 'Nym sender did not accept the queue request'];
}
-
- $response = json_decode($stdout, true);
+ $response = json_decode($responseText, true);
if (!is_array($response) || ($response['success'] ?? false) !== true) {
- return ['success' => false, 'error' => 'Invalid response from Nym sender'];
+ $queueError = is_array($response) && is_string($response['error'] ?? null)
+ ? $response['error']
+ : 'Nym sender rejected the queue request';
+ return ['success' => false, 'error' => $queueError];
+ }
+
+ if ($onHandoff !== null) {
+ $onHandoff();
}
return ['success' => true];