13 changed files with 9547 additions and 0 deletions
@ -0,0 +1,336 @@
|
||||
# This file is automatically @generated by Cargo. |
||||
# It is not intended for manual editing. |
||||
[[package]] |
||||
name = "aho-corasick" |
||||
version = "0.7.18" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" |
||||
dependencies = [ |
||||
"memchr", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "ansi_term" |
||||
version = "0.11.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" |
||||
dependencies = [ |
||||
"winapi", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "atty" |
||||
version = "0.2.14" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" |
||||
dependencies = [ |
||||
"hermit-abi", |
||||
"libc", |
||||
"winapi", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "bindgen" |
||||
version = "0.57.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "fd4865004a46a0aafb2a0a5eb19d3c9fc46ee5f063a6cfc605c69ac9ecf5263d" |
||||
dependencies = [ |
||||
"bitflags", |
||||
"cexpr", |
||||
"clang-sys", |
||||
"clap", |
||||
"env_logger", |
||||
"lazy_static", |
||||
"lazycell", |
||||
"log", |
||||
"peeking_take_while", |
||||
"proc-macro2", |
||||
"quote", |
||||
"regex", |
||||
"rustc-hash", |
||||
"shlex", |
||||
"which", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "bitflags" |
||||
version = "1.2.1" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" |
||||
|
||||
[[package]] |
||||
name = "cexpr" |
||||
version = "0.4.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" |
||||
dependencies = [ |
||||
"nom", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "cfg-if" |
||||
version = "1.0.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" |
||||
|
||||
[[package]] |
||||
name = "clang-sys" |
||||
version = "1.2.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "853eda514c284c2287f4bf20ae614f8781f40a81d32ecda6e91449304dfe077c" |
||||
dependencies = [ |
||||
"glob", |
||||
"libc", |
||||
"libloading", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "clap" |
||||
version = "2.33.3" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" |
||||
dependencies = [ |
||||
"ansi_term", |
||||
"atty", |
||||
"bitflags", |
||||
"strsim", |
||||
"textwrap", |
||||
"unicode-width", |
||||
"vec_map", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "env_logger" |
||||
version = "0.8.3" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" |
||||
dependencies = [ |
||||
"atty", |
||||
"humantime", |
||||
"log", |
||||
"regex", |
||||
"termcolor", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "glob" |
||||
version = "0.3.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" |
||||
|
||||
[[package]] |
||||
name = "hermit-abi" |
||||
version = "0.1.18" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" |
||||
dependencies = [ |
||||
"libc", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "humantime" |
||||
version = "2.1.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" |
||||
|
||||
[[package]] |
||||
name = "lazy_static" |
||||
version = "1.4.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" |
||||
|
||||
[[package]] |
||||
name = "lazycell" |
||||
version = "1.3.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" |
||||
|
||||
[[package]] |
||||
name = "libc" |
||||
version = "0.2.94" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" |
||||
|
||||
[[package]] |
||||
name = "libloading" |
||||
version = "0.7.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" |
||||
dependencies = [ |
||||
"cfg-if", |
||||
"winapi", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "libzt" |
||||
version = "0.1.0" |
||||
dependencies = [ |
||||
"bindgen", |
||||
"libc", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "log" |
||||
version = "0.4.14" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" |
||||
dependencies = [ |
||||
"cfg-if", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "memchr" |
||||
version = "2.4.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" |
||||
|
||||
[[package]] |
||||
name = "nom" |
||||
version = "5.1.2" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" |
||||
dependencies = [ |
||||
"memchr", |
||||
"version_check", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "peeking_take_while" |
||||
version = "0.1.2" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" |
||||
|
||||
[[package]] |
||||
name = "proc-macro2" |
||||
version = "1.0.26" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" |
||||
dependencies = [ |
||||
"unicode-xid", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "quote" |
||||
version = "1.0.9" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" |
||||
dependencies = [ |
||||
"proc-macro2", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "regex" |
||||
version = "1.5.3" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "ce5f1ceb7f74abbce32601642fcf8e8508a8a8991e0621c7d750295b9095702b" |
||||
dependencies = [ |
||||
"aho-corasick", |
||||
"memchr", |
||||
"regex-syntax", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "regex-syntax" |
||||
version = "0.6.25" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" |
||||
|
||||
[[package]] |
||||
name = "rustc-hash" |
||||
version = "1.1.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" |
||||
|
||||
[[package]] |
||||
name = "shlex" |
||||
version = "0.1.1" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" |
||||
|
||||
[[package]] |
||||
name = "strsim" |
||||
version = "0.8.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" |
||||
|
||||
[[package]] |
||||
name = "termcolor" |
||||
version = "1.1.2" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" |
||||
dependencies = [ |
||||
"winapi-util", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "textwrap" |
||||
version = "0.11.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" |
||||
dependencies = [ |
||||
"unicode-width", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "unicode-width" |
||||
version = "0.1.8" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" |
||||
|
||||
[[package]] |
||||
name = "unicode-xid" |
||||
version = "0.2.2" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" |
||||
|
||||
[[package]] |
||||
name = "vec_map" |
||||
version = "0.8.2" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" |
||||
|
||||
[[package]] |
||||
name = "version_check" |
||||
version = "0.9.3" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" |
||||
|
||||
[[package]] |
||||
name = "which" |
||||
version = "3.1.1" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" |
||||
dependencies = [ |
||||
"libc", |
||||
] |
||||
|
||||
[[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-util" |
||||
version = "0.1.5" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" |
||||
dependencies = [ |
||||
"winapi", |
||||
] |
||||
|
||||
[[package]] |
||||
name = "winapi-x86_64-pc-windows-gnu" |
||||
version = "0.4.0" |
||||
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" |
||||
@ -0,0 +1,27 @@
|
||||
[package] |
||||
name = "libzt" |
||||
version = "0.1.0" |
||||
authors = ["Joseph Henry <joseph.henry@zerotier.com>"] |
||||
edition = "2018" |
||||
description = "Encrypted P2P SD-WAN library by ZeroTier" |
||||
documentation = "https://github.com/zerotier/libzt" |
||||
readme = "README.md" |
||||
homepage = "https://www.zerotier.com" |
||||
license-file = "LICENSE.txt" |
||||
keywords = ["zerotier", "p2p", "vpn", "socket", "network"] |
||||
categories = ["network-programming", "cryptography"] |
||||
|
||||
[dependencies] |
||||
|
||||
[build-dependencies] |
||||
bindgen = "0.57" |
||||
libc = "0.2" |
||||
|
||||
[lib] |
||||
name = "libzt" |
||||
path = "src/lib.rs" |
||||
|
||||
[[bin]] |
||||
name = "libzt-test-app" |
||||
path = "src/bin/libzt-test-app.rs" |
||||
|
||||
@ -0,0 +1,631 @@
|
||||
----------------------------------------------------------------------------- |
||||
|
||||
Business Source License 1.1 |
||||
|
||||
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. |
||||
"Business Source License" is a trademark of MariaDB Corporation Ab. |
||||
|
||||
----------------------------------------------------------------------------- |
||||
|
||||
Parameters |
||||
|
||||
Licensor: ZeroTier, Inc. |
||||
Licensed Work: ZeroTier Network Virtualization Engine 1.4.4 |
||||
The Licensed Work is (c)2019 ZeroTier, Inc. |
||||
Additional Use Grant: You may make use of the Licensed Work, provided you |
||||
do not use it in any of the following ways: |
||||
|
||||
* Sell hosted ZeroTier services as a "SaaS" Product |
||||
|
||||
(1) Operate or sell access to ZeroTier root servers, |
||||
network controllers, or authorization key or certificate |
||||
generation components of the Licensed Work as a |
||||
for-profit service, regardless of whether the use of |
||||
these components is sold alone or is bundled with other |
||||
services. Note that this does not apply to the use of |
||||
ZeroTier behind the scenes to operate a service not |
||||
related to ZeroTier network administration. |
||||
|
||||
* Create Non-Open-Source Commercial Derviative Works |
||||
|
||||
(2) Link or directly include the Licensed Work in a |
||||
commercial or for-profit application or other product |
||||
not distributed under an Open Source Initiative (OSI) |
||||
compliant license. See: https://opensource.org/licenses |
||||
|
||||
(3) Remove the name, logo, copyright, or other branding |
||||
material from the Licensed Work to create a "rebranded" |
||||
or "white labeled" version to distribute as part of |
||||
any commercial or for-profit product or service. |
||||
|
||||
* Certain Government Uses |
||||
|
||||
(4) Use or deploy the Licensed Work in a government |
||||
setting in support of any active government function |
||||
or operation with the exception of the following: |
||||
physical or mental health care, family and social |
||||
services, social welfare, senior care, child care, and |
||||
the care of persons with disabilities. |
||||
|
||||
Change Date: 2023-01-01 |
||||
|
||||
Change License: Apache License version 2.0 as published by the Apache |
||||
Software Foundation |
||||
https://www.apache.org/licenses/ |
||||
|
||||
Alternative Licensing |
||||
|
||||
If you would like to use the Licensed Work in any way that conflicts with |
||||
the stipulations of the Additional Use Grant, contact ZeroTier, Inc. to |
||||
obtain an alternative commercial license. |
||||
|
||||
Visit us on the web at: https://www.zerotier.com/ |
||||
|
||||
Notice |
||||
|
||||
The Business Source License (this document, or the "License") is not an Open |
||||
Source license. However, the Licensed Work will eventually be made available |
||||
under an Open Source License, as stated in this License. |
||||
|
||||
For more information on the use of the Business Source License for ZeroTier |
||||
products, please visit our pricing page which contains license details and |
||||
and license FAQ: https://zerotier.com/pricing |
||||
|
||||
For more information on the use of the Business Source License generally, |
||||
please visit the Adopting and Developing Business Source License FAQ at |
||||
https://mariadb.com/bsl-faq-adopting. |
||||
|
||||
----------------------------------------------------------------------------- |
||||
|
||||
Business Source License 1.1 |
||||
|
||||
Terms |
||||
|
||||
The Licensor hereby grants you the right to copy, modify, create derivative |
||||
works, redistribute, and make non-production use of the Licensed Work. The |
||||
Licensor may make an Additional Use Grant, above, permitting limited |
||||
production use. |
||||
|
||||
Effective on the Change Date, or the fourth anniversary of the first publicly |
||||
available distribution of a specific version of the Licensed Work under this |
||||
License, whichever comes first, the Licensor hereby grants you rights under |
||||
the terms of the Change License, and the rights granted in the paragraph |
||||
above terminate. |
||||
|
||||
If your use of the Licensed Work does not comply with the requirements |
||||
currently in effect as described in this License, you must purchase a |
||||
commercial license from the Licensor, its affiliated entities, or authorized |
||||
resellers, or you must refrain from using the Licensed Work. |
||||
|
||||
All copies of the original and modified Licensed Work, and derivative works |
||||
of the Licensed Work, are subject to this License. This License applies |
||||
separately for each version of the Licensed Work and the Change Date may vary |
||||
for each version of the Licensed Work released by Licensor. |
||||
|
||||
You must conspicuously display this License on each original or modified copy |
||||
of the Licensed Work. If you receive the Licensed Work in original or |
||||
modified form from a third party, the terms and conditions set forth in this |
||||
License apply to your use of that work. |
||||
|
||||
Any use of the Licensed Work in violation of this License will automatically |
||||
terminate your rights under this License for the current and all other |
||||
versions of the Licensed Work. |
||||
|
||||
This License does not grant you any right in any trademark or logo of |
||||
Licensor or its affiliates (provided that you may use a trademark or logo of |
||||
Licensor as expressly required by this License). |
||||
|
||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON |
||||
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, |
||||
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF |
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND |
||||
TITLE. |
||||
|
||||
----------------------------------------------------------------------------- |
||||
|
||||
MariaDB hereby grants you permission to use this License’s text to license |
||||
your works, and to refer to it using the trademark "Business Source License", |
||||
as long as you comply with the Covenants of Licensor below. |
||||
|
||||
Covenants of Licensor |
||||
|
||||
In consideration of the right to use this License’s text and the "Business |
||||
Source License" name and trademark, Licensor covenants to MariaDB, and to all |
||||
other recipients of the licensed work to be provided by Licensor: |
||||
|
||||
1. To specify as the Change License the GPL Version 2.0 or any later version, |
||||
or a license that is compatible with GPL Version 2.0 or a later version, |
||||
where "compatible" means that software provided under the Change License can |
||||
be included in a program with software provided under GPL Version 2.0 or a |
||||
later version. Licensor may specify additional Change Licenses without |
||||
limitation. |
||||
|
||||
2. To either: (a) specify an additional grant of rights to use that does not |
||||
impose any additional restriction on the right granted in this License, as |
||||
the Additional Use Grant; or (b) insert the text "None". |
||||
|
||||
3. To specify a Change Date. |
||||
|
||||
4. Not to modify this License in any other way. |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
END OF Business Source License 1.1 |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------- |
||||
|
||||
Portions of the Rust crate that wraps the functionality of libzt into an |
||||
idiomatic interface are derived from the Rust standard library. The standard |
||||
library's copyright and associated licenses are reproduced below. The copyright |
||||
and its licenses only apply to the code derived from the Rust standard library |
||||
and not libzt or ZeroTier. libzt and ZeroTier are subject to the BUSL-1.1 |
||||
license reproduced above. |
||||
|
||||
-------------------------------------------------------------------------------- |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Short version for non-lawyers: |
||||
|
||||
The Rust Project is dual-licensed under Apache 2.0 and MIT |
||||
terms. |
||||
|
||||
|
||||
Longer version: |
||||
|
||||
Copyrights in the Rust project are retained by their contributors. No |
||||
copyright assignment is required to contribute to the Rust project. |
||||
|
||||
Some files include explicit copyright notices and/or license notices. |
||||
For full authorship information, see the version control history or |
||||
https://thanks.rust-lang.org |
||||
|
||||
Except as otherwise noted (below and/or in individual files), Rust is |
||||
licensed under the Apache License, Version 2.0 <LICENSE-APACHE> or |
||||
<http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
||||
<LICENSE-MIT> or <http://opensource.org/licenses/MIT>, at your option. |
||||
|
||||
|
||||
The Rust Project includes packages written by third parties. |
||||
The following third party packages are included, and carry |
||||
their own copyright notices and license terms: |
||||
|
||||
* LLVM. Code for this package is found in src/llvm-project. |
||||
|
||||
Copyright (c) 2003-2013 University of Illinois at |
||||
Urbana-Champaign. All rights reserved. |
||||
|
||||
Developed by: |
||||
|
||||
LLVM Team |
||||
|
||||
University of Illinois at Urbana-Champaign |
||||
|
||||
http://llvm.org |
||||
|
||||
Permission is hereby granted, free of charge, to any |
||||
person obtaining a copy of this software and associated |
||||
documentation files (the "Software"), to deal with 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: |
||||
|
||||
* Redistributions of source code must retain the |
||||
above copyright notice, this list of conditions |
||||
and the following disclaimers. |
||||
|
||||
* Redistributions in binary form must reproduce the |
||||
above copyright notice, this list of conditions |
||||
and the following disclaimers in the documentation |
||||
and/or other materials provided with the |
||||
distribution. |
||||
|
||||
* Neither the names of the LLVM Team, University of |
||||
Illinois at Urbana-Champaign, nor the names of its |
||||
contributors may be used to endorse or promote |
||||
products derived from this Software without |
||||
specific prior written permission. |
||||
|
||||
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 CONTRIBUTORS 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 WITH THE SOFTWARE. |
||||
|
||||
* Additional libraries included in LLVM carry separate |
||||
BSD-compatible licenses. See src/llvm-project/llvm/LICENSE.TXT |
||||
for details. |
||||
|
||||
* compiler-rt, in src/compiler-rt is dual licensed under |
||||
LLVM's license and MIT: |
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in |
||||
CREDITS.TXT |
||||
|
||||
All rights reserved. |
||||
|
||||
Developed by: |
||||
|
||||
LLVM Team |
||||
|
||||
University of Illinois at Urbana-Champaign |
||||
|
||||
http://llvm.org |
||||
|
||||
Permission is hereby granted, free of charge, to any |
||||
person obtaining a copy of this software and associated |
||||
documentation files (the "Software"), to deal with 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: |
||||
|
||||
* Redistributions of source code must retain the |
||||
above copyright notice, this list of conditions |
||||
and the following disclaimers. |
||||
|
||||
* Redistributions in binary form must reproduce the |
||||
above copyright notice, this list of conditions |
||||
and the following disclaimers in the documentation |
||||
and/or other materials provided with the |
||||
distribution. |
||||
|
||||
* Neither the names of the LLVM Team, University of |
||||
Illinois at Urbana-Champaign, nor the names of its |
||||
contributors may be used to endorse or promote |
||||
products derived from this Software without |
||||
specific prior written permission. |
||||
|
||||
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 CONTRIBUTORS 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 WITH THE SOFTWARE. |
||||
|
||||
======================================================== |
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in |
||||
CREDITS.TXT |
||||
|
||||
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. |
||||
|
||||
* Portions of the FFI code for interacting with the native ABI |
||||
is derived from the Clay programming language, which carries |
||||
the following license. |
||||
|
||||
Copyright (C) 2008-2010 Tachyon Technologies. |
||||
All rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with |
||||
or without modification, are permitted provided that the |
||||
following conditions are met: |
||||
|
||||
1. Redistributions of source code must retain the above |
||||
copyright notice, this list of conditions and the |
||||
following disclaimer. |
||||
|
||||
2. Redistributions in binary form must reproduce the |
||||
above copyright notice, this list of conditions and |
||||
the following disclaimer in the documentation and/or |
||||
other materials provided with the distribution. |
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR |
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
||||
DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
OF SUCH DAMAGE. |
||||
|
||||
* libbacktrace, under src/libbacktrace: |
||||
|
||||
Copyright (C) 2012-2014 Free Software Foundation, Inc. |
||||
Written by Ian Lance Taylor, Google. |
||||
|
||||
Redistribution and use in source and binary forms, with |
||||
or without modification, are permitted provided that the |
||||
following conditions are met: |
||||
|
||||
(1) Redistributions of source code must retain the |
||||
above copyright notice, this list of conditions and |
||||
the following disclaimer. |
||||
|
||||
(2) Redistributions in binary form must reproduce |
||||
the above copyright notice, this list of conditions |
||||
and the following disclaimer in the documentation |
||||
and/or other materials provided with the |
||||
distribution. |
||||
|
||||
(3) The name of the author may not be used to |
||||
endorse or promote products derived from this |
||||
software without specific prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND |
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
OF SUCH DAMAGE. */ |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------- |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MIT License |
||||
|
||||
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. |
||||
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------- |
||||
|
||||
|
||||
|
||||
|
||||
Apache License |
||||
Version 2.0, January 2004 |
||||
http://www.apache.org/licenses/ |
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
||||
1. Definitions. |
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
||||
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
||||
the copyright owner that is granting the License. |
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
||||
other entities that control, are controlled by, or are under common |
||||
control with that entity. For the purposes of this definition, |
||||
"control" means (i) the power, direct or indirect, to cause the |
||||
direction or management of such entity, whether by contract or |
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
||||
exercising permissions granted by this License. |
||||
|
||||
"Source" form shall mean the preferred form for making modifications, |
||||
including but not limited to software source code, documentation |
||||
source, and configuration files. |
||||
|
||||
"Object" form shall mean any form resulting from mechanical |
||||
transformation or translation of a Source form, including but |
||||
not limited to compiled object code, generated documentation, |
||||
and conversions to other media types. |
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or |
||||
Object form, made available under the License, as indicated by a |
||||
copyright notice that is included in or attached to the work |
||||
(an example is provided in the Appendix below). |
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
||||
form, that is based on (or derived from) the Work and for which the |
||||
editorial revisions, annotations, elaborations, or other modifications |
||||
represent, as a whole, an original work of authorship. For the purposes |
||||
of this License, Derivative Works shall not include works that remain |
||||
separable from, or merely link (or bind by name) to the interfaces of, |
||||
the Work and Derivative Works thereof. |
||||
|
||||
"Contribution" shall mean any work of authorship, including |
||||
the original version of the Work and any modifications or additions |
||||
to that Work or Derivative Works thereof, that is intentionally |
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
or by an individual or Legal Entity authorized to submit on behalf of |
||||
the copyright owner. For the purposes of this definition, "submitted" |
||||
means any form of electronic, verbal, or written communication sent |
||||
to the Licensor or its representatives, including but not limited to |
||||
communication on electronic mailing lists, source code control systems, |
||||
and issue tracking systems that are managed by, or on behalf of, the |
||||
Licensor for the purpose of discussing and improving the Work, but |
||||
excluding communication that is conspicuously marked or otherwise |
||||
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
on behalf of whom a Contribution has been received by Licensor and |
||||
subsequently incorporated within the Work. |
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
copyright license to reproduce, prepare Derivative Works of, |
||||
publicly display, publicly perform, sublicense, and distribute the |
||||
Work and such Derivative Works in Source or Object form. |
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
(except as stated in this section) patent license to make, have made, |
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
where such license applies only to those patent claims licensable |
||||
by such Contributor that are necessarily infringed by their |
||||
Contribution(s) alone or by combination of their Contribution(s) |
||||
with the Work to which such Contribution(s) was submitted. If You |
||||
institute patent litigation against any entity (including a |
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
or a Contribution incorporated within the Work constitutes direct |
||||
or contributory patent infringement, then any patent licenses |
||||
granted to You under this License for that Work shall terminate |
||||
as of the date such litigation is filed. |
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
||||
Work or Derivative Works thereof in any medium, with or without |
||||
modifications, and in Source or Object form, provided that You |
||||
meet the following conditions: |
||||
|
||||
(a) You must give any other recipients of the Work or |
||||
Derivative Works a copy of this License; and |
||||
|
||||
(b) You must cause any modified files to carry prominent notices |
||||
stating that You changed the files; and |
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works |
||||
that You distribute, all copyright, patent, trademark, and |
||||
attribution notices from the Source form of the Work, |
||||
excluding those notices that do not pertain to any part of |
||||
the Derivative Works; and |
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
||||
distribution, then any Derivative Works that You distribute must |
||||
include a readable copy of the attribution notices contained |
||||
within such NOTICE file, excluding those notices that do not |
||||
pertain to any part of the Derivative Works, in at least one |
||||
of the following places: within a NOTICE text file distributed |
||||
as part of the Derivative Works; within the Source form or |
||||
documentation, if provided along with the Derivative Works; or, |
||||
within a display generated by the Derivative Works, if and |
||||
wherever such third-party notices normally appear. The contents |
||||
of the NOTICE file are for informational purposes only and |
||||
do not modify the License. You may add Your own attribution |
||||
notices within Derivative Works that You distribute, alongside |
||||
or as an addendum to the NOTICE text from the Work, provided |
||||
that such additional attribution notices cannot be construed |
||||
as modifying the License. |
||||
|
||||
You may add Your own copyright statement to Your modifications and |
||||
may provide additional or different license terms and conditions |
||||
for use, reproduction, or distribution of Your modifications, or |
||||
for any such Derivative Works as a whole, provided Your use, |
||||
reproduction, and distribution of the Work otherwise complies with |
||||
the conditions stated in this License. |
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
any Contribution intentionally submitted for inclusion in the Work |
||||
by You to the Licensor shall be under the terms and conditions of |
||||
this License, without any additional terms or conditions. |
||||
Notwithstanding the above, nothing herein shall supersede or modify |
||||
the terms of any separate license agreement you may have executed |
||||
with Licensor regarding such Contributions. |
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade |
||||
names, trademarks, service marks, or product names of the Licensor, |
||||
except as required for reasonable and customary use in describing the |
||||
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
agreed to in writing, Licensor provides the Work (and each |
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
implied, including, without limitation, any warranties or conditions |
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
appropriateness of using or redistributing the Work and assume any |
||||
risks associated with Your exercise of permissions under this License. |
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
||||
whether in tort (including negligence), contract, or otherwise, |
||||
unless required by applicable law (such as deliberate and grossly |
||||
negligent acts) or agreed to in writing, shall any Contributor be |
||||
liable to You for damages, including any direct, indirect, special, |
||||
incidental, or consequential damages of any character arising as a |
||||
result of this License or out of the use or inability to use the |
||||
Work (including but not limited to damages for loss of goodwill, |
||||
work stoppage, computer failure or malfunction, or any and all |
||||
other commercial damages or losses), even if such Contributor |
||||
has been advised of the possibility of such damages. |
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
||||
the Work or Derivative Works thereof, You may choose to offer, |
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
or other liability obligations and/or rights consistent with this |
||||
License. However, in accepting such obligations, You may act only |
||||
on Your own behalf and on Your sole responsibility, not on behalf |
||||
of any other Contributor, and only if You agree to indemnify, |
||||
defend, and hold each Contributor harmless for any liability |
||||
incurred by, or claims asserted against, such Contributor by reason |
||||
of your accepting any such warranty or additional liability. |
||||
|
||||
END OF TERMS AND CONDITIONS |
||||
@ -0,0 +1,3 @@
|
||||
# Unsafe bindings for ZeroTier SDK |
||||
|
||||
This crate is a pre-Alpha work in progress intended as a placeholder as development continues. Currently only basic creation and management of a node and unsafe BSD-style socket operations are supported. An idiomatic wrapper will eventually replace this. |
||||
@ -0,0 +1,19 @@
|
||||
extern crate bindgen; |
||||
|
||||
fn main() { |
||||
println!("cargo:rustc-link-lib=zt"); |
||||
println!("cargo:rustc-env=LLVM_CONFIG_PATH=/usr/local/opt/llvm/bin/llvm-config"); |
||||
|
||||
//println!("cargo:rerun-if-changed=../../../include/ZeroTierSockets.h");
|
||||
//println!("cargo:include=/usr/local/include");
|
||||
|
||||
let bindings = bindgen::Builder::default() |
||||
.header("../../../include/ZeroTierSockets.h") |
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks)) |
||||
.generate() |
||||
.expect("Unable to generate bindings"); |
||||
|
||||
bindings |
||||
.write_to_file("./src/libzt.rs") |
||||
.expect("Couldn't write bindings!"); |
||||
} |
||||
@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#![allow(non_upper_case_globals)] |
||||
#![allow(non_camel_case_types)] |
||||
#![allow(non_snake_case)] |
||||
|
||||
include!(concat!("./libzt.rs")); |
||||
|
||||
pub mod node; |
||||
pub mod socket; |
||||
pub mod tcp; |
||||
pub mod udp; |
||||
pub mod utils; |
||||
@ -0,0 +1,115 @@
|
||||
/* |
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#![allow(non_upper_case_globals)] |
||||
#![allow(non_camel_case_types)] |
||||
#![allow(non_snake_case)] |
||||
|
||||
include!(concat!("./libzt.rs")); |
||||
|
||||
use std::ffi::{c_void, CStr, CString}; |
||||
|
||||
extern "C" fn native_event_handler(msg: *mut c_void) { |
||||
let event: &mut zts_event_msg_t = unsafe { &mut *(msg as *mut zts_event_msg_t) }; |
||||
println!("event: {}", event.event_code); |
||||
//user_event_handler(event.event_code);
|
||||
} |
||||
|
||||
pub struct ZeroTierNode { |
||||
// TODO
|
||||
} |
||||
|
||||
impl ZeroTierNode { |
||||
pub fn init_set_event_handler(&self, user_event_handler: impl Fn(i16) -> ()) -> i32 { |
||||
unsafe { |
||||
return zts_init_set_event_handler(Some(native_event_handler)); |
||||
} |
||||
} |
||||
|
||||
pub fn init_set_port(&self, port: u16) -> i32 { |
||||
unsafe { |
||||
return zts_init_set_port(port); |
||||
} |
||||
} |
||||
|
||||
pub fn init_from_storage(&self, storage_path: &str) -> i32 { |
||||
unsafe { |
||||
// This is a false-positive by the linter
|
||||
// See: https://github.com/rust-lang/rust/issues/78691
|
||||
#[allow(temporary_cstring_as_ptr)] |
||||
return zts_init_from_storage(CString::new(storage_path).unwrap().as_ptr()); |
||||
} |
||||
} |
||||
|
||||
pub fn start(&self) -> i32 { |
||||
unsafe { |
||||
return zts_node_start(); |
||||
} |
||||
} |
||||
|
||||
pub fn stop(&self) -> i32 { |
||||
unsafe { |
||||
return zts_node_stop(); |
||||
} |
||||
} |
||||
|
||||
pub fn free(&self) -> i32 { |
||||
unsafe { |
||||
return zts_node_free(); |
||||
} |
||||
} |
||||
|
||||
pub fn net_join(&self, net_id: u64) -> i32 { |
||||
unsafe { |
||||
return zts_net_join(net_id); |
||||
} |
||||
} |
||||
|
||||
pub fn net_leave(&self, net_id: u64) -> i32 { |
||||
unsafe { |
||||
return zts_net_leave(net_id); |
||||
} |
||||
} |
||||
|
||||
pub fn net_transport_is_ready(&self, net_id: u64) -> bool { |
||||
unsafe { |
||||
return zts_net_transport_is_ready(net_id) == 1; |
||||
} |
||||
} |
||||
|
||||
pub fn is_online(&self) -> bool { |
||||
unsafe { |
||||
return zts_node_is_online() == 1; |
||||
} |
||||
} |
||||
|
||||
pub fn id(&self) -> u64 { |
||||
unsafe { |
||||
return zts_node_get_id(); |
||||
} |
||||
} |
||||
|
||||
pub fn delay(&self, interval_ms: u64) -> () { |
||||
unsafe { zts_util_delay(interval_ms) } |
||||
} |
||||
|
||||
pub fn addr_get(&self, net_id: u64) -> String { |
||||
unsafe { |
||||
let mut v = vec![0; (ZTS_INET6_ADDRSTRLEN as usize) + 1]; |
||||
let ptr = v.as_mut_ptr() as *mut i8; |
||||
zts_addr_get_str(net_id, ZTS_AF_INET, ptr, ZTS_INET6_ADDRSTRLEN); |
||||
let c_str = CStr::from_ptr(ptr); |
||||
return c_str.to_string_lossy().into_owned(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,329 @@
|
||||
/* |
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
use std::convert::TryInto; |
||||
use std::ffi::c_void; |
||||
use std::io::{Error, ErrorKind}; |
||||
use std::net::{Shutdown, SocketAddr}; |
||||
use std::os::raw::c_int; |
||||
use std::time::Duration; |
||||
use std::{io, mem}; |
||||
|
||||
use crate::utils::*; |
||||
|
||||
// Note: FileDesc and c_int in libc are private so we can't use that. Use i32 instead
|
||||
pub struct Socket(c_int); |
||||
|
||||
impl Socket { |
||||
pub fn new(addr: &SocketAddr, sock_type: c_int) -> io::Result<Socket> { |
||||
let family = match *addr { |
||||
SocketAddr::V4(..) => ZTS_AF_INET, |
||||
SocketAddr::V6(..) => ZTS_AF_INET6, |
||||
}; |
||||
Socket::new_raw(family as i32, sock_type) |
||||
} |
||||
|
||||
pub fn new_raw(family: c_int, sock_type: c_int) -> io::Result<Socket> { |
||||
unsafe { |
||||
// TODO: Set O_CLOEXEC (this is done in the Rust netc implementation)
|
||||
let fd = zts_bsd_socket(family, sock_type, 0); |
||||
Ok(Socket(fd)) |
||||
} |
||||
} |
||||
|
||||
pub fn accept( |
||||
&self, |
||||
storage: *mut zts_sockaddr, |
||||
len: *mut zts_socklen_t, |
||||
) -> io::Result<Socket> { |
||||
let fd = unsafe { zts_bsd_accept(self.0, storage, len) }; |
||||
Ok(Socket(fd)) |
||||
} |
||||
|
||||
pub fn as_inner(&self) -> &c_int { |
||||
&self.0 |
||||
//.as_inner()
|
||||
} |
||||
|
||||
/* |
||||
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { |
||||
self.set_nonblocking(true)?; |
||||
let r = unsafe { |
||||
let (addrp, len) = addr.into_inner(); |
||||
cvt(zts_bsd_connect(self.0, addrp, len)) |
||||
}; |
||||
self.set_nonblocking(false)?; |
||||
|
||||
match r { |
||||
Ok(_) => return Ok(()), |
||||
// there's no ErrorKind for EINPROGRESS :(
|
||||
Err(ref e) if e.raw_os_error() == Some(ZTS_EINPROGRESS) => {} |
||||
Err(e) => return Err(e), |
||||
} |
||||
|
||||
let mut pollfd = zts_pollfd { fd: self.0, events: ZTS_POLLOUT, revents: 0 }; |
||||
|
||||
if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { |
||||
return Err(io::Error::new_const( |
||||
io::ErrorKind::InvalidInput, |
||||
&"cannot set a 0 duration timeout", |
||||
)); |
||||
} |
||||
|
||||
let start = Instant::now(); |
||||
|
||||
loop { |
||||
let elapsed = start.elapsed(); |
||||
if elapsed >= timeout { |
||||
return Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")); |
||||
} |
||||
|
||||
let timeout = timeout - elapsed; |
||||
let mut timeout = timeout |
||||
.as_secs() |
||||
.saturating_mul(1_000) |
||||
.saturating_add(timeout.subsec_nanos() as u64 / 1_000_000); |
||||
if timeout == 0 { |
||||
timeout = 1; |
||||
} |
||||
|
||||
let timeout = cmp::min(timeout, c_int::MAX as u64) as c_int; |
||||
|
||||
match unsafe { zts_bsd_poll(&mut pollfd, 1, timeout) } { |
||||
-1 => { |
||||
let err = io::Error::last_os_error(); |
||||
if err.kind() != io::ErrorKind::Interrupted { |
||||
return Err(err); |
||||
} |
||||
} |
||||
0 => {} |
||||
_ => { |
||||
// linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
|
||||
// for POLLHUP rather than read readiness
|
||||
if pollfd.revents & ZTS_POLLHUP != 0 { |
||||
let e = self.take_error()?.unwrap_or_else(|| { |
||||
io::Error::new_const( |
||||
io::ErrorKind::Other, |
||||
&"no error set after POLLHUP", |
||||
) |
||||
}); |
||||
return Err(e); |
||||
} |
||||
|
||||
return Ok(()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
*/ |
||||
|
||||
fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { |
||||
unsafe { |
||||
let raw = zts_bsd_recv( |
||||
self.0, |
||||
buf.as_mut_ptr() as *mut c_void, |
||||
(buf.len() as usize).try_into().unwrap(), |
||||
flags, |
||||
); |
||||
Ok(raw as usize) |
||||
} |
||||
} |
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.recv_with_flags(buf, 0) |
||||
} |
||||
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.recv_with_flags(buf, ZTS_MSG_PEEK as i32) |
||||
} |
||||
/* |
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
||||
self.0.read_vectored(bufs) |
||||
} |
||||
*/ |
||||
#[inline] |
||||
pub fn is_read_vectored(&self) -> bool { |
||||
// TODO: In principle this is possible but is not hooked up yet
|
||||
return false; |
||||
} |
||||
|
||||
fn recv_from_with_flags( |
||||
&self, |
||||
buf: &mut [u8], |
||||
flags: c_int, |
||||
) -> io::Result<(usize, SocketAddr)> { |
||||
let mut storage: zts_sockaddr_storage = unsafe { mem::zeroed() }; |
||||
let mut addrlen = mem::size_of_val(&storage) as zts_socklen_t; |
||||
|
||||
unsafe { |
||||
let n = zts_bsd_recvfrom( |
||||
self.0, |
||||
buf.as_mut_ptr() as *mut c_void, |
||||
buf.len().try_into().unwrap(), |
||||
flags, |
||||
&mut storage as *mut _ as *mut _, |
||||
&mut addrlen, |
||||
); |
||||
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) |
||||
} |
||||
} |
||||
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
||||
self.recv_from_with_flags(buf, 0) |
||||
} |
||||
|
||||
pub fn recv_msg(&self, msg: &mut zts_msghdr) -> io::Result<usize> { |
||||
unsafe { |
||||
let n = zts_bsd_recvmsg(self.0, msg, 0 /*ZTS_MSG_CMSG_CLOEXEC*/); |
||||
Ok(n as usize) |
||||
} |
||||
} |
||||
|
||||
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
||||
self.recv_from_with_flags(buf, ZTS_MSG_PEEK as i32) |
||||
} |
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { |
||||
unsafe { |
||||
let raw = zts_bsd_write( |
||||
self.0, |
||||
buf.as_ptr() as *const c_void, |
||||
buf.len().try_into().unwrap(), |
||||
); |
||||
if raw >= 0 { |
||||
Ok(raw.try_into().unwrap()) |
||||
} else { |
||||
Err(io::Error::from_raw_os_error(raw as i32)) |
||||
} |
||||
} |
||||
} |
||||
/* |
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
||||
self.0.write_vectored(bufs) |
||||
} |
||||
*/ |
||||
#[inline] |
||||
pub fn is_write_vectored(&self) -> bool { |
||||
// TODO: In principle this is possible but is not hooked up yet
|
||||
return false; |
||||
} |
||||
|
||||
pub fn send_msg(&self, msg: &mut zts_msghdr) -> io::Result<usize> { |
||||
unsafe { |
||||
let n = zts_bsd_sendmsg(self.0, msg, 0); |
||||
Ok(n as usize) |
||||
} |
||||
} |
||||
|
||||
pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()> { |
||||
let timeout = match dur { |
||||
Some(dur) => { |
||||
if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { |
||||
// TODO: Use new_const to avoid allocations
|
||||
return Err(Error::new( |
||||
ErrorKind::InvalidInput, |
||||
"Cannot set a 0 duration timeout", |
||||
)); |
||||
} |
||||
|
||||
let secs = if dur.as_secs() > time_t::MAX as u64 { |
||||
time_t::MAX |
||||
} else { |
||||
dur.as_secs() as time_t |
||||
}; |
||||
let mut timeout = zts_timeval { |
||||
tv_sec: secs, |
||||
tv_usec: dur.subsec_micros() as std::os::raw::c_long, |
||||
}; |
||||
if timeout.tv_sec == 0 && timeout.tv_usec == 0 { |
||||
timeout.tv_usec = 1; |
||||
} |
||||
timeout |
||||
} |
||||
None => zts_timeval { |
||||
tv_sec: 0, |
||||
tv_usec: 0, |
||||
}, |
||||
}; |
||||
setsockopt(self, ZTS_SOL_SOCKET as i32, kind, timeout) |
||||
} |
||||
|
||||
pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> { |
||||
let raw: zts_timeval = getsockopt(self, ZTS_SOL_SOCKET as i32, kind)?; |
||||
if raw.tv_sec == 0 && raw.tv_usec == 0 { |
||||
Ok(None) |
||||
} else { |
||||
let sec = raw.tv_sec as u64; |
||||
let nsec = (raw.tv_usec as u32) * 1000; |
||||
Ok(Some(Duration::new(sec, nsec))) |
||||
} |
||||
} |
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { |
||||
let how = match how { |
||||
Shutdown::Write => ZTS_SHUT_WR as i32, |
||||
Shutdown::Read => ZTS_SHUT_RD as i32, |
||||
Shutdown::Both => ZTS_SHUT_RDWR as i32, |
||||
}; |
||||
unsafe { |
||||
let raw: c_int = zts_bsd_shutdown(self.0, how); |
||||
if raw == 0 { |
||||
Ok(()) |
||||
} else { |
||||
Err(io::Error::from_raw_os_error(raw as i32)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { |
||||
let nodelay = nodelay as c_int; |
||||
unsafe { |
||||
let raw: c_int = zts_set_no_delay(self.0, nodelay); |
||||
if raw == 0 { |
||||
Ok(()) |
||||
} else { |
||||
Err(io::Error::from_raw_os_error(raw as i32)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn nodelay(&self) -> io::Result<bool> { |
||||
unsafe { |
||||
let raw: c_int = zts_get_no_delay(self.0); |
||||
Ok(raw != 0) |
||||
} |
||||
} |
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
||||
let nonblocking = nonblocking as c_int; |
||||
unsafe { |
||||
let raw: c_int = zts_set_blocking(self.0, !nonblocking); |
||||
if raw == 0 { |
||||
Ok(()) |
||||
} else { |
||||
Err(io::Error::from_raw_os_error(raw as i32)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
unsafe { |
||||
let raw: c_int = zts_get_last_socket_error(self.0); |
||||
if raw == 0 { |
||||
Ok(None) |
||||
} else { |
||||
Err(io::Error::from_raw_os_error(raw as i32)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,518 @@
|
||||
/* |
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
use std::ffi::{c_void, CString}; |
||||
use std::io; |
||||
use std::io::{Read, Write}; |
||||
use std::net::{Shutdown, SocketAddr, ToSocketAddrs}; |
||||
use std::os::raw::c_int; |
||||
use std::time::Duration; |
||||
use std::{cmp, mem}; |
||||
|
||||
use crate::socket::Socket; |
||||
use crate::utils::*; |
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// TcpStream //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
pub struct TcpStreamImpl { |
||||
inner: Socket, |
||||
} |
||||
|
||||
impl TcpStreamImpl { |
||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStreamImpl> { |
||||
let addr = addr?; |
||||
let socket = Socket::new(addr, ZTS_SOCK_STREAM as i32)?; |
||||
//let (addrp, len) = addr.into_inner();
|
||||
unsafe { |
||||
// TODO: Find a better way to split this address string
|
||||
let full_str = addr.to_string(); |
||||
let full_vec = full_str.split(":"); |
||||
let lvec: Vec<&str> = full_vec.collect(); |
||||
let addr_str = lvec[0]; |
||||
let port = addr.port(); |
||||
let timeout_ms = 0; |
||||
// TODO: Handle native error code, consider cvt?
|
||||
// This is a false-positive by the linter
|
||||
// See: https://github.com/rust-lang/rust/issues/78691
|
||||
#[allow(temporary_cstring_as_ptr)] |
||||
zts_connect( |
||||
*socket.as_inner(), |
||||
CString::new(addr_str).unwrap().as_ptr(), |
||||
port, |
||||
timeout_ms, |
||||
); |
||||
} |
||||
Ok(TcpStreamImpl { inner: socket }) |
||||
} |
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { |
||||
let len = cmp::min(buf.len(), <size_t>::MAX as usize) as size_t; |
||||
// TODO: Handle native error code, consider cvt?
|
||||
let ret = |
||||
unsafe { zts_bsd_write(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len) }; |
||||
Ok(ret as usize) |
||||
} |
||||
/* |
||||
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> { |
||||
init(); |
||||
|
||||
let sock = Socket::new(addr, c::SOCK_STREAM)?; |
||||
sock.connect_timeout(addr, timeout)?; |
||||
Ok(TcpStream { inner: sock }) |
||||
} |
||||
*/ |
||||
pub fn socket(&self) -> &Socket { |
||||
&self.inner |
||||
} |
||||
|
||||
pub fn into_socket(self) -> Socket { |
||||
self.inner |
||||
} |
||||
|
||||
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.inner.set_timeout(dur, ZTS_SO_RCVTIMEO as i32) |
||||
} |
||||
|
||||
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.inner.set_timeout(dur, ZTS_SO_SNDTIMEO as i32) |
||||
} |
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.inner.timeout(ZTS_SO_RCVTIMEO as i32) |
||||
} |
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.inner.timeout(ZTS_SO_SNDTIMEO as i32) |
||||
} |
||||
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.inner.peek(buf) |
||||
} |
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.inner.read(buf) |
||||
} |
||||
/* |
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
||||
self.inner.read_vectored(bufs) |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn is_read_vectored(&self) -> bool { |
||||
self.inner.is_read_vectored() |
||||
} |
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { |
||||
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t; |
||||
let ret = cvt(unsafe { |
||||
zts_bsd_send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, ZTS_MSG_NOSIGNAL) |
||||
})?; |
||||
Ok(ret as usize) |
||||
} |
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
||||
self.inner.write_vectored(bufs) |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn is_write_vectored(&self) -> bool { |
||||
self.inner.is_write_vectored() |
||||
} |
||||
*/ |
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
||||
sockname(|buf, len| unsafe { zts_bsd_getpeername(*self.inner.as_inner(), buf, len) }) |
||||
} |
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> { |
||||
sockname(|buf, len| unsafe { zts_bsd_getsockname(*self.inner.as_inner(), buf, len) }) |
||||
} |
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { |
||||
self.inner.shutdown(how) |
||||
} |
||||
|
||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { |
||||
self.inner.set_nodelay(nodelay) |
||||
} |
||||
|
||||
pub fn nodelay(&self) -> io::Result<bool> { |
||||
self.inner.nodelay() |
||||
} |
||||
|
||||
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
||||
setsockopt( |
||||
&self.inner, |
||||
ZTS_IPPROTO_IP as i32, |
||||
ZTS_IP_TTL as i32, |
||||
ttl as c_int, |
||||
) |
||||
} |
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> { |
||||
let raw: c_int = getsockopt(&self.inner, ZTS_IPPROTO_IP as i32, ZTS_IP_TTL as i32)?; |
||||
Ok(raw as u32) |
||||
} |
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
self.inner.take_error() |
||||
} |
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
||||
self.inner.set_nonblocking(nonblocking) |
||||
} |
||||
} |
||||
|
||||
pub struct TcpStream(TcpStreamImpl); |
||||
|
||||
impl TcpStream { |
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> { |
||||
each_addr(addr, TcpStreamImpl::connect).map(TcpStream) |
||||
} |
||||
/* |
||||
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> { |
||||
TcpStreamImpl::connect_timeout(addr, timeout).map(TcpStream) |
||||
} |
||||
*/ |
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
||||
self.0.peer_addr() |
||||
} |
||||
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> { |
||||
self.0.socket_addr() |
||||
} |
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { |
||||
self.0.shutdown(how) |
||||
} |
||||
|
||||
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.0.set_read_timeout(dur) |
||||
} |
||||
|
||||
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.0.set_write_timeout(dur) |
||||
} |
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.0.read_timeout() |
||||
} |
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.0.write_timeout() |
||||
} |
||||
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.0.peek(buf) |
||||
} |
||||
|
||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { |
||||
self.0.set_nodelay(nodelay) |
||||
} |
||||
|
||||
pub fn nodelay(&self) -> io::Result<bool> { |
||||
self.0.nodelay() |
||||
} |
||||
|
||||
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
||||
self.0.set_ttl(ttl) |
||||
} |
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> { |
||||
self.0.ttl() |
||||
} |
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
self.0.take_error() |
||||
} |
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
||||
self.0.set_nonblocking(nonblocking) |
||||
} |
||||
} |
||||
|
||||
impl Read for TcpStream { |
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.0.read(buf) |
||||
} |
||||
/* |
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
||||
self.0.read_vectored(bufs) |
||||
} |
||||
|
||||
#[inline] |
||||
fn is_read_vectored(&self) -> bool { |
||||
self.0.is_read_vectored() |
||||
} |
||||
|
||||
#[inline] |
||||
unsafe fn initializer(&self) -> Initializer { |
||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
||||
unsafe { Initializer::nop() } |
||||
} |
||||
*/ |
||||
} |
||||
|
||||
impl Write for TcpStream { |
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
||||
self.0.write(buf) |
||||
} |
||||
/* |
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
||||
self.0.write_vectored(bufs) |
||||
} |
||||
|
||||
#[inline] |
||||
fn is_write_vectored(&self) -> bool { |
||||
self.0.is_write_vectored() |
||||
} |
||||
*/ |
||||
fn flush(&mut self) -> io::Result<()> { |
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
impl Read for &TcpStream { |
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.0.read(buf) |
||||
} |
||||
/* |
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
||||
self.0.read_vectored(bufs) |
||||
} |
||||
|
||||
#[inline] |
||||
fn is_read_vectored(&self) -> bool { |
||||
self.0.is_read_vectored() |
||||
} |
||||
|
||||
#[inline] |
||||
unsafe fn initializer(&self) -> Initializer { |
||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
||||
unsafe { Initializer::nop() } |
||||
} |
||||
*/ |
||||
} |
||||
|
||||
impl Write for &TcpStream { |
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
||||
self.0.write(buf) |
||||
} |
||||
/* |
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
||||
self.0.write_vectored(bufs) |
||||
} |
||||
|
||||
#[inline] |
||||
fn is_write_vectored(&self) -> bool { |
||||
self.0.is_write_vectored() |
||||
} |
||||
*/ |
||||
fn flush(&mut self) -> io::Result<()> { |
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
impl AsInner<TcpStreamImpl> for TcpStream { |
||||
fn as_inner(&self) -> &TcpStreamImpl { |
||||
&self.0 |
||||
} |
||||
} |
||||
|
||||
impl FromInner<TcpStreamImpl> for TcpStream { |
||||
fn from_inner(inner: TcpStreamImpl) -> TcpStream { |
||||
TcpStream(inner) |
||||
} |
||||
} |
||||
|
||||
impl IntoInner<TcpStreamImpl> for TcpStream { |
||||
fn into_inner(self) -> TcpStreamImpl { |
||||
self.0 |
||||
} |
||||
} |
||||
/* |
||||
impl fmt::Debug for TcpStream { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||
self.0.fmt(f) |
||||
} |
||||
} |
||||
*/ |
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// TcpListener //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
pub struct TcpListenerImpl { |
||||
inner: Socket, |
||||
} |
||||
|
||||
impl TcpListenerImpl { |
||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListenerImpl> { |
||||
let addr = addr?; |
||||
let socket = Socket::new(addr, ZTS_SOCK_STREAM as i32)?; |
||||
// TODO: Possibly set SO_REUSEADDR
|
||||
//let (addrp, len) = addr.into_inner();
|
||||
unsafe { |
||||
//zts_bsd_bind(*socket.as_inner(), addrp, len as _);
|
||||
// TODO: Find a better way to split this address string
|
||||
let full_str = addr.to_string(); |
||||
let full_vec = full_str.split(":"); |
||||
let lvec: Vec<&str> = full_vec.collect(); |
||||
let addr_str = lvec[0]; |
||||
let port = addr.port(); |
||||
// TODO: Handle native error code, consider cvt?
|
||||
// This is a false-positive by the linter
|
||||
// See: https://github.com/rust-lang/rust/issues/78691
|
||||
#[allow(temporary_cstring_as_ptr)] |
||||
zts_bind( |
||||
*socket.as_inner(), |
||||
CString::new(addr_str).unwrap().as_ptr(), |
||||
port, |
||||
); |
||||
// TODO: Handle native error code, consider cvt?
|
||||
zts_bsd_listen(*socket.as_inner(), 128); |
||||
} |
||||
Ok(TcpListenerImpl { inner: socket }) |
||||
} |
||||
|
||||
pub fn accept(&self) -> io::Result<(TcpStreamImpl, SocketAddr)> { |
||||
let mut storage: zts_sockaddr_storage = unsafe { mem::zeroed() }; |
||||
let mut len = mem::size_of_val(&storage) as zts_socklen_t; |
||||
// TODO: Handle native error code, consider cvt?
|
||||
let socket = self |
||||
.inner |
||||
.accept(&mut storage as *mut _ as *mut _, &mut len)?; |
||||
let addr = sockaddr_to_addr(&storage, len as usize)?; |
||||
Ok((TcpStreamImpl { inner: socket }, addr)) |
||||
} |
||||
|
||||
pub fn socket(&self) -> &Socket { |
||||
&self.inner |
||||
} |
||||
|
||||
pub fn into_socket(self) -> Socket { |
||||
self.inner |
||||
} |
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> { |
||||
sockname(|buf, len| unsafe { zts_bsd_getsockname(*self.inner.as_inner(), buf, len) }) |
||||
} |
||||
|
||||
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
||||
setsockopt( |
||||
&self.inner, |
||||
ZTS_IPPROTO_IP as i32, |
||||
ZTS_IP_TTL as i32, |
||||
ttl as c_int, |
||||
) |
||||
} |
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> { |
||||
let raw: c_int = getsockopt(&self.inner, ZTS_IPPROTO_IP as i32, ZTS_IP_TTL as i32)?; |
||||
Ok(raw as u32) |
||||
} |
||||
|
||||
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { |
||||
setsockopt( |
||||
&self.inner, |
||||
ZTS_IPPROTO_IPV6 as i32, |
||||
ZTS_IPV6_V6ONLY as i32, |
||||
only_v6 as c_int, |
||||
) |
||||
} |
||||
|
||||
pub fn only_v6(&self) -> io::Result<bool> { |
||||
let raw: c_int = getsockopt(&self.inner, ZTS_IPPROTO_IPV6 as i32, ZTS_IPV6_V6ONLY as i32)?; |
||||
Ok(raw != 0) |
||||
} |
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
self.inner.take_error() |
||||
} |
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
||||
self.inner.set_nonblocking(nonblocking) |
||||
} |
||||
} |
||||
|
||||
pub struct TcpListener(TcpListenerImpl); |
||||
|
||||
pub struct Incoming<'a> { |
||||
listener: &'a TcpListener, |
||||
} |
||||
|
||||
impl<'a> Iterator for Incoming<'a> { |
||||
type Item = io::Result<TcpStream>; |
||||
fn next(&mut self) -> Option<io::Result<TcpStream>> { |
||||
Some(self.listener.accept().map(|p| p.0)) |
||||
} |
||||
} |
||||
|
||||
impl TcpListener { |
||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> { |
||||
each_addr(addr, TcpListenerImpl::bind).map(TcpListener) |
||||
} |
||||
|
||||
pub fn incoming(&self) -> Incoming<'_> { |
||||
Incoming { listener: self } |
||||
} |
||||
|
||||
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { |
||||
self.0.accept().map(|(a, b)| (TcpStream(a), b)) |
||||
} |
||||
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> { |
||||
self.0.socket_addr() |
||||
} |
||||
|
||||
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
||||
self.0.set_ttl(ttl) |
||||
} |
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> { |
||||
self.0.ttl() |
||||
} |
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
self.0.take_error() |
||||
} |
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
||||
self.0.set_nonblocking(nonblocking) |
||||
} |
||||
} |
||||
|
||||
impl AsInner<TcpListenerImpl> for TcpListener { |
||||
fn as_inner(&self) -> &TcpListenerImpl { |
||||
&self.0 |
||||
} |
||||
} |
||||
|
||||
impl FromInner<TcpListenerImpl> for TcpListener { |
||||
fn from_inner(inner: TcpListenerImpl) -> TcpListener { |
||||
TcpListener(inner) |
||||
} |
||||
} |
||||
|
||||
impl IntoInner<TcpListenerImpl> for TcpListener { |
||||
fn into_inner(self) -> TcpListenerImpl { |
||||
self.0 |
||||
} |
||||
} |
||||
/* |
||||
impl fmt::Debug for TcpListener { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||
self.0.fmt(f) |
||||
} |
||||
} |
||||
*/ |
||||
@ -0,0 +1,459 @@
|
||||
/* |
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
use std::convert::TryInto; |
||||
use std::ffi::{c_void, CString}; |
||||
use std::io::{self, Error, ErrorKind}; |
||||
use std::net::{/*Ipv4Addr, Ipv6Addr,*/ SocketAddr, ToSocketAddrs}; |
||||
use std::os::raw::c_int; |
||||
use std::time::Duration; |
||||
//use std::cmp;
|
||||
|
||||
use crate::socket::Socket; |
||||
use crate::utils::*; |
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// UdpSocketImpl //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
pub struct UdpSocketImpl { |
||||
inner: Socket, |
||||
} |
||||
|
||||
impl UdpSocketImpl { |
||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocketImpl> { |
||||
let addr = addr?; |
||||
let socket = Socket::new(addr, ZTS_SOCK_DGRAM as i32)?; |
||||
// TODO: Possibly set SO_REUSEADDR
|
||||
//let (addrp, len) = addr.into_inner();
|
||||
unsafe { |
||||
//zts_bsd_bind(*socket.as_inner(), addrp, len as _);
|
||||
// TODO: Find a better way to split this address string
|
||||
let full_str = addr.to_string(); |
||||
let full_vec = full_str.split(":"); |
||||
let lvec: Vec<&str> = full_vec.collect(); |
||||
let addr_str = lvec[0]; |
||||
let port = addr.port(); |
||||
// TODO: Handle native error code, consider cvt?
|
||||
// This is a false-positive by the linter
|
||||
// See: https://github.com/rust-lang/rust/issues/78691
|
||||
#[allow(temporary_cstring_as_ptr)] |
||||
zts_bind( |
||||
*socket.as_inner(), |
||||
CString::new(addr_str).unwrap().as_ptr(), |
||||
port, |
||||
); |
||||
} |
||||
Ok(UdpSocketImpl { inner: socket }) |
||||
} |
||||
|
||||
pub fn socket(&self) -> &Socket { |
||||
&self.inner |
||||
} |
||||
|
||||
pub fn into_socket(self) -> Socket { |
||||
self.inner |
||||
} |
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
||||
sockname(|buf, len| unsafe { zts_bsd_getpeername(*self.inner.as_inner(), buf, len) }) |
||||
} |
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> { |
||||
sockname(|buf, len| unsafe { zts_bsd_getsockname(*self.inner.as_inner(), buf, len) }) |
||||
} |
||||
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
||||
self.inner.recv_from(buf) |
||||
} |
||||
|
||||
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
||||
self.inner.peek_from(buf) |
||||
} |
||||
|
||||
pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> { |
||||
/* |
||||
let len = cmp::min(buf.len(), <size_t>::MAX as usize) as size_t; |
||||
let (dstp, dstlen) = dst.into_inner(); |
||||
let ret = cvt(unsafe { |
||||
zts_bsd_sendto( |
||||
*self.inner.as_inner(), |
||||
buf.as_ptr() as *const c_void, |
||||
len, |
||||
ZTS_MSG_NOSIGNAL, |
||||
dstp, |
||||
dstlen, |
||||
) |
||||
})?; |
||||
Ok(ret as usize) |
||||
*/ |
||||
Ok(0) |
||||
} |
||||
|
||||
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.inner.set_timeout(dur, ZTS_SO_RCVTIMEO as i32) |
||||
} |
||||
|
||||
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.inner.set_timeout(dur, ZTS_SO_SNDTIMEO as i32) |
||||
} |
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.inner.timeout(ZTS_SO_RCVTIMEO as i32) |
||||
} |
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.inner.timeout(ZTS_SO_SNDTIMEO as i32) |
||||
} |
||||
|
||||
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { |
||||
setsockopt( |
||||
&self.inner, |
||||
ZTS_SOL_SOCKET as i32, |
||||
ZTS_SO_BROADCAST as i32, |
||||
broadcast as c_int, |
||||
) |
||||
} |
||||
|
||||
pub fn broadcast(&self) -> io::Result<bool> { |
||||
let raw: c_int = getsockopt(&self.inner, ZTS_SOL_SOCKET as i32, ZTS_SO_BROADCAST as i32)?; |
||||
Ok(raw != 0) |
||||
} |
||||
/* |
||||
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { |
||||
setsockopt( |
||||
&self.inner, |
||||
ZTS_IPPROTO_IP, |
||||
ZTS_IP_MULTICAST_LOOP, |
||||
multicast_loop_v4 as IpV4MultiCastType, |
||||
) |
||||
} |
||||
|
||||
pub fn multicast_loop_v4(&self) -> io::Result<bool> { |
||||
let raw: IpV4MultiCastType = getsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_MULTICAST_LOOP)?; |
||||
Ok(raw != 0) |
||||
} |
||||
|
||||
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { |
||||
setsockopt( |
||||
&self.inner, |
||||
ZTS_IPPROTO_IP, |
||||
ZTS_IP_MULTICAST_TTL, |
||||
multicast_ttl_v4 as IpV4MultiCastType, |
||||
) |
||||
} |
||||
|
||||
pub fn multicast_ttl_v4(&self) -> io::Result<u32> { |
||||
let raw: IpV4MultiCastType = getsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_MULTICAST_TTL)?; |
||||
Ok(raw as u32) |
||||
} |
||||
|
||||
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { |
||||
setsockopt(&self.inner, ZTS_IPPROTO_IPV6, ZTS_IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int) |
||||
} |
||||
|
||||
pub fn multicast_loop_v6(&self) -> io::Result<bool> { |
||||
let raw: c_int = getsockopt(&self.inner, ZTS_IPPROTO_IPV6, ZTS_IPV6_MULTICAST_LOOP)?; |
||||
Ok(raw != 0) |
||||
} |
||||
|
||||
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { |
||||
let mreq = zts_ip_mreq { |
||||
imr_multiaddr: multiaddr.into_inner(), |
||||
imr_interface: interface.into_inner(), |
||||
}; |
||||
setsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_ADD_MEMBERSHIP, mreq) |
||||
} |
||||
|
||||
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
||||
let mreq = zts_ipv6_mreq { |
||||
ipv6mr_multiaddr: *multiaddr.as_inner(), |
||||
ipv6mr_interface: to_ipv6mr_interface(interface), |
||||
}; |
||||
setsockopt(&self.inner, ZTS_IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) |
||||
} |
||||
|
||||
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { |
||||
let mreq = zts_ip_mreq { |
||||
imr_multiaddr: multiaddr.into_inner(), |
||||
imr_interface: interface.into_inner(), |
||||
}; |
||||
setsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_DROP_MEMBERSHIP, mreq) |
||||
} |
||||
|
||||
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
||||
let mreq = zts_ipv6_mreq { |
||||
ipv6mr_multiaddr: *multiaddr.as_inner(), |
||||
ipv6mr_interface: to_ipv6mr_interface(interface), |
||||
}; |
||||
setsockopt(&self.inner, ZTS_IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) |
||||
} |
||||
*/ |
||||
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
||||
setsockopt( |
||||
&self.inner, |
||||
ZTS_IPPROTO_IP as i32, |
||||
ZTS_IP_TTL as i32, |
||||
ttl as c_int, |
||||
) |
||||
} |
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> { |
||||
let raw: c_int = getsockopt(&self.inner, ZTS_IPPROTO_IP as i32, ZTS_IP_TTL as i32)?; |
||||
Ok(raw as u32) |
||||
} |
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
self.inner.take_error() |
||||
} |
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
||||
self.inner.set_nonblocking(nonblocking) |
||||
} |
||||
|
||||
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.inner.read(buf) |
||||
} |
||||
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.inner.peek(buf) |
||||
} |
||||
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> { |
||||
/* |
||||
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t; |
||||
let ret = cvt(unsafe { |
||||
zts_bsd_send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, ZTS_MSG_NOSIGNAL) |
||||
})?; |
||||
Ok(ret as usize) |
||||
*/ |
||||
unsafe { |
||||
let raw = zts_bsd_write( |
||||
*self.inner.as_inner(), |
||||
buf.as_ptr() as *const c_void, |
||||
buf.len().try_into().unwrap(), |
||||
); |
||||
if raw >= 0 { |
||||
Ok(raw.try_into().unwrap()) |
||||
} else { |
||||
Err(io::Error::from_raw_os_error(raw as i32)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { |
||||
let addr = addr?; |
||||
//let (addrp, len) = addr?.into_inner();
|
||||
unsafe { |
||||
let full_str = addr.to_string(); |
||||
let full_vec = full_str.split(":"); |
||||
let lvec: Vec<&str> = full_vec.collect(); |
||||
let addr_str = lvec[0]; |
||||
let port = addr.port(); |
||||
let timeout_ms = 0; |
||||
// TODO: Handle native error code, consider cvt?
|
||||
// This is a false-positive by the linter
|
||||
// See: https://github.com/rust-lang/rust/issues/78691
|
||||
#[allow(temporary_cstring_as_ptr)] |
||||
cvt(zts_connect( |
||||
*self.inner.as_inner(), |
||||
CString::new(addr_str).unwrap().as_ptr(), |
||||
port, |
||||
timeout_ms, |
||||
))?; |
||||
} |
||||
|
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
impl FromInner<Socket> for UdpSocketImpl { |
||||
fn from_inner(socket: Socket) -> UdpSocketImpl { |
||||
UdpSocketImpl { inner: socket } |
||||
} |
||||
} |
||||
|
||||
/* |
||||
impl fmt::Debug for UdpSocketImpl { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||
let mut res = f.debug_struct("UdpSocketImpl"); |
||||
|
||||
if let Ok(addr) = self.socket_addr() { |
||||
res.field("addr", &addr); |
||||
} |
||||
|
||||
let name = if cfg!(windows) { "socket" } else { "fd" }; |
||||
res.field(name, &self.inner.as_inner()).finish() |
||||
} |
||||
} |
||||
*/ |
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// UdpSocket //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
pub struct UdpSocket(UdpSocketImpl); |
||||
|
||||
impl UdpSocket { |
||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> { |
||||
each_addr(addr, UdpSocketImpl::bind).map(UdpSocket) |
||||
} |
||||
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
||||
self.0.recv_from(buf) |
||||
} |
||||
|
||||
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
||||
self.0.peek_from(buf) |
||||
} |
||||
|
||||
pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> { |
||||
match addr.to_socket_addrs()?.next() { |
||||
Some(addr) => self.0.send_to(buf, &addr), |
||||
None => Err(Error::new( |
||||
ErrorKind::InvalidInput, |
||||
"No address to send data to", |
||||
)), |
||||
} |
||||
} |
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
||||
self.0.peer_addr() |
||||
} |
||||
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> { |
||||
self.0.socket_addr() |
||||
} |
||||
|
||||
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.0.set_read_timeout(dur) |
||||
} |
||||
|
||||
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> { |
||||
self.0.set_write_timeout(dur) |
||||
} |
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.0.read_timeout() |
||||
} |
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> { |
||||
self.0.write_timeout() |
||||
} |
||||
|
||||
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { |
||||
self.0.set_broadcast(broadcast) |
||||
} |
||||
|
||||
pub fn broadcast(&self) -> io::Result<bool> { |
||||
self.0.broadcast() |
||||
} |
||||
/* |
||||
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { |
||||
self.0.set_multicast_loop_v4(multicast_loop_v4) |
||||
} |
||||
|
||||
pub fn multicast_loop_v4(&self) -> io::Result<bool> { |
||||
self.0.multicast_loop_v4() |
||||
} |
||||
|
||||
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { |
||||
self.0.set_multicast_ttl_v4(multicast_ttl_v4) |
||||
} |
||||
|
||||
pub fn multicast_ttl_v4(&self) -> io::Result<u32> { |
||||
self.0.multicast_ttl_v4() |
||||
} |
||||
|
||||
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { |
||||
self.0.set_multicast_loop_v6(multicast_loop_v6) |
||||
} |
||||
|
||||
pub fn multicast_loop_v6(&self) -> io::Result<bool> { |
||||
self.0.multicast_loop_v6() |
||||
} |
||||
*/ |
||||
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
||||
self.0.set_ttl(ttl) |
||||
} |
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> { |
||||
self.0.ttl() |
||||
} |
||||
/* |
||||
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { |
||||
self.0.join_multicast_v4(multiaddr, interface) |
||||
} |
||||
|
||||
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
||||
self.0.join_multicast_v6(multiaddr, interface) |
||||
} |
||||
|
||||
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { |
||||
self.0.leave_multicast_v4(multiaddr, interface) |
||||
} |
||||
|
||||
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
||||
self.0.leave_multicast_v6(multiaddr, interface) |
||||
} |
||||
*/ |
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
self.0.take_error() |
||||
} |
||||
|
||||
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> { |
||||
each_addr(addr, |addr| self.0.connect(addr)) |
||||
} |
||||
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> { |
||||
self.0.send(buf) |
||||
} |
||||
|
||||
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.0.recv(buf) |
||||
} |
||||
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.0.peek(buf) |
||||
} |
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
||||
self.0.set_nonblocking(nonblocking) |
||||
} |
||||
} |
||||
|
||||
impl AsInner<UdpSocketImpl> for UdpSocket { |
||||
fn as_inner(&self) -> &UdpSocketImpl { |
||||
&self.0 |
||||
} |
||||
} |
||||
|
||||
impl FromInner<UdpSocketImpl> for UdpSocket { |
||||
fn from_inner(inner: UdpSocketImpl) -> UdpSocket { |
||||
UdpSocket(inner) |
||||
} |
||||
} |
||||
|
||||
impl IntoInner<UdpSocketImpl> for UdpSocket { |
||||
fn into_inner(self) -> UdpSocketImpl { |
||||
self.0 |
||||
} |
||||
} |
||||
|
||||
/* |
||||
impl fmt::Debug for UdpSocket { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||
self.0.fmt(f) |
||||
} |
||||
} |
||||
*/ |
||||
@ -0,0 +1,213 @@
|
||||
/* |
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#![allow(non_upper_case_globals)] |
||||
#![allow(non_camel_case_types)] |
||||
#![allow(non_snake_case)] |
||||
|
||||
include!(concat!("./libzt.rs")); |
||||
|
||||
use std::ffi::c_void; |
||||
use std::io::{Error, ErrorKind}; |
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; |
||||
use std::os::raw::c_int; |
||||
use std::{io, mem}; |
||||
|
||||
use crate::socket::Socket; |
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Utilities //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
/* |
||||
|
||||
The following utility functions were lifted directly from the Rust standard |
||||
library and tweaked to accommodate ZeroTier sockets. See their original |
||||
implementations here: |
||||
|
||||
- https://doc.rust-lang.org/src/std/net/tcp.rs.html#95-97
|
||||
- https://github.com/rust-lang/rust/blob/master/library/std/src/sys_common/net.rs
|
||||
- https://github.com/rust-lang/rust/blob/db492ecd5ba6bd82205612cebb9034710653f0c2/library/std/src/net/mod.rs
|
||||
*/ |
||||
|
||||
pub trait IsMinusOne { |
||||
fn is_minus_one(&self) -> bool; |
||||
} |
||||
|
||||
macro_rules! impl_is_minus_one { |
||||
($($t:ident)*) => ($(impl IsMinusOne for $t { |
||||
fn is_minus_one(&self) -> bool { |
||||
*self == -1 |
||||
} |
||||
})*) |
||||
} |
||||
|
||||
impl_is_minus_one! { i8 i16 i32 i64 isize } |
||||
|
||||
pub fn cvt<T: IsMinusOne>(t: T) -> std::io::Result<T> { |
||||
if t.is_minus_one() { |
||||
Err(std::io::Error::last_os_error()) |
||||
} else { |
||||
Ok(t) |
||||
} |
||||
} |
||||
|
||||
pub fn cvt_r<T, F>(mut f: F) -> std::io::Result<T> |
||||
where |
||||
T: IsMinusOne, |
||||
F: FnMut() -> T, |
||||
{ |
||||
loop { |
||||
match cvt(f()) { |
||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => {} |
||||
other => return other, |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> { |
||||
unsafe { |
||||
let payload = &payload as *const T as *const c_void; |
||||
cvt(zts_bsd_setsockopt( |
||||
*sock.as_inner(), |
||||
opt, |
||||
val, |
||||
payload, |
||||
mem::size_of::<T>() as zts_socklen_t, |
||||
))?; |
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<T> { |
||||
unsafe { |
||||
let mut slot: T = mem::zeroed(); |
||||
let mut len = mem::size_of::<T>() as zts_socklen_t; |
||||
cvt(zts_bsd_getsockopt( |
||||
*sock.as_inner(), |
||||
opt, |
||||
val, |
||||
&mut slot as *mut _ as *mut _, |
||||
&mut len, |
||||
))?; |
||||
Ok(slot) |
||||
} |
||||
} |
||||
|
||||
pub trait AsInner<Inner: ?Sized> { |
||||
fn as_inner(&self) -> &Inner; |
||||
} |
||||
|
||||
pub trait AsInnerMut<Inner: ?Sized> { |
||||
fn as_inner_mut(&mut self) -> &mut Inner; |
||||
} |
||||
|
||||
pub trait IntoInner<Inner> { |
||||
fn into_inner(self) -> Inner; |
||||
} |
||||
|
||||
pub trait FromInner<Inner> { |
||||
fn from_inner(inner: Inner) -> Self; |
||||
} |
||||
|
||||
pub fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T> |
||||
where |
||||
F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>, |
||||
{ |
||||
let addrs = match addr.to_socket_addrs() { |
||||
Ok(addrs) => addrs, |
||||
Err(e) => return f(Err(e)), |
||||
}; |
||||
let mut last_err = None; |
||||
for addr in addrs { |
||||
match f(Ok(&addr)) { |
||||
Ok(l) => return Ok(l), |
||||
Err(e) => last_err = Some(e), |
||||
} |
||||
} |
||||
// TODO: Should ideally use new_const as is used in std::net to avoid allocations
|
||||
Err(last_err.unwrap_or_else(|| { |
||||
Error::new( |
||||
ErrorKind::InvalidInput, |
||||
"Could not resolve to any addresses", |
||||
) |
||||
})) |
||||
} |
||||
|
||||
pub const fn ntohs(i: u16) -> u16 { |
||||
u16::from_be(i) |
||||
} |
||||
|
||||
pub const fn htons(i: u16) -> u16 { |
||||
i.to_be() |
||||
} |
||||
|
||||
pub fn ipv4_addr(addr: zts_in_addr) -> u32 { |
||||
(addr.s_addr as u32).to_be() |
||||
} |
||||
|
||||
// Copied from: https://docs.rs/pnet_sys/0.28.0/src/pnet_sys/unix.rs.html#162-201
|
||||
pub fn sockaddr_to_addr(storage: &zts_sockaddr_storage, len: usize) -> io::Result<SocketAddr> { |
||||
// See: https://github.com/rust-lang/rust/issues/76191
|
||||
match storage.ss_family as c_int { |
||||
// ZTS_AF_INET
|
||||
0x2 => { |
||||
assert!(len as usize >= mem::size_of::<zts_sockaddr_in>()); |
||||
let storage: &zts_sockaddr_in = unsafe { mem::transmute(storage) }; |
||||
let ip = ipv4_addr(storage.sin_addr); |
||||
let a = (ip >> 24) as u8; |
||||
let b = (ip >> 16) as u8; |
||||
let c = (ip >> 8) as u8; |
||||
let d = ip as u8; |
||||
let sockaddrv4 = SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), ntohs(storage.sin_port)); |
||||
Ok(SocketAddr::V4(sockaddrv4)) |
||||
} |
||||
// ZTS_AF_INET6
|
||||
0xA => { |
||||
assert!(len as usize >= mem::size_of::<zts_sockaddr_in6>()); |
||||
let storage: &zts_sockaddr_in6 = unsafe { mem::transmute(storage) }; |
||||
let arr: [u16; 8] = unsafe { mem::transmute(storage.sin6_addr.un.u8_addr) }; |
||||
let a = ntohs(arr[0]); |
||||
let b = ntohs(arr[1]); |
||||
let c = ntohs(arr[2]); |
||||
let d = ntohs(arr[3]); |
||||
let e = ntohs(arr[4]); |
||||
let f = ntohs(arr[5]); |
||||
let g = ntohs(arr[6]); |
||||
let h = ntohs(arr[7]); |
||||
let ip = Ipv6Addr::new(a, b, c, d, e, f, g, h); |
||||
Ok(SocketAddr::V6(SocketAddrV6::new( |
||||
ip, |
||||
ntohs(storage.sin6_port), |
||||
u32::from_be(storage.sin6_flowinfo), |
||||
storage.sin6_scope_id, |
||||
))) |
||||
} |
||||
_ => Err(io::Error::new( |
||||
io::ErrorKind::InvalidData, |
||||
"expected IPv4 or IPv6 socket", |
||||
)), |
||||
} |
||||
} |
||||
|
||||
pub fn sockname<F>(f: F) -> io::Result<SocketAddr> |
||||
where |
||||
F: FnOnce(*mut zts_sockaddr, *mut zts_socklen_t) -> c_int, |
||||
{ |
||||
unsafe { |
||||
let mut storage: zts_sockaddr_storage = mem::zeroed(); |
||||
let mut len = mem::size_of_val(&storage) as zts_socklen_t; |
||||
f(&mut storage as *mut _ as *mut _, &mut len); |
||||
sockaddr_to_addr(&storage, len as usize) |
||||
} |
||||
} |
||||
Loading…
Reference in new issue