Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
SafeSocketHandle.cs
Go to the documentation of this file.
5
6namespace System.Net.Sockets;
7
9{
10 private int _ownClose;
11
12 private volatile bool _released;
13
14 private bool _hasShutdownSend;
15
17
19
20 internal bool OwnsHandle { get; }
21
22 public override bool IsInvalid
23 {
24 get
25 {
26 if (!base.IsClosed)
27 {
28 return base.IsInvalid;
29 }
30 return true;
31 }
32 }
33
35
37
39 : base(ownsHandle: true)
40 {
41 OwnsHandle = true;
42 }
43
44 public SafeSocketHandle(IntPtr preexistingHandle, bool ownsHandle)
45 : base(ownsHandle)
46 {
47 OwnsHandle = ownsHandle;
48 SetHandleAndValid(preexistingHandle);
49 }
50
51 private bool TryOwnClose()
52 {
53 if (OwnsHandle)
54 {
55 return Interlocked.CompareExchange(ref _ownClose, 1, 0) == 0;
56 }
57 return false;
58 }
59
60 internal void TrackShutdown(SocketShutdown how)
61 {
62 if (how == SocketShutdown.Send || how == SocketShutdown.Both)
63 {
64 _hasShutdownSend = true;
65 }
66 }
67
68 protected override bool ReleaseHandle()
69 {
70 _released = true;
71 bool flag = TryOwnClose();
72 if (System.Net.NetEventSource.Log.IsEnabled())
73 {
74 System.Net.NetEventSource.Info(this, $"shouldClose={flag}", "ReleaseHandle");
75 }
76 if (flag)
77 {
78 CloseHandle(abortive: true, canceledOperations: false);
79 }
80 return true;
81 }
82
83 internal void CloseAsIs(bool abortive)
84 {
85 bool flag = TryOwnClose();
86 if (System.Net.NetEventSource.Log.IsEnabled())
87 {
88 System.Net.NetEventSource.Info(this, $"shouldClose={flag}", "CloseAsIs");
89 }
90 Dispose();
91 if (flag)
92 {
93 bool flag2 = false;
94 SpinWait spinWait = default(SpinWait);
95 while (!_released)
96 {
97 flag2 |= TryUnblockSocket(abortive);
98 spinWait.SpinOnce();
99 }
100 CloseHandle(abortive, flag2);
101 }
102 }
103
104 private bool CloseHandle(bool abortive, bool canceledOperations)
105 {
106 bool flag = false;
107 if (System.Net.NetEventSource.Log.IsEnabled())
108 {
109 System.Net.NetEventSource.Info(this, $"handle:{handle}", "CloseHandle");
110 }
111 canceledOperations |= OnHandleClose();
112 if (canceledOperations && !_hasShutdownSend)
113 {
114 abortive = true;
115 }
116 SocketError socketError = DoCloseHandle(abortive);
117 return flag = socketError == SocketError.Success;
118 }
119
121 {
123 if (IsInvalid)
124 {
125 TryOwnClose();
127 }
128 }
129
130 internal void SetExposed()
131 {
132 }
133
135 {
136 if (_released)
137 {
138 return null;
139 }
140 return _iocpBoundHandle;
141 }
142
143 internal ThreadPoolBoundHandle GetOrAllocateThreadPoolBoundHandle(bool trySkipCompletionPortOnSuccess)
144 {
145 if (_released)
146 {
148 }
149 if (_iocpBoundHandle != null)
150 {
151 return _iocpBoundHandle;
152 }
153 lock (this)
154 {
155 ThreadPoolBoundHandle threadPoolBoundHandle = _iocpBoundHandle;
156 if (threadPoolBoundHandle == null)
157 {
158 if (System.Net.NetEventSource.Log.IsEnabled())
159 {
160 System.Net.NetEventSource.Info(this, "calling ThreadPool.BindHandle()", "GetOrAllocateThreadPoolBoundHandle");
161 }
162 try
163 {
164 threadPoolBoundHandle = ThreadPoolBoundHandle.BindHandle(this);
165 }
166 catch (Exception ex) when (!ExceptionCheck.IsFatal(ex))
167 {
168 bool isClosed = base.IsClosed;
169 bool flag = !IsInvalid && !base.IsClosed && ex is ArgumentException;
170 CloseAsIs(abortive: false);
171 if (isClosed)
172 {
174 }
175 if (flag)
176 {
178 }
179 throw;
180 }
181 if (trySkipCompletionPortOnSuccess && CompletionPortHelper.SkipCompletionPortOnSuccess(threadPoolBoundHandle.Handle))
182 {
184 }
185 Volatile.Write(ref _iocpBoundHandle, threadPoolBoundHandle);
186 }
187 return threadPoolBoundHandle;
188 }
189 }
190
191 private bool OnHandleClose()
192 {
193 if (_iocpBoundHandle != null)
194 {
196 }
197 return false;
198 }
199
200 private unsafe bool TryUnblockSocket(bool abortive)
201 {
202 return global::Interop.Kernel32.CancelIoEx(handle, null);
203 }
204
205 private SocketError DoCloseHandle(bool abortive)
206 {
207 SocketError socketError;
208 if (!abortive)
209 {
210 if (System.Net.NetEventSource.Log.IsEnabled())
211 {
212 System.Net.NetEventSource.Info(this, $"handle:{handle}, Following 'blockable' branch", "DoCloseHandle");
213 }
214 socketError = global::Interop.Winsock.closesocket(handle);
215 if (socketError == SocketError.SocketError)
216 {
217 socketError = (SocketError)Marshal.GetLastWin32Error();
218 }
219 if (System.Net.NetEventSource.Log.IsEnabled())
220 {
221 System.Net.NetEventSource.Info(this, $"handle:{handle}, closesocket()#1:{socketError}", "DoCloseHandle");
222 }
223 if (socketError != SocketError.WouldBlock)
224 {
225 return socketError;
226 }
227 int argp = 0;
228 socketError = global::Interop.Winsock.ioctlsocket(handle, -2147195266, ref argp);
229 if (socketError == SocketError.SocketError)
230 {
231 socketError = (SocketError)Marshal.GetLastWin32Error();
232 }
233 if (System.Net.NetEventSource.Log.IsEnabled())
234 {
235 System.Net.NetEventSource.Info(this, $"handle:{handle}, ioctlsocket()#1:{socketError}", "DoCloseHandle");
236 }
237 if (socketError == SocketError.Success)
238 {
239 socketError = global::Interop.Winsock.closesocket(handle);
240 if (socketError == SocketError.SocketError)
241 {
242 socketError = (SocketError)Marshal.GetLastWin32Error();
243 }
244 if (System.Net.NetEventSource.Log.IsEnabled())
245 {
246 System.Net.NetEventSource.Info(this, $"handle:{handle}, closesocket#2():{socketError}", "DoCloseHandle");
247 }
248 if (socketError != SocketError.WouldBlock)
249 {
250 return socketError;
251 }
252 }
253 }
254 Unsafe.SkipInit(out global::Interop.Winsock.Linger linger);
255 linger.OnOff = 1;
256 linger.Time = 0;
257 socketError = global::Interop.Winsock.setsockopt(handle, SocketOptionLevel.Socket, SocketOptionName.Linger, ref linger, 4);
258 if (socketError == SocketError.SocketError)
259 {
260 socketError = (SocketError)Marshal.GetLastWin32Error();
261 }
262 if (System.Net.NetEventSource.Log.IsEnabled())
263 {
264 System.Net.NetEventSource.Info(this, $"handle:{handle}, setsockopt():{socketError}", "DoCloseHandle");
265 }
266 if (socketError != 0 && socketError != SocketError.InvalidArgument && socketError != SocketError.ProtocolOption)
267 {
268 return socketError;
269 }
270 socketError = global::Interop.Winsock.closesocket(handle);
271 if (System.Net.NetEventSource.Log.IsEnabled())
272 {
273 System.Net.NetEventSource.Info(this, $"handle:{handle}, closesocket#3():{((socketError == SocketError.SocketError) ? ((SocketError)Marshal.GetLastWin32Error()) : socketError)}", "DoCloseHandle");
274 }
275 return socketError;
276 }
277
278 private static void ThrowSocketDisposedException(Exception innerException = null)
279 {
280 throw new ObjectDisposedException(typeof(Socket).FullName, innerException);
281 }
282}
static bool IsFatal(Exception exception)
static readonly System.Net.NetEventSource Log
static void Info(object thisOrContextObject, FormattableString formattableString=null, [CallerMemberName] string memberName=null)
static bool SkipCompletionPortOnSuccess(SafeHandle handle)
unsafe bool TryUnblockSocket(bool abortive)
SafeSocketHandle(IntPtr preexistingHandle, bool ownsHandle)
ThreadPoolBoundHandle? IOCPBoundHandle
ThreadPoolBoundHandle GetThreadPoolBoundHandle()
SocketError DoCloseHandle(bool abortive)
ThreadPoolBoundHandle GetOrAllocateThreadPoolBoundHandle(bool trySkipCompletionPortOnSuccess)
void TrackShutdown(SocketShutdown how)
bool CloseHandle(bool abortive, bool canceledOperations)
static void ThrowSocketDisposedException(Exception innerException=null)
static string net_sockets_asyncoperations_notallowed
Definition SR.cs:116
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
static ThreadPoolBoundHandle BindHandle(SafeHandle handle)
static void Write(ref bool location, bool value)
Definition Volatile.cs:74