Compare commits

...

6 Commits

5 changed files with 37 additions and 3 deletions

View File

@@ -1,5 +1,21 @@
# Changelog # Changelog
## 2026-03-17 - 4.8.7 - fix(remoteingress-core)
perform graceful TLS shutdown on edge and hub tunnel streams
- Send TLS close_notify before cleanup to avoid peer disconnect warnings on both tunnel endpoints
- Wrap stream shutdown in a 2 second timeout so connection teardown does not block cleanup
## 2026-03-17 - 4.8.6 - fix(remoteingress-core)
initialize disconnect reason only when set in hub loop break paths
- Replace the default "unknown" disconnect reason with an explicitly assigned string and document that all hub loop exits set it before use
- Add an allow attribute for unused assignments to avoid warnings around the deferred initialization pattern
## 2026-03-17 - 4.8.5 - fix(repo)
no changes to commit
## 2026-03-17 - 4.8.4 - fix(remoteingress-core) ## 2026-03-17 - 4.8.4 - fix(remoteingress-core)
prevent stream stalls by guaranteeing flow-control updates and avoiding bounded per-stream channel overflows prevent stream stalls by guaranteeing flow-control updates and avoiding bounded per-stream channel overflows

View File

@@ -1,6 +1,6 @@
{ {
"name": "@serve.zone/remoteingress", "name": "@serve.zone/remoteingress",
"version": "4.8.4", "version": "4.8.7",
"private": false, "private": false,
"description": "Edge ingress tunnel for DcRouter - accepts incoming TCP connections at network edge and tunnels them to DcRouter SmartProxy preserving client IP via PROXY protocol v1.", "description": "Edge ingress tunnel for DcRouter - accepts incoming TCP connections at network edge and tunnels them to DcRouter SmartProxy preserving client IP via PROXY protocol v1.",
"main": "dist_ts/index.js", "main": "dist_ts/index.js",

View File

@@ -587,6 +587,14 @@ async fn connect_to_hub_and_run(
} }
}; };
// Graceful TLS shutdown: send close_notify so the hub sees a clean disconnect
// instead of "peer closed connection without sending TLS close_notify".
let mut tls_stream = tunnel_io.into_inner();
let _ = tokio::time::timeout(
Duration::from_secs(2),
tls_stream.shutdown(),
).await;
// Cleanup // Cleanup
connection_token.cancel(); connection_token.cancel();
stun_handle.abort(); stun_handle.abort();

View File

@@ -735,7 +735,9 @@ async fn handle_edge_connection(
// Single-owner I/O engine — no tokio::io::split, no mutex // Single-owner I/O engine — no tokio::io::split, no mutex
let mut tunnel_io = remoteingress_protocol::TunnelIo::new(tls_stream, Vec::new()); let mut tunnel_io = remoteingress_protocol::TunnelIo::new(tls_stream, Vec::new());
let mut disconnect_reason = "unknown".to_string(); // Assigned in every break path of the hub_loop before use at the end.
#[allow(unused_assignments)]
let mut disconnect_reason = String::new();
'hub_loop: loop { 'hub_loop: loop {
// Drain completed stream cleanups from spawned tasks // Drain completed stream cleanups from spawned tasks
@@ -822,6 +824,14 @@ async fn handle_edge_connection(
} }
} }
// Graceful TLS shutdown: send close_notify so the edge sees a clean disconnect
// instead of "peer closed connection without sending TLS close_notify".
let mut tls_stream = tunnel_io.into_inner();
let _ = tokio::time::timeout(
Duration::from_secs(2),
tls_stream.shutdown(),
).await;
// Cleanup: cancel edge token to propagate to all child tasks // Cleanup: cancel edge token to propagate to all child tasks
edge_token.cancel(); edge_token.cancel();
config_handle.abort(); config_handle.abort();

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/remoteingress', name: '@serve.zone/remoteingress',
version: '4.8.4', version: '4.8.7',
description: 'Edge ingress tunnel for DcRouter - accepts incoming TCP connections at network edge and tunnels them to DcRouter SmartProxy preserving client IP via PROXY protocol v1.' description: 'Edge ingress tunnel for DcRouter - accepts incoming TCP connections at network edge and tunnels them to DcRouter SmartProxy preserving client IP via PROXY protocol v1.'
} }