185 lines
6.4 KiB
C#
Raw Normal View History

2022-07-20 17:50:01 +08:00
using Lidgren.Network;
2022-05-22 15:55:26 +08:00
using RageCoop.Core;
2022-07-20 17:50:01 +08:00
using System;
2022-07-19 17:15:53 +08:00
using System.Security.Cryptography;
2022-07-20 17:50:01 +08:00
using System.Threading;
using System.Threading.Tasks;
2022-05-22 15:55:26 +08:00
namespace RageCoop.Client
{
internal static partial class Networking
2022-05-22 15:55:26 +08:00
{
public static NetClient Client;
public static float Latency = 0;
public static bool ShowNetworkInfo = false;
2022-06-24 10:33:36 +08:00
public static Security Security;
static Networking()
{
2022-06-24 10:33:36 +08:00
Security=new Security(Main.Logger);
Task.Run(() =>
{
while (true)
{
if (Client!=null)
{
ProcessMessage(Client.WaitMessage(200));
Client.FlushSendQueue();
}
else
{
Thread.Sleep(20);
}
}
});
}
2022-07-20 17:50:01 +08:00
public static void ToggleConnection(string address, string username = null, string password = null)
2022-05-22 15:55:26 +08:00
{
if (IsOnServer)
2022-05-22 15:55:26 +08:00
{
Client.Disconnect("Bye!");
}
else
{
2022-06-24 10:33:36 +08:00
password = password ?? Main.Settings.Password;
username=username ?? Main.Settings.Username;
2022-05-22 15:55:26 +08:00
// 623c92c287cc392406e7aaaac1c0f3b0 = RAGECOOP
NetPeerConfiguration config = new NetPeerConfiguration("623c92c287cc392406e7aaaac1c0f3b0")
{
AutoFlushSendQueue = true
2022-05-22 15:55:26 +08:00
};
config.EnableMessageType(NetIncomingMessageType.ConnectionLatencyUpdated);
2022-06-24 10:33:36 +08:00
config.EnableMessageType(NetIncomingMessageType.UnconnectedData);
2022-05-22 15:55:26 +08:00
string[] ip = new string[2];
int idx = address.LastIndexOf(':');
if (idx != -1)
{
ip[0] = address.Substring(0, idx);
ip[1] = address.Substring(idx + 1);
}
if (ip.Length != 2)
{
throw new Exception("Malformed URL");
}
2022-05-22 15:55:26 +08:00
EntityPool.AddPlayer();
2022-06-24 10:33:36 +08:00
Task.Run(() =>
2022-05-22 15:55:26 +08:00
{
2022-07-02 17:14:56 +08:00
try
{
DownloadManager.Cleanup();
Client = new NetClient(config);
Client.Start();
Main.QueueAction(() => { GTA.UI.Notification.Show($"~y~Trying to connect..."); });
2022-07-11 11:06:31 +08:00
Menus.CoopMenu._serverConnectItem.Enabled=false;
2022-07-02 17:14:56 +08:00
Security.Regen();
2022-07-20 17:50:01 +08:00
if (!GetServerPublicKey(address))
2022-07-11 11:06:31 +08:00
{
Menus.CoopMenu._serverConnectItem.Enabled=true;
throw new TimeoutException("Failed to retrive server's public key");
}
2022-07-20 17:50:01 +08:00
2022-07-02 17:14:56 +08:00
// Send HandshakePacket
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
var handshake = new Packets.Handshake()
{
PedID = Main.LocalPlayerID,
Username =username,
ModVersion = Main.CurrentVersion,
PassHashEncrypted=Security.Encrypt(password.GetSHA256Hash())
2022-07-02 17:14:56 +08:00
};
Security.GetSymmetricKeysCrypted(out handshake.AesKeyCrypted, out handshake.AesIVCrypted);
handshake.Pack(outgoingMessage);
Client.Connect(ip[0], short.Parse(ip[1]), outgoingMessage);
2022-06-24 10:33:36 +08:00
2022-07-02 17:14:56 +08:00
}
2022-07-20 17:50:01 +08:00
catch (Exception ex)
2022-06-24 10:33:36 +08:00
{
2022-07-11 11:06:31 +08:00
Main.Logger.Error("Cannot connect to server: ", ex);
Main.QueueAction(() => GTA.UI.Notification.Show("Cannot connect to server: "+ex.Message));
2022-07-02 17:14:56 +08:00
}
2022-06-24 10:33:36 +08:00
});
2022-05-22 15:55:26 +08:00
}
}
public static bool IsOnServer
2022-05-22 15:55:26 +08:00
{
get { return Client?.ConnectionStatus == NetConnectionStatus.Connected; }
2022-05-22 15:55:26 +08:00
}
2022-07-20 17:50:01 +08:00
2022-05-22 15:55:26 +08:00
#region -- GET --
#region -- PLAYER --
private static void PlayerConnect(Packets.PlayerConnect packet)
2022-05-22 15:55:26 +08:00
{
var p = new PlayerData
{
PedID = packet.PedID,
Username= packet.Username,
};
GTA.UI.Notification.Show($"~h~{p.Username}~h~ connected.");
PlayerList.SetPlayer(packet.PedID, packet.Username);
2022-05-22 15:55:26 +08:00
Main.Logger.Debug($"player connected:{p.Username}");
}
private static void PlayerDisconnect(Packets.PlayerDisconnect packet)
2022-05-22 15:55:26 +08:00
{
2022-07-20 17:50:01 +08:00
var name = PlayerList.GetPlayer(packet.PedID).Username;
GTA.UI.Notification.Show($"~h~{name}~h~ left.");
PlayerList.RemovePlayer(packet.PedID);
2022-05-22 15:55:26 +08:00
EntityPool.RemoveAllFromPlayer(packet.PedID);
}
#endregion // -- PLAYER --
2022-07-20 17:50:01 +08:00
private static bool GetServerPublicKey(string address, int timeout = 10000)
2022-06-24 10:33:36 +08:00
{
2022-07-20 17:50:01 +08:00
var msg = Client.CreateMessage();
new Packets.PublicKeyRequest().Pack(msg);
var adds = address.Split(':');
Client.SendUnconnectedMessage(msg, adds[0], int.Parse(adds[1]));
return _publicKeyReceived.WaitOne(timeout);
2022-06-24 10:33:36 +08:00
}
2022-05-22 15:55:26 +08:00
#endregion
2022-07-19 17:15:53 +08:00
internal static void GetResponse<T>(Packet request, Action<T> callback, ConnectionChannel channel = ConnectionChannel.RequestResponse) where T : Packet, new()
{
var received = new AutoResetEvent(false);
var id = NewRequestID();
PendingResponses.Add(id, (type, p) =>
{
var result = new T();
result.Unpack(p);
callback(result);
});
var msg = Client.CreateMessage();
msg.Write((byte)PacketType.Request);
msg.Write(id);
request.Pack(msg);
Client.SendMessage(msg, NetDeliveryMethod.ReliableOrdered, (int)channel);
}
private static int NewRequestID()
{
int ID = 0;
while ((ID==0)
|| PendingResponses.ContainsKey(ID))
{
byte[] rngBytes = new byte[4];
RandomNumberGenerator.Create().GetBytes(rngBytes);
// Convert the bytes into an integer
ID = BitConverter.ToInt32(rngBytes, 0);
}
return ID;
}
2022-05-22 15:55:26 +08:00
}
}