diff --git a/ClientServerLib/AndroidRemote/AndroidRemote.csproj b/ClientServerLib/AndroidRemote/AndroidRemote.csproj index a5f49241..91c8cc78 100644 --- a/ClientServerLib/AndroidRemote/AndroidRemote.csproj +++ b/ClientServerLib/AndroidRemote/AndroidRemote.csproj @@ -76,6 +76,9 @@ ClientServerLib\Vocaluxe\VocaluxeStructs.cs + + ClientServerLib\CDiscover.cs + diff --git a/ClientServerLib/ClientServerLib/CDiscover.cs b/ClientServerLib/ClientServerLib/CDiscover.cs new file mode 100644 index 00000000..2242cf92 --- /dev/null +++ b/ClientServerLib/ClientServerLib/CDiscover.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Timers; + +namespace ClientServerLib +{ + public delegate void OnServerDiscovered(string IPAddress, string Hostname); + + public class CDiscover + { + private string _Keyword; + private string _BroadcastAddress; + private int _Port; + + private Thread _DiscoverThread; + private bool _DiscoverRunning; + private OnServerDiscovered _OnDiscovered; + + + private System.Timers.Timer _BroadcastTimer; + + public CDiscover(int Port, string Keyword, string BroadcastAddress = "255.255.255.255") + { + _BroadcastAddress = BroadcastAddress; + _Port = Port; + _Keyword = Keyword; + + _DiscoverRunning = false; + _BroadcastTimer = new System.Timers.Timer(); + _BroadcastTimer.Elapsed += new ElapsedEventHandler(OnBroadcastEvent); + _BroadcastTimer.Interval = 2500; + } + + public void StartBroadcasting() + { + _BroadcastTimer.Start(); + } + + public void Stop() + { + _BroadcastTimer.Stop(); + _DiscoverRunning = false; + } + + public void Discover(OnServerDiscovered OnDiscovered, int Timeout = 5000) + { + if (_DiscoverRunning) + return; + + _DiscoverRunning = true; + _DiscoverThread = new Thread(() => _Discover(Timeout)); + _OnDiscovered = OnDiscovered; + _DiscoverThread.Start(); + } + + private void OnBroadcastEvent(object source, ElapsedEventArgs e) + { + Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + s.EnableBroadcast = true; + IPAddress broadcast = IPAddress.Parse(_BroadcastAddress); + byte[] sendbuf = Encoding.UTF8.GetBytes(_Keyword); + IPEndPoint ep = new IPEndPoint(broadcast, _Port); + + s.SendTo(sendbuf, ep); + s.Close(); + } + + private void _Discover(int Timeout) + { + UdpClient listener = null; + Stopwatch timer = new Stopwatch(); + + List knownServer = new List(); + bool foundSomething = false; + timer.Start(); + while (_DiscoverRunning && timer.ElapsedMilliseconds < Timeout * 2) + { + try + { + listener = new UdpClient(_Port); + IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, _Port); + listener.Client.ReceiveTimeout = Timeout; + + byte[] bytes = listener.Receive(ref groupEP); + string message = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + + foundSomething = true; + if (!knownServer.Contains(groupEP.Address.ToString())) + { + knownServer.Add(groupEP.Address.ToString()); + if (_OnDiscovered != null) + { + IPHostEntry e = Dns.GetHostEntry(groupEP.Address); + string hostname = e.HostName; + + _OnDiscovered(groupEP.Address.ToString(), hostname); + } + } + + listener.Close(); + } + catch (Exception) + { + if (listener != null) + listener.Close(); + } + } + _DiscoverRunning = false; + + if (!foundSomething) + _OnDiscovered("Timeout", "unknown"); + } + } +} diff --git a/ClientServerLib/ClientServerLib/ClientServerLib.csproj b/ClientServerLib/ClientServerLib/ClientServerLib.csproj index d5bd8b7e..fbda0800 100644 --- a/ClientServerLib/ClientServerLib/ClientServerLib.csproj +++ b/ClientServerLib/ClientServerLib/ClientServerLib.csproj @@ -46,6 +46,7 @@ + diff --git a/ClientServerLib/ClientServerLib/Vocaluxe/CCommands.cs b/ClientServerLib/ClientServerLib/Vocaluxe/CCommands.cs index ff9f518b..ecfa087e 100644 --- a/ClientServerLib/ClientServerLib/Vocaluxe/CCommands.cs +++ b/ClientServerLib/ClientServerLib/Vocaluxe/CCommands.cs @@ -14,6 +14,8 @@ namespace Vocaluxe.Base.Server private static UTF8Encoding encoder = new UTF8Encoding(); public static SHA256Managed SHA256 = new SHA256Managed(); + public const string BroadcastKeyword = "I am a Vocaluxe Server"; + #region Commands public const int ResponseOK = 1; public const int ResponseNOK = 2; diff --git a/ClientServerLib/ClientTest/ClientTest.Designer.cs b/ClientServerLib/ClientTest/ClientTest.Designer.cs index 65d2f867..33b815d3 100644 --- a/ClientServerLib/ClientTest/ClientTest.Designer.cs +++ b/ClientServerLib/ClientTest/ClientTest.Designer.cs @@ -49,6 +49,9 @@ this.btDown = new System.Windows.Forms.Button(); this.btSendAvatar = new System.Windows.Forms.Button(); this.btSendProfile = new System.Windows.Forms.Button(); + this.btDiscover = new System.Windows.Forms.Button(); + this.tbDiscoveredServer = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); this.statusStrip1.SuspendLayout(); this.SuspendLayout(); // @@ -251,11 +254,44 @@ this.btSendProfile.UseVisualStyleBackColor = true; this.btSendProfile.Click += new System.EventHandler(this.btSendProfile_Click); // + // btDiscover + // + this.btDiscover.Location = new System.Drawing.Point(831, 502); + this.btDiscover.Name = "btDiscover"; + this.btDiscover.Size = new System.Drawing.Size(165, 23); + this.btDiscover.TabIndex = 16; + this.btDiscover.Text = "Discover"; + this.btDiscover.UseVisualStyleBackColor = true; + this.btDiscover.Click += new System.EventHandler(this.btDiscover_Click); + // + // tbDiscoveredServer + // + this.tbDiscoveredServer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tbDiscoveredServer.Location = new System.Drawing.Point(15, 405); + this.tbDiscoveredServer.Multiline = true; + this.tbDiscoveredServer.Name = "tbDiscoveredServer"; + this.tbDiscoveredServer.Size = new System.Drawing.Size(810, 120); + this.tbDiscoveredServer.TabIndex = 17; + this.tbDiscoveredServer.WordWrap = false; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 389); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(41, 13); + this.label1.TabIndex = 18; + this.label1.Text = "Server:"; + // // ClientTest // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1008, 550); + this.Controls.Add(this.label1); + this.Controls.Add(this.tbDiscoveredServer); + this.Controls.Add(this.btDiscover); this.Controls.Add(this.btSendProfile); this.Controls.Add(this.btSendAvatar); this.Controls.Add(this.btDown); @@ -307,6 +343,9 @@ private System.Windows.Forms.Button btDown; private System.Windows.Forms.Button btSendAvatar; private System.Windows.Forms.Button btSendProfile; + private System.Windows.Forms.Button btDiscover; + private System.Windows.Forms.TextBox tbDiscoveredServer; + private System.Windows.Forms.Label label1; } } diff --git a/ClientServerLib/ClientTest/ClientTest.cs b/ClientServerLib/ClientTest/ClientTest.cs index f8c4a60d..af0be5b5 100644 --- a/ClientServerLib/ClientTest/ClientTest.cs +++ b/ClientServerLib/ClientTest/ClientTest.cs @@ -19,12 +19,15 @@ namespace ClientTest public partial class ClientTest : Form { CClient client; + CDiscover discover; + private bool loggedIn; public ClientTest() { client = new CClient(); loggedIn = false; + discover = new CDiscover(3000, CCommands.BroadcastKeyword); InitializeComponent(); } @@ -32,6 +35,7 @@ namespace ClientTest protected override void OnClosing(CancelEventArgs e) { client.Close(); + discover.Stop(); base.OnClosing(e); } @@ -262,5 +266,22 @@ namespace ClientTest client.SendMessage(CCommands.CreateCommandSendProfile(data, "TestUser", 0), OnResponse); } } + + private void btDiscover_Click(object sender, EventArgs e) + { + tbDiscoveredServer.Text = "Searching for Vocaluxe Server:\r\n"; + discover.Discover(_OnDiscovered); + } + + private void _OnDiscovered(string Address, string HostName) + { + this.Invoke((MethodInvoker)delegate + { + if (Address != "Timeout") + tbDiscoveredServer.Text += "IP = " + Address + "; HostName = " + HostName + "\r\n"; + else + tbDiscoveredServer.Text += "Timeout" + "\r\n"; + }); + } } } diff --git a/Output/ClientServerLib.dll b/Output/ClientServerLib.dll index f59ca7e8..78c652b3 100644 Binary files a/Output/ClientServerLib.dll and b/Output/ClientServerLib.dll differ diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index f82f81b5..78f7d189 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -19,6 +19,7 @@ namespace Vocaluxe.Base.Server static class CVocaluxeServer { private static CServer _Server; + private static CDiscover _Discover; private static Dictionary _Clients; public static CControllerFramework Controller = new CControllerFramework(); @@ -27,18 +28,23 @@ namespace Vocaluxe.Base.Server { _Clients = new Dictionary(); _Server = new CServer(RequestHandler, CConfig.ServerPort, CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON); + _Discover = new CDiscover(CConfig.ServerPort, CCommands.ResponseKeyword); Controller.Init(); } public static void Start() { if (CConfig.ServerActive == EOffOn.TR_CONFIG_ON) + { _Server.Start(); + _Discover.StartBroadcasting(); + } } public static void Close() { _Server.Stop(); + _Discover.Stop(); _Clients = new Dictionary(); }