From 4096a3abebce4d8184794b1985fe0988adbfb418 Mon Sep 17 00:00:00 2001 From: Xathz Date: Wed, 18 Feb 2015 11:55:14 -0500 Subject: [PATCH] Added listen interface option Added an option to force the server to listen on a certain IP address. Only works with the GUI version, not the console. --- SimpleDLNA/FormSettings.Designer.cs | 279 +++++----- SimpleDLNA/FormSettings.cs | 79 ++- SimpleDLNA/Properties/Settings.Designer.cs | 14 +- SimpleDLNA/Properties/Settings.settings | 3 + SimpleDLNA/ServerListViewItem.cs | 2 +- SimpleDLNA/app.config | 3 + UpgradeLog.htm | Bin 0 -> 41534 bytes sdlna.sln | 6 +- sdlna/Program.cs | 4 +- server/Http/HTTPServer.cs | 611 ++++++++++++--------- util/IP.cs | 1 + 11 files changed, 590 insertions(+), 412 deletions(-) create mode 100644 UpgradeLog.htm diff --git a/SimpleDLNA/FormSettings.Designer.cs b/SimpleDLNA/FormSettings.Designer.cs index 13e8a210..7c74915f 100644 --- a/SimpleDLNA/FormSettings.Designer.cs +++ b/SimpleDLNA/FormSettings.Designer.cs @@ -27,137 +27,164 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.numericPort = new System.Windows.Forms.NumericUpDown(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.textCacheFile = new System.Windows.Forms.TextBox(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.buttonBrowseCacheFile = new System.Windows.Forms.Button(); - this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); - this.checkStartMinimized = new System.Windows.Forms.CheckBox(); - this.checkFileLogging = new System.Windows.Forms.CheckBox(); - this.buttonOK = new System.Windows.Forms.Button(); - this.groupBox1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.numericPort)).BeginInit(); - this.groupBox2.SuspendLayout(); - this.SuspendLayout(); - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.numericPort); - this.groupBox1.Location = new System.Drawing.Point(14, 14); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(303, 55); - this.groupBox1.TabIndex = 1; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Port"; - // - // numericPort - // - this.numericPort.DataBindings.Add(new System.Windows.Forms.Binding("Value", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "port", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.numericPort.Location = new System.Drawing.Point(7, 22); - this.numericPort.Maximum = new decimal(new int[] { + this.components = new System.ComponentModel.Container(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.numericPort = new System.Windows.Forms.NumericUpDown(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.textCacheFile = new System.Windows.Forms.TextBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.buttonBrowseCacheFile = new System.Windows.Forms.Button(); + this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.checkStartMinimized = new System.Windows.Forms.CheckBox(); + this.checkFileLogging = new System.Windows.Forms.CheckBox(); + this.buttonOK = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.comboInterfaceList = new System.Windows.Forms.ComboBox(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericPort)).BeginInit(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.numericPort); + this.groupBox1.Location = new System.Drawing.Point(14, 14); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(303, 55); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Port"; + // + // numericPort + // + this.numericPort.DataBindings.Add(new System.Windows.Forms.Binding("Value", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "port", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); + this.numericPort.Location = new System.Drawing.Point(7, 22); + this.numericPort.Maximum = new decimal(new int[] { 65535, 0, 0, 0}); - this.numericPort.Name = "numericPort"; - this.numericPort.Size = new System.Drawing.Size(80, 23); - this.numericPort.TabIndex = 0; - this.toolTip.SetToolTip(this.numericPort, "Port of the http server.\r\nLeave at 0 to automatically have a port selected on sta" + + this.numericPort.Name = "numericPort"; + this.numericPort.Size = new System.Drawing.Size(80, 23); + this.numericPort.TabIndex = 0; + this.toolTip.SetToolTip(this.numericPort, "Port of the http server.\r\nLeave at 0 to automatically have a port selected on sta" + "rtup.\r\n\r\n(Requires restart)"); - this.numericPort.Value = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.port; - // - // textCacheFile - // - this.textCacheFile.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "cache", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.textCacheFile.Location = new System.Drawing.Point(7, 22); - this.textCacheFile.Name = "textCacheFile"; - this.textCacheFile.Size = new System.Drawing.Size(194, 23); - this.textCacheFile.TabIndex = 1; - this.textCacheFile.Text = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.cache; - this.toolTip.SetToolTip(this.textCacheFile, "Location of the cache directory.\r\nLeave blank to use the default location (TEMP)." + + this.numericPort.Value = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.port; + // + // textCacheFile + // + this.textCacheFile.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "cache", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); + this.textCacheFile.Location = new System.Drawing.Point(7, 22); + this.textCacheFile.Name = "textCacheFile"; + this.textCacheFile.Size = new System.Drawing.Size(194, 23); + this.textCacheFile.TabIndex = 1; + this.textCacheFile.Text = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.cache; + this.toolTip.SetToolTip(this.textCacheFile, "Location of the cache directory.\r\nLeave blank to use the default location (TEMP)." + "\r\n\r\n(Requires restart)"); - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.buttonBrowseCacheFile); - this.groupBox2.Controls.Add(this.textCacheFile); - this.groupBox2.Location = new System.Drawing.Point(14, 76); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(303, 55); - this.groupBox2.TabIndex = 2; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "Cache directory"; - // - // buttonBrowseCacheFile - // - this.buttonBrowseCacheFile.Location = new System.Drawing.Point(209, 20); - this.buttonBrowseCacheFile.Name = "buttonBrowseCacheFile"; - this.buttonBrowseCacheFile.Size = new System.Drawing.Size(87, 27); - this.buttonBrowseCacheFile.TabIndex = 0; - this.buttonBrowseCacheFile.Text = "Browse"; - this.buttonBrowseCacheFile.UseVisualStyleBackColor = true; - this.buttonBrowseCacheFile.Click += new System.EventHandler(this.buttonBrowseCacheFile_Click); - // - // checkStartMinimized - // - this.checkStartMinimized.AutoSize = true; - this.checkStartMinimized.Checked = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.startminimized; - this.checkStartMinimized.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "startminimized", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.checkStartMinimized.Location = new System.Drawing.Point(14, 165); - this.checkStartMinimized.Name = "checkStartMinimized"; - this.checkStartMinimized.Size = new System.Drawing.Size(109, 19); - this.checkStartMinimized.TabIndex = 4; - this.checkStartMinimized.Text = "Start minimized"; - this.checkStartMinimized.UseVisualStyleBackColor = true; - // - // checkFileLogging - // - this.checkFileLogging.AutoSize = true; - this.checkFileLogging.Checked = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.filelogging; - this.checkFileLogging.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "filelogging", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); - this.checkFileLogging.Location = new System.Drawing.Point(14, 138); - this.checkFileLogging.Name = "checkFileLogging"; - this.checkFileLogging.Size = new System.Drawing.Size(200, 19); - this.checkFileLogging.TabIndex = 3; - this.checkFileLogging.Text = "Log diagnostic messages to a file"; - this.checkFileLogging.UseVisualStyleBackColor = true; - // - // buttonOK - // - this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonOK.Location = new System.Drawing.Point(230, 192); - this.buttonOK.Name = "buttonOK"; - this.buttonOK.Size = new System.Drawing.Size(87, 27); - this.buttonOK.TabIndex = 0; - this.buttonOK.Text = "OK"; - this.buttonOK.UseVisualStyleBackColor = true; - // - // FormSettings - // - this.AcceptButton = this.buttonOK; - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(331, 232); - this.Controls.Add(this.buttonOK); - this.Controls.Add(this.checkFileLogging); - this.Controls.Add(this.checkStartMinimized); - this.Controls.Add(this.groupBox2); - this.Controls.Add(this.groupBox1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Name = "FormSettings"; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Settings"; - this.groupBox1.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.numericPort)).EndInit(); - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.buttonBrowseCacheFile); + this.groupBox2.Controls.Add(this.textCacheFile); + this.groupBox2.Location = new System.Drawing.Point(14, 140); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(303, 55); + this.groupBox2.TabIndex = 2; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Cache directory"; + // + // buttonBrowseCacheFile + // + this.buttonBrowseCacheFile.Location = new System.Drawing.Point(209, 20); + this.buttonBrowseCacheFile.Name = "buttonBrowseCacheFile"; + this.buttonBrowseCacheFile.Size = new System.Drawing.Size(87, 27); + this.buttonBrowseCacheFile.TabIndex = 0; + this.buttonBrowseCacheFile.Text = "Browse"; + this.buttonBrowseCacheFile.UseVisualStyleBackColor = true; + this.buttonBrowseCacheFile.Click += new System.EventHandler(this.buttonBrowseCacheFile_Click); + // + // checkStartMinimized + // + this.checkStartMinimized.AutoSize = true; + this.checkStartMinimized.Checked = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.startminimized; + this.checkStartMinimized.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "startminimized", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); + this.checkStartMinimized.Location = new System.Drawing.Point(21, 232); + this.checkStartMinimized.Name = "checkStartMinimized"; + this.checkStartMinimized.Size = new System.Drawing.Size(109, 19); + this.checkStartMinimized.TabIndex = 4; + this.checkStartMinimized.Text = "Start minimized"; + this.checkStartMinimized.UseVisualStyleBackColor = true; + // + // checkFileLogging + // + this.checkFileLogging.AutoSize = true; + this.checkFileLogging.Checked = global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.filelogging; + this.checkFileLogging.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::NMaier.SimpleDlna.GUI.Properties.Settings.Default, "filelogging", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); + this.checkFileLogging.Location = new System.Drawing.Point(21, 205); + this.checkFileLogging.Name = "checkFileLogging"; + this.checkFileLogging.Size = new System.Drawing.Size(200, 19); + this.checkFileLogging.TabIndex = 3; + this.checkFileLogging.Text = "Log diagnostic messages to a file"; + this.checkFileLogging.UseVisualStyleBackColor = true; + // + // buttonOK + // + this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOK.Location = new System.Drawing.Point(230, 256); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.Size = new System.Drawing.Size(87, 27); + this.buttonOK.TabIndex = 0; + this.buttonOK.Text = "OK"; + this.buttonOK.UseVisualStyleBackColor = true; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.comboInterfaceList); + this.groupBox3.Location = new System.Drawing.Point(14, 75); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(303, 59); + this.groupBox3.TabIndex = 5; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Listen Interface"; + // + // comboInterfaceList + // + this.comboInterfaceList.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboInterfaceList.FormattingEnabled = true; + this.comboInterfaceList.Location = new System.Drawing.Point(7, 22); + this.comboInterfaceList.Name = "comboInterfaceList"; + this.comboInterfaceList.Size = new System.Drawing.Size(289, 23); + this.comboInterfaceList.TabIndex = 0; + this.comboInterfaceList.SelectedIndexChanged += new System.EventHandler(this.comboInterfaceList_SelectedIndexChanged); + // + // FormSettings + // + this.AcceptButton = this.buttonOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(331, 296); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.buttonOK); + this.Controls.Add(this.checkFileLogging); + this.Controls.Add(this.checkStartMinimized); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Name = "FormSettings"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Settings"; + this.Load += new System.EventHandler(this.FormSettings_Load); + this.groupBox1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.numericPort)).EndInit(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); } @@ -173,5 +200,7 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox checkStartMinimized; private System.Windows.Forms.CheckBox checkFileLogging; private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.ComboBox comboInterfaceList; } } \ No newline at end of file diff --git a/SimpleDLNA/FormSettings.cs b/SimpleDLNA/FormSettings.cs index 00e51fd5..4d9b2972 100644 --- a/SimpleDLNA/FormSettings.cs +++ b/SimpleDLNA/FormSettings.cs @@ -1,21 +1,76 @@ using System; using System.Windows.Forms; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; namespace NMaier.SimpleDlna.GUI { - public partial class FormSettings : NMaier.Windows.Forms.Form - { - public FormSettings() + public partial class FormSettings : NMaier.Windows.Forms.Form { - InitializeComponent(); - Icon = Properties.Resources.preferencesIcon; - } + public FormSettings() + { + InitializeComponent(); + Icon = Properties.Resources.preferencesIcon; + } - private void buttonBrowseCacheFile_Click(object sender, EventArgs e) - { - if (folderBrowserDialog.ShowDialog() == DialogResult.OK) { - textCacheFile.Text = folderBrowserDialog.SelectedPath; - } + private void buttonBrowseCacheFile_Click(object sender, EventArgs e) + { + if (folderBrowserDialog.ShowDialog() == DialogResult.OK) + { + textCacheFile.Text = folderBrowserDialog.SelectedPath; + } + } + + private void buttonOK_Click(object sender, EventArgs e) + { + + } + + private void FormSettings_Load(object sender, EventArgs e) + { + comboInterfaceList.Items.Add("Auto"); + if (global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.listeninterface == "Auto") + { + comboInterfaceList.SelectedItem = ("Auto"); + } + + foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) + { + IPInterfaceProperties ipProps = netInterface.GetIPProperties(); + foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses) + { + if (addr.Address.AddressFamily == AddressFamily.InterNetwork) + { + comboInterfaceList.Items.Add(addr.Address.ToString() + " (" + netInterface.Name + ")"); + } + + if (netInterface.Id == global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.listeninterface) + { + comboInterfaceList.SelectedItem = (addr.Address.ToString() + " (" + netInterface.Name + ")"); + } + } + } + + } + + private void comboInterfaceList_SelectedIndexChanged(object sender, EventArgs e) + { + for (int i = 0; i < comboInterfaceList.Items.Count; i++) + { + foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) + { + if (comboInterfaceList.Text.Contains(netInterface.Name)) + { + global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.listeninterface = (netInterface.Id); + return; + } + } + } + global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.listeninterface = ("Auto"); + + } } - } } diff --git a/SimpleDLNA/Properties/Settings.Designer.cs b/SimpleDLNA/Properties/Settings.Designer.cs index db06330a..137bfd1d 100644 --- a/SimpleDLNA/Properties/Settings.Designer.cs +++ b/SimpleDLNA/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18444 +// Runtime Version:4.0.30319.34209 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -82,5 +82,17 @@ public bool startminimized { this["startminimized"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Auto")] + public string listeninterface { + get { + return ((string)(this["listeninterface"])); + } + set { + this["listeninterface"] = value; + } + } } } diff --git a/SimpleDLNA/Properties/Settings.settings b/SimpleDLNA/Properties/Settings.settings index 8a76ab1f..e9fa13d4 100644 --- a/SimpleDLNA/Properties/Settings.settings +++ b/SimpleDLNA/Properties/Settings.settings @@ -17,5 +17,8 @@ False + + Auto + \ No newline at end of file diff --git a/SimpleDLNA/ServerListViewItem.cs b/SimpleDLNA/ServerListViewItem.cs index 4fcc465e..c0499008 100644 --- a/SimpleDLNA/ServerListViewItem.cs +++ b/SimpleDLNA/ServerListViewItem.cs @@ -124,7 +124,7 @@ where d.Exists authorizer.AddMethod(new UserAgentAuthorizer(Description.UserAgents)); } fileServer.Authorizer = authorizer; - server.RegisterMediaServer(fileServer); + server.RegisterMediaServer(fileServer, global::NMaier.SimpleDlna.GUI.Properties.Settings.Default.listeninterface); state = State.Running; var elapsed = DateTime.Now - start; LogManager.GetLogger("State").Logger.Log( diff --git a/SimpleDLNA/app.config b/SimpleDLNA/app.config index a3471e29..53c487f5 100644 --- a/SimpleDLNA/app.config +++ b/SimpleDLNA/app.config @@ -22,6 +22,9 @@ False + + Auto + \ No newline at end of file diff --git a/UpgradeLog.htm b/UpgradeLog.htm new file mode 100644 index 0000000000000000000000000000000000000000..bca6dcacbe52a99af9316034140f4f444af19b39 GIT binary patch literal 41534 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 clients = - new ConcurrentDictionary(); - - private readonly ConcurrentDictionary prefixes = - new ConcurrentDictionary(); - - private readonly ConcurrentDictionary> devicesForServers = - new ConcurrentDictionary>(); - - private readonly ConcurrentDictionary servers = - new ConcurrentDictionary(); + public sealed class HttpServer : Logging, IDisposable + { + private readonly ConcurrentDictionary clients = + new ConcurrentDictionary(); - public static readonly string Signature = GenerateServerSignature(); + private readonly ConcurrentDictionary prefixes = + new ConcurrentDictionary(); - private readonly Timer timeouter = new Timer(10 * 1000); + private readonly ConcurrentDictionary> devicesForServers = + new ConcurrentDictionary>(); - private readonly TcpListener listener = null; + private readonly ConcurrentDictionary servers = + new ConcurrentDictionary(); - private readonly SsdpHandler ssdpServer; + public static readonly string Signature = GenerateServerSignature(); - public HttpServer() - : this(port: 0) - { - } + private readonly Timer timeouter = new Timer(10 * 1000); - public HttpServer(int port) - { - prefixes.TryAdd( - "/favicon.ico", - new StaticHandler( - new ResourceResponse(HttpCode.Ok, "image/icon", "favicon")) - ); - prefixes.TryAdd( - "/static/browse.css", - new StaticHandler( - new ResourceResponse(HttpCode.Ok, "text/css", "browse_css")) - ); - RegisterHandler(new IconHandler()); - - listener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); - listener.Server.Ttl = 32; - listener.Server.UseOnlyOverlappedIO = true; - listener.Start(); - - RealPort = (listener.LocalEndpoint as IPEndPoint).Port; - - NoticeFormat( - "Running HTTP Server: {0} on port {1}", Signature, RealPort); - ssdpServer = new SsdpHandler(); - - timeouter.Elapsed += TimeouterCallback; - timeouter.Enabled = true; - - Accept(); - } + private readonly TcpListener listener = null; - public event EventHandler OnAuthorizeClient; + private readonly SsdpHandler ssdpServer; - public Dictionary MediaMounts - { - get - { - var rv = new Dictionary(); - foreach (var m in servers) { - rv[m.Value.Prefix] = m.Value.FriendlyName; + public HttpServer() + : this(port: 0) + { } - return rv; - } - } - - public int RealPort { get; private set; } - private void Accept() - { - try { - if (!listener.Server.IsBound) { - return; + public HttpServer(int port) + { + prefixes.TryAdd( + "/favicon.ico", + new StaticHandler( + new ResourceResponse(HttpCode.Ok, "image/icon", "favicon")) + ); + prefixes.TryAdd( + "/static/browse.css", + new StaticHandler( + new ResourceResponse(HttpCode.Ok, "text/css", "browse_css")) + ); + RegisterHandler(new IconHandler()); + + listener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); + listener.Server.Ttl = 32; + listener.Server.UseOnlyOverlappedIO = true; + listener.Start(); + + RealPort = (listener.LocalEndpoint as IPEndPoint).Port; + + NoticeFormat( + "Running HTTP Server: {0} on port {1}", Signature, RealPort); + ssdpServer = new SsdpHandler(); + + timeouter.Elapsed += TimeouterCallback; + timeouter.Enabled = true; + + Accept(); } - listener.BeginAcceptTcpClient(AcceptCallback, null); - } - catch (ObjectDisposedException) { - } - catch (Exception ex) { - Fatal("Failed to accept", ex); - } - } - private void AcceptCallback(IAsyncResult result) - { - try { - var tcpclient = listener.EndAcceptTcpClient(result); - var client = new HttpClient(this, tcpclient); - try { - clients.AddOrUpdate(client, DateTime.Now, (k, v) => - { - return DateTime.Now; - }); - DebugFormat("Accepted client {0}", client); - client.Start(); - } - catch (Exception) { - client.Dispose(); - throw; + public event EventHandler OnAuthorizeClient; + + public Dictionary MediaMounts + { + get + { + var rv = new Dictionary(); + foreach (var m in servers) + { + rv[m.Value.Prefix] = m.Value.FriendlyName; + } + return rv; + } } - } - catch (ObjectDisposedException) { - } - catch (Exception ex) { - Error("Failed to accept a client", ex); - } - finally { - Accept(); - } - } - private static string GenerateServerSignature() - { - var os = Environment.OSVersion; - var pstring = os.Platform.ToString(); - switch (os.Platform) { - case PlatformID.Win32NT: - case PlatformID.Win32S: - case PlatformID.Win32Windows: - pstring = "WIN"; - break; - default: - break; - } - return String.Format( - "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 sdlna/{4}.{5}", - pstring, - IntPtr.Size * 8, - os.Version.Major, - os.Version.Minor, - Assembly.GetExecutingAssembly().GetName().Version.Major, - Assembly.GetExecutingAssembly().GetName().Version.Minor - ); - } - - private void TimeouterCallback(object sender, ElapsedEventArgs e) - { - foreach (var c in clients.ToList()) { - if (c.Key.IsATimeout) { - DebugFormat("Collected timeout client {0}", c); - c.Key.Close(); + public int RealPort { get; private set; } + + private void Accept() + { + try + { + if (!listener.Server.IsBound) + { + return; + } + listener.BeginAcceptTcpClient(AcceptCallback, null); + } + catch (ObjectDisposedException) + { + } + catch (Exception ex) + { + Fatal("Failed to accept", ex); + } } - } - } - internal bool AuthorizeClient(HttpClient client) - { - if (OnAuthorizeClient == null) { - return true; - } - if (IPAddress.IsLoopback(client.RemoteEndpoint.Address)) { - return true; - } - var e = new HttpAuthorizationEventArgs( - client.Headers, client.RemoteEndpoint); - OnAuthorizeClient(this, e); - return !e.Cancel; - } - - internal IPrefixHandler FindHandler(string prefix) - { - if (string.IsNullOrEmpty(prefix)) { - throw new ArgumentNullException("prefix"); - } + private void AcceptCallback(IAsyncResult result) + { + try + { + var tcpclient = listener.EndAcceptTcpClient(result); + var client = new HttpClient(this, tcpclient); + try + { + clients.AddOrUpdate(client, DateTime.Now, (k, v) => + { + return DateTime.Now; + }); + DebugFormat("Accepted client {0}", client); + client.Start(); + } + catch (Exception) + { + client.Dispose(); + throw; + } + } + catch (ObjectDisposedException) + { + } + catch (Exception ex) + { + Error("Failed to accept a client", ex); + } + finally + { + Accept(); + } + } - if (prefix == "/") { - return new IndexHandler(this); - } + private static string GenerateServerSignature() + { + var os = Environment.OSVersion; + var pstring = os.Platform.ToString(); + switch (os.Platform) + { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + pstring = "WIN"; + break; + default: + break; + } + return String.Format( + "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 sdlna/{4}.{5}", + pstring, + IntPtr.Size * 8, + os.Version.Major, + os.Version.Minor, + Assembly.GetExecutingAssembly().GetName().Version.Major, + Assembly.GetExecutingAssembly().GetName().Version.Minor + ); + } - foreach (var s in prefixes.Keys) { - if (prefix.StartsWith(s, StringComparison.Ordinal)) { - return prefixes[s]; + private void TimeouterCallback(object sender, ElapsedEventArgs e) + { + foreach (var c in clients.ToList()) + { + if (c.Key.IsATimeout) + { + DebugFormat("Collected timeout client {0}", c); + c.Key.Close(); + } + } } - } - return null; - } - internal void RegisterHandler(IPrefixHandler handler) - { - if (handler == null) { - throw new ArgumentNullException("handler"); - } - var prefix = handler.Prefix; - if (!prefix.StartsWith("/", StringComparison.Ordinal)) { - throw new ArgumentException("Invalid prefix; must start with /"); - } - if (!prefix.EndsWith("/", StringComparison.Ordinal)) { - throw new ArgumentException("Invalid prefix; must end with /"); - } - if (FindHandler(prefix) != null) { - throw new ArgumentException("Invalid prefix; already taken"); - } - if (!prefixes.TryAdd(prefix, handler)) { - throw new ArgumentException("Invalid preifx; already taken"); - } - DebugFormat("Registered Handler for {0}", prefix); - } + internal bool AuthorizeClient(HttpClient client) + { + if (OnAuthorizeClient == null) + { + return true; + } + if (IPAddress.IsLoopback(client.RemoteEndpoint.Address)) + { + return true; + } + var e = new HttpAuthorizationEventArgs( + client.Headers, client.RemoteEndpoint); + OnAuthorizeClient(this, e); + return !e.Cancel; + } - internal void RemoveClient(HttpClient client) - { - DateTime ignored; - clients.TryRemove(client, out ignored); - } + internal IPrefixHandler FindHandler(string prefix) + { + if (string.IsNullOrEmpty(prefix)) + { + throw new ArgumentNullException("prefix"); + } + + if (prefix == "/") + { + return new IndexHandler(this); + } + + foreach (var s in prefixes.Keys) + { + if (prefix.StartsWith(s, StringComparison.Ordinal)) + { + return prefixes[s]; + } + } + return null; + } - internal void UnregisterHandler(IPrefixHandler handler) - { - IPrefixHandler ignored; - if (prefixes.TryRemove(handler.Prefix, out ignored)) { - DebugFormat("Unregistered Handler for {0}", handler.Prefix); - } - } + internal void RegisterHandler(IPrefixHandler handler) + { + if (handler == null) + { + throw new ArgumentNullException("handler"); + } + var prefix = handler.Prefix; + if (!prefix.StartsWith("/", StringComparison.Ordinal)) + { + throw new ArgumentException("Invalid prefix; must start with /"); + } + if (!prefix.EndsWith("/", StringComparison.Ordinal)) + { + throw new ArgumentException("Invalid prefix; must end with /"); + } + if (FindHandler(prefix) != null) + { + throw new ArgumentException("Invalid prefix; already taken"); + } + if (!prefixes.TryAdd(prefix, handler)) + { + throw new ArgumentException("Invalid preifx; already taken"); + } + DebugFormat("Registered Handler for {0}", prefix); + } - public void Dispose() - { - Debug("Disposing HTTP"); - timeouter.Enabled = false; - foreach (var s in servers.Values.ToList()) { - UnregisterMediaServer(s); - } - ssdpServer.Dispose(); - timeouter.Dispose(); - listener.Stop(); - foreach (var c in clients.ToList()) { - c.Key.Dispose(); - } - clients.Clear(); - } + internal void RemoveClient(HttpClient client) + { + DateTime ignored; + clients.TryRemove(client, out ignored); + } - public void RegisterMediaServer(IMediaServer server) - { - if (server == null) { - throw new ArgumentNullException("server"); - } - var guid = server.Uuid; - if (servers.ContainsKey(guid)) { - throw new ArgumentException("Attempting to register more than once"); - } - - var end = listener.LocalEndpoint as IPEndPoint; - var mount = new MediaMount(server); - servers[guid] = mount; - RegisterHandler(mount); - - foreach (var address in IP.ExternalIPAddresses) { - DebugFormat("Registering device for {0}", address); - var deviceGuid = Guid.NewGuid(); - var list = devicesForServers.GetOrAdd(guid, new List()); - lock (list) { - list.Add(deviceGuid); + internal void UnregisterHandler(IPrefixHandler handler) + { + IPrefixHandler ignored; + if (prefixes.TryRemove(handler.Prefix, out ignored)) + { + DebugFormat("Unregistered Handler for {0}", handler.Prefix); + } } - mount.AddDeviceGuid(deviceGuid, address); - var uri = new Uri(string.Format( - "http://{0}:{1}{2}", - address, - end.Port, - mount.DescriptorURI - )); - ssdpServer.RegisterNotification(deviceGuid, uri, address); - NoticeFormat("New mount at: {0}", uri); - } - } - public void UnregisterMediaServer(IMediaServer server) - { - if (server == null) { - throw new ArgumentNullException("server"); - } - MediaMount mount; - if (!servers.TryGetValue(server.Uuid, out mount)) { - return; - } - - List list; - if (devicesForServers.TryGetValue(server.Uuid, out list)) { - lock (list) { - foreach (var deviceGuid in list) { - ssdpServer.UnregisterNotification(deviceGuid); - } + public void Dispose() + { + Debug("Disposing HTTP"); + timeouter.Enabled = false; + foreach (var s in servers.Values.ToList()) + { + UnregisterMediaServer(s); + } + ssdpServer.Dispose(); + timeouter.Dispose(); + listener.Stop(); + foreach (var c in clients.ToList()) + { + c.Key.Dispose(); + } + clients.Clear(); } - devicesForServers.TryRemove(server.Uuid, out list); - } - UnregisterHandler(mount); + public void RegisterMediaServer(IMediaServer server, String listenID) + { + if (server == null) + { + throw new ArgumentNullException("server"); + } + var guid = server.Uuid; + if (servers.ContainsKey(guid)) + { + throw new ArgumentException("Attempting to register more than once"); + } + var end = listener.LocalEndpoint as IPEndPoint; + var mount = new MediaMount(server); + servers[guid] = mount; + RegisterHandler(mount); + + IPAddress overrideIP = null; + foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) + { + if (listenID == "Auto") + { + + } + else if (listenID == netInterface.Id) + { + IPInterfaceProperties ipProps = netInterface.GetIPProperties(); + foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses) + { + if (addr.Address.AddressFamily == AddressFamily.InterNetwork) + { + overrideIP = addr.Address; + } + } + } + else + { + + } + } + + foreach (var address in IP.ExternalIPAddresses) + { + DebugFormat("Registering device for {0}", address); + var deviceGuid = Guid.NewGuid(); + var list = devicesForServers.GetOrAdd(guid, new List()); + lock (list) + { + list.Add(deviceGuid); + } + + if (overrideIP == null) + { + mount.AddDeviceGuid(deviceGuid, address); + var uri = new Uri(string.Format( + "http://{0}:{1}{2}", + address, + end.Port, + mount.DescriptorURI + )); + ssdpServer.RegisterNotification(deviceGuid, uri, address); + NoticeFormat("New mount at: {0}", uri); + } + else + { + mount.AddDeviceGuid(deviceGuid, overrideIP); + var uri = new Uri(string.Format( + "http://{0}:{1}{2}", + overrideIP, + end.Port, + mount.DescriptorURI + )); + ssdpServer.RegisterNotification(deviceGuid, uri, address); + NoticeFormat("New mount at: {0}", uri); + } + + } + } - MediaMount ignored; - if (servers.TryRemove(server.Uuid, out ignored)) { - InfoFormat("Unregistered Media Server {0}", server.Uuid); - } + public void UnregisterMediaServer(IMediaServer server) + { + if (server == null) + { + throw new ArgumentNullException("server"); + } + MediaMount mount; + if (!servers.TryGetValue(server.Uuid, out mount)) + { + return; + } + + List list; + if (devicesForServers.TryGetValue(server.Uuid, out list)) + { + lock (list) + { + foreach (var deviceGuid in list) + { + ssdpServer.UnregisterNotification(deviceGuid); + } + } + devicesForServers.TryRemove(server.Uuid, out list); + } + + UnregisterHandler(mount); + + MediaMount ignored; + if (servers.TryRemove(server.Uuid, out ignored)) + { + InfoFormat("Unregistered Media Server {0}", server.Uuid); + } + } } - } } diff --git a/util/IP.cs b/util/IP.cs index e8abb665..63e6451f 100644 --- a/util/IP.cs +++ b/util/IP.cs @@ -49,6 +49,7 @@ public static IEnumerable ExternalIPAddresses private static IEnumerable GetIPsDefault() { var returned = false; + foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces()) { var props = adapter.GetIPProperties(); var gateways = from ga in props.GatewayAddresses