markus / Rhino.Licensing / Discovery / DiscoveryHost.cs @ 42d49521
이력 | 보기 | 이력해설 | 다운로드 (4.42 KB)
1 | 42d49521 | taeseongkim | using System; |
---|---|---|---|
2 | using System.IO; |
||
3 | using System.Net; |
||
4 | using System.Net.NetworkInformation; |
||
5 | using System.Net.Sockets; |
||
6 | using System.Linq; |
||
7 | //using log4net; |
||
8 | |||
9 | namespace Rhino.Licensing.Discovery |
||
10 | { |
||
11 | ///<summary> |
||
12 | /// Listen to precense notifications |
||
13 | ///</summary> |
||
14 | public class DiscoveryHost : IDisposable |
||
15 | { |
||
16 | private Socket socket; |
||
17 | private readonly byte[] buffer = new byte[1024*4]; |
||
18 | private const string AllHostsMulticastIP = "224.0.0.1"; |
||
19 | private const int DiscoveryPort = 12391; |
||
20 | //private static readonly ILog Log = LogManager.GetLogger(typeof(DiscoveryHost)); |
||
21 | |||
22 | ///<summary> |
||
23 | /// Starts listening to network notifications |
||
24 | ///</summary> |
||
25 | public void Start() |
||
26 | { |
||
27 | socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); |
||
28 | socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); |
||
29 | BindUpAdaptersToMulticast(); |
||
30 | socket.Bind(new IPEndPoint(IPAddress.Any, DiscoveryPort)); |
||
31 | StartListening(); |
||
32 | } |
||
33 | |||
34 | private void BindUpAdaptersToMulticast() |
||
35 | { |
||
36 | NetworkInterface.GetAllNetworkInterfaces() |
||
37 | .Where(card => card.OperationalStatus == OperationalStatus.Up) |
||
38 | .ToList() |
||
39 | .ForEach(SetSocketOptionsForNic); |
||
40 | } |
||
41 | |||
42 | private void SetSocketOptionsForNic(NetworkInterface nic) |
||
43 | { |
||
44 | nic.GetIPProperties() |
||
45 | .UnicastAddresses |
||
46 | .Where(unicast => unicast.Address.AddressFamily == AddressFamily.InterNetwork) |
||
47 | .ToList() |
||
48 | .ForEach(SafelySetSocketOptionsForAddress); |
||
49 | } |
||
50 | |||
51 | private void SafelySetSocketOptionsForAddress(UnicastIPAddressInformation address) |
||
52 | { |
||
53 | try |
||
54 | { |
||
55 | socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, |
||
56 | new MulticastOption(IPAddress.Parse(AllHostsMulticastIP), address.Address)); |
||
57 | } |
||
58 | catch (SocketException ex) |
||
59 | { |
||
60 | throw new Exception($"Setting socket options failed for address: {address?.Address}", ex); |
||
61 | //Log.Warn($"Setting socket options failed for address: {address?.Address}", ex); |
||
62 | } |
||
63 | } |
||
64 | |||
65 | private void StartListening() |
||
66 | { |
||
67 | var socketAsyncEventArgs = new SocketAsyncEventArgs |
||
68 | { |
||
69 | RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0), |
||
70 | }; |
||
71 | socketAsyncEventArgs.Completed += Completed; |
||
72 | socketAsyncEventArgs.SetBuffer(buffer, 0, buffer.Length); |
||
73 | |||
74 | bool startedAsync; |
||
75 | try |
||
76 | { |
||
77 | startedAsync = socket.ReceiveFromAsync(socketAsyncEventArgs); |
||
78 | } |
||
79 | catch (Exception) |
||
80 | { |
||
81 | return; |
||
82 | } |
||
83 | if (startedAsync == false) |
||
84 | Completed(this, socketAsyncEventArgs); |
||
85 | } |
||
86 | |||
87 | private void Completed(object sender, SocketAsyncEventArgs socketAsyncEventArgs) |
||
88 | { |
||
89 | using (socketAsyncEventArgs) |
||
90 | { |
||
91 | try |
||
92 | { |
||
93 | using (var stream = new MemoryStream(socketAsyncEventArgs.Buffer, 0, socketAsyncEventArgs.BytesTransferred)) |
||
94 | using (var streamReader = new StreamReader(stream)) |
||
95 | { |
||
96 | var senderId = streamReader.ReadLine(); |
||
97 | var userId = streamReader.ReadLine(); |
||
98 | var clientDiscovered = new ClientDiscoveredEventArgs |
||
99 | { |
||
100 | MachineName = streamReader.ReadLine(), |
||
101 | UserName = streamReader.ReadLine() |
||
102 | }; |
||
103 | |||
104 | Guid result; |
||
105 | if (Guid.TryParse(userId, out result)) |
||
106 | { |
||
107 | clientDiscovered.UserId = result; |
||
108 | } |
||
109 | |||
110 | if (Guid.TryParse(senderId, out result)) |
||
111 | { |
||
112 | clientDiscovered.SenderId = result; |
||
113 | InvokeClientDiscovered(clientDiscovered); |
||
114 | } |
||
115 | } |
||
116 | } |
||
117 | catch |
||
118 | { |
||
119 | } |
||
120 | StartListening(); |
||
121 | } |
||
122 | } |
||
123 | |||
124 | ///<summary> |
||
125 | /// Notify when a client is discovered |
||
126 | ///</summary> |
||
127 | public event EventHandler<ClientDiscoveredEventArgs> ClientDiscovered; |
||
128 | |||
129 | private void InvokeClientDiscovered(ClientDiscoveredEventArgs e) |
||
130 | { |
||
131 | EventHandler<ClientDiscoveredEventArgs> handler = ClientDiscovered; |
||
132 | if (handler != null) handler(this, e); |
||
133 | } |
||
134 | |||
135 | /// <summary> |
||
136 | /// Notification raised when a client is discovered |
||
137 | /// </summary> |
||
138 | public class ClientDiscoveredEventArgs : EventArgs |
||
139 | { |
||
140 | /// <summary> |
||
141 | /// The client's license id |
||
142 | /// </summary> |
||
143 | public Guid UserId { get; set; } |
||
144 | |||
145 | /// <summary> |
||
146 | /// The client machine name |
||
147 | /// </summary> |
||
148 | public string MachineName { get; set; } |
||
149 | |||
150 | /// <summary> |
||
151 | /// The client user name |
||
152 | /// </summary> |
||
153 | public string UserName { get; set; } |
||
154 | |||
155 | /// <summary> |
||
156 | /// The id of the sender |
||
157 | /// </summary> |
||
158 | public Guid SenderId { get; set; } |
||
159 | |||
160 | } |
||
161 | |||
162 | /// <summary> |
||
163 | /// Disposes of the object |
||
164 | /// </summary> |
||
165 | public void Dispose() |
||
166 | { |
||
167 | if (socket != null) |
||
168 | socket.Dispose(); |
||
169 | } |
||
170 | } |
||
171 | } |