using System.Text;
using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Common.Network;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Server.Others;
using Milimoe.FunGame.Server.Services;
namespace Milimoe.FunGame.Server.Controller
{
public class ConnectController
{
///
/// 因为异步函数无法使用 ref 变量,因此使用元组返回
///
///
///
///
///
///
///
/// [0]isConnected;[1]isDebugMode
public static async Task<(bool, bool)> Connect(ISocketListener listener, ISocketMessageProcessor socket, Guid token, string clientip, IEnumerable objs) where T : ISocketMessageProcessor
{
try
{
bool isConnected = false;
bool isDebugMode = false;
objs = objs.Where(o => o.SocketType == SocketMessageType.Connect);
foreach (SocketObject obj in objs)
{
if (Config.ConnectingPlayerCount + Config.OnlinePlayerCount > Config.MaxPlayers)
{
await SendRefuseConnect(socket, "服务器可接受的连接数量已上限!");
ServerHelper.WriteLine("服务器可接受的连接数量已上限!", InvokeMessageType.Core);
return (isConnected, isDebugMode);
}
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 正在连接服务器 . . .", InvokeMessageType.Core);
if (IsIPBanned(listener, clientip))
{
await SendRefuseConnect(socket, "服务器已拒绝黑名单用户连接。");
ServerHelper.WriteLine("检测到 " + ServerHelper.MakeClientName(clientip) + " 为黑名单用户,已禁止其连接!", InvokeMessageType.Core);
return (isConnected, isDebugMode);
}
ServerHelper.WriteLine("[" + SocketSet.GetTypeString(obj.SocketType) + "] " + ServerHelper.MakeClientName(socket.ClientIP), InvokeMessageType.Core);
// 验证客户端参数
string msg = OnValidateClientParameters(ref isDebugMode, obj);
if (msg == "" && await socket.SendAsync(SocketMessageType.Connect, true, msg, token, Config.ServerName, Config.ServerNotice) == SocketResult.Success)
{
isConnected = true;
ServerHelper.WriteLine(ServerHelper.MakeClientName(socket.ClientIP) + " <- " + "已确认连接", InvokeMessageType.Core);
return (isConnected, isDebugMode);
}
else if (msg != "" && await socket.SendAsync(SocketMessageType.Connect, false, msg) == SocketResult.Success)
{
ServerHelper.WriteLine(ServerHelper.MakeClientName(socket.ClientIP) + " <- " + "拒绝连接", InvokeMessageType.Core);
return (isConnected, isDebugMode);
}
else
{
ServerHelper.WriteLine("无法传输数据,与客户端的连接可能丢失。", InvokeMessageType.Core);
return (isConnected, isDebugMode);
}
}
await SendRefuseConnect(socket, "服务器已拒绝连接。");
ServerHelper.WriteLine("客户端发送了不符合FunGame规定的字符,拒绝连接。", InvokeMessageType.Core);
return (isConnected, isDebugMode);
}
catch (Exception e)
{
ServerHelper.Error(e);
await SendRefuseConnect(socket, "请勿发送错误的数据,请保持FunGame版本为最新。");
throw new SocketWrongInfoException();
}
}
///
/// 回复拒绝连接消息
///
///
///
///
private static async Task SendRefuseConnect(ISocketMessageProcessor socket, string msg)
{
// 发送消息给客户端
msg = "连接被拒绝,如有疑问请联系服务器管理员:" + msg;
if (await socket.SendAsync(SocketMessageType.Connect, false, msg) == SocketResult.Success)
{
ServerHelper.WriteLine(ServerHelper.MakeClientName(socket.ClientIP) + " <- " + "已拒绝连接", InvokeMessageType.Core);
return true;
}
else
{
ServerHelper.WriteLine("无法传输数据,与客户端的连接可能丢失。", InvokeMessageType.Core);
return false;
}
}
///
/// 判断是否是黑名单里的IP
///
///
///
///
///
private static bool IsIPBanned(ISocketListener server, string ip) where T : ISocketMessageProcessor
{
string[] strs = ip.Split(":");
if (strs.Length == 2 && server.BannedList.Contains(strs[0]))
{
return true;
}
return false;
}
///
/// 验证客户端参数事件
///
public static event Func? ValidateClientParameters;
///
/// 触发验证客户端参数事件
///
///
///
public static string OnValidateClientParameters(ref bool isDebugMode, SocketObject obj)
{
StringBuilder builder = new();
// 先检查 Desktop 参数
if (Config.UseDesktopParameters)
{
// 参数1:客户端的游戏模组列表,没有服务器的需要拒绝
if (obj.Parameters.Length > 0)
{
string[] modes = obj.GetParam(0) ?? [];
List ClientDontHave = [];
string strDontHave = string.Join("\r\n", Config.GameModuleSupported.Where(mode => !modes.Contains(mode)));
if (strDontHave != "")
{
strDontHave = "客户端缺少服务器所需的模组:" + strDontHave;
ServerHelper.WriteLine(strDontHave, InvokeMessageType.Core);
builder.AppendLine(strDontHave);
}
}
// 参数2:客户端是否开启了开发者模式,开启开发者模式部分功能不可用
if (obj.Parameters.Length > 1)
{
isDebugMode = obj.GetParam(1);
if (isDebugMode) ServerHelper.WriteLine("客户端已开启开发者模式");
}
}
if (ValidateClientParameters is null)
{
return "";
}
foreach (Func handler in ValidateClientParameters.GetInvocationList().Cast>())
{
string msg = handler(obj);
if (msg != "")
{
builder.AppendLine(msg);
ServerHelper.WriteLine(msg, InvokeMessageType.Error);
}
}
return builder.ToString().Trim();
}
}
}