From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id D82E81FF0C1 for ; Wed, 26 Aug 2026 11:29:51 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 0D14A215C4; Wed, 26 Aug 2026 11:29:21 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=g/EZU/5/Adm8KI6EOLwl+O+yC5fLSxeW7/3bqv2TBy9dtKGhq3sy9aIXnsjCv4wmhyHThhT7fMnJPAIMZQpXWAzTX8JjNtdEDZHG6jTfkL0mVSiUnzAYcVmJrF95Tpa1AARlIEVK8fQG4VmUfq4ab/1T538h//lLwoaXZ1awiRtywGymSaSbUWMj13KjusOeSs5Cdx5Y2duYLUMH+lp2UYtrdEQbRqjEj/hTpcHmMignnK67XYM3uB/2v0r4LE+xXi55Hn4PcYtfH3buu+KI+jOPlehGoDVy0Lg7saCTpaVut1WbD4eL6Ki/zAcpwDt08RuiQgHyyhhcS28OVCxX1Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=F5UOJ9KNWHmeTKQGkXq3OstQzDL+rE5o8hpm/c13BVU=; b=k2mk16ZrPIFcSZqx+CzkUDbobaFgT/VJoRrL8uR9nG4PPXznVhjEIrnbRCXbzkTKh4T+fc+3pLCNozWZ2rRNfQkAeODlypGWfrM/EJrLxD/BH/G9m4zELhgsuXlm7klXRkFEYUBpVGzgJP+lQAGtb/7ackp30JmDIxagkeBtqNDy6lBO0t+8hhaC20SVZ78dCBL/rpPySKpssfM8T7Ll4Lso6FsermmVpqlVQbremwhm6vpwRwJYIOFBTgY/dL2A1yshQ36SXIX8XGEH5wVuacu7wUBWGpbPQyEzasp1Vrwt06oUVrQ93N29adv4FHckFHxJbcA/X4T45UMiJ9zuNg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=groupe-cyllene.com; dmarc=pass action=none header.from=groupe-cyllene.com; dkim=pass header.d=groupe-cyllene.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=groupecyllene.onmicrosoft.com; s=selector2-groupecyllene-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=F5UOJ9KNWHmeTKQGkXq3OstQzDL+rE5o8hpm/c13BVU=; b=gcsoWofozFqswitiPB/fnEWWTb8LG+fIV3RSS8iA/UWq03K5NpJkAQQpYB63djBsrxod0b3iqt0a/N14E9L90QO47MO42UVcNNNS3fXrZ+fvWcBEuyD43eUNQhPizQO4SUADiUhuId9FYiJ7hDSBwjwWYUDnzshXR1StOVw68pU= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=groupe-cyllene.com; From: Alexandre Derumier To: pve-devel@lists.proxmox.com Subject: [RFC pve-rdp-web 13/13] add pve-rdp-web: console's webassembly client Date: Tue, 25 Aug 2026 13:34:38 +0200 Message-ID: <20260825113442.947620-14-alexandre.derumier@groupe-cyllene.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825113442.947620-1-alexandre.derumier@groupe-cyllene.com> References: <20260825113442.947620-1-alexandre.derumier@groupe-cyllene.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-ClientProxiedBy: PR3P192CA0021.EURP192.PROD.OUTLOOK.COM (2603:10a6:102:56::26) To PR0P264MB3691.FRAP264.PROD.OUTLOOK.COM (2603:10a6:102:14b::12) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PR0P264MB3691:EE_|PATP264MB7783:EE_ X-MS-Office365-Filtering-Correlation-Id: 1fc2738b-bb96-4f13-d4a8-08df029ce7aa X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|52116014|376014|1800799024|23010399003|366016|13003099007|38350700014|6133799003|3023799007|56012099006|10067099003|5023799004|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: 5oACzVoXmeXOz8QPWtJhcKIkOLCI9GpY6dh7juaTlZY8SL5EXhAM2V441QX3tmRfL2Bk6+aaCmtzZCF2SCrMjMTiYjPUJSSISeoxEvGV4IxZG+PFfDftas1B3JM5dxmxmURHRu5+4P59qouhEKPn74QUIBSPzyhXLpwekxCjM/NaZNDMGsv7/DFosHpz6aM4ozQMR3S1MC11iFlhNXYHkJ+2ao+Ya+RLs3cZ3yDX6QfIHHVdRAbYQOPxuBMQgzMZ1+lGHeuC2zB7NpF0hUVgH1bebNWjpETadlGhG1scp+FlpD0dOilIAHsJIFs58qClhbwgP9+fCssZVomZax/fdIV4Nod5MHYxqn/BAw0Fvta2lJDIwyP6e1xUDaEEFDli+BvKVJc881b5HjGrO1dGohbyklbRKvf3Vcndx1H6HQWZob7Lb9wCe3ZYuXpEvQLE9UUKXpfa0a6MzlNtZ7dJf62PkZ9UNCDcCgkwDl1cFZ9l+ygrO1ooYaxBG6yt3dcf6uefdZtnTx5se8p+tkQpphphGu1lvFVPnuGLr4m172YiN+0OfRfbM2w7sFHkAnbYVq+8SCNPYZ7qPKc0DncYDdI680k4IzJX6Efwi8Zep9n0HzNtzcBXGW4jVBqNriJYPUf0TXB16VuIKAxpC0NtUEYbLGav4vBXKhQsOWd84ktGlLJVNS/rXf5AIgvtXaffi/GqMFdgAdlfmO3LHX2PGC+cgL7/vao31xHO38/3ZdY= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PR0P264MB3691.FRAP264.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(52116014)(376014)(1800799024)(23010399003)(366016)(13003099007)(38350700014)(6133799003)(3023799007)(56012099006)(10067099003)(5023799004)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?MDBVbG8rVmx1czVweFZTdUVWUVY1WGw3Q2RDbG5zZm0rOG1wWjZoMWhnTXpV?= =?utf-8?B?YnpIaFkrem16SHY5eVJmQW1jWStpZ2hWUURDb1l4SW5wMEloVktabGw4NzBu?= =?utf-8?B?R2xrR0x4SklETEhxbzhxNVdReFMrSGZYM0lrRDRsVUJiN0N4SHpIaEVQbTk5?= =?utf-8?B?RTJscTBURk5UcVVkekRmSlJlZ3Jkd2dGQURFMUxnQnh3L2o5NEVUK082M08x?= =?utf-8?B?WEZaTUZiVjNZZVFLdEFSTDRHbWxqMVVMNjY0bG9sbHdSWGg0eURpdkszVVlO?= =?utf-8?B?K01FUmRsYmc0OFdSMUNvb1hHZXJydzhtbC9GdUkrMzZuSksxTW5hS0tLcVVO?= =?utf-8?B?M3JWUjk3bFhHK2oxT1dQNUlHKzZJSjVHc1k4TFI4cHVEUnlyek93STBLdFNw?= =?utf-8?B?M2x4TGtLNXN1US9qN1pJWHo3VTdjbFppNEptQVZjQmxEQVQzSE1qZXFrbFBD?= =?utf-8?B?RlVuTDk3UnV4KzRERnpjMFlkMG1NMzRwMnJmdDE4MlRZWjFXcnRiVGNJNThm?= =?utf-8?B?ZzMxQmFSTjlMUkF4QWY5N3hEeUE5aldxVk82a0M4MzJ0ZnVMSUZKSENrNFhy?= =?utf-8?B?N1NEVmdWcUwvclJrS0tKcVMvZXh5a2tLSm1VRUNjdnJYS01vYW1RUmYzUWhw?= =?utf-8?B?R3VnQ1lJNWRVTUFTRmNhS3RlRTh6c1BoOUo1QmJScUFpV21selpidUMyb0tC?= =?utf-8?B?OHBvdUN1Q3NwZ2NKOFhmaCtNVjhLUzZ0NStFUlpjT1Uwb0YzQU5haFhSQ2cr?= =?utf-8?B?RUdDVGVkc3FKTDZuM3ZqYnRieUp2SUl0dkFrWFc4MllwRFMzb2hPWjBjN1Rm?= =?utf-8?B?VHZERVIwd01FbWlGTXQ0cXJpTjZpOTRWL2R2ejNzWUZjeENOaHB5aVYrMFJ2?= =?utf-8?B?OW5jTCtkTGpmaDl2WElnYlV3WlA3bnFldXNmdFZpc21IS3IyS1JoNVg3K1I5?= =?utf-8?B?aWM2aGxYV2FSWEFaZ2ZlNWdvYmV2eFNodjQxcGR5aEN2VlorRDNSbmRZQ2li?= =?utf-8?B?VmY3U080b21pZXZULzFuTk1Dei9hSlNzYVNvSGpHVmQ2SnYvZ05vcHhNcFMv?= =?utf-8?B?NWVtMmZnQmtWdHZsbk8xRW9yTnhqbEN5L2c1MmdpVWhqdHVvS3ZkcTZMcW5I?= =?utf-8?B?NlVpWGxKang2T2NYU3RmVHpBZVFaa2VBSG51OW80OU9xbjRldkUxUjJHOFNE?= =?utf-8?B?ODU0WHU4UDBYOW5ic0ZzRUIvZ0hQWW5jcnQ2S3hqQkxnN05xUUxJQ2lPbEF6?= =?utf-8?B?NGRIekhNbXBPNURkdWlTVnJzd0htTi9UZ0pKeTdpTDRGdlVnd3VnTlBmbVAw?= =?utf-8?B?K2NaeTJGY05uQVI3cTd2QnJwMXczVE42L29LcDdrcUNBTnhOQ1pFNWl3K0NX?= =?utf-8?B?dkNhWUhadUlwOHBCUDdCa0lpNXRCWm5Tc1BFeWhYdm5zVjhmZEkram4rSG5I?= =?utf-8?B?Z1d2UjR4UWl1bE03cEtvTjJ4eDU4Z2NLVVc3dlh2eUNEb3ZGQ0UyclFvSnlG?= =?utf-8?B?eDZlZXJiUExVcHF6RGR4eWZYN1hDM0E4ZEFVdStRYjgwbEJFL3c0cTNxNWJR?= =?utf-8?B?MXFEZmI0VFN5MmZDa3BFZmFSOWt2V2l0cXJNNEtjdkxzLytPNzR1V2Y0NEZh?= =?utf-8?B?dDJEY2sxbzUzZkNlS2M4c01lVEdBS3p3VmFWOVdPY0RFR2pSRjRWT3VaUDNV?= =?utf-8?B?R2pFMDZwMzVSeERJdUhnNDcrVThyaSs0aTJJcG5sWmtHWHVVOUYvQXVzY1dp?= =?utf-8?B?bW9YbnJzQlF5WWNEckcvaEhRVGdhOVg3d0hLcHFYRGlpbXg4b0VwTnFFNGpT?= =?utf-8?B?dGtvWkJCR0lMSWRTK3RNdEwyK29KMk5uOVRVelRsbEc1ODBqalZQZXVObWRF?= =?utf-8?B?Rnp5ZFY1dEFnNy8xT0FwZndLZzhjOHY5UW91SStQaE5wSGdyTjR6cVlpb0xY?= =?utf-8?B?MlRPSHA2Zlo3WkF1bnA1Mk1lcDBBSldsa1BWWkcwbUxRWjJuNVVVS3RHejVQ?= =?utf-8?B?bk9uYmlWNlhIZ0JTZmdaYWkxSHFsdEdCbkJuRERPSEQxbmRnRU1td1dLMkxX?= =?utf-8?B?Q0NIWFB3WUltcTlib3k3UGNBb01ZczJnQzlaT09TQnJHdTc3WG5Ld01qMmZM?= =?utf-8?B?eUV3dEllQ0JBRjZYL1N3M29CeTRrNk1MejBGdFM3Z3JweHk0RFl1S2xsQndw?= =?utf-8?B?UFZYTlhZRllpS2Z3Mmd1NXFidmNqbnpwREFOS3ZvenpZWExXWm9ldVRPdzhl?= =?utf-8?B?Yi9zNVRlell4Q1dWTmJTdTVzb0FudWJ3UXdvekErN3doa0tQTG1wek81bXJ0?= =?utf-8?B?WjVRaXdkNEgxTmpEdHlqdFZsTGZVaVozc2JscytZTGRCMVhaY1k0YUIyUHpk?= =?utf-8?Q?kU53Lo/CIEs9GVXWOjp44KSvzFFjSpMAm3yXV?= X-OriginatorOrg: groupe-cyllene.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1fc2738b-bb96-4f13-d4a8-08df029ce7aa X-MS-Exchange-CrossTenant-AuthSource: PR0P264MB3691.FRAP264.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Aug 2026 11:35:03.7586 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: ee11ccf7-112c-4284-848b-f229745e715b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: yfee6EuRIfmOfRC0nlKeCgH+4+GVVMrs2Se1wGSDelNcaxcM3UrdrN51oqotWRwLoTnj/8XPWDHOByw+gmox2PZQX9O2Rqa4hodU2XusgcDpNDEOykucYUhVJjPX5fTj X-MS-Exchange-Transport-CrossTenantHeadersStamped: PATP264MB7783 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.059 Adjusted score from AWL reputation of From: address DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DMARC_PASS -0.1 DMARC pass policy KAM_LOTSOFHASH 0.25 Emails with lots of hash-like gibberish POISEN_SPAM_PILL 0.1 Meta: its spam POISEN_SPAM_PILL_1 0.1 random spam to be learned in bayes RCVD_IN_DNSWL_NONE -0.0001 Sender listed at https://www.dnswl.org/, no trust SPF_HELO_PASS -0.001 SPF: HELO matches SPF record SPF_PASS -0.001 SPF: sender matches SPF record X-MailFrom: Alexandre.DERUMIER@groupe-cyllene.com X-Mailman-Rule-Hits: max-size X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; news-moderation; no-subject; digests; suspicious-header Message-ID-Hash: XVCBKAYUD7O6VILNEDTHIRB7RL5VTD6L X-Message-ID-Hash: XVCBKAYUD7O6VILNEDTHIRB7RL5VTD6L X-Mailman-Approved-At: Wed, 26 Aug 2026 11:28:46 +0200 X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: The console page use IronRDP WASM SDK directly, with some modifications: - 0001 pins ironrdp-web by revision and add qoi/qoiz compression instead Rremote FX. - ironrdp/add_audio_support plays guest audio Signed-off-by: Alexandre Derumier --- .gitignore | 5 + .gitmodules | 3 + Cargo.lock | 4100 +++++++++++++++++ Makefile | 149 + debian/changelog | 5 + debian/control | 19 + debian/copyright | 38 + debian/install | 1 + debian/rules | 10 + debian/source/format | 1 + ironrdp-wasm | 1 + js/rdp-audio-worklet.js | 106 + js/rdp-audio.js | 222 + .../0001-pin-ironrdp-web-to-a-revision.patch | 33 + patches/ironrdp/add_audio_support.patch | 362 ++ 15 files changed, 5055 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Cargo.lock create mode 100644 Makefile create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/install create mode 100755 debian/rules create mode 100644 debian/source/format create mode 160000 ironrdp-wasm create mode 100644 js/rdp-audio-worklet.js create mode 100644 js/rdp-audio.js create mode 100644 patches/0001-pin-ironrdp-web-to-a-revision.patch create mode 100644 patches/ironrdp/add_audio_support.patch diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b35dabf --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/sdk/ +/pve-rdp-web-[0-9]*/ +*.deb +*.changes +*.buildinfo diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..731b9c1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ironrdp-wasm"] + path = ironrdp-wasm + url = https://github.com/electerm/ironrdp-wasm.git diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c2237b3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4100 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addchain" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" +dependencies = [ + "num-bigint 0.3.3", + "num-integer", + "num-traits", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99" +dependencies = [ + "crypto-common 0.2.2", + "inout", +] + +[[package]] +name = "aes" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58" +dependencies = [ + "cipher", + "cpubits", + "cpufeatures 0.3.0", +] + +[[package]] +name = "aes-gcm" +version = "0.11.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da8c919c118108f144adecad74b425b804ad075580d605d9b33c2d6d1c62a2f8" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aes-kw" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ac571010bd60765c56085a4f1d412012a9be2663b1a2f2b19b49318653fd0d" +dependencies = [ + "aes", + "const-oid 0.10.2", +] + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "asn1-rs" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-dnssd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d49ffe175ab45bbfd74b548313d9d7cdfff27161a94b007b52eeeb5f9aaa15e" +dependencies = [ + "bitflags 1.3.2", + "futures-channel", + "futures-core", + "futures-executor", + "futures-util", + "libc", + "log", + "pin-utils", + "pkg-config", + "tokio", + "winapi", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "aws-lc-rs" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2b2dcc879c3bae0d371e77c99f2238400ef24ec001394befa67b6e543add9e" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09fae7be8bb3174e05c6afdb34199e6dc0c7c04ba9fa237b1967adfbde27483" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] + +[[package]] +name = "base16ct" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" + +[[package]] +name = "bitvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "block-padding" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "cbc" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509591b7bcd67f4ef775afad7662703b4935daaa6ec0e5605cfb1090b32a2b6d" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" +dependencies = [ + "block-buffer 0.12.1", + "crypto-common 0.2.2", + "inout", +] + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crypto-bigint" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a52aa3fcda4e6302a9f48734f234d35d4721b96f8fe07d073f07ce9df4f0271" +dependencies = [ + "cpubits", + "ctutils", + "getrandom 0.4.3", + "hybrid-array", + "num-traits", + "rand_core 0.10.1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "getrandom 0.4.3", + "hybrid-array", + "rand_core 0.10.1", +] + +[[package]] +name = "crypto-mac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-primes" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3633a51a39c69ebbaa4feaa694bd83d241e4093901c84a0963b19d9bb3f0cf8f" +dependencies = [ + "crypto-bigint", + "rand_core 0.10.1", +] + +[[package]] +name = "cryptoki" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff765b99fc49f3116c9a908484486a2b92fd73c48da45c3a69716471c6cc56c6" +dependencies = [ + "bitflags 2.13.1", + "cryptoki-sys", + "libloading", + "log", + "secrecy", +] + +[[package]] +name = "cryptoki-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fd850498411e4057f1cba79e6e2bc7cbe960544c1046ab46d4685c403a1121" +dependencies = [ + "libloading", +] + +[[package]] +name = "ctr" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21" +dependencies = [ + "cipher", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c906a87e53a36ff795d72e06e8162a83c5436e3ea89e942a9cb9fc083f0a384f" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "curve25519-dalek-derive", + "digest 0.11.3", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "data-encoding" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid 0.9.6", + "zeroize", +] + +[[package]] +name = "der" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d" +dependencies = [ + "const-oid 0.10.2", + "der_derive", + "flagset", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59600e2c2d636fde9b65e99cc6445ac770c63d3628195ff39932b8d6d7409903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "des" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916a94e407b54f9034d71dd748234cd1e516ced6284009906ae246f177eafe5a" +dependencies = [ + "cipher", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common 0.1.7", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "const-oid 0.10.2", + "crypto-common 0.2.2", + "ctutils", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.17.0-rc.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c72d1455753a703ad4b90ed2a759f2bc4562024a303176439cf6e593b5ade4" +dependencies = [ + "der 0.8.1", + "digest 0.11.3", + "elliptic-curve", + "rfc6979", + "signature", + "spki 0.8.0", + "zeroize", +] + +[[package]] +name = "ed25519" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "3.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1685663e23882cd8517dcbcb1c23a6ebff4433c22dfb681d760219b62cd1b849" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.10.1", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + +[[package]] +name = "elliptic-curve" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d65aa39b3a5c1c9c1b745c9a019234bb7a21b77abcb4f4d266d706e2d577d65" +dependencies = [ + "base16ct", + "crypto-bigint", + "crypto-common 0.2.2", + "digest 0.11.3", + "ff", + "group", + "hkdf", + "hybrid-array", + "pem-rfc7468", + "pkcs8 0.11.0", + "rand_core 0.10.1", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "ff" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f" +dependencies = [ + "rand_core 0.10.1", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "find-msvc-tools" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" + +[[package]] +name = "flagset" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "libz-sys", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-executor" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-macro" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5" +dependencies = [ + "polyval", +] + +[[package]] +name = "gloo-net" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6420f887c48417e9e86c6cf61274eb231830cccc100e49613f7952e269a1fe1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "482ce8a491a501da4cd806bd190275363d674f2845005c6ddbd5d3e1dd54495d" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4202275d95a142fa209a1e35e91c250a710c5600731372cd3464a39ed01573d6" +dependencies = [ + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "group" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4" +dependencies = [ + "ff", + "rand_core 0.10.1", + "subtle", +] + +[[package]] +name = "h2" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" +dependencies = [ + "hmac 0.13.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.3", +] + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hybrid-array" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +dependencies = [ + "subtle", + "typenum", + "zeroize", +] + +[[package]] +name = "hyper" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" + +[[package]] +name = "icu_properties" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" + +[[package]] +name = "icu_provider" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92a7ed671a6aad807a8651a2e1782a6598fda9ce5185dd8158549e95a91c6428" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "inout" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +dependencies = [ + "block-padding", + "hybrid-array", +] + +[[package]] +name = "ipnet" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" + +[[package]] +name = "iron-remote-desktop" +version = "0.7.1" +dependencies = [ + "console_error_panic_hook", + "tracing", + "tracing-subscriber", + "tracing-web", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ironrdp" +version = "0.17.0" +dependencies = [ + "ironrdp-client", + "ironrdp-cliprdr", + "ironrdp-connector", + "ironrdp-core", + "ironrdp-displaycontrol", + "ironrdp-dvc", + "ironrdp-graphics", + "ironrdp-input", + "ironrdp-pdu", + "ironrdp-rdpdr", + "ironrdp-rdpsnd", + "ironrdp-server", + "ironrdp-session", + "ironrdp-svc", +] + +[[package]] +name = "ironrdp-acceptor" +version = "0.10.0" +dependencies = [ + "ironrdp-async", + "ironrdp-connector", + "ironrdp-core", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + +[[package]] +name = "ironrdp-ainput" +version = "0.8.0" +dependencies = [ + "bitflags 2.13.1", + "ironrdp-core", + "ironrdp-dvc", + "num-derive 0.5.1", + "num-traits", +] + +[[package]] +name = "ironrdp-async" +version = "0.10.0" +dependencies = [ + "bytes", + "ironrdp-connector", + "ironrdp-core", + "ironrdp-pdu", + "tracing", +] + +[[package]] +name = "ironrdp-bulk" +version = "0.1.1" + +[[package]] +name = "ironrdp-cfg" +version = "0.1.0" +dependencies = [ + "ironrdp-propertyset", +] + +[[package]] +name = "ironrdp-client" +version = "0.1.0" +dependencies = [ + "anyhow", + "futures-util", + "ironrdp-cfg", + "ironrdp-connector", + "ironrdp-core", + "ironrdp-displaycontrol", + "ironrdp-dvc", + "ironrdp-echo", + "ironrdp-graphics", + "ironrdp-pdu", + "ironrdp-propertyset", + "ironrdp-rail", + "ironrdp-rdcleanpath", + "ironrdp-rdpei", + "ironrdp-session", + "ironrdp-svc", + "ironrdp-tls", + "ironrdp-tokio", + "smallvec", + "tokio", + "tokio-tungstenite", + "tracing", + "url", + "x509-cert", +] + +[[package]] +name = "ironrdp-cliprdr" +version = "0.7.0" +dependencies = [ + "bitflags 2.13.1", + "ironrdp-core", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + +[[package]] +name = "ironrdp-cliprdr-format" +version = "0.2.0" +dependencies = [ + "ironrdp-core", + "png", +] + +[[package]] +name = "ironrdp-connector" +version = "0.10.0" +dependencies = [ + "ironrdp-core", + "ironrdp-error", + "ironrdp-pdu", + "ironrdp-svc", + "picky", + "picky-asn1-der", + "picky-asn1-x509", + "rand 0.9.5", + "sspi", + "tracing", + "url", +] + +[[package]] +name = "ironrdp-core" +version = "0.2.1" +dependencies = [ + "ironrdp-error", +] + +[[package]] +name = "ironrdp-displaycontrol" +version = "0.8.0" +dependencies = [ + "ironrdp-core", + "ironrdp-dvc", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + +[[package]] +name = "ironrdp-dvc" +version = "0.8.0" +dependencies = [ + "ironrdp-core", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + +[[package]] +name = "ironrdp-echo" +version = "0.4.0" +dependencies = [ + "ironrdp-core", + "ironrdp-dvc", + "ironrdp-pdu", + "tracing", +] + +[[package]] +name = "ironrdp-error" +version = "0.2.0" + +[[package]] +name = "ironrdp-futures" +version = "0.8.0" +dependencies = [ + "futures-util", + "ironrdp-async", +] + +[[package]] +name = "ironrdp-graphics" +version = "0.9.0" +dependencies = [ + "bit_field", + "bitflags 2.13.1", + "bitvec", + "byteorder", + "ironrdp-core", + "ironrdp-pdu", + "num-derive 0.5.1", + "num-traits", + "wide", + "yuv", +] + +[[package]] +name = "ironrdp-input" +version = "0.7.0" +dependencies = [ + "bitvec", + "ironrdp-pdu", + "smallvec", +] + +[[package]] +name = "ironrdp-pdu" +version = "0.9.0" +dependencies = [ + "bit_field", + "bitflags 2.13.1", + "byteorder", + "der-parser", + "hmac 0.12.1", + "ironrdp-core", + "ironrdp-error", + "md-5 0.10.6", + "num-bigint 0.4.8", + "num-derive 0.5.1", + "num-integer", + "num-traits", + "pkcs1 0.7.5", + "sha1 0.11.0", + "tap", + "x509-cert", +] + +[[package]] +name = "ironrdp-propertyset" +version = "0.1.0" + +[[package]] +name = "ironrdp-rail" +version = "0.1.0" +dependencies = [ + "ironrdp-core", + "ironrdp-svc", +] + +[[package]] +name = "ironrdp-rdcleanpath" +version = "0.2.2" +dependencies = [ + "der 0.8.1", +] + +[[package]] +name = "ironrdp-rdpdr" +version = "0.7.0" +dependencies = [ + "bitflags 2.13.1", + "getrandom 0.3.4", + "ironrdp-core", + "ironrdp-error", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + +[[package]] +name = "ironrdp-rdpei" +version = "0.1.0" +dependencies = [ + "bitflags 2.13.1", + "ironrdp-core", + "ironrdp-dvc", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + +[[package]] +name = "ironrdp-rdpfile" +version = "0.1.0" +dependencies = [ + "ironrdp-propertyset", +] + +[[package]] +name = "ironrdp-rdpsnd" +version = "0.9.0" +dependencies = [ + "bitflags 2.13.1", + "ironrdp-core", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + +[[package]] +name = "ironrdp-server" +version = "0.13.0" +dependencies = [ + "anyhow", + "async-trait", + "bytes", + "ironrdp-acceptor", + "ironrdp-ainput", + "ironrdp-async", + "ironrdp-cliprdr", + "ironrdp-core", + "ironrdp-displaycontrol", + "ironrdp-dvc", + "ironrdp-echo", + "ironrdp-graphics", + "ironrdp-pdu", + "ironrdp-rdpsnd", + "ironrdp-svc", + "ironrdp-tokio", + "qoicoubeh", + "rand 0.9.5", + "rayon", + "rustls-pemfile", + "tokio", + "tokio-rustls", + "tracing", + "x509-cert", + "zstd-safe", +] + +[[package]] +name = "ironrdp-session" +version = "0.11.0" +dependencies = [ + "ironrdp-bulk", + "ironrdp-core", + "ironrdp-displaycontrol", + "ironrdp-dvc", + "ironrdp-error", + "ironrdp-graphics", + "ironrdp-pdu", + "ironrdp-rdpei", + "ironrdp-svc", + "qoicoubeh", + "tracing", + "zstd-safe", +] + +[[package]] +name = "ironrdp-svc" +version = "0.8.0" +dependencies = [ + "bitflags 2.13.1", + "ironrdp-core", + "ironrdp-pdu", +] + +[[package]] +name = "ironrdp-tls" +version = "0.2.2" +dependencies = [ + "tokio", +] + +[[package]] +name = "ironrdp-tokio" +version = "0.10.0" +dependencies = [ + "ironrdp-async", + "ironrdp-connector", + "reqwest", + "tokio", + "url", +] + +[[package]] +name = "ironrdp-vmconnect" +version = "0.1.0" +dependencies = [ + "ironrdp-async", + "ironrdp-connector", + "ironrdp-core", + "ironrdp-pdu", + "tracing", +] + +[[package]] +name = "ironrdp-web" +version = "0.0.0" +dependencies = [ + "anyhow", + "base64", + "chrono", + "futures-channel", + "futures-util", + "getrandom 0.2.17", + "getrandom 0.3.4", + "getrandom 0.4.3", + "gloo-net", + "gloo-timers", + "iron-remote-desktop", + "ironrdp", + "ironrdp-cliprdr-format", + "ironrdp-core", + "ironrdp-futures", + "ironrdp-pdu", + "ironrdp-propertyset", + "ironrdp-rdcleanpath", + "ironrdp-rdpfile", + "ironrdp-svc", + "ironrdp-vmconnect", + "js-sys", + "png", + "resize", + "rgb", + "semver", + "smallvec", + "tap", + "time", + "tracing", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "x509-cert", +] + +[[package]] +name = "iso7816" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c7e91da489667bb054f9cd2f1c60cc2ac4478a899f403d11dbc62189215b0" +dependencies = [ + "heapless", +] + +[[package]] +name = "iso7816-tlv" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7660d28d24a831d690228a275d544654a30f3b167a8e491cf31af5fe5058b546" +dependencies = [ + "untrusted", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd9697dc4a9a62e2da93389f34400b77a28f0287711263cabb203b3ccb9c0e4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libz-sys" +version = "1.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest 0.11.3", +] + +[[package]] +name = "md4" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da5ac363534dce5fabf69949225e174fbf111a498bf0ff794c8ea1fba9f3dda" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "num-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e98dc3b890f6c23a0f9d3d491a2823d0dea0fa656302a13dd225fa924112a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "oid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c19903c598813dba001b53beeae59bb77ad4892c5c1b9b3500ce4293a0d06c2" +dependencies = [ + "serde", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "p256" +version = "0.14.0-rc.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c855a8d2ffd346aa03122626f22e96e3aa75e3bfe64e6bf6cb82f71821ed6ae7" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.14.0-rc.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62941b68907ddf996ac20f0debf700c236ccc3d874637731a93c631129ca042f" +dependencies = [ + "ecdsa", + "elliptic-curve", + "fiat-crypto", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.14.0-rc.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd6f2fe6e76c8d5e8828e92aafa463777d1e72e70b78acc724214757e92479a" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "pbkdf2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629" +dependencies = [ + "digest 0.11.3", + "hmac 0.13.0", +] + +[[package]] +name = "pem-rfc7468" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "picky" +version = "7.0.0-rc.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ae9cd78eb1d61be4790713d28368cf71c844218fcd91542768805423f02666" +dependencies = [ + "aes", + "aes-gcm", + "aes-kw", + "base64", + "cbc", + "crypto-bigint", + "crypto-common 0.2.2", + "ctr", + "curve25519-dalek", + "des", + "digest 0.11.3", + "ecdsa", + "ed25519-dalek", + "hex", + "hmac 0.13.0", + "http", + "inout", + "md-5 0.11.0", + "p256", + "p384", + "p521", + "pbkdf2", + "picky-asn1", + "picky-asn1-der", + "picky-asn1-x509", + "pkcs1 0.8.0-rc.4", + "primeorder", + "rand 0.10.2", + "rand_core 0.10.1", + "rc2", + "rsa", + "rustcrypto-ff", + "rustcrypto-ff_derive", + "rustcrypto-group", + "serde", + "serde_json", + "sha1 0.11.0", + "sha2", + "sha3", + "thiserror", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "picky-asn1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ff038f9360b934342fb3c0a1d6e82c438a2624b51c3c6e3e6d7cf252b6f3ee3" +dependencies = [ + "oid", + "serde", + "serde_bytes", + "time", + "zeroize", +] + +[[package]] +name = "picky-asn1-der" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d413165e4bf7f808b9a27cbaba657657a2921f0965db833f488c4d4be96dcd2e" +dependencies = [ + "picky-asn1", + "serde", + "serde_bytes", +] + +[[package]] +name = "picky-asn1-x509" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d4117bd1b1dc5646359ee7243c50c5000c0920ea2d1fb120335a2f4c684b8" +dependencies = [ + "base64", + "crypto-bigint", + "oid", + "picky-asn1", + "picky-asn1-der", + "serde", + "widestring", + "zeroize", +] + +[[package]] +name = "picky-krb" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d188f3192356068dbdba54bddbca6fd0f7a09565d3861eeb8efe1ab77ae8e97" +dependencies = [ + "aes", + "block-padding", + "byteorder", + "cbc", + "cipher", + "crypto-bigint", + "des", + "hmac 0.13.0", + "inout", + "oid", + "pbkdf2", + "picky-asn1", + "picky-asn1-der", + "picky-asn1-x509", + "rand 0.10.2", + "rand_core 0.10.1", + "serde", + "sha1 0.11.0", + "thiserror", + "uuid", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der 0.7.10", + "pkcs8 0.10.2", + "spki 0.7.3", +] + +[[package]] +name = "pkcs1" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e" +dependencies = [ + "der 0.8.1", + "spki 0.8.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.10", + "spki 0.7.3", +] + +[[package]] +name = "pkcs8" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" +dependencies = [ + "der 0.8.1", + "spki 0.8.0", +] + +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polyval" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" +dependencies = [ + "cpubits", + "cpufeatures 0.3.0", + "universal-hash", +] + +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primefield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c555a6e4eb7d4e158fcb028c835c3b8642206ddc279b5c6b202ef9a8bdb592f4" +dependencies = [ + "crypto-bigint", + "crypto-common 0.2.2", + "ff", + "rand_core 0.10.1", + "subtle", + "zeroize", +] + +[[package]] +name = "primeorder" +version = "0.14.0-rc.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e56e6d67fdf5744e9e245ae571450fe584b91f5af261d0e40163b618e53a1f6" +dependencies = [ + "elliptic-curve", + "once_cell", + "primefield", + "serdect", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qoicoubeh" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b82aa3fef8a980075775b8c46f874823b5b4a15de327d2dbb3b6fd818480ba" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rc2" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceda21af1ae61033b63175653a1af86cae399d79cd03ca80ba347eb3a6c4a7fe" +dependencies = [ + "cipher", +] + +[[package]] +name = "rdp-client" +version = "0.1.0" +dependencies = [ + "ironrdp-web", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64", + "bytes", + "futures-core", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "resize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71725ecd5e0197b54fe859055b108688472ab6a358f8fbe5cee4a556b1b5bfea" +dependencies = [ + "rgb", +] + +[[package]] +name = "rfc6979" +version = "0.6.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9935425142ac6e252364413291d96c8bc9898d0876a801824c7af4eae397b689" +dependencies = [ + "ctutils", + "hmac 0.13.0", +] + +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rsa" +version = "0.10.0-rc.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b2aa4ba0d89f73d1e332df05be0eeab8840351c36ca5654341dfdb57bb3caf" +dependencies = [ + "const-oid 0.10.2", + "crypto-bigint", + "crypto-primes", + "digest 0.11.3", + "pkcs1 0.8.0-rc.4", + "pkcs8 0.11.0", + "rand_core 0.10.1", + "signature", + "spki 0.8.0", + "zeroize", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustcrypto-ff" +version = "0.14.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd2a8adb347447693cd2ba0d218c4b66c62da9b0a5672b17b981e4291ec65ff6" +dependencies = [ + "bitvec", + "rand_core 0.10.1", + "rustcrypto-ff_derive", + "subtle", +] + +[[package]] +name = "rustcrypto-ff_derive" +version = "0.14.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cda22ea03582974ab5687fc131eba2dc78e258e7eef4d7e01bcd0522ed79f66" +dependencies = [ + "addchain", + "num-bigint 0.3.3", + "num-integer", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rustcrypto-group" +version = "0.14.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "369f9b61aa45933c062c9f6b5c3c50ab710687eca83dd3802653b140b43f85ed" +dependencies = [ + "rand_core 0.10.1", + "rustcrypto-ff", + "subtle", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustls" +version = "0.23.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" +dependencies = [ + "base16ct", + "ctutils", + "der 0.8.1", + "hybrid-array", + "subtle", + "zeroize", +] + +[[package]] +name = "secrecy" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serdect" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + +[[package]] +name = "sha3" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9bad02c26382724b2d2692c6f179285e4b54eeecd7968f52a50059c3c11759" +dependencies = [ + "digest 0.11.3", + "keccak", + "sponge-cursor", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signature" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" +dependencies = [ + "digest 0.11.3", + "rand_core 0.10.1", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.10", +] + +[[package]] +name = "spki" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" +dependencies = [ + "base64ct", + "der 0.8.1", +] + +[[package]] +name = "sponge-cursor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" + +[[package]] +name = "sspi" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3bd2a45e7e24fd72eba100ced3fd847e05fe4657d7f067eb06d1a894f0d4e5" +dependencies = [ + "async-dnssd", + "async-recursion", + "bitflags 2.13.1", + "bytemuck", + "byteorder", + "cfg-if", + "crypto-bigint", + "crypto-mac", + "cryptoki", + "curve25519-dalek", + "ed25519-dalek", + "futures", + "getrandom 0.3.4", + "hmac 0.13.0", + "md-5 0.11.0", + "md4", + "num-derive 0.4.2", + "num-traits", + "oid", + "p256", + "p384", + "p521", + "picky", + "picky-asn1", + "picky-asn1-der", + "picky-asn1-x509", + "picky-krb", + "pkcs1 0.8.0-rc.4", + "primeorder", + "rand 0.10.2", + "rand_core 0.10.1", + "rsa", + "rustcrypto-ff", + "rustcrypto-ff_derive", + "rustcrypto-group", + "rustls", + "serde", + "sha1 0.11.0", + "sha2", + "time", + "tokio", + "tracing", + "url", + "uuid", + "widestring", + "windows", + "windows-registry", + "winscard", + "zeroize", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.13.1", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "js-sys", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tokio" +version = "1.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "libc", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.1", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-web" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e6a141feebd51f8d91ebfd785af50fca223c570b86852166caa3b141defe7c" +dependencies = [ + "js-sys", + "tracing-core", + "tracing-subscriber", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.5", + "sha1 0.10.7", + "thiserror", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "universal-hash" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" +dependencies = [ + "crypto-common 0.2.2", + "ctutils", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cefc03fd367c0c6d4305de1b312cf00248c4114f4a0418ce6a6af769e3b0bd9" +dependencies = [ + "getrandom 0.4.3", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winscard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dafb3c1468d0a3f5440e21e51614b53d1fdc62c9f82cc861c447906d09c69a" +dependencies = [ + "bitflags 2.13.1", + "crypto-bigint", + "flate2", + "iso7816", + "iso7816-tlv", + "num-derive 0.4.2", + "num-traits", + "picky", + "picky-asn1-x509", + "rsa", + "sha1 0.11.0", + "time", + "tracing", + "uuid", + "widestring", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x25519-dalek" +version = "3.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee64e8620caa64914d669b1f68f858aaff54e2d0f9ad3b30a613b58a1baa83e" +dependencies = [ + "curve25519-dalek", + "rand_core 0.10.1", + "zeroize", +] + +[[package]] +name = "x509-cert" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "105ef4642d9cb137ef83d623d0e4bf08b8adf69e9918ca904a174adb6d3d038b" +dependencies = [ + "const-oid 0.10.2", + "der 0.8.1", + "spki 0.8.0", + "tls_codec", +] + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + +[[package]] +name = "yuv" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220655e1c245693beb13b377d3174b9efcb1645018d1d4ec53903fc211b135ae" +dependencies = [ + "num-traits", +] + +[[package]] +name = "zerocopy" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b5c6b5976d66c1d703c4fd17d3f5e43c8cedaacf604961b171adc7130896d8" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f212a141d820099d57ffafb9569be9617a6f27d3dc881fbee8fb56642f917a9" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0eb470c --- /dev/null +++ b/Makefile @@ -0,0 +1,149 @@ +include /usr/share/dpkg/architecture.mk +include /usr/share/dpkg/pkg-info.mk + +PACKAGE=pve-rdp-web +DEB=$(PACKAGE)_$(DEB_VERSION)_all.deb +DSC=$(PACKAGE)_$(DEB_VERSION).dsc +BUILDDIR=$(PACKAGE)-$(DEB_VERSION_UPSTREAM) + +# ironrdp-wasm: MIT like this package, but a separate upstream, so it is cloned +# at build time rather than vendored or carried as a submodule. This repo then +# holds nothing but packaging, and the revision it builds is one greppable line +# rather than a gitlink you need `git log` to read. +# +# The crate itself is two lines re-exporting IronRDP's own ironrdp-web; what it +# really carries is the build recipe. Pinned by commit - it has no releases. +RDP_WEB_DIR = ironrdp-wasm + +# IronRDP itself. Normally a plain git dependency of the crate above, but the +# audio patch is against this tree, so it is cloned and overridden with +# [patch]. Pinned to the same revision `patches/0001` pins the dependency to - +# the two must agree or cargo resolves two copies of every IronRDP type. +IRONRDP_DIR = ironrdp +IRONRDP_REV = f24685cde66bd290a3f7d35f506b9d8840452b92 + +# The two files the console page loads, plus the audio sink it installs before +# connecting. The sink is ours and lives here rather than in pve-manager: it is +# the other half of patches/ironrdp/add_audio_support and has to move with it. +SDK_FILES = rdp_client.js rdp_client_bg.wasm +JS_FILES = js/rdp-audio.js js/rdp-audio-worklet.js + +all: $(DEB) + +# --- upstream --------------------------------------------------------------- +# Fetched once, and left alone after that, following pve-qemu: a build must not +# depend on re-fetching, and a checkout someone has been working in is theirs. +# +# The patch below is what needs the tree pristine, so it resets just the files +# it touches rather than the whole submodule - which would discard the build +# output beside them for nothing. +.PHONY: submodule +submodule: +ifeq ($(shell test -f "$(RDP_WEB_DIR)/Cargo.toml" && echo 1 || echo 0), 0) + git submodule update --init --recursive $(RDP_WEB_DIR) +endif + +# Fetched once and left alone afterwards, as above. Cloned rather than made a +# submodule because it is an override, not an input we track: the revision is +# one greppable line here and in patches/0001. +.PHONY: ironrdp +ironrdp: +ifeq ($(shell test -d "$(IRONRDP_DIR)/crates" && echo 1 || echo 0), 0) + git clone --quiet https://github.com/Devolutions/IronRDP.git $(IRONRDP_DIR) +endif + git -C $(IRONRDP_DIR) checkout --quiet --force $(IRONRDP_REV) + +.PHONY: patch +patch: submodule ironrdp + git -C $(RDP_WEB_DIR) checkout --force -- . + set -e; for p in $(CURDIR)/patches/000*.patch; do \ + git -C $(RDP_WEB_DIR) apply "$$p"; \ + done + git -C $(IRONRDP_DIR) checkout --force -- . + # checkout restores tracked files but leaves untracked ones behind, and + # the audio patch adds a module - without this its create-file hunk fails + # to reapply on the second build. `target` is excluded so a reset does not + # throw away the compiled dependencies with it. + git -C $(IRONRDP_DIR) clean -fdq -e /target + set -e; for p in $(CURDIR)/patches/ironrdp/*.patch; do \ + git -C $(IRONRDP_DIR) apply "$$p"; \ + done + # Relative, so the tree can live anywhere. Appended rather than carried in + # patches/0001 because the path is a property of this checkout, not of the + # crate. + printf '\n[patch."https://github.com/Devolutions/IronRDP.git"]\nironrdp-web = { path = "../$(IRONRDP_DIR)/crates/ironrdp-web" }\n' \ + >> $(RDP_WEB_DIR)/Cargo.toml + +# --- build ------------------------------------------------------------------ +# wasm-pack and its node wrapper are skipped: they run cargo, wasm-bindgen and +# wasm-opt in turn, and all three are already here for pve-kyber-web. Doing it +# directly costs one Makefile rule and removes node from the build entirely. +.PHONY: wasm +wasm: patch + # Upstream ships no lockfile, so this one is ours: without it every build + # re-resolves the transitive dependencies at whatever is current that day, + # and two builds of the same tree produce different clients. + install -m 0644 $(CURDIR)/Cargo.lock $(RDP_WEB_DIR)/Cargo.lock + # The CLI has to match the crate, or the glue will not load the module. + cd $(RDP_WEB_DIR) && \ + want=$$(sed -n '/^name = "wasm-bindgen"$$/{n;s/^version = "\(.*\)"/\1/p;q}' Cargo.lock); \ + have=$$(wasm-bindgen --version | awk '{print $$2}'); \ + if [ "$$have" != "$$want" ]; then \ + echo "wasm-bindgen $$have found, Cargo.lock pins $$want" >&2; \ + echo "install it with: cargo install --locked wasm-bindgen-cli@$$want" >&2; \ + exit 1; \ + fi + # --locked so a lockfile that no longer matches Cargo.toml stops the build + # rather than being silently rewritten, which is the whole point of it. + cd $(RDP_WEB_DIR) && cargo build --locked --target wasm32-unknown-unknown --release + cd $(RDP_WEB_DIR) && wasm-bindgen --target web --no-typescript --out-dir pkg \ + target/wasm32-unknown-unknown/release/rdp_client.wasm + cd $(RDP_WEB_DIR) && wasm-opt pkg/rdp_client_bg.wasm -o pkg/rdp_client_bg.wasm -Os -g + +# --- packaging -------------------------------------------------------------- +.PHONY: sdk +sdk: wasm + rm -rf sdk && mkdir sdk + for f in $(SDK_FILES); do install -m 0644 "$(RDP_WEB_DIR)/pkg/$$f" sdk/; done + install -m 0644 $(JS_FILES) sdk/ + +.PHONY: builddir +builddir: + rm -rf $(BUILDDIR) + $(MAKE) $(BUILDDIR) + +$(BUILDDIR): sdk + rm -rf $@ $@.tmp + mkdir $@.tmp + cp -a sdk debian Makefile js $@.tmp/ + mv $@.tmp $@ + +deb: $(DEB) +$(DEB): $(BUILDDIR) + cd $(BUILDDIR); dpkg-buildpackage -b -us -uc + lintian $(DEB) || true + +# A source package, for sbuild and for review: Proxmox builds every package +# this way, so it has to work even when the binary path is what gets used. +.PHONY: dsc +dsc: + rm -rf $(BUILDDIR) $(DSC) + $(MAKE) $(DSC) + lintian $(DSC) + +$(DSC): $(BUILDDIR) + cd $(BUILDDIR); dpkg-buildpackage -S -us -uc -d + +sbuild: $(DSC) + sbuild $< + +.PHONY: dinstall +dinstall: deb + dpkg -i $(DEB) + +.PHONY: clean +clean: + rm -rf *.deb *.changes *.dsc *.buildinfo *.build $(PACKAGE)-[0-9]*/ sdk/ + +.PHONY: distclean +distclean: clean diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..900fd08 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +pve-rdp-web (0.1.0) trixie; urgency=medium + + * initial package + + -- Alexandre Derumier Wed, 19 Aug 2026 12:00:00 +0200 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..e0015b1 --- /dev/null +++ b/debian/control @@ -0,0 +1,19 @@ +Source: pve-rdp-web +Section: admin +Priority: optional +Maintainer: Proxmox Support Team +Uploaders: Alexandre Derumier +Build-Depends: debhelper-compat (= 13), + binaryen, + git, +Standards-Version: 4.7.0.0 + +Package: pve-rdp-web +Architecture: all +Depends: ${misc:Depends}, +Description: RDP client for the Proxmox VE console + IronRDP compiled to WebAssembly: the RDP client the console page drives, and + its JavaScript glue. + . + It reaches a VM through pveproxy and pve-rdpproxy, which performs the TLS + handshake on its behalf - a browser cannot drive one over a websocket. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..6e9cc34 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,38 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: ironrdp-wasm +Source: https://github.com/electerm/ironrdp-wasm + +Files: * +Copyright: 2026 Marc-Andre Moreau + 2024-2026 electerm contributors +License: MIT + +Files: debian/* +Copyright: 2026 Proxmox Server Solutions GmbH +License: MIT + +Comment: The wasm itself is built from IronRDP (Devolutions), MIT OR + Apache-2.0, pinned by revision - see patches/0001. + +License: MIT + MIT License + . + Copyright (c) 2026 Marc-André Moreau + . + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. \ No newline at end of file diff --git a/debian/install b/debian/install new file mode 100644 index 0000000..5cc3bdf --- /dev/null +++ b/debian/install @@ -0,0 +1 @@ +sdk/* usr/share/pve-rdp-web/ diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..5df993d --- /dev/null +++ b/debian/rules @@ -0,0 +1,10 @@ +#!/usr/bin/make -f +%: + dh $@ + +# The wasm is built by the top-level Makefile before dpkg-buildpackage runs, +# which is also what stages it. The Makefile carried into the build dir has a +# distclean that would remove sdk/. +override_dh_auto_clean: +override_dh_auto_build: +override_dh_auto_test: diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/ironrdp-wasm b/ironrdp-wasm new file mode 160000 index 0000000..103e36b --- /dev/null +++ b/ironrdp-wasm @@ -0,0 +1 @@ +Subproject commit 103e36ba0bcfeb1950b2ff2d94cc4897588fcfc9 diff --git a/js/rdp-audio-worklet.js b/js/rdp-audio-worklet.js new file mode 100644 index 0000000..3a72737 --- /dev/null +++ b/js/rdp-audio-worklet.js @@ -0,0 +1,106 @@ +/* + * Playback end of the RDP audio path: a ring buffer drained by the audio + * thread. + * + * Deliberately not a SharedArrayBuffer. The usual low-latency recipe shares + * one with the main thread, but SAB requires cross-origin isolation + * (COOP/COEP), which the Proxmox console page cannot assume behind pveproxy. + * postMessage copies each block instead: a few hundred samples every 20 ms, + * which costs far less than the isolation headers would. + */ + +const CHANNELS = 2; +/* About 400 ms. Large enough to ride out a scheduling hiccup, small enough that + * recovering from an underrun is not audible as a long delay. */ +const CAPACITY = 48000 * 0.4; + +class RdpAudioProcessor extends AudioWorkletProcessor { + constructor() { + super(); + + this.buf = []; + for (let c = 0; c < CHANNELS; c++) { + this.buf.push(new Float32Array(CAPACITY)); + } + this.read = 0; + this.write = 0; + this.filled = 0; + + /* + * Start muted and wait for a cushion to build. Playing the first block + * the moment it lands guarantees an underrun on the next one. + */ + this.priming = true; + this.primeTarget = 48000 * 0.06; + + this.port.onmessage = (e) => { + const d = e.data; + if (d.reset) { + this.read = this.write = this.filled = 0; + this.priming = true; + return; + } + this.push(d.channels); + }; + } + + push(channels) { + const n = channels[0].length; + + /* Overflow means the far end is producing faster than this clock + * consumes. Drop the oldest rather than the newest: the newest is the + * one the user is waiting to hear. */ + if (this.filled + n > CAPACITY) { + const drop = this.filled + n - CAPACITY; + this.read = (this.read + drop) % CAPACITY; + this.filled -= drop; + } + + for (let c = 0; c < CHANNELS; c++) { + const src = channels[Math.min(c, channels.length - 1)]; + let w = this.write; + for (let i = 0; i < n; i++) { + this.buf[c][w] = src[i]; + w = w + 1 === CAPACITY ? 0 : w + 1; + } + } + this.write = (this.write + n) % CAPACITY; + this.filled += n; + + if (this.priming && this.filled >= this.primeTarget) { + this.priming = false; + } + } + + process(inputs, outputs) { + const out = outputs[0]; + const n = out[0].length; + + if (this.priming || this.filled < n) { + for (let c = 0; c < out.length; c++) { + out[c].fill(0); + } + /* Rebuild the cushion after an underrun instead of stuttering + * block by block. */ + if (!this.priming && this.filled < n) { + this.priming = true; + } + return true; + } + + for (let c = 0; c < out.length; c++) { + const src = this.buf[Math.min(c, CHANNELS - 1)]; + let r = this.read; + for (let i = 0; i < n; i++) { + out[c][i] = src[r]; + r = r + 1 === CAPACITY ? 0 : r + 1; + } + } + this.read = (this.read + n) % CAPACITY; + this.filled -= n; + + return true; + } +} + +registerProcessor('rdp-audio', RdpAudioProcessor); diff --git a/js/rdp-audio.js b/js/rdp-audio.js new file mode 100644 index 0000000..6b974b9 --- /dev/null +++ b/js/rdp-audio.js @@ -0,0 +1,222 @@ +/* + * Guest audio for the RDP console. + * + * Installs `globalThis.pveRdpAudio`, which the wasm client looks up once when a + * session starts and calls for every wave block the server sends. A global + * rather than a client callback because adding one to IronRDP's SessionBuilder + * would mean patching `iron-remote-desktop` and its TypeScript glue too, for a + * hook only this console uses. + * + * Opus arrives as bare packets - no Ogg framing - which is exactly what + * WebCodecs wants. PCM is handled without a decoder at all. + * + * Browsers will not start an AudioContext without a user gesture, so the + * context stays suspended until `resume()` is called from a click. Blocks that + * arrive before then are decoded and discarded rather than queued, so audio + * begins at the moment the user allows it rather than replaying a backlog. + */ + +(function () { + 'use strict'; + + const SAMPLE_RATE = 48000; + const WORKLET_URL = '/rdp/rdp-audio-worklet.js'; + + let ctx = null; + let node = null; + let gain = null; + let decoder = null; + let starting = null; + let ts = 0; + let warned = false; + + function warnOnce(...args) { + if (!warned) { + warned = true; + console.warn('[rdp-audio]', ...args); + } + } + + /* One AudioContext and one worklet per page, created on the first block. */ + async function start(workletUrl) { + if (node) { + return; + } + if (starting) { + return starting; + } + + starting = (async () => { + ctx = new (window.AudioContext || window.webkitAudioContext)({ + sampleRate: SAMPLE_RATE, + latencyHint: 'interactive', + }); + await ctx.audioWorklet.addModule(workletUrl || WORKLET_URL); + + node = new AudioWorkletNode(ctx, 'rdp-audio', { + numberOfInputs: 0, + numberOfOutputs: 1, + outputChannelCount: [2], + }); + gain = ctx.createGain(); + node.connect(gain).connect(ctx.destination); + })(); + + return starting; + } + + function toWorklet(channels) { + if (!node || !ctx || ctx.state !== 'running') { + return; + } + node.port.postMessage( + { channels }, + channels.map((c) => c.buffer), + ); + } + + /* AudioData -> plain Float32Arrays, one per channel. */ + function emit(frame) { + try { + const n = frame.numberOfFrames; + const count = Math.min(frame.numberOfChannels, 2); + const channels = []; + + for (let c = 0; c < count; c++) { + const out = new Float32Array(n); + /* planar float is the only layout guaranteed across browsers; + * ask for it explicitly rather than assuming the native one. */ + frame.copyTo(out, { planeIndex: c, format: 'f32-planar' }); + channels.push(out); + } + toWorklet(channels); + } catch (e) { + warnOnce('cannot read decoded frame:', e); + } finally { + frame.close(); + } + } + + function ensureDecoder() { + if (decoder && decoder.state !== 'closed') { + return decoder; + } + if (typeof AudioDecoder === 'undefined') { + warnOnce('WebCodecs AudioDecoder unavailable; guest audio needs a recent browser'); + return null; + } + + decoder = new AudioDecoder({ + output: emit, + error: (e) => { + warnOnce('decoder error:', e); + decoder = null; + }, + }); + decoder.configure({ + codec: 'opus', + sampleRate: SAMPLE_RATE, + numberOfChannels: 2, + }); + return decoder; + } + + /* s16le interleaved -> planar float, for servers that offer no Opus. */ + function pcmToPlanar(bytes, channelCount) { + const pcm = new Int16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 1); + const frames = Math.floor(pcm.length / channelCount); + const channels = []; + + for (let c = 0; c < channelCount; c++) { + const out = new Float32Array(frames); + for (let i = 0; i < frames; i++) { + out[i] = pcm[i * channelCount + c] / 32768; + } + channels.push(out); + } + return channels; + } + + globalThis.pveRdpAudio = { + /* Called by the wasm client for each wave block. `data` is a + * Uint8Array owned by the caller, so anything kept must be copied. */ + wave(data, _serverTs, opus, channels, sampleRate) { + start().catch((e) => warnOnce('cannot start audio:', e)); + + if (!ctx || ctx.state !== 'running') { + /* Suspended: no gesture yet. Drop rather than queue. */ + return; + } + + if (!opus) { + if (sampleRate !== SAMPLE_RATE) { + warnOnce(`PCM at ${sampleRate} Hz not resampled; expected ${SAMPLE_RATE}`); + return; + } + toWorklet(pcmToPlanar(data, channels || 2)); + return; + } + + const dec = ensureDecoder(); + if (!dec) { + return; + } + + /* The server's timestamp has an arbitrary epoch (MS-RDPEA leaves + * it to the implementation), so it is not a media clock. Count + * decoded time instead; the ring buffer does the real pacing. */ + const chunk = new EncodedAudioChunk({ + type: 'key', + timestamp: ts, + data: data.slice(), + }); + ts += 20000; /* one 20 ms Opus frame, in microseconds */ + + try { + dec.decode(chunk); + } catch (e) { + warnOnce('decode failed:', e); + } + }, + + /* SNDC_SETVOLUME, per channel, 0..0xFFFF. One GainNode, so the two are + * averaged - a stereo balance control would need a StereoPannerNode + * and the guest's own mixer already offers one. */ + volume(left, right) { + if (!gain) { + return; + } + const v = (left + right) / 2 / 0xffff; + gain.gain.value = Math.min(1, Math.max(0, v)); + }, + + close() { + try { + if (decoder && decoder.state !== 'closed') { + decoder.close(); + } + if (node) { + node.port.postMessage({ reset: true }); + } + } catch (e) { + /* teardown races the session ending; nothing to do */ + } + decoder = null; + ts = 0; + }, + + /* The console page calls this from a click handler: browsers refuse to + * start an AudioContext without one. */ + async resume(workletUrl) { + await start(workletUrl); + if (ctx && ctx.state !== 'running') { + await ctx.resume(); + } + return ctx ? ctx.state : 'closed'; + }, + + get state() { + return ctx ? ctx.state : 'closed'; + }, + }; +})(); diff --git a/patches/0001-pin-ironrdp-web-to-a-revision.patch b/patches/0001-pin-ironrdp-web-to-a-revision.patch new file mode 100644 index 0000000..97a9217 --- /dev/null +++ b/patches/0001-pin-ironrdp-web-to-a-revision.patch @@ -0,0 +1,33 @@ +From 7da6daa20712ff4ef8c0f18cfec0ce0171b7fe88 Mon Sep 17 00:00:00 2001 +From: Alexandre Derumier +Date: Wed, 19 Aug 2026 14:12:52 +0200 +Subject: [PATCH] pin ironrdp-web to a revision, and ask for QOI + +A git dependency on branch = "master" resolves to whatever IronRDP happens to +be on the day of the build, so two builds of the same tree can differ. A +package needs a fixed input. + +qoi and qoiz are opt-in. Without them the client advertises RemoteFX alone, so +that is what the server encodes with - lossy, fixed quantization, visibly +flattened colour, and slow. QOI is lossless, and qemu-rdp prefers it. +--- +diff --git a/Cargo.toml b/Cargo.toml +index d6279a9..5baa400 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -9,5 +9,12 @@ crate-type = ["cdylib"] + [dependencies] + # WASM dependencies + wasm-bindgen = "0.2" +-ironrdp-web = { git = "https://github.com/Devolutions/IronRDP.git", branch = "master" } +-web-sys = { version = "0.3", features = ["console"] } +\ No newline at end of file ++# Pinned by revision, not branch: "master" makes every build pull whatever ++# IronRDP happens to be that day, which a package cannot do. ++# ++# qoi/qoiz are off by default, and a client that does not offer them leaves the ++# server with RemoteFX - a lossy wavelet codec whose fixed quantization visibly ++# flattens colour. QOI is lossless and cheaper to encode; qemu-rdp already ++# builds with qoiz, and prefers it when the client asks. ++ironrdp-web = { git = "https://github.com/Devolutions/IronRDP.git", rev = "f24685cde66bd290a3f7d35f506b9d8840452b92", features = ["qoiz", "qoi"] } ++web-sys = { version = "0.3", features = ["console"] } diff --git a/patches/ironrdp/add_audio_support.patch b/patches/ironrdp/add_audio_support.patch new file mode 100644 index 0000000..3b5d58f --- /dev/null +++ b/patches/ironrdp/add_audio_support.patch @@ -0,0 +1,362 @@ +From: Alexandre Derumier +Subject: [PATCH] play guest audio in the browser + +ironrdp-web attaches the RDPSND channel only alongside a printer, and with +NoopRdpsndBackend - a handler advertising no formats. That is not merely +silent: the server never reaches the end of format negotiation, so its +handler's start() never runs and every wave block is dropped before it is +sent. MS-RDPEFS Appendix A<1> made the channel a prerequisite for RDPDR, +which is the only reason it was attached at all. + +qemu-rdp offers Opus at 48 kHz, which browsers decode natively through +WebCodecs, so there is nothing to transcode on either side. Attach the +channel unconditionally with a handler that advertises Opus first and PCM +as a fallback, and hand the blocks to the page. + +The split follows the printer backend: RdpsndClientHandler is Send and JS +values are not, so the SVC-side handler holds only an mpsc proxy while the +sink that owns the JS lives in the session event loop. + +The sink is looked up as globalThis.pveRdpAudio rather than passed as a +builder callback: adding one to the SessionBuilder trait would mean +patching iron-remote-desktop and its TypeScript glue as well, for a hook +only this console uses. +--- +--- a/crates/ironrdp-web/src/lib.rs ++++ b/crates/ironrdp-web/src/lib.rs +@@ -24,6 +24,7 @@ + mod printer; + mod rdp_file; + mod session; ++mod sound; + + mod wasm_bridge { + use tracing::debug; +--- a/crates/ironrdp-web/src/session.rs ++++ b/crates/ironrdp-web/src/session.rs +@@ -28,7 +28,7 @@ + use ironrdp::pdu::rdp::client_info::{PerformanceFlags, TimezoneInfo}; + use ironrdp::rdpdr::Rdpdr; + use ironrdp::rdpdr::pdu::efs::{DEFAULT_PRINTER_DRIVER_NAME, MICROSOFT_PRINT_TO_PDF_DRIVER_NAME}; +-use ironrdp::rdpsnd::client::{NoopRdpsndBackend, Rdpsnd}; ++use ironrdp::rdpsnd::client::Rdpsnd; + use ironrdp::session::image::DecodedImage; + use ironrdp::session::{ActiveStageBuilder, ActiveStageOutput, GracefulDisconnectReason}; + use ironrdp_core::WriteBuf; +@@ -48,6 +48,7 @@ + use crate::input::InputTransaction; + use crate::network_client::WasmNetworkClient; + use crate::printer::{JsPrinterStreamCallbacks, WasmPrinter, WasmPrinterBackend, wasm_printer_pair}; ++use crate::sound::{SoundBackendMessage, WasmRdpsndBackend, WasmSound}; + + const DEFAULT_WIDTH: u16 = 1280; + const DEFAULT_HEIGHT: u16 = 720; +@@ -493,6 +494,7 @@ + kdc_proxy_url, + clipboard_backend: clipboard.as_ref().map(|clip| clip.backend()), + printer_backend, ++ sound_backend: WasmRdpsndBackend::new(input_events_tx.clone()), + printer_device_id, + printer_name, + printer_driver_name, +@@ -537,6 +539,9 @@ + /// Printer backend → event loop: a print job finished and its bytes are + /// ready for delivery to JS. See [`crate::printer::PrinterBackendMessage`]. + Printer(crate::printer::PrinterBackendMessage), ++ /// RDPSND backend → event loop: a wave block (or volume change) arrived ++ /// from the server. See [`crate::sound`]. ++ Sound(SoundBackendMessage), + FastPath(FastPathInputEvents), + Resize { + width: u32, +@@ -642,6 +647,7 @@ + + let mut clipboard = self.clipboard.borrow_mut().take().expect("run called only once"); + let mut wasm_printer = self.printer.borrow_mut().take().expect("run called only once"); ++ let mut wasm_sound = WasmSound::new(); + + let mut framed = ironrdp_futures::LocalFuturesFramed::new(rdp_reader); + +@@ -868,6 +874,13 @@ + } + Vec::new() + } ++ RdpInputEvent::Sound(message) => { ++ // Same split as the printer: the backend is Send ++ // and lives in the SVC processor, the JS sink is ++ // !Send and lives here. ++ wasm_sound.process_message(message); ++ Vec::new() ++ } + RdpInputEvent::TerminateSession => { + active_stage.graceful_shutdown() + .context("graceful shutdown")? +@@ -1546,6 +1559,8 @@ + kdc_proxy_url: Option, + clipboard_backend: Option, + printer_backend: Option, ++ /// Always present: the RDPSND channel is attached unconditionally. ++ sound_backend: WasmRdpsndBackend, + printer_device_id: u32, + printer_name: String, + printer_driver_name: String, +@@ -1598,6 +1613,7 @@ + kdc_proxy_url, + clipboard_backend, + printer_backend, ++ sound_backend, + printer_device_id, + printer_name, + printer_driver_name, +@@ -1616,11 +1632,14 @@ + connector.attach_static_channel(CliprdrClient::new(Box::new(clipboard_backend))); + } + ++ // Unconditional: the channel carries guest audio in its own right, and ++ // MS-RDPEFS Appendix A<1> separately makes it a prerequisite for RDPDR, so ++ // one attachment serves both. Upstream attached it only alongside a ++ // printer, and with a handler advertising no formats - which stalls the ++ // server before it finishes negotiating. ++ connector.attach_static_channel(Rdpsnd::new(Box::new(sound_backend))); ++ + if let Some(printer_backend) = printer_backend { +- // Windows servers only speak on RDPDR when RDPSND is advertised too +- // (MS-RDPEFS Appendix A<1>). We do not play audio in the web client, +- // but the no-op RDPSND processor satisfies that channel dependency. +- connector.attach_static_channel(Rdpsnd::new(Box::new(NoopRdpsndBackend))); + connector.attach_static_channel( + Rdpdr::new(Box::new(printer_backend), computer_name).with_printer_driver( + printer_device_id, +--- a/crates/ironrdp-web/src/sound.rs ++++ b/crates/ironrdp-web/src/sound.rs +@@ -0,0 +1,230 @@ ++//! Browser audio sink for the RDPSND static channel. ++//! ++//! Architecture mirrors the printer backend ([`crate::printer`]), for the same ++//! reason: [`RdpsndClientHandler`] is `Send`, JS values are not. ++//! ++//! * [`WasmRdpsndBackend`] lives on the SVC processor side. It holds the ++//! advertised format list and an mpsc proxy - never a `JsValue`. ++//! * [`WasmSound`] lives in the session event loop, owns the JS callbacks and ++//! hands wave blocks to the page. ++//! ++//! Upstream attaches RDPSND with a no-op handler, and only when a printer is ++//! configured: MS-RDPEFS Appendix A<1> makes the channel a prerequisite for ++//! RDPDR, and the web client had nothing to play what arrived with. A client ++//! advertising no formats is not merely silent - the server never reaches the ++//! end of format negotiation, so nothing downstream of it runs either. ++//! ++//! Opus is listed first because it is what we would rather be sent: browsers ++//! decode it natively through WebCodecs, and `qemu-rdp` already encodes it, so ++//! neither side has to transcode. PCM is kept as a fallback for servers that ++//! do not offer Opus. Both entries must match the server's own table field for ++//! field - it selects by structural equality, not by a subset match - so the ++//! constants below are deliberately spelled out rather than derived. ++ ++use std::borrow::Cow; ++ ++use futures_channel::mpsc; ++use ironrdp::rdpsnd::client::RdpsndClientHandler; ++use ironrdp::rdpsnd::pdu::{AudioFormat, AudioFormatFlags, PitchPdu, VolumePdu, WaveFormat}; ++use tracing::{debug, trace, warn}; ++use wasm_bindgen::prelude::*; ++ ++use crate::session::RdpInputEvent; ++ ++/// Opus, 48 kHz stereo. `n_avg_bytes_per_sec` and `n_block_align` describe the ++/// *decoded* stream, as MS-RDPEA requires for a compressed format. ++fn opus_48k() -> AudioFormat { ++ AudioFormat { ++ format: WaveFormat::OPUS, ++ n_channels: 2, ++ n_samples_per_sec: 48000, ++ n_avg_bytes_per_sec: 192000, ++ n_block_align: 4, ++ bits_per_sample: 16, ++ data: None, ++ } ++} ++ ++/// Uncompressed fallback, same shape. ++fn pcm_48k() -> AudioFormat { ++ AudioFormat { ++ format: WaveFormat::PCM, ++ n_channels: 2, ++ n_samples_per_sec: 48000, ++ n_avg_bytes_per_sec: 192000, ++ n_block_align: 4, ++ bits_per_sample: 16, ++ data: None, ++ } ++} ++ ++/// Messages sent from the RDPSND backend to the session event loop. ++#[derive(Debug)] ++pub(crate) enum SoundBackendMessage { ++ /// One wave block, already in the negotiated format. ++ Wave { ++ /// True when the payload is an Opus packet rather than raw PCM. ++ opus: bool, ++ channels: u16, ++ sample_rate: u32, ++ /// Server timestamp, milliseconds. Advisory: MS-RDPEA lets the server ++ /// pick the epoch, so this is only useful as a relative measure. ++ ts: u32, ++ data: Vec, ++ }, ++ /// Per-channel volume, 0..=0xFFFF. ++ Volume { left: u16, right: u16 }, ++ /// The server closed the stream. ++ Close, ++} ++ ++/// SVC-side handler. `Send`, and holds no JS state. ++#[derive(Debug)] ++pub(crate) struct WasmRdpsndBackend { ++ formats: Vec, ++ tx: mpsc::UnboundedSender, ++} ++ ++impl WasmRdpsndBackend { ++ pub(crate) fn new(tx: mpsc::UnboundedSender) -> Self { ++ Self { ++ formats: vec![opus_48k(), pcm_48k()], ++ tx, ++ } ++ } ++ ++ fn send(&self, message: SoundBackendMessage) { ++ if let Err(e) = self.tx.unbounded_send(RdpInputEvent::Sound(message)) { ++ // The loop is gone: the session is ending. Not worth a warning per ++ // 20 ms block. ++ trace!("Failed to send audio to the event loop: {e}"); ++ } ++ } ++} ++ ++impl RdpsndClientHandler for WasmRdpsndBackend { ++ fn get_flags(&self) -> AudioFormatFlags { ++ // VOLUME asks the server to send us SNDC_SETVOLUME; the page applies ++ // it with a GainNode. ALIVE is added by the channel itself. ++ AudioFormatFlags::VOLUME ++ } ++ ++ fn get_formats(&self) -> &[AudioFormat] { ++ &self.formats ++ } ++ ++ fn wave(&mut self, format: &AudioFormat, ts: u32, data: Cow<'_, [u8]>) { ++ if data.is_empty() { ++ return; ++ } ++ ++ self.send(SoundBackendMessage::Wave { ++ opus: format.format == WaveFormat::OPUS, ++ channels: format.n_channels, ++ sample_rate: format.n_samples_per_sec, ++ ts, ++ data: data.into_owned(), ++ }); ++ } ++ ++ fn set_volume(&mut self, volume: VolumePdu) { ++ self.send(SoundBackendMessage::Volume { ++ left: volume.volume_left, ++ right: volume.volume_right, ++ }); ++ } ++ ++ fn set_pitch(&mut self, _pitch: PitchPdu) { ++ // MS-RDPEA leaves this optional and no server we target sends it. ++ } ++ ++ fn close(&mut self) { ++ self.send(SoundBackendMessage::Close); ++ } ++} ++ ++/// Event-loop side. Owns the JS callbacks, so it is `!Send` and never crosses ++/// into the SVC processor. ++pub(crate) struct WasmSound { ++ sink: Option, ++ warned: bool, ++} ++ ++impl WasmSound { ++ /// Looks the sink up once, at session start. ++ /// ++ /// A global rather than a builder callback: adding one to the ++ /// `SessionBuilder` trait would mean patching `iron-remote-desktop` and ++ /// its TypeScript glue as well, for a hook only this console uses. The ++ /// page installs `globalThis.pveRdpAudio` before it connects. ++ pub(crate) fn new() -> Self { ++ let sink = js_sys::Reflect::get(&js_sys::global(), &JsValue::from_str("pveRdpAudio")) ++ .ok() ++ .and_then(|v| v.dyn_into::().ok()); ++ ++ if sink.is_none() { ++ debug!("No globalThis.pveRdpAudio installed; guest audio will be dropped"); ++ } ++ ++ Self { sink, warned: false } ++ } ++ ++ fn call(&mut self, method: &str, args: &js_sys::Array) { ++ let Some(sink) = self.sink.as_ref() else { ++ return; ++ }; ++ ++ let func = js_sys::Reflect::get(sink, &JsValue::from_str(method)) ++ .ok() ++ .and_then(|v| v.dyn_into::().ok()); ++ ++ let Some(func) = func else { ++ if !self.warned { ++ warn!("globalThis.pveRdpAudio has no {method}() method"); ++ self.warned = true; ++ } ++ return; ++ }; ++ ++ if let Err(e) = func.apply(sink, args) { ++ if !self.warned { ++ warn!("pveRdpAudio.{method}() threw: {e:?}"); ++ self.warned = true; ++ } ++ } ++ } ++ ++ pub(crate) fn process_message(&mut self, message: SoundBackendMessage) { ++ match message { ++ SoundBackendMessage::Wave { ++ opus, ++ channels, ++ sample_rate, ++ ts, ++ data, ++ } => { ++ // Copies into the JS heap. A wave block is one 20 ms frame, ++ // so this is a few hundred bytes for Opus. ++ let buf = js_sys::Uint8Array::from(data.as_slice()); ++ let args = js_sys::Array::of5( ++ &buf.into(), ++ &JsValue::from_f64(f64::from(ts)), ++ &JsValue::from_bool(opus), ++ &JsValue::from_f64(f64::from(channels)), ++ &JsValue::from_f64(f64::from(sample_rate)), ++ ); ++ self.call("wave", &args); ++ } ++ SoundBackendMessage::Volume { left, right } => { ++ let args = js_sys::Array::of2( ++ &JsValue::from_f64(f64::from(left)), ++ &JsValue::from_f64(f64::from(right)), ++ ); ++ self.call("volume", &args); ++ } ++ SoundBackendMessage::Close => { ++ self.call("close", &js_sys::Array::new()); ++ } ++ } ++ } ++} -- 2.55.0