Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ee6b121370 | |||
| f476f6b145 |
@@ -85,7 +85,7 @@ sealed class SessionManager : IDisposable
|
||||
lock (_openLock)
|
||||
{
|
||||
if (_pending != null)
|
||||
_pending.Client.Dispose();
|
||||
NetUtil.RstClose(_pending.Client);
|
||||
}
|
||||
ProcessQueue();
|
||||
break;
|
||||
@@ -546,7 +546,21 @@ sealed class Session(
|
||||
_cts.Cancel();
|
||||
_deliverChannel.Writer.TryComplete();
|
||||
SendClose();
|
||||
try { client.Dispose(); } catch { }
|
||||
NetUtil.RstClose(client);
|
||||
_cts.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// Close a TcpClient with a TCP RST instead of a FIN.
|
||||
static partial class NetUtil
|
||||
{
|
||||
public static void RstClose(TcpClient c)
|
||||
{
|
||||
try
|
||||
{
|
||||
c.LingerState = new LingerOption(true, 0);
|
||||
c.Close();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="2.0.0.0" name="gatuna" />
|
||||
<assemblyIdentity version="2.1.0.0" name="gatuna" />
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<AssemblyName>gatuna</AssemblyName>
|
||||
<RootNamespace>gatuna</RootNamespace>
|
||||
<Version>2.0.0</Version>
|
||||
<Version>2.1.0</Version>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "gatuna"
|
||||
version = "2.0.0"
|
||||
version = "2.1.0"
|
||||
edition = "2021"
|
||||
license = "CC0-1.0"
|
||||
|
||||
|
||||
+12
-2
@@ -16,7 +16,7 @@ use std::sync::{Arc, Mutex};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::Mutex as AsyncMutex;
|
||||
use tracing::{error, Level};
|
||||
use tracing::{error, info, Level};
|
||||
|
||||
use crate::frame::{
|
||||
Frame, REASON_CONNECT_FAILED, REASON_UNKNOWN_SESSION, REASON_UNKNOWN_UPSTREAM,
|
||||
@@ -33,12 +33,16 @@ struct Args {
|
||||
/// One or more TCP upstreams as PORT[:label], relayed to 127.0.0.1:PORT.
|
||||
#[arg(num_args = 1..)]
|
||||
ports: Vec<String>,
|
||||
/// Verbose logging (lifecycle events to stdout).
|
||||
#[arg(short, long)]
|
||||
verbose: bool,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> ExitCode {
|
||||
let level = if args.verbose { Level::INFO } else { Level::ERROR };
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(Level::ERROR)
|
||||
.with_max_level(level)
|
||||
.with_writer(|| std::io::stdout())
|
||||
.init();
|
||||
|
||||
@@ -141,13 +145,16 @@ async fn handle_frame(
|
||||
) {
|
||||
match frame {
|
||||
Frame::Discover => {
|
||||
info!("DISCOVER from {src:?}");
|
||||
let manifest = Frame::Manifest {
|
||||
hostname: (**hostname).clone(),
|
||||
entries: table.entries(),
|
||||
};
|
||||
let _ = tx.send((src, manifest.encode())).await;
|
||||
info!("MANIFEST sent to {src:?} ({} upstreams)", table.0.len());
|
||||
}
|
||||
Frame::Open { upstream_id, proto: _ } => {
|
||||
info!("OPEN upstream {upstream_id} from {src:?}");
|
||||
let upstream = table.get(upstream_id);
|
||||
match upstream {
|
||||
Some(upstream) => {
|
||||
@@ -176,10 +183,12 @@ async fn handle_frame(
|
||||
);
|
||||
let ack = Frame::OpenAck { session_id: sid, upstream_id, proto };
|
||||
let _ = tx.send((src, ack.encode())).await;
|
||||
info!("session {sid} established (upstream {upstream_id})");
|
||||
spawn_pump(r, sid, proto, src, tx, store);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("connect 127.0.0.1:{port} failed: {e}");
|
||||
info!("OPEN_NAK upstream {upstream_id} (connect_failed) to {src:?}");
|
||||
let nak =
|
||||
Frame::OpenNak { upstream_id, reason: REASON_CONNECT_FAILED };
|
||||
let _ = tx.send((src, nak.encode())).await;
|
||||
@@ -215,6 +224,7 @@ async fn handle_frame(
|
||||
}
|
||||
}
|
||||
Frame::Close { session_id, reason: _ } => {
|
||||
info!("CLOSE session {session_id} from {src:?}");
|
||||
store.lock().expect("store poisoned").remove(&session_id);
|
||||
}
|
||||
Frame::Ping { nonce } => {
|
||||
|
||||
Reference in New Issue
Block a user