Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
NameResolutionPal.cs
Go to the documentation of this file.
7
8namespace System.Net;
9
10internal static class NameResolutionPal
11{
13 {
15
17
19
21
22 private object _result;
23
24 public string HostName { get; }
25
26 public bool JustAddresses { get; }
27
28 public Task Task
29 {
30 get
31 {
32 if (!JustAddresses)
33 {
35 }
36 return IPAddressArrayBuilder.Task;
37 }
38 }
39
40 public unsafe GetAddrInfoExState(GetAddrInfoExContext* context, string hostName, bool justAddresses)
41 {
42 _cancellationContext = context;
43 HostName = hostName;
44 JustAddresses = justAddresses;
45 if (justAddresses)
46 {
48 _ = IPAddressArrayBuilder.Task;
49 }
50 else
51 {
53 _ = IPHostEntryBuilder.Task;
54 }
55 }
56
58 {
59 if (!cancellationToken.CanBeCanceled)
60 {
61 return;
62 }
63 lock (this)
64 {
65 if (_cancellationContext == null)
66 {
67 return;
68 }
69 _cancellationRegistration = cancellationToken.UnsafeRegister(delegate(object o)
70 {
71 GetAddrInfoExState getAddrInfoExState = (GetAddrInfoExState)o;
72 int num = 0;
73 lock (getAddrInfoExState)
74 {
75 GetAddrInfoExContext* cancellationContext = getAddrInfoExState._cancellationContext;
76 if (cancellationContext != null)
77 {
78 num = global::Interop.Winsock.GetAddrInfoExCancel(&cancellationContext->CancelHandle);
79 }
80 }
81 if (num != 0 && num != 6 && System.Net.NetEventSource.Log.IsEnabled())
82 {
83 System.Net.NetEventSource.Info(getAddrInfoExState, $"GetAddrInfoExCancel returned error {num}", "RegisterForCancellation");
84 }
85 }, this);
86 }
87 }
88
98
99 public void SetResult(object result)
100 {
101 _result = result;
102 ThreadPool.UnsafeQueueUserWorkItem(this, preferLocal: false);
103 }
104
106 {
107 if (JustAddresses)
108 {
110 {
111 IPAddressArrayBuilder.SetException(exception);
112 }
113 else
114 {
116 }
117 }
118 else if (_result is Exception exception2)
119 {
120 IPHostEntryBuilder.SetException(exception2);
121 }
122 else
123 {
125 }
126 }
127
129 {
130 return GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Normal));
131 }
132
134 {
137 gCHandle.Free();
138 return result;
139 }
140 }
141
142 private struct GetAddrInfoExContext
143 {
145
146 public unsafe global::Interop.Winsock.AddressInfoEx* Result;
147
149
151
152 public unsafe static GetAddrInfoExContext* AllocateContext()
153 {
155 *ptr = default(GetAddrInfoExContext);
156 return ptr;
157 }
158
159 public unsafe static void FreeContext(GetAddrInfoExContext* context)
160 {
161 if (context->Result != null)
162 {
163 global::Interop.Winsock.FreeAddrInfoExW(context->Result);
164 }
165 Marshal.FreeHGlobal((IntPtr)context);
166 }
167 }
168
169 private static volatile int s_getAddrInfoExSupported;
170
171 public static bool SupportsGetAddrInfoAsync
172 {
173 get
174 {
175 int num = s_getAddrInfoExSupported;
176 if (num == 0)
177 {
178 Initialize();
180 }
181 return num == 1;
182 static void Initialize()
183 {
184 global::Interop.Winsock.EnsureInitialized();
185 IntPtr handle = global::Interop.Kernel32.LoadLibraryEx("ws2_32.dll", IntPtr.Zero, 2048);
186 IntPtr address;
187 bool flag = NativeLibrary.TryGetExport(handle, "GetAddrInfoExCancel", out address);
189 }
190 }
191 }
192
193 public unsafe static SocketError TryGetAddrInfo(string name, bool justAddresses, AddressFamily addressFamily, out string hostName, out string[] aliases, out IPAddress[] addresses, out int nativeErrorCode)
194 {
195 global::Interop.Winsock.EnsureInitialized();
196 aliases = Array.Empty<string>();
197 global::Interop.Winsock.AddressInfo addressInfo = default(global::Interop.Winsock.AddressInfo);
198 addressInfo.ai_family = addressFamily;
199 global::Interop.Winsock.AddressInfo addressInfo2 = addressInfo;
200 if (!justAddresses)
201 {
202 addressInfo2.ai_flags = AddressInfoHints.AI_CANONNAME;
203 }
204 global::Interop.Winsock.AddressInfo* ptr = null;
205 try
206 {
207 SocketError addrInfoW = (SocketError)global::Interop.Winsock.GetAddrInfoW(name, null, &addressInfo2, &ptr);
208 if (addrInfoW != 0)
209 {
210 nativeErrorCode = (int)addrInfoW;
211 hostName = name;
212 addresses = Array.Empty<IPAddress>();
213 return addrInfoW;
214 }
215 addresses = ParseAddressInfo(ptr, justAddresses, out hostName);
216 nativeErrorCode = 0;
217 return SocketError.Success;
218 }
219 finally
220 {
221 if (ptr != null)
222 {
223 global::Interop.Winsock.FreeAddrInfoW(ptr);
224 }
225 }
226 }
227
228 public unsafe static string TryGetNameInfo(IPAddress addr, out SocketError errorCode, out int nativeErrorCode)
229 {
230 global::Interop.Winsock.EnsureInitialized();
231 SocketAddress socketAddress = new IPEndPoint(addr, 0).Serialize();
232 Span<byte> span = ((socketAddress.Size > 64) ? ((Span<byte>)new byte[socketAddress.Size]) : stackalloc byte[64]);
233 Span<byte> span2 = span;
234 for (int i = 0; i < socketAddress.Size; i++)
235 {
236 span2[i] = socketAddress[i];
237 }
238 char* ptr = stackalloc char[1025];
239 fixed (byte* pSockaddr = span2)
240 {
241 errorCode = global::Interop.Winsock.GetNameInfoW(pSockaddr, socketAddress.Size, ptr, 1025, null, 0, 4);
242 }
243 if (errorCode == SocketError.Success)
244 {
245 nativeErrorCode = 0;
246 return new string(ptr);
247 }
248 nativeErrorCode = (int)errorCode;
249 return null;
250 }
251
252 public unsafe static string GetHostName()
253 {
254 global::Interop.Winsock.EnsureInitialized();
255 byte* ptr = stackalloc byte[256];
256 SocketError socketError = global::Interop.Winsock.gethostname(ptr, 256);
257 if (socketError != 0)
258 {
259 if (System.Net.NetEventSource.Log.IsEnabled())
260 {
261 System.Net.NetEventSource.Error(null, $"GetHostName failed with {socketError}", "GetHostName");
262 }
263 throw new SocketException();
264 }
265 return new string((sbyte*)ptr);
266 }
267
268 public unsafe static Task GetAddrInfoAsync(string hostName, bool justAddresses, AddressFamily family, CancellationToken cancellationToken)
269 {
270 global::Interop.Winsock.EnsureInitialized();
272 GetAddrInfoExState getAddrInfoExState;
273 try
274 {
275 getAddrInfoExState = new GetAddrInfoExState(ptr, hostName, justAddresses);
276 ptr->QueryStateHandle = getAddrInfoExState.CreateHandle();
277 }
278 catch
279 {
281 throw;
282 }
283 global::Interop.Winsock.AddressInfoEx addressInfoEx = default(global::Interop.Winsock.AddressInfoEx);
284 addressInfoEx.ai_family = family;
285 global::Interop.Winsock.AddressInfoEx addressInfoEx2 = addressInfoEx;
286 if (!justAddresses)
287 {
288 addressInfoEx2.ai_flags = AddressInfoHints.AI_CANONNAME;
289 }
290 SocketError addrInfoExW = (SocketError)global::Interop.Winsock.GetAddrInfoExW(hostName, null, 0, IntPtr.Zero, &addressInfoEx2, &ptr->Result, IntPtr.Zero, &ptr->Overlapped, (delegate* unmanaged<int, int, NativeOverlapped*, void>)(delegate*<int, int, NativeOverlapped*, void>)(&GetAddressInfoExCallback), &ptr->CancelHandle);
291 switch (addrInfoExW)
292 {
293 case SocketError.IOPending:
294 getAddrInfoExState.RegisterForCancellation(cancellationToken);
295 break;
296 case (SocketError)10111:
297 case SocketError.TryAgain:
299 return null;
300 default:
301 ProcessResult(addrInfoExW, ptr);
302 break;
303 }
304 return getAddrInfoExState.Task;
305 }
306
307 [UnmanagedCallersOnly]
308 private unsafe static void GetAddressInfoExCallback(int error, int bytes, NativeOverlapped* overlapped)
309 {
310 ProcessResult((SocketError)error, (GetAddrInfoExContext*)overlapped);
311 }
312
313 private unsafe static void ProcessResult(SocketError errorCode, GetAddrInfoExContext* context)
314 {
315 try
316 {
318 CancellationToken token = getAddrInfoExState.UnregisterAndGetCancellationToken();
319 if (errorCode == SocketError.Success)
320 {
321 string hostName;
322 IPAddress[] array = ParseAddressInfoEx(context->Result, getAddrInfoExState.JustAddresses, out hostName);
323 getAddrInfoExState.SetResult(getAddrInfoExState.JustAddresses ? ((object)array) : ((object)new IPHostEntry
324 {
325 HostName = (hostName ?? getAddrInfoExState.HostName),
326 Aliases = Array.Empty<string>(),
327 AddressList = array
328 }));
329 }
330 else
331 {
332 Exception currentStackTrace = ((errorCode == (SocketError)10111 && token.IsCancellationRequested) ? ((Exception)new OperationCanceledException(token)) : ((Exception)(object)new SocketException((int)errorCode)));
333 getAddrInfoExState.SetResult(ExceptionDispatchInfo.SetCurrentStackTrace(currentStackTrace));
334 }
335 }
336 finally
337 {
339 }
340 }
341
342 private unsafe static IPAddress[] ParseAddressInfo(global::Interop.Winsock.AddressInfo* addressInfoPtr, bool justAddresses, out string hostName)
343 {
344 int num = 0;
345 for (global::Interop.Winsock.AddressInfo* ptr = addressInfoPtr; ptr != null; ptr = ptr->ai_next)
346 {
347 int num2 = (int)ptr->ai_addrlen;
348 if (ptr->ai_family == AddressFamily.InterNetwork)
349 {
350 if (num2 == 16)
351 {
352 num++;
353 }
354 }
355 else if (SocketProtocolSupportPal.OSSupportsIPv6 && ptr->ai_family == AddressFamily.InterNetworkV6 && num2 == 28)
356 {
357 num++;
358 }
359 }
360 IPAddress[] array = new IPAddress[num];
361 num = 0;
362 string text = (justAddresses ? "NONNULLSENTINEL" : null);
363 for (global::Interop.Winsock.AddressInfo* ptr2 = addressInfoPtr; ptr2 != null; ptr2 = ptr2->ai_next)
364 {
365 if (text == null && ptr2->ai_canonname != null)
366 {
367 text = Marshal.PtrToStringUni((IntPtr)ptr2->ai_canonname);
368 }
369 int num3 = (int)ptr2->ai_addrlen;
370 ReadOnlySpan<byte> socketAddress = new ReadOnlySpan<byte>(ptr2->ai_addr, num3);
371 if (ptr2->ai_family == AddressFamily.InterNetwork)
372 {
373 if (num3 == 16)
374 {
375 array[num++] = CreateIPv4Address(socketAddress);
376 }
377 }
378 else if (SocketProtocolSupportPal.OSSupportsIPv6 && ptr2->ai_family == AddressFamily.InterNetworkV6 && num3 == 28)
379 {
380 array[num++] = CreateIPv6Address(socketAddress);
381 }
382 }
383 hostName = (justAddresses ? null : text);
384 return array;
385 }
386
387 private unsafe static IPAddress[] ParseAddressInfoEx(global::Interop.Winsock.AddressInfoEx* addressInfoExPtr, bool justAddresses, out string hostName)
388 {
389 int num = 0;
390 for (global::Interop.Winsock.AddressInfoEx* ptr = addressInfoExPtr; ptr != null; ptr = ptr->ai_next)
391 {
392 int num2 = (int)ptr->ai_addrlen;
393 if (ptr->ai_family == AddressFamily.InterNetwork)
394 {
395 if (num2 == 16)
396 {
397 num++;
398 }
399 }
400 else if (SocketProtocolSupportPal.OSSupportsIPv6 && ptr->ai_family == AddressFamily.InterNetworkV6 && num2 == 28)
401 {
402 num++;
403 }
404 }
405 IPAddress[] array = new IPAddress[num];
406 num = 0;
407 string text = (justAddresses ? "NONNULLSENTINEL" : null);
408 for (global::Interop.Winsock.AddressInfoEx* ptr2 = addressInfoExPtr; ptr2 != null; ptr2 = ptr2->ai_next)
409 {
410 if (text == null && ptr2->ai_canonname != IntPtr.Zero)
411 {
412 text = Marshal.PtrToStringUni(ptr2->ai_canonname);
413 }
414 int num3 = (int)ptr2->ai_addrlen;
415 ReadOnlySpan<byte> socketAddress = new ReadOnlySpan<byte>(ptr2->ai_addr, num3);
416 if (ptr2->ai_family == AddressFamily.InterNetwork)
417 {
418 if (num3 == 16)
419 {
420 array[num++] = CreateIPv4Address(socketAddress);
421 }
422 }
423 else if (SocketProtocolSupportPal.OSSupportsIPv6 && ptr2->ai_family == AddressFamily.InterNetworkV6 && num3 == 28)
424 {
425 array[num++] = CreateIPv6Address(socketAddress);
426 }
427 }
428 hostName = (justAddresses ? null : text);
429 return array;
430 }
431
432 private static IPAddress CreateIPv4Address(ReadOnlySpan<byte> socketAddress)
433 {
434 long newAddress = (long)System.Net.SocketAddressPal.GetIPv4Address(socketAddress) & 0xFFFFFFFFL;
435 return new IPAddress(newAddress);
436 }
437
438 private static IPAddress CreateIPv6Address(ReadOnlySpan<byte> socketAddress)
439 {
440 Span<byte> span = stackalloc byte[16];
441 System.Net.SocketAddressPal.GetIPv6Address(socketAddress, span, out var scope);
442 return new IPAddress(span, scope);
443 }
444}
override SocketAddress Serialize()
AsyncTaskMethodBuilder< IPAddress[]> IPAddressArrayBuilder
static GetAddrInfoExState FromHandleAndFree(IntPtr handle)
AsyncTaskMethodBuilder< IPHostEntry > IPHostEntryBuilder
unsafe CancellationToken UnregisterAndGetCancellationToken()
unsafe GetAddrInfoExContext * _cancellationContext
unsafe GetAddrInfoExState(GetAddrInfoExContext *context, string hostName, bool justAddresses)
unsafe void RegisterForCancellation(CancellationToken cancellationToken)
CancellationTokenRegistration _cancellationRegistration
static unsafe IPAddress[] ParseAddressInfoEx(global::Interop.Winsock.AddressInfoEx *addressInfoExPtr, bool justAddresses, out string hostName)
static IPAddress CreateIPv6Address(ReadOnlySpan< byte > socketAddress)
static IPAddress CreateIPv4Address(ReadOnlySpan< byte > socketAddress)
static unsafe void GetAddressInfoExCallback(int error, int bytes, NativeOverlapped *overlapped)
static unsafe IPAddress[] ParseAddressInfo(global::Interop.Winsock.AddressInfo *addressInfoPtr, bool justAddresses, out string hostName)
static unsafe void ProcessResult(SocketError errorCode, GetAddrInfoExContext *context)
static unsafe string GetHostName()
static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, AddressFamily addressFamily, out string hostName, out string[] aliases, out IPAddress[] addresses, out int nativeErrorCode)
static unsafe string TryGetNameInfo(IPAddress addr, out SocketError errorCode, out int nativeErrorCode)
static unsafe Task GetAddrInfoAsync(string hostName, bool justAddresses, AddressFamily family, CancellationToken cancellationToken)
static volatile int s_getAddrInfoExSupported
static readonly System.Net.NetEventSource Log
static void Info(object thisOrContextObject, FormattableString formattableString=null, [CallerMemberName] string memberName=null)
static void Error(object thisOrContextObject, FormattableString formattableString, [CallerMemberName] string memberName=null)
static uint GetIPv4Address(ReadOnlySpan< byte > buffer)
static void GetIPv6Address(ReadOnlySpan< byte > buffer, Span< byte > address, out uint scope)
static void FreeHGlobal(IntPtr hglobal)
Definition Marshal.cs:1680
static unsafe? string PtrToStringUni(IntPtr ptr)
Definition Marshal.cs:652
static IntPtr AllocHGlobal(int cb)
Definition Marshal.cs:625
static bool TryGetExport(IntPtr handle, string name, out IntPtr address)
static int CompareExchange(ref int location1, int value, int comparand)
static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object? state)
static readonly IntPtr Zero
Definition IntPtr.cs:18
unsafe global::Interop.Winsock.AddressInfoEx * Result
static unsafe GetAddrInfoExContext * AllocateContext()
static unsafe void FreeContext(GetAddrInfoExContext *context)
static IntPtr ToIntPtr(GCHandle value)
Definition GCHandle.cs:138
static GCHandle Alloc(object? value)
Definition GCHandle.cs:81
static GCHandle FromIntPtr(IntPtr value)
Definition GCHandle.cs:127