提取接口,进行重构

This commit is contained in:
SpringHgui 2020-09-21 11:48:15 +08:00
parent 7c4f5aa3f7
commit 60aea3e9f4
13 changed files with 437 additions and 369 deletions

View File

@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using FastTunnel.Core.Handlers.Server;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net;
@ -17,14 +18,11 @@ namespace FastTunnel.Core
public int Port { get; set; }
Action<Socket> receiveClient;
int m_numConnectedSockets;
IListenerDispatcher _requestDispatcher;
Socket listenSocket;
bool Shutdown { get; set; }
// Thread signal.
ManualResetEvent allDone = new ManualResetEvent(false);
public AsyncListener(string ip, int port, ILogger logerr)
{
_logerr = logerr;
@ -38,9 +36,9 @@ namespace FastTunnel.Core
listenSocket.Bind(localEndPoint);
}
public void Listen(Action<Socket> receiveClient)
public void Listen(IListenerDispatcher requestDispatcher)
{
this.receiveClient = receiveClient;
_requestDispatcher = requestDispatcher;
listenSocket.Listen(100);
@ -68,8 +66,6 @@ namespace FastTunnel.Core
}
}
int m_numConnectedSockets;
private void ProcessAccept(SocketAsyncEventArgs e)
{
Interlocked.Increment(ref m_numConnectedSockets);
@ -81,7 +77,7 @@ namespace FastTunnel.Core
// Accept the next connection request
StartAccept(e);
receiveClient.Invoke(accept);
_requestDispatcher.Dispatch(accept);
}
private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
@ -91,7 +87,6 @@ namespace FastTunnel.Core
public void ShutdownAndClose()
{
Shutdown = true;
try
{
listenSocket.Shutdown(SocketShutdown.Both);

View File

@ -1,343 +1,47 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using FastTunnel.Core.Config;
using FastTunnel.Core.Exceptions;
using FastTunnel.Core.Extensions;
using FastTunnel.Core.Config;
using FastTunnel.Core.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using FastTunnel.Core.Handlers;
using FastTunnel.Core.Handlers.Server;
using Microsoft.AspNetCore.Http;
using FastTunnel.Core.Helper;
using System.IO;
using System.Collections.Concurrent;
namespace FastTunnel.Core.Core
{
public class FastTunnelServer
{
public Dictionary<string, NewRequest> newRequest = new Dictionary<string, NewRequest>();
public Dictionary<string, WebInfo> WebList = new Dictionary<string, WebInfo>();
public Dictionary<int, SSHInfo<SSHHandlerArg>> SSHList = new Dictionary<int, SSHInfo<SSHHandlerArg>>();
public ConcurrentDictionary<string, NewRequest> newRequest = new ConcurrentDictionary<string, NewRequest>();
public ConcurrentDictionary<string, WebInfo> WebList = new ConcurrentDictionary<string, WebInfo>();
public ConcurrentDictionary<int, SSHInfo<SSHHandlerArg>> SSHList = new ConcurrentDictionary<int, SSHInfo<SSHHandlerArg>>();
public IServerConfig _serverSettings { get; private set; }
public readonly IServerConfig ServerSettings;
readonly ILogger _logger;
ILogger<FastTunnelServer> _logger;
LoginHandler _loginHandler;
HeartHandler _heartHandler;
SwapMsgHandler _swapMsgHandler;
public FastTunnelServer(ILogger<FastTunnelServer> logger)
public FastTunnelServer(ILogger logger, IServerConfig settings)
{
_logger = logger;
_loginHandler = new LoginHandler(logger);
_heartHandler = new HeartHandler();
_swapMsgHandler = new SwapMsgHandler(logger);
ServerSettings = settings;
}
public void Run(IServerConfig settings)
public void Run()
{
_serverSettings = settings;
_logger.LogDebug("FastTunnel Server Start");
ListenFastTunnelClient();
ListenCustomer();
ListenClient();
ListenHttp();
}
private void ListenFastTunnelClient()
private void ListenClient()
{
IListener listener = new AsyncListener(_serverSettings.BindAddr, _serverSettings.BindPort, _logger);
listener.Listen(ReceiveClient);
_logger.LogDebug($"监听客户端 -> {_serverSettings.BindAddr}:{_serverSettings.BindPort}");
IListener client_listener = new AsyncListener(ServerSettings.BindAddr, ServerSettings.BindPort, _logger);
client_listener.Listen(new ClientDispatcher(this, _logger, ServerSettings));
_logger.LogDebug($"监听客户端 -> {ServerSettings.BindAddr}:{ServerSettings.BindPort}");
}
private void ListenCustomer()
private void ListenHttp()
{
var listener = new AsyncListener(_serverSettings.BindAddr, _serverSettings.WebProxyPort, _logger);
listener.Listen(ReceiveCustomer);
IListener http_listener = new AsyncListener(ServerSettings.BindAddr, ServerSettings.WebProxyPort, _logger);
http_listener.Listen(new HttpDispatcher(this, _logger, ServerSettings));
_logger.LogDebug($"监听HTTP -> {_serverSettings.BindAddr}:{_serverSettings.WebProxyPort}");
}
void ReceiveCustomer(Socket client)
{
try
{
//定义byte数组存放从客户端接收过来的数据
byte[] buffer = new byte[1024];
int count;
try
{
count = client.Receive(buffer);
if (count == 0)
{
client.Close();
return;
}
}
catch (SocketException ex)
{
_logger.LogError(ex.Message);
if (client.Connected)
client.Close();
return;
}
catch (Exception ex)
{
_logger.LogError(ex);
throw;
}
try
{
var endpoint = client.RemoteEndPoint as System.Net.IPEndPoint;
_logger.LogInformation($"Receive HTTP Request {endpoint.Address}:{endpoint.Port}");
if (_serverSettings.WebAllowAccessIps != null)
{
if (!_serverSettings.WebAllowAccessIps.Contains(endpoint.Address.ToString()))
{
HandlerHostNotAccess(client);
return;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex);
}
//将字节转换成字符串
string words = Encoding.UTF8.GetString(buffer, 0, count);
// 正则获取Host
String Host = string.Empty;
var pattern = @"[hH]ost:.+";
var collection = Regex.Matches(words, pattern);
if (collection.Count == 0)
{
_logger.LogError($"Host异常{words}");
// 返回错误页
HandlerHostRequired(client);
return;
}
else
{
Host = collection[0].Value;
}
_logger.LogDebug(Host.Replace("\r", ""));
var domain = Host.Split(":")[1].Trim();
// 判断是否为ip
if (IsIpDomian(domain))
{
// 返回错误页
HandlerHostRequired(client);
return;
}
WebInfo web;
if (!WebList.TryGetValue(domain, out web))
{
HandlerClientNotOnLine(client, domain, buffer);
return;
}
if (!web.Socket.Connected)
{
WebList.Remove(domain);
HandlerClientNotOnLine(client, domain, buffer);
return;
}
var msgid = Guid.NewGuid().ToString();
byte[] bytes = new byte[count];
Array.Copy(buffer, bytes, count);
newRequest.Add(msgid, new NewRequest
{
CustomerClient = client,
Buffer = bytes
});
_logger.LogDebug($"OK");
web.Socket.Send(new Message<NewCustomerMassage> { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = msgid, WebConfig = web.WebConfig } });
}
catch (Exception ex)
{
_logger.LogError("处理Http失败" + ex);
client.Close();
}
}
private bool IsIpDomian(string domain)
{
return Regex.IsMatch(domain, @"^\d.\d.\d.\d.\d$");
}
private void HandlerHostNotAccess(Socket client)
{
_logger.LogDebug($"### NotAccessIps:'{client.RemoteEndPoint}'");
string statusLine = "HTTP/1.1 200 OK\r\n";
string responseHeader = "Content-Type: text/html\r\n";
byte[] responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NotAccessIps);
client.Send(Encoding.UTF8.GetBytes(statusLine));
client.Send(Encoding.UTF8.GetBytes(responseHeader));
client.Send(Encoding.UTF8.GetBytes("\r\n"));
client.Send(responseBody);
client.Close();
}
private void HandlerHostRequired(Socket client)
{
_logger.LogDebug($"### HostRequired:'{client.RemoteEndPoint}'");
string statusLine = "HTTP/1.1 200 OK\r\n";
string responseHeader = "Content-Type: text/html\r\n";
byte[] responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_HostRequired);
client.Send(Encoding.UTF8.GetBytes(statusLine));
client.Send(Encoding.UTF8.GetBytes(responseHeader));
client.Send(Encoding.UTF8.GetBytes("\r\n"));
client.Send(responseBody);
client.Close();
}
private void HandlerClientNotOnLine(Socket client, string domain, byte[] buffer)
{
_logger.LogDebug($"### TunnelNotFound:'{domain}'");
string statusLine = "HTTP/1.1 200 OK\r\n";
string responseHeader = "Content-Type: text/html\r\n";
byte[] responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NoTunnel);
client.Send(Encoding.UTF8.GetBytes(statusLine));
client.Send(Encoding.UTF8.GetBytes(responseHeader));
client.Send(Encoding.UTF8.GetBytes("\r\n"));
client.Send(responseBody);
client.Close();
}
byte[] buffer = new byte[1024 * 1024];
string temp = string.Empty;
public void ReceiveClient(Socket client)
{
//定义byte数组存放从客户端接收过来的数据
int length;
try
{
length = client.Receive(buffer);
if (length == 0)
{
try
{
client.Shutdown(SocketShutdown.Both);
}
catch
{
client.Close();
}
// 递归结束
return;
}
}
catch (Exception ex)
{
_logger.LogError($"接收客户端异常 -> 退出登录 {ex.Message}");
if (client.Connected)
{
client.Close();
}
return;
}
// 将字节转换成字符串
string words = Encoding.UTF8.GetString(buffer, 0, length);
words += temp;
temp = string.Empty;
_logger.LogDebug($"revice from client: {words}");
try
{
int index = 0;
bool needRecive = false;
while (true)
{
var firstIndex = words.IndexOf("\n");
if (firstIndex < 0)
{
temp += words;
ReceiveClient(client);
break;
}
var sub_words = words.Substring(index, firstIndex + 1);
var res = handle(sub_words, client);
if (res.NeedRecive)
needRecive = true;
words = words.Replace(sub_words, string.Empty);
if (string.IsNullOrEmpty(words))
break;
}
if (needRecive)
{
ReceiveClient(client);
}
}
catch (Exception ex)
{
_logger.LogError(ex);
_logger.LogError($"handle fail msg{words}");
// throw;
client.Send(new Message<LogMassage>() { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Error, ex.Message) });
}
}
private IServerHandler handle(string words, Socket client)
{
Message<JObject> msg = JsonConvert.DeserializeObject<Message<JObject>>(words);
IServerHandler handler = null;
switch (msg.MessageType)
{
case MessageType.C_LogIn: // 登录
handler = _loginHandler;
break;
case MessageType.Heart: // 心跳
handler = _heartHandler;
break;
case MessageType.C_SwapMsg: // 交换数据
handler = _swapMsgHandler;
break;
default:
throw new Exception($"未知的通讯指令 {msg.MessageType}");
}
handler.HandlerMsg(this, client, msg);
return handler;
_logger.LogDebug($"监听HTTP -> {ServerSettings.BindAddr}:{ServerSettings.WebProxyPort}");
}
}
}

View File

@ -0,0 +1,144 @@
using FastTunnel.Core.Config;
using FastTunnel.Core.Core;
using FastTunnel.Core.Extensions;
using FastTunnel.Core.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net.Sockets;
using System.Text;
namespace FastTunnel.Core.Handlers.Server
{
public class ClientDispatcher : IListenerDispatcher
{
readonly ILogger _logger;
readonly IServerConfig _serverSettings;
readonly FastTunnelServer _fastTunnelServer;
readonly LoginMessageHandler _loginHandler;
readonly HeartMessageHandler _heartHandler;
readonly SwapMessageHandler _swapMsgHandler;
public ClientDispatcher(FastTunnelServer fastTunnelServer, ILogger logger, IServerConfig serverSettings)
{
_logger = logger;
_serverSettings = serverSettings;
_fastTunnelServer = fastTunnelServer;
_loginHandler = new LoginMessageHandler(logger);
_heartHandler = new HeartMessageHandler();
_swapMsgHandler = new SwapMessageHandler(logger);
}
byte[] buffer = new byte[1024 * 1024];
string temp = string.Empty;
public void Dispatch(Socket client)
{
//定义byte数组存放从客户端接收过来的数据
int length;
try
{
length = client.Receive(buffer);
if (length == 0)
{
try
{
client.Shutdown(SocketShutdown.Both);
}
catch
{
client.Close();
}
// 递归结束
return;
}
}
catch (Exception ex)
{
_logger.LogError($"接收客户端异常 -> 退出登录 {ex.Message}");
if (client.Connected)
{
client.Close();
}
return;
}
// 将字节转换成字符串
string words = Encoding.UTF8.GetString(buffer, 0, length);
words += temp;
temp = string.Empty;
_logger.LogDebug($"revice from client: {words}");
try
{
int index = 0;
bool needRecive = false;
while (true)
{
var firstIndex = words.IndexOf("\n");
if (firstIndex < 0)
{
temp += words;
Dispatch(client);
break;
}
var sub_words = words.Substring(index, firstIndex + 1);
var res = handle(sub_words, client);
if (res.NeedRecive)
needRecive = true;
words = words.Replace(sub_words, string.Empty);
if (string.IsNullOrEmpty(words))
break;
}
if (needRecive)
{
Dispatch(client);
}
}
catch (Exception ex)
{
_logger.LogError(ex);
_logger.LogError($"handle fail msg{words}");
// throw;
client.Send(new Message<LogMassage>() { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Error, ex.Message) });
}
}
private IClientMessageHandler handle(string words, Socket client)
{
Message<JObject> msg = JsonConvert.DeserializeObject<Message<JObject>>(words);
IClientMessageHandler handler = null;
switch (msg.MessageType)
{
case MessageType.C_LogIn: // 登录
handler = _loginHandler;
break;
case MessageType.Heart: // 心跳
handler = _heartHandler;
break;
case MessageType.C_SwapMsg: // 交换数据
handler = _swapMsgHandler;
break;
default:
throw new Exception($"未知的通讯指令 {msg.MessageType}");
}
handler.HandlerMsg(this._fastTunnelServer, client, msg);
return handler;
}
}
}

View File

@ -9,7 +9,7 @@ using System.Text;
namespace FastTunnel.Core.Handlers.Server
{
public class HeartHandler : IServerHandler
public class HeartMessageHandler : IClientMessageHandler
{
public bool NeedRecive => true;

View File

@ -0,0 +1,194 @@
using FastTunnel.Core.Config;
using FastTunnel.Core.Core;
using FastTunnel.Core.Extensions;
using FastTunnel.Core.Models;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
namespace FastTunnel.Core.Handlers.Server
{
public class HttpDispatcher : IListenerDispatcher
{
readonly ILogger _logger;
readonly IServerConfig _serverSettings;
readonly FastTunnelServer _fastTunnelServer;
public HttpDispatcher(FastTunnelServer fastTunnelServer, ILogger logger, IServerConfig serverSettings)
{
_logger = logger;
_serverSettings = serverSettings;
_fastTunnelServer = fastTunnelServer;
}
public void Dispatch(Socket httpClient)
{
try
{
//定义byte数组存放从客户端接收过来的数据
byte[] buffer = new byte[1024];
int count;
try
{
count = httpClient.Receive(buffer);
if (count == 0)
{
httpClient.Close();
return;
}
}
catch (SocketException ex)
{
_logger.LogError(ex.Message);
if (httpClient.Connected)
httpClient.Close();
return;
}
catch (Exception ex)
{
_logger.LogError(ex);
throw;
}
try
{
var endpoint = httpClient.RemoteEndPoint as System.Net.IPEndPoint;
_logger.LogInformation($"Receive HTTP Request {endpoint.Address}:{endpoint.Port}");
if (_serverSettings.WebAllowAccessIps != null)
{
if (!_serverSettings.WebAllowAccessIps.Contains(endpoint.Address.ToString()))
{
HandlerHostNotAccess(httpClient);
return;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex);
}
//将字节转换成字符串
string words = Encoding.UTF8.GetString(buffer, 0, count);
// 正则获取Host
String Host = string.Empty;
var pattern = @"[hH]ost:.+";
var collection = Regex.Matches(words, pattern);
if (collection.Count == 0)
{
_logger.LogError($"Host异常{words}");
// 返回错误页
HandlerHostRequired(httpClient);
return;
}
else
{
Host = collection[0].Value;
}
_logger.LogDebug(Host.Replace("\r", ""));
var domain = Host.Split(":")[1].Trim();
// 判断是否为ip
if (IsIpDomian(domain))
{
// 返回错误页
HandlerHostRequired(httpClient);
return;
}
WebInfo web;
if (!_fastTunnelServer.WebList.TryGetValue(domain, out web))
{
HandlerClientNotOnLine(httpClient, domain, buffer);
return;
}
if (!web.Socket.Connected)
{
_fastTunnelServer.WebList.TryRemove(domain, out WebInfo invalidWeb);
HandlerClientNotOnLine(httpClient, domain, buffer);
return;
}
var msgid = Guid.NewGuid().ToString();
byte[] bytes = new byte[count];
Array.Copy(buffer, bytes, count);
_fastTunnelServer.newRequest.TryAdd(msgid, new NewRequest
{
CustomerClient = httpClient,
Buffer = bytes
});
_logger.LogDebug($"OK");
web.Socket.Send(new Message<NewCustomerMassage> { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = msgid, WebConfig = web.WebConfig } });
}
catch (Exception ex)
{
_logger.LogError("处理Http失败" + ex);
httpClient.Close();
}
}
private bool IsIpDomian(string domain)
{
return Regex.IsMatch(domain, @"^\d.\d.\d.\d.\d$");
}
private void HandlerHostNotAccess(Socket client)
{
_logger.LogDebug($"### NotAccessIps:'{client.RemoteEndPoint}'");
string statusLine = "HTTP/1.1 200 OK\r\n";
string responseHeader = "Content-Type: text/html\r\n";
byte[] responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NotAccessIps);
client.Send(Encoding.UTF8.GetBytes(statusLine));
client.Send(Encoding.UTF8.GetBytes(responseHeader));
client.Send(Encoding.UTF8.GetBytes("\r\n"));
client.Send(responseBody);
client.Close();
}
private void HandlerHostRequired(Socket client)
{
_logger.LogDebug($"### HostRequired:'{client.RemoteEndPoint}'");
string statusLine = "HTTP/1.1 200 OK\r\n";
string responseHeader = "Content-Type: text/html\r\n";
byte[] responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_HostRequired);
client.Send(Encoding.UTF8.GetBytes(statusLine));
client.Send(Encoding.UTF8.GetBytes(responseHeader));
client.Send(Encoding.UTF8.GetBytes("\r\n"));
client.Send(responseBody);
client.Close();
}
private void HandlerClientNotOnLine(Socket client, string domain, byte[] buffer)
{
_logger.LogDebug($"### TunnelNotFound:'{domain}'");
string statusLine = "HTTP/1.1 200 OK\r\n";
string responseHeader = "Content-Type: text/html\r\n";
byte[] responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NoTunnel);
client.Send(Encoding.UTF8.GetBytes(statusLine));
client.Send(Encoding.UTF8.GetBytes(responseHeader));
client.Send(Encoding.UTF8.GetBytes("\r\n"));
client.Send(responseBody);
client.Close();
}
}
}

View File

@ -8,7 +8,7 @@ using System.Text;
namespace FastTunnel.Core.Handlers
{
public interface IServerHandler
public interface IClientMessageHandler
{
Boolean NeedRecive { get; }

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
namespace FastTunnel.Core.Handlers.Server
{
public interface IListenerDispatcher
{
void Dispatch(Socket httpClient);
}
}

View File

@ -12,14 +12,14 @@ using System.Text;
namespace FastTunnel.Core.Handlers
{
public class LoginHandler : IServerHandler
public class LoginMessageHandler : IClientMessageHandler
{
ILogger _logger;
public bool NeedRecive => true;
IConfigHandler _configHandler;
public LoginHandler(ILogger logger)
public LoginMessageHandler(ILogger logger)
{
_logger = logger;
_configHandler = new ConfigHandler();
@ -45,21 +45,21 @@ namespace FastTunnel.Core.Handlers
hasTunnel = true;
foreach (var item in requet.Webs)
{
var hostName = $"{item.SubDomain}.{server._serverSettings.WebDomain}".Trim();
var hostName = $"{item.SubDomain}.{server.ServerSettings.WebDomain}".Trim();
if (server.WebList.ContainsKey(hostName))
{
_logger.LogDebug($"renew domain '{hostName}'");
server.WebList.Remove(hostName);
server.WebList.Add(hostName, new WebInfo { Socket = client, WebConfig = item });
server.WebList.TryRemove(hostName, out WebInfo web);
server.WebList.TryAdd(hostName, new WebInfo { Socket = client, WebConfig = item });
}
else
{
_logger.LogDebug($"new domain '{hostName}'");
server.WebList.Add(hostName, new WebInfo { Socket = client, WebConfig = item });
server.WebList.TryAdd(hostName, new WebInfo { Socket = client, WebConfig = item });
}
sb.Append($"{Environment.NewLine} http://{hostName}{(server._serverSettings.WebHasNginxProxy ? string.Empty : ":" + server._serverSettings.WebProxyPort)} => {item.LocalIp}:{item.LocalPort}");
sb.Append($"{Environment.NewLine} http://{hostName}{(server.ServerSettings.WebHasNginxProxy ? string.Empty : ":" + server.ServerSettings.WebProxyPort)} => {item.LocalIp}:{item.LocalPort}");
}
}
@ -72,13 +72,13 @@ namespace FastTunnel.Core.Handlers
{
try
{
if (item.RemotePort.Equals(server._serverSettings.BindPort))
if (item.RemotePort.Equals(server.ServerSettings.BindPort))
{
_logger.LogError($"RemotePort can not be same with BindPort: {item.RemotePort}");
continue;
}
if (item.RemotePort.Equals(server._serverSettings.WebProxyPort))
if (item.RemotePort.Equals(server.ServerSettings.WebProxyPort))
{
_logger.LogError($"RemotePort can not be same with ProxyPort_HTTP: {item.RemotePort}");
continue;
@ -89,26 +89,18 @@ namespace FastTunnel.Core.Handlers
{
_logger.LogDebug($"Remove Listener {old.Listener.IP}:{old.Listener.Port}");
old.Listener.ShutdownAndClose();
server.SSHList.Remove(item.RemotePort);
server.SSHList.TryRemove(item.RemotePort, out SSHInfo<SSHHandlerArg> _);
}
var ls = new AsyncListener("0.0.0.0", item.RemotePort, _logger);
ls.Listen((_socket) =>
{
var msgid = Guid.NewGuid().ToString();
client.Send(new Message<NewSSHRequest> { MessageType = MessageType.S_NewSSH, Content = new NewSSHRequest { MsgId = msgid, SSHConfig = item } });
server.newRequest.Add(msgid, new NewRequest
{
CustomerClient = _socket,
});
});
ls.Listen(new SSHDispatcher(server, client, item));
// listen success
server.SSHList.Add(item.RemotePort, new SSHInfo<SSHHandlerArg> { Listener = ls, Socket = client, SSHConfig = item });
server.SSHList.TryAdd(item.RemotePort, new SSHInfo<SSHHandlerArg> { Listener = ls, Socket = client, SSHConfig = item });
_logger.LogDebug($"SSH proxy success: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
sb.Append($"{Environment.NewLine} {server._serverSettings.WebDomain}:{item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
sb.Append($"{Environment.NewLine} {server.ServerSettings.WebDomain}:{item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
}
catch (Exception ex)
{

View File

@ -0,0 +1,34 @@
using FastTunnel.Core.Core;
using FastTunnel.Core.Extensions;
using FastTunnel.Core.Models;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
namespace FastTunnel.Core.Handlers.Server
{
public class SSHDispatcher : IListenerDispatcher
{
private FastTunnelServer _server;
private Socket _client;
private SSHConfig _config;
public SSHDispatcher(FastTunnelServer server, Socket client, SSHConfig config)
{
_server = server;
_client = client;
_config = config;
}
public void Dispatch(Socket _socket)
{
var msgid = Guid.NewGuid().ToString();
_client.Send(new Message<NewSSHRequest> { MessageType = MessageType.S_NewSSH, Content = new NewSSHRequest { MsgId = msgid, SSHConfig = _config } });
_server.newRequest.TryAdd(msgid, new NewRequest
{
CustomerClient = _socket,
});
}
}
}

View File

@ -11,13 +11,13 @@ using System.Threading.Tasks;
namespace FastTunnel.Core.Handlers.Server
{
public class SwapMsgHandler : IServerHandler
public class SwapMessageHandler : IClientMessageHandler
{
public bool NeedRecive => false;
ILogger _logger;
public SwapMsgHandler(ILogger logger)
public SwapMessageHandler(ILogger logger)
{
_logger = logger;
}

View File

@ -1,4 +1,5 @@
using System;
using FastTunnel.Core.Handlers.Server;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
@ -11,7 +12,7 @@ namespace FastTunnel.Core
int Port { get; }
void Listen(Action<Socket> receiveClient);
void Listen(IListenerDispatcher requestDispatcher);
void ShutdownAndClose();
}

View File

@ -7,6 +7,7 @@ using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Hosting;
using FastTunnel.Server.Service;
using FastTunnel.Core.Logger;
using FastTunnel.Core.Config;
namespace FastTunnel.Server
{
@ -34,6 +35,7 @@ namespace FastTunnel.Server
// DI
services.AddTransient<FastTunnelServer>();
//services.AddSingleton<IServerConfig>();
});
}
}

View File

@ -14,14 +14,12 @@ namespace FastTunnel.Server.Service
public class ServiceFastTunnelServer : IHostedService
{
ILogger<ServiceFastTunnelServer> _logger;
IConfiguration _configuration;
FastTunnelServer _fastTunnelServer;
public ServiceFastTunnelServer(ILogger<ServiceFastTunnelServer> logger, IConfiguration configuration, FastTunnelServer fastTunnelServer)
public ServiceFastTunnelServer(ILogger<ServiceFastTunnelServer> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
_fastTunnelServer = fastTunnelServer;
_fastTunnelServer = new FastTunnelServer(_logger, configuration.Get<Appsettings>().ServerSettings);
}
public Task StartAsync(CancellationToken cancellationToken)
@ -30,15 +28,7 @@ namespace FastTunnel.Server.Service
try
{
var setting = _configuration.Get<Appsettings>().ServerSettings;
_fastTunnelServer.Run(
new DefaultServerConfigBuilder()
.WithWebAllowAccessIps(setting.WebAllowAccessIps)
.WithBindInfo(setting.BindAddr, setting.BindPort)
.WithHasNginxProxy(setting.WebHasNginxProxy)
.WithWebDomain(setting.WebDomain).WithSSHEnabled(false)
.WithHTTPPort(setting.WebProxyPort).Build());
_fastTunnelServer.Run();
}
catch (Exception ex)
{