summaryrefslogtreecommitdiffstats
path: root/win/CS/HandBrakeWPF/Services/PortService.cs
blob: 1a10db29850fbd9b3707731887b919a8c490dc78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PortService.cs" company="HandBrake Project (http://handbrake.fr)">
//   This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
// </copyright>
// <summary>
//   Defines the PortService type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace HandBrakeWPF.Services
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.NetworkInformation;

    using HandBrakeWPF.Services.Interfaces;

    public class PortService : IPortService
    {
        private readonly object lockObject = new object();
        private List<int> usedPorts = new List<int>();

        public PortService()
        {
        }

        public void FreePort(int port)
        {
            lock (this.lockObject)
            {
                this.usedPorts.Remove(port);
            }
        }

        public int GetOpenPort(int startPort)
        {
            lock (this.lockObject)
            {
                int foundPort = FindUnusedPort(startPort);

                // If we find a port that's free on the system, but we've already allocated, try find another.
                while (this.usedPorts.Contains(foundPort))
                {
                    int nextPort = foundPort + 1;
                    foundPort = FindUnusedPort(nextPort);
                }

                // Record we've used this port.
                this.usedPorts.Add(foundPort);

                return foundPort;
            }
        }

        private int FindUnusedPort(int startPort)
        {
            if (startPort == 0)
            {
                startPort = 8037;
            }

            int portStartIndex = startPort;

            IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
            IPEndPoint[] tcpEndPoints = properties.GetActiveTcpListeners();

            List<int> usedPorts = tcpEndPoints.Select(p => p.Port).ToList<int>();
            int unusedPort = 0;

            unusedPort = Enumerable.Range(portStartIndex, 99).FirstOrDefault(p => !usedPorts.Contains(p));

            return unusedPort;
        }
    }
}