diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d70c2d --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +/.vs +/Dust765LobbyServer/bin/Release +/Dust765LobbyServer/obj/Release diff --git a/Dust765LobbyServer.sln b/Dust765LobbyServer.sln new file mode 100644 index 0000000..c1b39ba --- /dev/null +++ b/Dust765LobbyServer.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29215.179 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dust765LobbyServer", "Dust765LobbyServer\Dust765LobbyServer.csproj", "{890A8A6A-F09C-4797-874B-E709017CF574}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {890A8A6A-F09C-4797-874B-E709017CF574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {890A8A6A-F09C-4797-874B-E709017CF574}.Debug|Any CPU.Build.0 = Debug|Any CPU + {890A8A6A-F09C-4797-874B-E709017CF574}.Release|Any CPU.ActiveCfg = Release|Any CPU + {890A8A6A-F09C-4797-874B-E709017CF574}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6F414244-7101-4E07-9480-D469103E35D0} + EndGlobalSection +EndGlobal diff --git a/Dust765LobbyServer/App.config b/Dust765LobbyServer/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/Dust765LobbyServer/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dust765LobbyServer/AppMain.cs b/Dust765LobbyServer/AppMain.cs new file mode 100644 index 0000000..a3cbb28 --- /dev/null +++ b/Dust765LobbyServer/AppMain.cs @@ -0,0 +1,251 @@ +using System; +using System.Threading; +using System.Net; +using System.Net.Sockets; +using System.Collections; + +namespace Dust765LobbyServer +{ + class AppMain + { + private ArrayList m_aryClients = new ArrayList(); + public static IPAddress IP = null; + public static int nPortListen = 2596; + public static int BufferSize = 1024; + + static void Main(string[] args) + { + for (int i = 0; i < args.Length; i++) + { + try + { + if ((args[i][0] == '-') || (args[i][0] == '/')) + { + switch (Char.ToLower(args[i][1])) + { + case 'l': + IP = IPAddress.Parse(args[++i]); + break; + case 'p': + nPortListen = System.Convert.ToInt32(args[++i]); + break; + case 'x': + BufferSize = System.Convert.ToInt32(args[++i]); + break; + + default: + usage(); + break; + } + } + } + catch + { + usage(); + } + } + usage(); + + + AppMain app = new AppMain(); + Console.WriteLine( "*** Dust765 Lobby Server Started {0} *** ", DateTime.Now.ToString( "G" ) ); + IPAddress[] aryLocalAddr = null; + String strHostName = ""; + + if (IP == null) + { + try + { + strHostName = Dns.GetHostName(); + IPHostEntry ipEntry = Dns.GetHostByName(strHostName); + aryLocalAddr = ipEntry.AddressList; + } + catch (Exception ex) + { + Console.WriteLine("Error trying to get local address {0} ", ex.Message); + } + if (aryLocalAddr == null || aryLocalAddr.Length < 1) + { + Console.WriteLine("Unable to get local address"); + return; + } + } + else + { + aryLocalAddr[0] = IP; + } + + Console.WriteLine( "Listening on : [{0}] {1}:{2}", strHostName, aryLocalAddr[0], nPortListen ); + + Socket listener = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); + listener.Bind( new IPEndPoint( aryLocalAddr[0], nPortListen) ); + listener.Listen( 100 ); + listener.BeginAccept( new AsyncCallback( app.OnConnectRequest ), listener ); + + Console.WriteLine ("Press Enter to exit" ); + Console.ReadLine(); + Console.WriteLine ("Closing down Dust765 Lobby Server" ); + + listener.Close(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + public void OnConnectRequest( IAsyncResult ar ) + { + Socket listener = (Socket)ar.AsyncState; + NewConnection( listener.EndAccept( ar ) ); + listener.BeginAccept( new AsyncCallback( OnConnectRequest ), listener ); + } + public void NewConnection( Socket sockClient ) + { + SocketLobbyClient client = new SocketLobbyClient( sockClient ); + m_aryClients.Add( client ); + Console.WriteLine( "Client {0}, joined {1}", client.Sock.RemoteEndPoint, DateTime.Now.ToString("G")); + Console.WriteLine( "Total clients connected {0}", m_aryClients.Count); + client.SetupRecieveCallback( this ); + } + public void OnRecievedData( IAsyncResult ar ) + { + SocketLobbyClient client = (SocketLobbyClient)ar.AsyncState; + byte [] aryRet = client.GetRecievedData( ar ); + + if( aryRet.Length < 1 ) + { + Console.WriteLine( "Client {0}, disconnected {1}", client.Sock.RemoteEndPoint, DateTime.Now.ToString("G")); + client.Sock.Close(); + m_aryClients.Remove( client ); + Console.WriteLine( "Total clients connected {0}", m_aryClients.Count); + return; + } + + int packetNR = aryRet.Length >= 1 ? aryRet[0] : -1; + string packetIdentifiedString = IdentifyPacket(packetNR); + + Console.WriteLine( "Read {0} bytes from client {1} with PacketNR {2} ({3})", + aryRet.Length, client.Sock.RemoteEndPoint, packetNR, packetIdentifiedString); + + //BROADCAST + foreach ( SocketLobbyClient clientSend in m_aryClients ) + { + try + { + if (packetNR == 6 && client.Sock == clientSend.Sock) + { + //DONT SEND TO SENDER ON PACKET 6 + }else + { + Console.WriteLine("Sending {0} bytes to client {1}.", aryRet.Length, clientSend.Sock.RemoteEndPoint); + clientSend.Sock.Send(aryRet); + } + } + catch + { + Console.WriteLine( "Send to client {0} failed {1}", client.Sock.RemoteEndPoint, DateTime.Now.ToString("G")); + Console.WriteLine( "Client {0}, disconnected {1}", client.Sock.RemoteEndPoint, DateTime.Now.ToString("G")); + clientSend.Sock.Close(); + m_aryClients.Remove( client ); + Console.WriteLine( "Total clients connected {0}", m_aryClients.Count); + return; + } + } + client.SetupRecieveCallback( this ); + } + + static void usage() + { + Console.WriteLine("Executable_file_name [-l bind-address] [-p port] [-x size]"); + Console.WriteLine(" -l bind-address Local address to bind to"); + Console.WriteLine(" -p port Local port to bind to"); + Console.WriteLine(" -x size Size of send and receive buffer"); + Console.WriteLine(" Else, default values will be used..."); + Console.WriteLine(" ----------------------------------- "); + } + + static string IdentifyPacket (int PacketNR) + { + switch (PacketNR) + { + case 1: + return "Connect"; + + break; + + case 2: + return "Disconnect"; + + break; + + case 3: + return "Spellcast"; + + break; + + case 4: + return "SetTarget"; + + break; + + case 5: + return "DropTarget"; + + break; + + case 6: + return "HiddenPosition"; + + break; + + case 7: + return "Attack"; + + break; + + default: + return PacketNR.ToString(); + + } + } + } + internal class SocketLobbyClient + { + private Socket m_sock; + private byte[] m_byBuff = new byte[AppMain.BufferSize]; + + public SocketLobbyClient( Socket sock ) + { + m_sock = sock; + } + + public Socket Sock + { + get{ return m_sock; } + } + + public void SetupRecieveCallback( AppMain app ) + { + try + { + AsyncCallback recieveData = new AsyncCallback(app.OnRecievedData); + m_sock.BeginReceive( m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, this ); + } + catch( Exception ex ) + { + Console.WriteLine( "Recieve callback setup failed! {0} {1}", ex.Message, DateTime.Now.ToString("G")); + } + } + + public byte [] GetRecievedData( IAsyncResult ar ) + { + int nBytesRec = 0; + try + { + nBytesRec = m_sock.EndReceive( ar ); + } + catch{} + byte [] byReturn = new byte[nBytesRec]; + Array.Copy( m_byBuff, byReturn, nBytesRec ); + + return byReturn; + } + } +} \ No newline at end of file diff --git a/Dust765LobbyServer/Dust765LobbyServer.csproj b/Dust765LobbyServer/Dust765LobbyServer.csproj new file mode 100644 index 0000000..ded12c0 --- /dev/null +++ b/Dust765LobbyServer/Dust765LobbyServer.csproj @@ -0,0 +1,53 @@ + + + + + Debug + AnyCPU + {890A8A6A-F09C-4797-874B-E709017CF574} + Exe + Dust765LobbyServer + Dust765LobbyServer + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dust765LobbyServer/Properties/AssemblyInfo.cs b/Dust765LobbyServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..81339c8 --- /dev/null +++ b/Dust765LobbyServer/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Dust765LobbyServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Dust765LobbyServer")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("890a8a6a-f09c-4797-874b-e709017cf574")] + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/README.md b/README.md new file mode 100644 index 0000000..1ee9eb3 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Dust765LobbyServer + +socket based relay server to connect multiple clients of Dust765's fork of ClassicUO + +[Dust765's Fork of ClassicUO] (https://github.com/dust765/ClassicUO/tree/dev_dust765) \ No newline at end of file