mirror of
https://github.com/denoland/deno.git
synced 2024-12-24 08:09:08 -05:00
refactor(ext/net): use concrete error type (#26227)
This commit is contained in:
parent
ee35b9d28e
commit
1da0ee2d14
10 changed files with 317 additions and 191 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -1423,9 +1423,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_core"
|
||||
version = "0.313.0"
|
||||
version = "0.314.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29f36be738d78e39b6603a6b07f1cf91e28baf3681f87205f07482999e0d0bc2"
|
||||
checksum = "1fcd11ab87426c611b7170138a768dad7170c8fb66d8095b773d25e58fd254ea"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
@ -1797,6 +1797,7 @@ dependencies = [
|
|||
"rustls-tokio-stream",
|
||||
"serde",
|
||||
"socket2",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"trust-dns-proto",
|
||||
"trust-dns-resolver",
|
||||
|
@ -1913,9 +1914,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_ops"
|
||||
version = "0.189.0"
|
||||
version = "0.190.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8f998ad1d5b36064109367ffe67b1088385eb3d8025efc95e445bc013a147a2"
|
||||
checksum = "a48a3e06cace18a2c49e148da067678c6af80e70757a8c3991301397cf6b9919"
|
||||
dependencies = [
|
||||
"proc-macro-rules",
|
||||
"proc-macro2",
|
||||
|
@ -6211,9 +6212,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_v8"
|
||||
version = "0.222.0"
|
||||
version = "0.223.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27130b5cd87f6f06228940a1f3a7ecc988ea13d1bede1398a48d74cb59dabc9a"
|
||||
checksum = "c127bb9f2024433d06789b242477c808fd7f7dc4c3278576dd5bc99c4e5c75ff"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"serde",
|
||||
|
|
|
@ -46,7 +46,7 @@ repository = "https://github.com/denoland/deno"
|
|||
|
||||
[workspace.dependencies]
|
||||
deno_ast = { version = "=0.42.2", features = ["transpiling"] }
|
||||
deno_core = { version = "0.313.0" }
|
||||
deno_core = { version = "0.314.1" }
|
||||
|
||||
deno_bench_util = { version = "0.166.0", path = "./bench_util" }
|
||||
deno_lockfile = "=0.23.1"
|
||||
|
|
2
ext/cache/lib.rs
vendored
2
ext/cache/lib.rs
vendored
|
@ -28,7 +28,7 @@ pub enum CacheError {
|
|||
Resource(deno_core::error::AnyError),
|
||||
#[error(transparent)]
|
||||
Other(deno_core::error::AnyError),
|
||||
#[error(transparent)]
|
||||
#[error("{0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ pin-project.workspace = true
|
|||
rustls-tokio-stream.workspace = true
|
||||
serde.workspace = true
|
||||
socket2.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
trust-dns-proto = "0.23"
|
||||
trust-dns-resolver = { version = "0.23", features = ["tokio-runtime", "serde-config"] }
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::TryFutureExt;
|
||||
use deno_core::AsyncMutFuture;
|
||||
use deno_core::AsyncRefCell;
|
||||
use deno_core::AsyncResult;
|
||||
|
@ -69,25 +68,36 @@ where
|
|||
pub async fn read(
|
||||
self: Rc<Self>,
|
||||
data: &mut [u8],
|
||||
) -> Result<usize, AnyError> {
|
||||
) -> Result<usize, std::io::Error> {
|
||||
let mut rd = self.rd_borrow_mut().await;
|
||||
let nread = rd.read(data).try_or_cancel(self.cancel_handle()).await?;
|
||||
Ok(nread)
|
||||
}
|
||||
|
||||
pub async fn write(self: Rc<Self>, data: &[u8]) -> Result<usize, AnyError> {
|
||||
pub async fn write(
|
||||
self: Rc<Self>,
|
||||
data: &[u8],
|
||||
) -> Result<usize, std::io::Error> {
|
||||
let mut wr = self.wr_borrow_mut().await;
|
||||
let nwritten = wr.write(data).await?;
|
||||
Ok(nwritten)
|
||||
}
|
||||
|
||||
pub async fn shutdown(self: Rc<Self>) -> Result<(), AnyError> {
|
||||
pub async fn shutdown(self: Rc<Self>) -> Result<(), std::io::Error> {
|
||||
let mut wr = self.wr_borrow_mut().await;
|
||||
wr.shutdown().await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum MapError {
|
||||
#[error("{0}")]
|
||||
Io(std::io::Error),
|
||||
#[error("Unable to get resources")]
|
||||
NoResources,
|
||||
}
|
||||
|
||||
pub type TcpStreamResource =
|
||||
FullDuplexResource<tcp::OwnedReadHalf, tcp::OwnedWriteHalf>;
|
||||
|
||||
|
@ -100,7 +110,7 @@ impl Resource for TcpStreamResource {
|
|||
}
|
||||
|
||||
fn shutdown(self: Rc<Self>) -> AsyncResult<()> {
|
||||
Box::pin(self.shutdown())
|
||||
Box::pin(self.shutdown().map_err(Into::into))
|
||||
}
|
||||
|
||||
fn close(self: Rc<Self>) {
|
||||
|
@ -109,31 +119,30 @@ impl Resource for TcpStreamResource {
|
|||
}
|
||||
|
||||
impl TcpStreamResource {
|
||||
pub fn set_nodelay(self: Rc<Self>, nodelay: bool) -> Result<(), AnyError> {
|
||||
self.map_socket(Box::new(move |socket| Ok(socket.set_nodelay(nodelay)?)))
|
||||
pub fn set_nodelay(self: Rc<Self>, nodelay: bool) -> Result<(), MapError> {
|
||||
self.map_socket(Box::new(move |socket| socket.set_nodelay(nodelay)))
|
||||
}
|
||||
|
||||
pub fn set_keepalive(
|
||||
self: Rc<Self>,
|
||||
keepalive: bool,
|
||||
) -> Result<(), AnyError> {
|
||||
self
|
||||
.map_socket(Box::new(move |socket| Ok(socket.set_keepalive(keepalive)?)))
|
||||
) -> Result<(), MapError> {
|
||||
self.map_socket(Box::new(move |socket| socket.set_keepalive(keepalive)))
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn map_socket(
|
||||
self: Rc<Self>,
|
||||
map: Box<dyn FnOnce(SockRef) -> Result<(), AnyError>>,
|
||||
) -> Result<(), AnyError> {
|
||||
map: Box<dyn FnOnce(SockRef) -> Result<(), std::io::Error>>,
|
||||
) -> Result<(), MapError> {
|
||||
if let Some(wr) = RcRef::map(self, |r| &r.wr).try_borrow() {
|
||||
let stream = wr.as_ref().as_ref();
|
||||
let socket = socket2::SockRef::from(stream);
|
||||
|
||||
return map(socket);
|
||||
return map(socket).map_err(MapError::Io);
|
||||
}
|
||||
|
||||
Err(generic_error("Unable to get resources"))
|
||||
Err(MapError::NoResources)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +162,9 @@ impl UnixStreamResource {
|
|||
unreachable!()
|
||||
}
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn shutdown(self: Rc<Self>) -> Result<(), AnyError> {
|
||||
pub async fn shutdown(
|
||||
self: Rc<Self>,
|
||||
) -> Result<(), deno_core::error::AnyError> {
|
||||
unreachable!()
|
||||
}
|
||||
pub fn cancel_read_ops(&self) {
|
||||
|
@ -170,7 +181,7 @@ impl Resource for UnixStreamResource {
|
|||
}
|
||||
|
||||
fn shutdown(self: Rc<Self>) -> AsyncResult<()> {
|
||||
Box::pin(self.shutdown())
|
||||
Box::pin(self.shutdown().map_err(Into::into))
|
||||
}
|
||||
|
||||
fn close(self: Rc<Self>) {
|
||||
|
|
212
ext/net/ops.rs
212
ext/net/ops.rs
|
@ -6,10 +6,6 @@ use crate::resolve_addr::resolve_addr;
|
|||
use crate::resolve_addr::resolve_addr_sync;
|
||||
use crate::tcp::TcpListener;
|
||||
use crate::NetPermissions;
|
||||
use deno_core::error::bad_resource;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::CancelFuture;
|
||||
|
||||
|
@ -43,6 +39,7 @@ use trust_dns_proto::rr::record_type::RecordType;
|
|||
use trust_dns_resolver::config::NameServerConfigGroup;
|
||||
use trust_dns_resolver::config::ResolverConfig;
|
||||
use trust_dns_resolver::config::ResolverOpts;
|
||||
use trust_dns_resolver::error::ResolveError;
|
||||
use trust_dns_resolver::error::ResolveErrorKind;
|
||||
use trust_dns_resolver::system_conf;
|
||||
use trust_dns_resolver::AsyncResolver;
|
||||
|
@ -68,11 +65,69 @@ impl From<SocketAddr> for IpAddr {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn accept_err(e: std::io::Error) -> AnyError {
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum NetError {
|
||||
#[error("Listener has been closed")]
|
||||
ListenerClosed,
|
||||
#[error("Listener already in use")]
|
||||
ListenerBusy,
|
||||
#[error("Socket has been closed")]
|
||||
SocketClosed,
|
||||
#[error("Socket has been closed")]
|
||||
SocketClosedNotConnected,
|
||||
#[error("Socket already in use")]
|
||||
SocketBusy,
|
||||
#[error("{0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("Another accept task is ongoing")]
|
||||
AcceptTaskOngoing,
|
||||
#[error("{0}")]
|
||||
Permission(deno_core::error::AnyError),
|
||||
#[error("{0}")]
|
||||
Resource(deno_core::error::AnyError),
|
||||
#[error("No resolved address found")]
|
||||
NoResolvedAddress,
|
||||
#[error("{0}")]
|
||||
AddrParse(#[from] std::net::AddrParseError),
|
||||
#[error("{0}")]
|
||||
Map(crate::io::MapError),
|
||||
#[error("{0}")]
|
||||
Canceled(#[from] deno_core::Canceled),
|
||||
#[error("{0}")]
|
||||
DnsNotFound(ResolveError),
|
||||
#[error("{0}")]
|
||||
DnsNotConnected(ResolveError),
|
||||
#[error("{0}")]
|
||||
DnsTimedOut(ResolveError),
|
||||
#[error("{0}")]
|
||||
Dns(#[from] ResolveError),
|
||||
#[error("Provided record type is not supported")]
|
||||
UnsupportedRecordType,
|
||||
#[error("File name or path {0:?} is not valid UTF-8")]
|
||||
InvalidUtf8(std::ffi::OsString),
|
||||
#[error("unexpected key type")]
|
||||
UnexpectedKeyType,
|
||||
#[error("Invalid hostname: '{0}'")]
|
||||
InvalidHostname(String), // TypeError
|
||||
#[error("TCP stream is currently in use")]
|
||||
TcpStreamBusy,
|
||||
#[error("{0}")]
|
||||
Rustls(#[from] deno_tls::rustls::Error),
|
||||
#[error("{0}")]
|
||||
Tls(#[from] deno_tls::TlsError),
|
||||
#[error("Error creating TLS certificate: Deno.listenTls requires a key")]
|
||||
ListenTlsRequiresKey, // InvalidData
|
||||
#[error("{0}")]
|
||||
RootCertStore(deno_core::anyhow::Error),
|
||||
#[error("{0}")]
|
||||
Reunite(tokio::net::tcp::ReuniteError),
|
||||
}
|
||||
|
||||
pub(crate) fn accept_err(e: std::io::Error) -> NetError {
|
||||
if let std::io::ErrorKind::Interrupted = e.kind() {
|
||||
bad_resource("Listener has been closed")
|
||||
NetError::ListenerClosed
|
||||
} else {
|
||||
e.into()
|
||||
NetError::Io(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,15 +136,15 @@ pub(crate) fn accept_err(e: std::io::Error) -> AnyError {
|
|||
pub async fn op_net_accept_tcp(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> {
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), NetError> {
|
||||
let resource = state
|
||||
.borrow()
|
||||
.resource_table
|
||||
.get::<NetworkListenerResource<TcpListener>>(rid)
|
||||
.map_err(|_| bad_resource("Listener has been closed"))?;
|
||||
.map_err(|_| NetError::ListenerClosed)?;
|
||||
let listener = RcRef::map(&resource, |r| &r.listener)
|
||||
.try_borrow_mut()
|
||||
.ok_or_else(|| custom_error("Busy", "Another accept task is ongoing"))?;
|
||||
.ok_or_else(|| NetError::AcceptTaskOngoing)?;
|
||||
let cancel = RcRef::map(resource, |r| &r.cancel);
|
||||
let (tcp_stream, _socket_addr) = listener
|
||||
.accept()
|
||||
|
@ -112,12 +167,12 @@ pub async fn op_net_recv_udp(
|
|||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
#[buffer] mut buf: JsBuffer,
|
||||
) -> Result<(usize, IpAddr), AnyError> {
|
||||
) -> Result<(usize, IpAddr), NetError> {
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
let cancel_handle = RcRef::map(&resource, |r| &r.cancel);
|
||||
let (nread, remote_addr) = socket
|
||||
|
@ -134,27 +189,29 @@ pub async fn op_net_send_udp<NP>(
|
|||
#[smi] rid: ResourceId,
|
||||
#[serde] addr: IpAddr,
|
||||
#[buffer] zero_copy: JsBuffer,
|
||||
) -> Result<usize, AnyError>
|
||||
) -> Result<usize, NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
{
|
||||
let mut s = state.borrow_mut();
|
||||
s.borrow_mut::<NP>().check_net(
|
||||
s.borrow_mut::<NP>()
|
||||
.check_net(
|
||||
&(&addr.hostname, Some(addr.port)),
|
||||
"Deno.DatagramConn.send()",
|
||||
)?;
|
||||
)
|
||||
.map_err(NetError::Permission)?;
|
||||
}
|
||||
let addr = resolve_addr(&addr.hostname, addr.port)
|
||||
.await?
|
||||
.next()
|
||||
.ok_or_else(|| generic_error("No resolved address found"))?;
|
||||
.ok_or(NetError::NoResolvedAddress)?;
|
||||
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
let nwritten = socket.send_to(&zero_copy, &addr).await?;
|
||||
|
||||
|
@ -167,12 +224,12 @@ pub async fn op_net_join_multi_v4_udp(
|
|||
#[smi] rid: ResourceId,
|
||||
#[string] address: String,
|
||||
#[string] multi_interface: String,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
|
||||
let addr = Ipv4Addr::from_str(address.as_str())?;
|
||||
|
@ -189,12 +246,12 @@ pub async fn op_net_join_multi_v6_udp(
|
|||
#[smi] rid: ResourceId,
|
||||
#[string] address: String,
|
||||
#[smi] multi_interface: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
|
||||
let addr = Ipv6Addr::from_str(address.as_str())?;
|
||||
|
@ -210,12 +267,12 @@ pub async fn op_net_leave_multi_v4_udp(
|
|||
#[smi] rid: ResourceId,
|
||||
#[string] address: String,
|
||||
#[string] multi_interface: String,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
|
||||
let addr = Ipv4Addr::from_str(address.as_str())?;
|
||||
|
@ -232,12 +289,12 @@ pub async fn op_net_leave_multi_v6_udp(
|
|||
#[smi] rid: ResourceId,
|
||||
#[string] address: String,
|
||||
#[smi] multi_interface: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
|
||||
let addr = Ipv6Addr::from_str(address.as_str())?;
|
||||
|
@ -253,16 +310,16 @@ pub async fn op_net_set_multi_loopback_udp(
|
|||
#[smi] rid: ResourceId,
|
||||
is_v4_membership: bool,
|
||||
loopback: bool,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
|
||||
if is_v4_membership {
|
||||
socket.set_multicast_loop_v4(loopback)?
|
||||
socket.set_multicast_loop_v4(loopback)?;
|
||||
} else {
|
||||
socket.set_multicast_loop_v6(loopback)?;
|
||||
}
|
||||
|
@ -275,12 +332,12 @@ pub async fn op_net_set_multi_ttl_udp(
|
|||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
#[smi] ttl: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
let resource = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.get::<UdpSocketResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
|
||||
|
||||
socket.set_multicast_ttl_v4(ttl)?;
|
||||
|
@ -293,7 +350,7 @@ pub async fn op_net_set_multi_ttl_udp(
|
|||
pub async fn op_net_connect_tcp<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[serde] addr: IpAddr,
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -304,7 +361,7 @@ where
|
|||
pub async fn op_net_connect_tcp_inner<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
addr: IpAddr,
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -312,13 +369,14 @@ where
|
|||
let mut state_ = state.borrow_mut();
|
||||
state_
|
||||
.borrow_mut::<NP>()
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connect()")?;
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connect()")
|
||||
.map_err(NetError::Permission)?;
|
||||
}
|
||||
|
||||
let addr = resolve_addr(&addr.hostname, addr.port)
|
||||
.await?
|
||||
.next()
|
||||
.ok_or_else(|| generic_error("No resolved address found"))?;
|
||||
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
||||
let tcp_stream = TcpStream::connect(&addr).await?;
|
||||
let local_addr = tcp_stream.local_addr()?;
|
||||
let remote_addr = tcp_stream.peer_addr()?;
|
||||
|
@ -353,7 +411,7 @@ pub fn op_net_listen_tcp<NP>(
|
|||
#[serde] addr: IpAddr,
|
||||
reuse_port: bool,
|
||||
load_balanced: bool,
|
||||
) -> Result<(ResourceId, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -362,10 +420,11 @@ where
|
|||
}
|
||||
state
|
||||
.borrow_mut::<NP>()
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listen()")?;
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listen()")
|
||||
.map_err(NetError::Permission)?;
|
||||
let addr = resolve_addr_sync(&addr.hostname, addr.port)?
|
||||
.next()
|
||||
.ok_or_else(|| generic_error("No resolved address found"))?;
|
||||
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
||||
|
||||
let listener = if load_balanced {
|
||||
TcpListener::bind_load_balanced(addr)
|
||||
|
@ -384,16 +443,17 @@ fn net_listen_udp<NP>(
|
|||
addr: IpAddr,
|
||||
reuse_address: bool,
|
||||
loopback: bool,
|
||||
) -> Result<(ResourceId, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
state
|
||||
.borrow_mut::<NP>()
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()")?;
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()")
|
||||
.map_err(NetError::Permission)?;
|
||||
let addr = resolve_addr_sync(&addr.hostname, addr.port)?
|
||||
.next()
|
||||
.ok_or_else(|| generic_error("No resolved address found"))?;
|
||||
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
||||
|
||||
let domain = if addr.is_ipv4() {
|
||||
Domain::IPV4
|
||||
|
@ -453,7 +513,7 @@ pub fn op_net_listen_udp<NP>(
|
|||
#[serde] addr: IpAddr,
|
||||
reuse_address: bool,
|
||||
loopback: bool,
|
||||
) -> Result<(ResourceId, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -468,7 +528,7 @@ pub fn op_node_unstable_net_listen_udp<NP>(
|
|||
#[serde] addr: IpAddr,
|
||||
reuse_address: bool,
|
||||
loopback: bool,
|
||||
) -> Result<(ResourceId, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -551,7 +611,7 @@ pub struct NameServer {
|
|||
pub async fn op_dns_resolve<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[serde] args: ResolveAddrArgs,
|
||||
) -> Result<Vec<DnsReturnRecord>, AnyError>
|
||||
) -> Result<Vec<DnsReturnRecord>, NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -587,7 +647,9 @@ where
|
|||
let socker_addr = &ns.socket_addr;
|
||||
let ip = socker_addr.ip().to_string();
|
||||
let port = socker_addr.port();
|
||||
perm.check_net(&(ip, Some(port)), "Deno.resolveDns()")?;
|
||||
perm
|
||||
.check_net(&(ip, Some(port)), "Deno.resolveDns()")
|
||||
.map_err(NetError::Permission)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,22 +680,17 @@ where
|
|||
};
|
||||
|
||||
lookup
|
||||
.map_err(|e| {
|
||||
let message = format!("{e}");
|
||||
match e.kind() {
|
||||
ResolveErrorKind::NoRecordsFound { .. } => {
|
||||
custom_error("NotFound", message)
|
||||
}
|
||||
.map_err(|e| match e.kind() {
|
||||
ResolveErrorKind::NoRecordsFound { .. } => NetError::DnsNotFound(e),
|
||||
ResolveErrorKind::Message("No connections available") => {
|
||||
custom_error("NotConnected", message)
|
||||
}
|
||||
ResolveErrorKind::Timeout => custom_error("TimedOut", message),
|
||||
_ => generic_error(message),
|
||||
NetError::DnsNotConnected(e)
|
||||
}
|
||||
ResolveErrorKind::Timeout => NetError::DnsTimedOut(e),
|
||||
_ => NetError::Dns(e),
|
||||
})?
|
||||
.iter()
|
||||
.filter_map(|rdata| rdata_to_return_record(record_type)(rdata).transpose())
|
||||
.collect::<Result<Vec<DnsReturnRecord>, AnyError>>()
|
||||
.collect::<Result<Vec<DnsReturnRecord>, NetError>>()
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
|
@ -641,7 +698,7 @@ pub fn op_set_nodelay(
|
|||
state: &mut OpState,
|
||||
#[smi] rid: ResourceId,
|
||||
nodelay: bool,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
op_set_nodelay_inner(state, rid, nodelay)
|
||||
}
|
||||
|
||||
|
@ -650,10 +707,12 @@ pub fn op_set_nodelay_inner(
|
|||
state: &mut OpState,
|
||||
rid: ResourceId,
|
||||
nodelay: bool,
|
||||
) -> Result<(), AnyError> {
|
||||
let resource: Rc<TcpStreamResource> =
|
||||
state.resource_table.get::<TcpStreamResource>(rid)?;
|
||||
resource.set_nodelay(nodelay)
|
||||
) -> Result<(), NetError> {
|
||||
let resource: Rc<TcpStreamResource> = state
|
||||
.resource_table
|
||||
.get::<TcpStreamResource>(rid)
|
||||
.map_err(NetError::Resource)?;
|
||||
resource.set_nodelay(nodelay).map_err(NetError::Map)
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
|
@ -661,7 +720,7 @@ pub fn op_set_keepalive(
|
|||
state: &mut OpState,
|
||||
#[smi] rid: ResourceId,
|
||||
keepalive: bool,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
op_set_keepalive_inner(state, rid, keepalive)
|
||||
}
|
||||
|
||||
|
@ -670,17 +729,19 @@ pub fn op_set_keepalive_inner(
|
|||
state: &mut OpState,
|
||||
rid: ResourceId,
|
||||
keepalive: bool,
|
||||
) -> Result<(), AnyError> {
|
||||
let resource: Rc<TcpStreamResource> =
|
||||
state.resource_table.get::<TcpStreamResource>(rid)?;
|
||||
resource.set_keepalive(keepalive)
|
||||
) -> Result<(), NetError> {
|
||||
let resource: Rc<TcpStreamResource> = state
|
||||
.resource_table
|
||||
.get::<TcpStreamResource>(rid)
|
||||
.map_err(NetError::Resource)?;
|
||||
resource.set_keepalive(keepalive).map_err(NetError::Map)
|
||||
}
|
||||
|
||||
fn rdata_to_return_record(
|
||||
ty: RecordType,
|
||||
) -> impl Fn(&RData) -> Result<Option<DnsReturnRecord>, AnyError> {
|
||||
) -> impl Fn(&RData) -> Result<Option<DnsReturnRecord>, NetError> {
|
||||
use RecordType::*;
|
||||
move |r: &RData| -> Result<Option<DnsReturnRecord>, AnyError> {
|
||||
move |r: &RData| -> Result<Option<DnsReturnRecord>, NetError> {
|
||||
let record = match ty {
|
||||
A => r.as_a().map(ToString::to_string).map(DnsReturnRecord::A),
|
||||
AAAA => r
|
||||
|
@ -761,12 +822,7 @@ fn rdata_to_return_record(
|
|||
.collect();
|
||||
DnsReturnRecord::Txt(texts)
|
||||
}),
|
||||
_ => {
|
||||
return Err(custom_error(
|
||||
"NotSupported",
|
||||
"Provided record type is not supported",
|
||||
))
|
||||
}
|
||||
_ => return Err(NetError::UnsupportedRecordType),
|
||||
};
|
||||
Ok(record)
|
||||
}
|
||||
|
@ -985,7 +1041,7 @@ mod tests {
|
|||
&mut self,
|
||||
_host: &(T, Option<u16>),
|
||||
_api_name: &str,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), deno_core::error::AnyError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -993,7 +1049,7 @@ mod tests {
|
|||
&mut self,
|
||||
p: &str,
|
||||
_api_name: &str,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, deno_core::error::AnyError> {
|
||||
Ok(PathBuf::from(p))
|
||||
}
|
||||
|
||||
|
@ -1001,7 +1057,7 @@ mod tests {
|
|||
&mut self,
|
||||
p: &str,
|
||||
_api_name: &str,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, deno_core::error::AnyError> {
|
||||
Ok(PathBuf::from(p))
|
||||
}
|
||||
|
||||
|
@ -1009,7 +1065,7 @@ mod tests {
|
|||
&mut self,
|
||||
p: &'a Path,
|
||||
_api_name: &str,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
) -> Result<Cow<'a, Path>, deno_core::error::AnyError> {
|
||||
Ok(Cow::Borrowed(p))
|
||||
}
|
||||
}
|
||||
|
@ -1091,7 +1147,7 @@ mod tests {
|
|||
let vals = result.unwrap();
|
||||
rid = rid.or(Some(vals.0));
|
||||
}
|
||||
};
|
||||
}
|
||||
let rid = rid.unwrap();
|
||||
|
||||
let state = runtime.op_state();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use crate::io::TcpStreamResource;
|
||||
use crate::ops::IpAddr;
|
||||
use crate::ops::NetError;
|
||||
use crate::ops::TlsHandshakeInfo;
|
||||
use crate::raw::NetworkListenerResource;
|
||||
use crate::resolve_addr::resolve_addr;
|
||||
|
@ -10,13 +11,7 @@ use crate::tcp::TcpListener;
|
|||
use crate::DefaultTlsOptions;
|
||||
use crate::NetPermissions;
|
||||
use crate::UnsafelyIgnoreCertificateErrors;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::error::bad_resource;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::invalid_hostname;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::TryFutureExt;
|
||||
use deno_core::op2;
|
||||
use deno_core::v8;
|
||||
use deno_core::AsyncRefCell;
|
||||
|
@ -118,20 +113,23 @@ impl TlsStreamResource {
|
|||
pub async fn read(
|
||||
self: Rc<Self>,
|
||||
data: &mut [u8],
|
||||
) -> Result<usize, AnyError> {
|
||||
) -> Result<usize, std::io::Error> {
|
||||
let mut rd = RcRef::map(&self, |r| &r.rd).borrow_mut().await;
|
||||
let cancel_handle = RcRef::map(&self, |r| &r.cancel_handle);
|
||||
Ok(rd.read(data).try_or_cancel(cancel_handle).await?)
|
||||
rd.read(data).try_or_cancel(cancel_handle).await
|
||||
}
|
||||
|
||||
pub async fn write(self: Rc<Self>, data: &[u8]) -> Result<usize, AnyError> {
|
||||
pub async fn write(
|
||||
self: Rc<Self>,
|
||||
data: &[u8],
|
||||
) -> Result<usize, std::io::Error> {
|
||||
let mut wr = RcRef::map(self, |r| &r.wr).borrow_mut().await;
|
||||
let nwritten = wr.write(data).await?;
|
||||
wr.flush().await?;
|
||||
Ok(nwritten)
|
||||
}
|
||||
|
||||
pub async fn shutdown(self: Rc<Self>) -> Result<(), AnyError> {
|
||||
pub async fn shutdown(self: Rc<Self>) -> Result<(), std::io::Error> {
|
||||
let mut wr = RcRef::map(self, |r| &r.wr).borrow_mut().await;
|
||||
wr.shutdown().await?;
|
||||
Ok(())
|
||||
|
@ -139,7 +137,7 @@ impl TlsStreamResource {
|
|||
|
||||
pub async fn handshake(
|
||||
self: &Rc<Self>,
|
||||
) -> Result<TlsHandshakeInfo, AnyError> {
|
||||
) -> Result<TlsHandshakeInfo, std::io::Error> {
|
||||
if let Some(tls_info) = &*self.handshake_info.borrow() {
|
||||
return Ok(tls_info.clone());
|
||||
}
|
||||
|
@ -164,7 +162,7 @@ impl Resource for TlsStreamResource {
|
|||
}
|
||||
|
||||
fn shutdown(self: Rc<Self>) -> AsyncResult<()> {
|
||||
Box::pin(self.shutdown())
|
||||
Box::pin(self.shutdown().map_err(Into::into))
|
||||
}
|
||||
|
||||
fn close(self: Rc<Self>) {
|
||||
|
@ -201,7 +199,7 @@ pub fn op_tls_key_null() -> TlsKeysHolder {
|
|||
pub fn op_tls_key_static(
|
||||
#[string] cert: &str,
|
||||
#[string] key: &str,
|
||||
) -> Result<TlsKeysHolder, AnyError> {
|
||||
) -> Result<TlsKeysHolder, deno_tls::TlsError> {
|
||||
let cert = load_certs(&mut BufReader::new(cert.as_bytes()))?;
|
||||
let key = load_private_keys(key.as_bytes())?
|
||||
.into_iter()
|
||||
|
@ -236,9 +234,9 @@ pub fn op_tls_cert_resolver_resolve(
|
|||
#[cppgc] lookup: &TlsKeyLookup,
|
||||
#[string] sni: String,
|
||||
#[cppgc] key: &TlsKeysHolder,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), NetError> {
|
||||
let TlsKeys::Static(key) = key.take() else {
|
||||
bail!("unexpected key type");
|
||||
return Err(NetError::UnexpectedKeyType);
|
||||
};
|
||||
lookup.resolve(sni, Ok(key));
|
||||
Ok(())
|
||||
|
@ -258,7 +256,7 @@ pub fn op_tls_cert_resolver_resolve_error(
|
|||
pub fn op_tls_start<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[serde] args: StartTlsArgs,
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -271,7 +269,9 @@ where
|
|||
{
|
||||
let mut s = state.borrow_mut();
|
||||
let permissions = s.borrow_mut::<NP>();
|
||||
permissions.check_net(&(&hostname, Some(0)), "Deno.startTls()")?;
|
||||
permissions
|
||||
.check_net(&(&hostname, Some(0)), "Deno.startTls()")
|
||||
.map_err(NetError::Permission)?;
|
||||
}
|
||||
|
||||
let ca_certs = args
|
||||
|
@ -281,7 +281,7 @@ where
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let hostname_dns = ServerName::try_from(hostname.to_string())
|
||||
.map_err(|_| invalid_hostname(&hostname))?;
|
||||
.map_err(|_| NetError::InvalidHostname(hostname))?;
|
||||
|
||||
let unsafely_ignore_certificate_errors = state
|
||||
.borrow()
|
||||
|
@ -291,19 +291,21 @@ where
|
|||
let root_cert_store = state
|
||||
.borrow()
|
||||
.borrow::<DefaultTlsOptions>()
|
||||
.root_cert_store()?;
|
||||
.root_cert_store()
|
||||
.map_err(NetError::RootCertStore)?;
|
||||
|
||||
let resource_rc = state
|
||||
.borrow_mut()
|
||||
.resource_table
|
||||
.take::<TcpStreamResource>(rid)?;
|
||||
.take::<TcpStreamResource>(rid)
|
||||
.map_err(NetError::Resource)?;
|
||||
// This TCP connection might be used somewhere else. If it's the case, we cannot proceed with the
|
||||
// process of starting a TLS connection on top of this TCP connection, so we just return a Busy error.
|
||||
// See also: https://github.com/denoland/deno/pull/16242
|
||||
let resource = Rc::try_unwrap(resource_rc)
|
||||
.map_err(|_| custom_error("Busy", "TCP stream is currently in use"))?;
|
||||
let resource =
|
||||
Rc::try_unwrap(resource_rc).map_err(|_| NetError::TcpStreamBusy)?;
|
||||
let (read_half, write_half) = resource.into_inner();
|
||||
let tcp_stream = read_half.reunite(write_half)?;
|
||||
let tcp_stream = read_half.reunite(write_half).map_err(NetError::Reunite)?;
|
||||
|
||||
let local_addr = tcp_stream.local_addr()?;
|
||||
let remote_addr = tcp_stream.peer_addr()?;
|
||||
|
@ -345,7 +347,7 @@ pub async fn op_net_connect_tls<NP>(
|
|||
#[serde] addr: IpAddr,
|
||||
#[serde] args: ConnectTlsArgs,
|
||||
#[cppgc] key_pair: &TlsKeysHolder,
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -359,9 +361,14 @@ where
|
|||
let mut s = state.borrow_mut();
|
||||
let permissions = s.borrow_mut::<NP>();
|
||||
permissions
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connectTls()")?;
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connectTls()")
|
||||
.map_err(NetError::Permission)?;
|
||||
if let Some(path) = cert_file {
|
||||
Some(permissions.check_read(path, "Deno.connectTls()")?)
|
||||
Some(
|
||||
permissions
|
||||
.check_read(path, "Deno.connectTls()")
|
||||
.map_err(NetError::Permission)?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -382,17 +389,18 @@ where
|
|||
let root_cert_store = state
|
||||
.borrow()
|
||||
.borrow::<DefaultTlsOptions>()
|
||||
.root_cert_store()?;
|
||||
.root_cert_store()
|
||||
.map_err(NetError::RootCertStore)?;
|
||||
let hostname_dns = if let Some(server_name) = args.server_name {
|
||||
ServerName::try_from(server_name)
|
||||
} else {
|
||||
ServerName::try_from(addr.hostname.clone())
|
||||
}
|
||||
.map_err(|_| invalid_hostname(&addr.hostname))?;
|
||||
.map_err(|_| NetError::InvalidHostname(addr.hostname.clone()))?;
|
||||
let connect_addr = resolve_addr(&addr.hostname, addr.port)
|
||||
.await?
|
||||
.next()
|
||||
.ok_or_else(|| generic_error("No resolved address found"))?;
|
||||
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
||||
let tcp_stream = TcpStream::connect(connect_addr).await?;
|
||||
let local_addr = tcp_stream.local_addr()?;
|
||||
let remote_addr = tcp_stream.peer_addr()?;
|
||||
|
@ -444,7 +452,7 @@ pub fn op_net_listen_tls<NP>(
|
|||
#[serde] addr: IpAddr,
|
||||
#[serde] args: ListenTlsArgs,
|
||||
#[cppgc] keys: &TlsKeysHolder,
|
||||
) -> Result<(ResourceId, IpAddr), AnyError>
|
||||
) -> Result<(ResourceId, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -455,12 +463,13 @@ where
|
|||
{
|
||||
let permissions = state.borrow_mut::<NP>();
|
||||
permissions
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenTls()")?;
|
||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenTls()")
|
||||
.map_err(NetError::Permission)?;
|
||||
}
|
||||
|
||||
let bind_addr = resolve_addr_sync(&addr.hostname, addr.port)?
|
||||
.next()
|
||||
.ok_or_else(|| generic_error("No resolved address found"))?;
|
||||
.ok_or(NetError::NoResolvedAddress)?;
|
||||
|
||||
let tcp_listener = if args.load_balanced {
|
||||
TcpListener::bind_load_balanced(bind_addr)
|
||||
|
@ -475,28 +484,24 @@ where
|
|||
.map(|s| s.into_bytes())
|
||||
.collect();
|
||||
let listener = match keys.take() {
|
||||
TlsKeys::Null => Err(anyhow!("Deno.listenTls requires a key")),
|
||||
TlsKeys::Null => return Err(NetError::ListenTlsRequiresKey),
|
||||
TlsKeys::Static(TlsKey(cert, key)) => {
|
||||
let mut tls_config = ServerConfig::builder()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(cert, key)
|
||||
.map_err(|e| anyhow!(e))?;
|
||||
.with_single_cert(cert, key)?;
|
||||
tls_config.alpn_protocols = alpn;
|
||||
Ok(TlsListener {
|
||||
TlsListener {
|
||||
tcp_listener,
|
||||
tls_config: Some(tls_config.into()),
|
||||
server_config_provider: None,
|
||||
})
|
||||
}
|
||||
TlsKeys::Resolver(resolver) => Ok(TlsListener {
|
||||
}
|
||||
TlsKeys::Resolver(resolver) => TlsListener {
|
||||
tcp_listener,
|
||||
tls_config: None,
|
||||
server_config_provider: Some(resolver.into_server_config_provider(alpn)),
|
||||
}),
|
||||
}
|
||||
.map_err(|e| {
|
||||
custom_error("InvalidData", "Error creating TLS certificate").context(e)
|
||||
})?;
|
||||
},
|
||||
};
|
||||
|
||||
let tls_listener_resource = NetworkListenerResource::new(listener);
|
||||
|
||||
|
@ -510,23 +515,23 @@ where
|
|||
pub async fn op_net_accept_tls(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> {
|
||||
) -> Result<(ResourceId, IpAddr, IpAddr), NetError> {
|
||||
let resource = state
|
||||
.borrow()
|
||||
.resource_table
|
||||
.get::<NetworkListenerResource<TlsListener>>(rid)
|
||||
.map_err(|_| bad_resource("Listener has been closed"))?;
|
||||
.map_err(|_| NetError::ListenerClosed)?;
|
||||
|
||||
let cancel_handle = RcRef::map(&resource, |r| &r.cancel);
|
||||
let listener = RcRef::map(&resource, |r| &r.listener)
|
||||
.try_borrow_mut()
|
||||
.ok_or_else(|| custom_error("Busy", "Another accept task is ongoing"))?;
|
||||
.ok_or_else(|| NetError::AcceptTaskOngoing)?;
|
||||
|
||||
let (tls_stream, remote_addr) =
|
||||
match listener.accept().try_or_cancel(&cancel_handle).await {
|
||||
Ok(tuple) => tuple,
|
||||
Err(err) if err.kind() == ErrorKind::Interrupted => {
|
||||
return Err(bad_resource("Listener has been closed"));
|
||||
return Err(NetError::ListenerClosed);
|
||||
}
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
|
@ -547,11 +552,11 @@ pub async fn op_net_accept_tls(
|
|||
pub async fn op_tls_handshake(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<TlsHandshakeInfo, AnyError> {
|
||||
) -> Result<TlsHandshakeInfo, NetError> {
|
||||
let resource = state
|
||||
.borrow()
|
||||
.resource_table
|
||||
.get::<TlsStreamResource>(rid)
|
||||
.map_err(|_| bad_resource("Listener has been closed"))?;
|
||||
resource.handshake().await
|
||||
.map_err(|_| NetError::ListenerClosed)?;
|
||||
resource.handshake().await.map_err(Into::into)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::io::UnixStreamResource;
|
||||
use crate::ops::NetError;
|
||||
use crate::raw::NetworkListenerResource;
|
||||
use crate::NetPermissions;
|
||||
use deno_core::error::bad_resource;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::AsyncRefCell;
|
||||
use deno_core::CancelHandle;
|
||||
|
@ -26,11 +24,8 @@ use tokio::net::UnixListener;
|
|||
pub use tokio::net::UnixStream;
|
||||
|
||||
/// A utility function to map OsStrings to Strings
|
||||
pub fn into_string(s: std::ffi::OsString) -> Result<String, AnyError> {
|
||||
s.into_string().map_err(|s| {
|
||||
let message = format!("File name or path {s:?} is not valid UTF-8");
|
||||
custom_error("InvalidData", message)
|
||||
})
|
||||
pub fn into_string(s: std::ffi::OsString) -> Result<String, NetError> {
|
||||
s.into_string().map_err(NetError::InvalidUtf8)
|
||||
}
|
||||
|
||||
pub struct UnixDatagramResource {
|
||||
|
@ -63,15 +58,15 @@ pub struct UnixListenArgs {
|
|||
pub async fn op_net_accept_unix(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<(ResourceId, Option<String>, Option<String>), AnyError> {
|
||||
) -> Result<(ResourceId, Option<String>, Option<String>), NetError> {
|
||||
let resource = state
|
||||
.borrow()
|
||||
.resource_table
|
||||
.get::<NetworkListenerResource<UnixListener>>(rid)
|
||||
.map_err(|_| bad_resource("Listener has been closed"))?;
|
||||
.map_err(|_| NetError::ListenerClosed)?;
|
||||
let listener = RcRef::map(&resource, |r| &r.listener)
|
||||
.try_borrow_mut()
|
||||
.ok_or_else(|| custom_error("Busy", "Listener already in use"))?;
|
||||
.ok_or(NetError::ListenerBusy)?;
|
||||
let cancel = RcRef::map(resource, |r| &r.cancel);
|
||||
let (unix_stream, _socket_addr) = listener
|
||||
.accept()
|
||||
|
@ -95,7 +90,7 @@ pub async fn op_net_accept_unix(
|
|||
pub async fn op_net_connect_unix<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[string] address_path: String,
|
||||
) -> Result<(ResourceId, Option<String>, Option<String>), AnyError>
|
||||
) -> Result<(ResourceId, Option<String>, Option<String>), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -103,10 +98,12 @@ where
|
|||
let mut state_ = state.borrow_mut();
|
||||
let address_path = state_
|
||||
.borrow_mut::<NP>()
|
||||
.check_read(&address_path, "Deno.connect()")?;
|
||||
.check_read(&address_path, "Deno.connect()")
|
||||
.map_err(NetError::Permission)?;
|
||||
_ = state_
|
||||
.borrow_mut::<NP>()
|
||||
.check_write_path(&address_path, "Deno.connect()")?;
|
||||
.check_write_path(&address_path, "Deno.connect()")
|
||||
.map_err(NetError::Permission)?;
|
||||
address_path
|
||||
};
|
||||
let unix_stream = UnixStream::connect(&address_path).await?;
|
||||
|
@ -127,15 +124,15 @@ pub async fn op_net_recv_unixpacket(
|
|||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
#[buffer] mut buf: JsBuffer,
|
||||
) -> Result<(usize, Option<String>), AnyError> {
|
||||
) -> Result<(usize, Option<String>), NetError> {
|
||||
let resource = state
|
||||
.borrow()
|
||||
.resource_table
|
||||
.get::<UnixDatagramResource>(rid)
|
||||
.map_err(|_| bad_resource("Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosed)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket)
|
||||
.try_borrow_mut()
|
||||
.ok_or_else(|| custom_error("Busy", "Socket already in use"))?;
|
||||
.ok_or(NetError::SocketBusy)?;
|
||||
let cancel = RcRef::map(resource, |r| &r.cancel);
|
||||
let (nread, remote_addr) =
|
||||
socket.recv_from(&mut buf).try_or_cancel(cancel).await?;
|
||||
|
@ -150,24 +147,25 @@ pub async fn op_net_send_unixpacket<NP>(
|
|||
#[smi] rid: ResourceId,
|
||||
#[string] address_path: String,
|
||||
#[buffer] zero_copy: JsBuffer,
|
||||
) -> Result<usize, AnyError>
|
||||
) -> Result<usize, NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
let address_path = {
|
||||
let mut s = state.borrow_mut();
|
||||
s.borrow_mut::<NP>()
|
||||
.check_write(&address_path, "Deno.DatagramConn.send()")?
|
||||
.check_write(&address_path, "Deno.DatagramConn.send()")
|
||||
.map_err(NetError::Permission)?
|
||||
};
|
||||
|
||||
let resource = state
|
||||
.borrow()
|
||||
.resource_table
|
||||
.get::<UnixDatagramResource>(rid)
|
||||
.map_err(|_| custom_error("NotConnected", "Socket has been closed"))?;
|
||||
.map_err(|_| NetError::SocketClosedNotConnected)?;
|
||||
let socket = RcRef::map(&resource, |r| &r.socket)
|
||||
.try_borrow_mut()
|
||||
.ok_or_else(|| custom_error("Busy", "Socket already in use"))?;
|
||||
.ok_or(NetError::SocketBusy)?;
|
||||
let nwritten = socket.send_to(&zero_copy, address_path).await?;
|
||||
|
||||
Ok(nwritten)
|
||||
|
@ -179,14 +177,18 @@ pub fn op_net_listen_unix<NP>(
|
|||
state: &mut OpState,
|
||||
#[string] address_path: String,
|
||||
#[string] api_name: String,
|
||||
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||
) -> Result<(ResourceId, Option<String>), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<NP>();
|
||||
let api_call_expr = format!("{}()", api_name);
|
||||
let address_path = permissions.check_read(&address_path, &api_call_expr)?;
|
||||
_ = permissions.check_write_path(&address_path, &api_call_expr)?;
|
||||
let address_path = permissions
|
||||
.check_read(&address_path, &api_call_expr)
|
||||
.map_err(NetError::Permission)?;
|
||||
_ = permissions
|
||||
.check_write_path(&address_path, &api_call_expr)
|
||||
.map_err(NetError::Permission)?;
|
||||
let listener = UnixListener::bind(address_path)?;
|
||||
let local_addr = listener.local_addr()?;
|
||||
let pathname = local_addr.as_pathname().map(pathstring).transpose()?;
|
||||
|
@ -198,14 +200,17 @@ where
|
|||
pub fn net_listen_unixpacket<NP>(
|
||||
state: &mut OpState,
|
||||
address_path: String,
|
||||
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||
) -> Result<(ResourceId, Option<String>), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<NP>();
|
||||
let address_path =
|
||||
permissions.check_read(&address_path, "Deno.listenDatagram()")?;
|
||||
_ = permissions.check_write_path(&address_path, "Deno.listenDatagram()")?;
|
||||
let address_path = permissions
|
||||
.check_read(&address_path, "Deno.listenDatagram()")
|
||||
.map_err(NetError::Permission)?;
|
||||
_ = permissions
|
||||
.check_write_path(&address_path, "Deno.listenDatagram()")
|
||||
.map_err(NetError::Permission)?;
|
||||
let socket = UnixDatagram::bind(address_path)?;
|
||||
let local_addr = socket.local_addr()?;
|
||||
let pathname = local_addr.as_pathname().map(pathstring).transpose()?;
|
||||
|
@ -222,7 +227,7 @@ where
|
|||
pub fn op_net_listen_unixpacket<NP>(
|
||||
state: &mut OpState,
|
||||
#[string] path: String,
|
||||
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||
) -> Result<(ResourceId, Option<String>), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
|
@ -235,13 +240,13 @@ where
|
|||
pub fn op_node_unstable_net_listen_unixpacket<NP>(
|
||||
state: &mut OpState,
|
||||
#[string] path: String,
|
||||
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||
) -> Result<(ResourceId, Option<String>), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
net_listen_unixpacket::<NP>(state, path)
|
||||
}
|
||||
|
||||
pub fn pathstring(pathname: &Path) -> Result<String, AnyError> {
|
||||
pub fn pathstring(pathname: &Path) -> Result<String, NetError> {
|
||||
into_string(pathname.into())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::ToSocketAddrs;
|
||||
use tokio::net::lookup_host;
|
||||
|
@ -9,7 +8,7 @@ use tokio::net::lookup_host;
|
|||
pub async fn resolve_addr(
|
||||
hostname: &str,
|
||||
port: u16,
|
||||
) -> Result<impl Iterator<Item = SocketAddr> + '_, AnyError> {
|
||||
) -> Result<impl Iterator<Item = SocketAddr> + '_, std::io::Error> {
|
||||
let addr_port_pair = make_addr_port_pair(hostname, port);
|
||||
let result = lookup_host(addr_port_pair).await?;
|
||||
Ok(result)
|
||||
|
@ -19,7 +18,7 @@ pub async fn resolve_addr(
|
|||
pub fn resolve_addr_sync(
|
||||
hostname: &str,
|
||||
port: u16,
|
||||
) -> Result<impl Iterator<Item = SocketAddr>, AnyError> {
|
||||
) -> Result<impl Iterator<Item = SocketAddr>, std::io::Error> {
|
||||
let addr_port_pair = make_addr_port_pair(hostname, port);
|
||||
let result = addr_port_pair.to_socket_addrs()?;
|
||||
Ok(result)
|
||||
|
|
|
@ -23,6 +23,7 @@ use deno_ffi::DlfcnError;
|
|||
use deno_ffi::IRError;
|
||||
use deno_ffi::ReprError;
|
||||
use deno_ffi::StaticError;
|
||||
use deno_net::ops::NetError;
|
||||
use deno_tls::TlsError;
|
||||
use deno_webstorage::WebStorageError;
|
||||
use std::env;
|
||||
|
@ -292,6 +293,48 @@ fn get_broadcast_channel_error(error: &BroadcastChannelError) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_net_error(error: &NetError) -> &'static str {
|
||||
match error {
|
||||
NetError::ListenerClosed => "BadResource",
|
||||
NetError::ListenerBusy => "Busy",
|
||||
NetError::SocketClosed => "BadResource",
|
||||
NetError::SocketClosedNotConnected => "NotConnected",
|
||||
NetError::SocketBusy => "Busy",
|
||||
NetError::Io(e) => get_io_error_class(e),
|
||||
NetError::AcceptTaskOngoing => "Busy",
|
||||
NetError::RootCertStore(e)
|
||||
| NetError::Permission(e)
|
||||
| NetError::Resource(e) => get_error_class_name(e).unwrap_or("Error"),
|
||||
NetError::NoResolvedAddress => "Error",
|
||||
NetError::AddrParse(_) => "Error",
|
||||
NetError::Map(e) => get_net_map_error(e),
|
||||
NetError::Canceled(e) => {
|
||||
let io_err: io::Error = e.to_owned().into();
|
||||
get_io_error_class(&io_err)
|
||||
}
|
||||
NetError::DnsNotFound(_) => "NotFound",
|
||||
NetError::DnsNotConnected(_) => "NotConnected",
|
||||
NetError::DnsTimedOut(_) => "TimedOut",
|
||||
NetError::Dns(_) => "Error",
|
||||
NetError::UnsupportedRecordType => "NotSupported",
|
||||
NetError::InvalidUtf8(_) => "InvalidData",
|
||||
NetError::UnexpectedKeyType => "Error",
|
||||
NetError::InvalidHostname(_) => "TypeError",
|
||||
NetError::TcpStreamBusy => "Busy",
|
||||
NetError::Rustls(_) => "Error",
|
||||
NetError::Tls(e) => get_tls_error_class(e),
|
||||
NetError::ListenTlsRequiresKey => "InvalidData",
|
||||
NetError::Reunite(_) => "Error",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_net_map_error(error: &deno_net::io::MapError) -> &'static str {
|
||||
match error {
|
||||
deno_net::io::MapError::Io(e) => get_io_error_class(e),
|
||||
deno_net::io::MapError::NoResources => "Error",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
||||
deno_core::error::get_custom_error_class(e)
|
||||
.or_else(|| deno_webgpu::error::get_error_class_name(e))
|
||||
|
@ -316,6 +359,11 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
|||
.or_else(|| e.downcast_ref::<CronError>().map(get_cron_error_class))
|
||||
.or_else(|| e.downcast_ref::<CanvasError>().map(get_canvas_error))
|
||||
.or_else(|| e.downcast_ref::<CacheError>().map(get_cache_error))
|
||||
.or_else(|| e.downcast_ref::<NetError>().map(get_net_error))
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<deno_net::io::MapError>()
|
||||
.map(get_net_map_error)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<BroadcastChannelError>()
|
||||
.map(get_broadcast_channel_error)
|
||||
|
|
Loading…
Reference in a new issue