markus / Rhino.Licensing / Discovery / DiscoveryHost.cs @ 42d49521
이력 | 보기 | 이력해설 | 다운로드 (4.42 KB)
1 |
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 |
} |