Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
WebSocketBase.cs
Go to the documentation of this file.
4using System.IO;
7using System.Text;
10
11namespace System.Net.WebSockets;
12
13internal abstract class WebSocketBase : WebSocket, IDisposable
14{
15 private abstract class WebSocketOperation
16 {
18 {
19 private int _receiveState;
20
21 private bool _pongReceived;
22
23 private bool _receiveCompleted;
24
26
27 protected override int BufferCount => 1;
28
33
35 {
36 _pongReceived = false;
37 _receiveCompleted = false;
40 {
41 case 0:
42 _receiveState = 1;
43 break;
44 case 2:
45 {
47 {
49 }
50 base.ReceiveResult = receiveResult;
51 _receiveCompleted = true;
52 break;
53 }
54 case 1:
55 break;
56 }
57 }
58
59 protected override void Cleanup()
60 {
61 }
62
64 {
65 cancellationToken.ThrowIfCancellationRequested();
67 {
68 return false;
69 }
73 return true;
74 }
75
76 protected override bool ProcessAction_NoAction()
77 {
78 if (_pongReceived)
79 {
80 _receiveCompleted = false;
81 _pongReceived = false;
82 return false;
83 }
84 _receiveCompleted = true;
85 if (base.ReceiveResult.MessageType == WebSocketMessageType.Close)
86 {
87 return true;
88 }
89 return false;
90 }
91
93 {
94 int num = 0;
95 _pongReceived = false;
97 {
98 _pongReceived = true;
100 return;
101 }
103 try
104 {
106 int newReceiveState = 0;
108 {
112 }
113 else
114 {
116 bool endOfMessage = bufferType == WebSocketProtocolComponent.BufferType.BinaryMessage || bufferType == WebSocketProtocolComponent.BufferType.UTF8Message || bufferType == WebSocketProtocolComponent.BufferType.Close;
117 if (empty.Count > buffer.Value.Count)
118 {
120 newReceiveState = 2;
121 endOfMessage = false;
122 }
123 num = Math.Min(empty.Count, buffer.Value.Count);
124 if (num > 0)
125 {
126 Buffer.BlockCopy(empty.Array, empty.Offset, buffer.Value.Array, buffer.Value.Offset, num);
127 }
129 }
131 }
132 finally
133 {
135 }
136 base.ReceiveResult = receiveResult;
137 }
138 }
139
141 {
142 protected bool _BufferHasBeenPinned;
143
145
146 protected override int BufferCount => 2;
147
148 internal WebSocketProtocolComponent.BufferType BufferType { get; set; }
149
154
155 protected virtual global::Interop.WebSocket.Buffer? CreateBuffer(ArraySegment<byte>? buffer)
156 {
157 if (!buffer.HasValue)
158 {
159 return null;
160 }
161 global::Interop.WebSocket.Buffer value = default(global::Interop.WebSocket.Buffer);
164 value.Data.BufferLength = (uint)buffer.Value.Count;
165 return value;
166 }
167
168 protected override bool ProcessAction_NoAction()
169 {
170 return false;
171 }
172
173 protected override void Cleanup()
174 {
176 {
177 _BufferHasBeenPinned = false;
179 }
180 }
181
183 {
186 global::Interop.WebSocket.Buffer? buffer2 = CreateBuffer(buffer);
187 if (buffer2.HasValue)
188 {
190 }
191 else
192 {
194 }
195 }
196
198 {
199 if (base.AsyncOperationCompleted)
200 {
201 return false;
202 }
203 cancellationToken.ThrowIfCancellationRequested();
204 return true;
205 }
206 }
207
209 {
210 internal WebSocketCloseStatus CloseStatus { get; set; }
211
212 internal string CloseReason { get; set; }
213
215 : base(webSocket)
216 {
217 base.BufferType = WebSocketProtocolComponent.BufferType.Close;
218 }
219
220 protected override global::Interop.WebSocket.Buffer? CreateBuffer(ArraySegment<byte>? buffer)
221 {
225 {
226 return null;
227 }
228 global::Interop.WebSocket.Buffer value = default(global::Interop.WebSocket.Buffer);
229 if (CloseReason != null)
230 {
231 byte[] bytes = Encoding.UTF8.GetBytes(CloseReason);
235 value.CloseStatus.ReasonLength = (uint)payload.Count;
236 }
237 value.CloseStatus.CloseStatus = (ushort)CloseStatus;
238 return value;
239 }
240 }
241
242 private readonly WebSocketBase _webSocket;
243
244 protected bool AsyncOperationCompleted { get; set; }
245
246 public WebSocketReceiveResult ReceiveResult { get; protected set; }
247
248 protected abstract int BufferCount { get; }
249
251
257
259
261
262 protected abstract bool ProcessAction_NoAction();
263
268
269 protected abstract void Cleanup();
270
272 {
273 bool sessionHandleLockTaken = false;
275 ReceiveResult = null;
276 try
277 {
282 {
283 bool completed = false;
284 while (!completed)
285 {
286 global::Interop.WebSocket.Buffer[] array = new global::Interop.WebSocket.Buffer[BufferCount];
287 uint dataBufferCount = (uint)BufferCount;
290 switch (action)
291 {
294 {
295 bool thisLockTaken = false;
296 try
297 {
299 {
301 bool flag;
302 try
303 {
305 }
306 catch (Exception)
307 {
309 throw;
310 }
311 if (flag)
312 {
315 }
316 }
318 }
319 finally
320 {
321 if (thisLockTaken)
322 {
324 }
325 }
326 }
327 completed = true;
328 break;
329 case WebSocketProtocolComponent.Action.IndicateReceiveComplete:
331 break;
332 case WebSocketProtocolComponent.Action.ReceiveFromNetwork:
333 {
334 int count = 0;
335 try
336 {
340 try
341 {
343 count = await task.SuppressContextFlow();
345 }
347 {
348 throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, innerException);
349 }
351 {
352 throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, innerException2);
353 }
356 if (count == 0)
357 {
358 throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely);
359 }
360 }
361 finally
362 {
364 }
365 break;
366 }
367 case WebSocketProtocolComponent.Action.IndicateSendComplete:
373 break;
374 case WebSocketProtocolComponent.Action.SendToNetwork:
375 {
376 int bytesSent = 0;
377 try
378 {
380 {
382 int sendBufferSize2 = 0;
384 list.Add(item);
386 if (dataBufferCount == 2)
387 {
389 list.Add(item2);
391 }
394 await _webSocket.SendFrameAsync(list, cancellationToken).SuppressContextFlow();
397 bytesSent += sendBufferSize2;
399 }
400 }
401 finally
402 {
404 }
405 break;
406 }
407 default:
408 throw new InvalidOperationException();
409 }
410 }
413 }
414 }
415 finally
416 {
417 Cleanup();
419 }
420 return ReceiveResult;
421 }
422 }
423
424 private abstract class KeepAliveTracker : IDisposable
425 {
427 {
428 public override void OnDataReceived()
429 {
430 }
431
432 public override void OnDataSent()
433 {
434 }
435
436 public override void ResetTimer()
437 {
438 }
439
440 public override void StartTimer(WebSocketBase webSocket)
441 {
442 }
443
444 public override bool ShouldSendKeepAlive()
445 {
446 return false;
447 }
448
449 public override void Dispose()
450 {
451 }
452 }
453
455 {
457
458 private readonly TimeSpan _keepAliveInterval;
459
460 private readonly Stopwatch _lastSendActivity;
461
463
465
472
473 public override void OnDataReceived()
474 {
476 }
477
478 public override void OnDataSent()
479 {
481 }
482
483 public override void ResetTimer()
484 {
486 }
487
494
495 public override bool ShouldSendKeepAlive()
496 {
499 {
500 return true;
501 }
502 ResetTimer((int)(_keepAliveInterval - idleTime).TotalMilliseconds);
503 return false;
504 }
505
506 public override void Dispose()
507 {
509 }
510
512 {
514 }
515
526
528 {
529 if (watch.IsRunning)
530 {
531 return watch.Elapsed;
532 }
533 return _keepAliveInterval;
534 }
535 }
536
537 public abstract void OnDataReceived();
538
539 public abstract void OnDataSent();
540
541 public abstract void Dispose();
542
543 public abstract void StartTimer(WebSocketBase webSocket);
544
545 public abstract void ResetTimer();
546
547 public abstract bool ShouldSendKeepAlive();
548
550 {
551 if ((int)keepAliveInterval.TotalMilliseconds > 0)
552 {
554 }
555 return new DisabledKeepAliveTracker();
556 }
557 }
558
560 {
561 private volatile int _operationsOutstanding;
562
564
565 private volatile bool _isDisposed;
566
567 private readonly object _thisLock = new object();
568
583
602
607
608 public void CancelIO()
609 {
612 {
613 if (_operationsOutstanding == 0)
614 {
615 return;
616 }
618 }
619 if (cancellationTokenSource != null)
620 {
621 try
622 {
624 }
626 {
627 }
628 }
629 }
630
631 public void Dispose()
632 {
633 if (_isDisposed)
634 {
635 return;
636 }
639 {
640 if (_isDisposed)
641 {
642 return;
643 }
644 _isDisposed = true;
647 }
648 cancellationTokenSource?.Dispose();
649 }
650
651 private void ThrowIfDisposed()
652 {
653 if (_isDisposed)
654 {
655 throw new ObjectDisposedException(GetType().FullName);
656 }
657 }
658 }
659
672
674
676
678
680
681 private readonly Stream _innerStream;
682
684
685 private readonly string _subProtocol;
686
688
689 private readonly object _thisLock;
690
692
694
695 private volatile bool _cleanedUp;
696
698
699 private volatile Task _closeOutputTask;
700
701 private volatile bool _isDisposed;
702
704
705 private volatile bool _closeAsyncStartedReceive;
706
707 private volatile WebSocketState _state;
708
709 private volatile Task _keepAliveTask;
710
712
714
716
718
720
722
723 private int _receiveState;
724
726
727 public override WebSocketState State => _state;
728
729 public override string SubProtocol => _subProtocol;
730
732
734
736
737 internal abstract SafeHandle SessionHandle { get; }
738
767
768 protected void StartKeepAliveTimer()
769 {
771 }
772
778
780 {
784 bool ownsCancellationTokenSource = false;
787 try
788 {
791 {
793 {
795 {
797 }
799 }
800 }
804 {
805 System.Net.NetEventSource.DumpBuffer(this, buffer.Array, buffer.Offset, webSocketReceiveResult.Count, "ReceiveAsyncCore");
806 }
807 }
808 catch (Exception exception)
809 {
810 bool isCancellationRequested = linkedCancellationToken.IsCancellationRequested;
811 Abort();
813 throw;
814 }
815 finally
816 {
818 }
820 }
821
831
833 {
837 bool ownsCancellationTokenSource = false;
839 try
840 {
841 while (true)
842 {
843 bool flag;
845 if (flag)
846 {
847 break;
848 }
851 {
853 if (keepAliveTask == null)
854 {
857 if (flag)
858 {
859 break;
860 }
862 }
863 }
864 await keepAliveTask.SuppressContextFlow();
867 }
868 if (System.Net.NetEventSource.Log.IsEnabled() && buffer.Count > 0)
869 {
870 System.Net.NetEventSource.DumpBuffer(this, buffer.Array, buffer.Offset, buffer.Count, "SendAsyncCore");
871 }
873 _sendOperation.BufferType = GetBufferType(messageType, endOfMessage);
874 await _sendOperation.Process(buffer, linkedCancellationToken).SuppressContextFlow();
875 }
876 catch (Exception exception)
877 {
878 bool isCancellationRequested = linkedCancellationToken.IsCancellationRequested;
879 Abort();
881 throw;
882 }
883 finally
884 {
886 }
887 }
888
890 {
891 bool sendFrameLockTaken = false;
892 try
893 {
895 sendFrameLockTaken = true;
897 {
899 return;
900 }
902 {
904 }
905 }
907 {
908 throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, innerException);
909 }
911 {
912 throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, innerException2);
913 }
914 finally
915 {
917 {
919 }
920 }
921 }
922
957
963
965 {
967 if (WebSocket.IsStateTerminal(State))
968 {
969 return;
970 }
972 bool thisLockTaken = false;
973 bool sessionHandleLockTaken = false;
974 bool needToCompleteSendOperation = false;
978 try
979 {
983 if (WebSocket.IsStateTerminal(State))
984 {
985 return;
986 }
990 {
992 if (closeOutputTask != null)
993 {
995 await closeOutputTask.SuppressContextFlow();
997 }
998 return;
999 }
1001 while (true)
1002 {
1003 bool flag;
1005 if (flag)
1006 {
1007 break;
1008 }
1009 if (_keepAliveTask != null)
1010 {
1013 await keepAliveTask.SuppressContextFlow();
1017 continue;
1018 }
1020 }
1022 _closeOutputOperation.CloseStatus = closeStatus;
1023 _closeOutputOperation.CloseReason = statusDescription;
1026 await _closeOutputTask.SuppressContextFlow();
1029 {
1030 bool flag2;
1031 try
1032 {
1034 }
1035 catch (Exception)
1036 {
1038 throw;
1039 }
1040 if (flag2)
1041 {
1044 }
1045 }
1046 }
1047 catch (Exception exception)
1048 {
1049 bool isCancellationRequested = linkedCancellationToken.IsCancellationRequested;
1050 Abort();
1052 throw;
1053 }
1054 finally
1055 {
1058 {
1060 }
1061 _closeOutputTask = null;
1063 }
1064 }
1065
1067 {
1068 if (WebSocket.IsStateTerminal(State))
1069 {
1070 return false;
1071 }
1072 switch (State)
1073 {
1074 case WebSocketState.Open:
1075 _state = WebSocketState.CloseSent;
1076 return false;
1077 case WebSocketState.CloseReceived:
1078 return true;
1079 default:
1080 return false;
1081 }
1082 }
1083
1085 {
1087 {
1088 return false;
1089 }
1090 _state = WebSocketState.Closed;
1092 {
1095 try
1096 {
1097 if (_closeNetworkConnectionTask == null)
1098 {
1100 }
1102 {
1104 }
1105 else if (lockTaken)
1106 {
1108 }
1109 await _closeNetworkConnectionTask.SuppressContextFlow();
1110 }
1111 catch (Exception ex)
1112 {
1114 {
1115 ThrowIfConvertibleException("StartOnCloseCompleted", ex, cancellationToken, cancellationToken.IsCancellationRequested);
1116 throw;
1117 }
1118 }
1119 }
1120 return true;
1121 }
1122
1124 {
1125 CleanUp();
1126 }
1127
1133
1135 {
1137 if (WebSocket.IsStateTerminal(State))
1138 {
1139 return;
1140 }
1142 bool lockTaken = false;
1146 try
1147 {
1149 if (WebSocket.IsStateTerminal(State))
1150 {
1151 return;
1152 }
1154 WebSocket.ThrowOnInvalidState(State, WebSocketState.Open, WebSocketState.CloseReceived, WebSocketState.CloseSent);
1156 Task task;
1158 {
1160 if (task == null && State != WebSocketState.CloseSent)
1161 {
1163 {
1165 }
1167 }
1168 }
1169 else
1170 {
1172 }
1173 if (task != null)
1174 {
1176 try
1177 {
1178 await task.SuppressContextFlow();
1179 }
1180 catch (Exception ex)
1181 {
1184 {
1185 ThrowIfConvertibleException("CloseOutputAsync", ex, cancellationToken, linkedCancellationToken.IsCancellationRequested);
1186 throw;
1187 }
1188 }
1189 if (!lockTaken)
1190 {
1192 }
1193 }
1195 {
1196 bool flag;
1197 try
1198 {
1200 }
1201 catch (Exception)
1202 {
1204 throw;
1205 }
1206 if (flag)
1207 {
1210 }
1211 }
1212 if (WebSocket.IsStateTerminal(State))
1213 {
1214 return;
1215 }
1218 if (flag2)
1219 {
1226 try
1227 {
1228 receiveResult = await task2.SuppressContextFlow();
1229 }
1230 catch (Exception ex3)
1231 {
1234 {
1235 ThrowIfConvertibleException("CloseAsync", ex3, cancellationToken, linkedCancellationToken.IsCancellationRequested);
1236 throw;
1237 }
1238 }
1239 if (receiveResult != null)
1240 {
1241 if (System.Net.NetEventSource.Log.IsEnabled() && receiveResult.Count > 0)
1242 {
1244 }
1245 if (receiveResult.MessageType != WebSocketMessageType.Close)
1246 {
1247 throw new WebSocketException(WebSocketError.InvalidMessageType, System.SR.Format(System.SR.net_WebSockets_InvalidMessageType, "WebSocket.CloseAsync", "WebSocket.CloseOutputAsync", receiveResult.MessageType));
1248 }
1249 }
1250 }
1251 else
1252 {
1255 await _closeReceivedTaskCompletionSource.Task.SuppressContextFlow();
1256 }
1257 if (!lockTaken)
1258 {
1260 }
1261 if (WebSocket.IsStateTerminal(State))
1262 {
1263 return;
1264 }
1265 bool ownsSendCancellationSource = false;
1266 try
1267 {
1269 bool flag3;
1270 try
1271 {
1273 }
1274 catch (Exception)
1275 {
1277 throw;
1278 }
1279 if (flag3)
1280 {
1283 }
1284 }
1285 finally
1286 {
1288 }
1289 }
1290 catch (Exception exception)
1291 {
1292 bool isCancellationRequested = linkedCancellationToken.IsCancellationRequested;
1293 Abort();
1295 throw;
1296 }
1297 finally
1298 {
1301 }
1302 }
1303
1304 public override void Dispose()
1305 {
1306 if (_isDisposed)
1307 {
1308 return;
1309 }
1310 bool thisLockTaken = false;
1311 bool sessionHandleLockTaken = false;
1312 try
1313 {
1315 if (!_isDisposed)
1316 {
1317 if (!WebSocket.IsStateTerminal(State))
1318 {
1319 Abort();
1320 }
1321 else
1322 {
1323 CleanUp();
1324 }
1325 _isDisposed = true;
1326 }
1327 }
1328 finally
1329 {
1331 }
1332 }
1333
1335 {
1336 thisLockTaken = false;
1338 }
1339
1346
1352
1354 {
1355 if (thisLockTaken)
1356 {
1358 thisLockTaken = false;
1359 }
1361 {
1363 sessionHandleLockTaken = false;
1364 }
1365 }
1366
1368 {
1369 if (_receiveOperation != null)
1370 {
1371 return;
1372 }
1373 lock (_thisLock)
1374 {
1375 if (_receiveOperation == null)
1376 {
1378 }
1379 }
1380 }
1381
1382 private void EnsureSendOperation()
1383 {
1384 if (_sendOperation != null)
1385 {
1386 return;
1387 }
1388 lock (_thisLock)
1389 {
1390 if (_sendOperation == null)
1391 {
1393 }
1394 }
1395 }
1396
1398 {
1399 if (_keepAliveOperation != null)
1400 {
1401 return;
1402 }
1403 lock (_thisLock)
1404 {
1405 if (_keepAliveOperation == null)
1406 {
1408 sendOperation.BufferType = WebSocketProtocolComponent.BufferType.UnsolicitedPong;
1410 }
1411 }
1412 }
1413
1415 {
1416 if (_closeOutputOperation != null)
1417 {
1418 return;
1419 }
1420 lock (_thisLock)
1421 {
1422 if (_closeOutputOperation == null)
1423 {
1425 }
1426 }
1427 }
1428
1429 private static void ReleaseLock(object lockObject, ref bool lockTaken)
1430 {
1431 if (lockTaken)
1432 {
1434 lockTaken = false;
1435 }
1436 }
1437
1439 {
1441 {
1442 if (endOfMessage)
1443 {
1444 return WebSocketProtocolComponent.BufferType.UTF8Message;
1445 }
1446 return WebSocketProtocolComponent.BufferType.UTF8Fragment;
1447 }
1448 if (endOfMessage)
1449 {
1450 return WebSocketProtocolComponent.BufferType.BinaryMessage;
1451 }
1452 return WebSocketProtocolComponent.BufferType.BinaryFragment;
1453 }
1454
1471
1476
1478 {
1479 if (aborted)
1480 {
1482 }
1483 }
1484
1486 {
1487 if (State != WebSocketState.Closed)
1488 {
1489 return false;
1490 }
1492 {
1493 return error is IOException;
1494 }
1495 return true;
1496 }
1497
1499 {
1500 if (System.Net.NetEventSource.Log.IsEnabled() && !string.IsNullOrEmpty(methodName))
1501 {
1502 System.Net.NetEventSource.Error(this, $"methodName: {methodName}, exception: {exception}", "ThrowIfConvertibleException");
1503 }
1505 {
1506 if (cancellationToken.IsCancellationRequested || !aborted)
1507 {
1508 return;
1509 }
1511 }
1513 if (ex2 != null)
1514 {
1515 cancellationToken.ThrowIfCancellationRequested();
1517 return;
1518 }
1520 {
1521 ex2 = new WebSocketException(ex3.NativeErrorCode, ex3);
1522 }
1524 {
1525 ex2 = new WebSocketException(ex4.ErrorCode, ex4);
1526 }
1528 {
1529 ex2 = new WebSocketException(ex5.NativeErrorCode, innerException);
1530 }
1531 if (ex2 != null)
1532 {
1533 cancellationToken.ThrowIfCancellationRequested();
1535 throw ex2;
1536 }
1538 {
1539 return;
1540 }
1541 ReadOnlyCollection<Exception> innerExceptions = ex6.Flatten().InnerExceptions;
1542 if (innerExceptions.Count == 0)
1543 {
1544 return;
1545 }
1546 foreach (Exception item in innerExceptions)
1547 {
1549 }
1550 }
1551
1552 private void CleanUp()
1553 {
1554 if (_cleanedUp)
1555 {
1556 return;
1557 }
1558 _cleanedUp = true;
1559 if (SessionHandle != null)
1560 {
1562 }
1563 if (_internalBuffer != null)
1564 {
1565 _internalBuffer.Dispose(State);
1566 }
1568 {
1570 }
1572 {
1574 }
1576 {
1578 }
1580 {
1582 }
1583 if (_innerStream != null)
1584 {
1585 try
1586 {
1588 }
1590 {
1591 }
1592 catch (IOException)
1593 {
1594 }
1595 catch (SocketException)
1596 {
1597 }
1598 catch (HttpListenerException)
1599 {
1600 }
1601 }
1603 }
1604
1606 {
1608 {
1609 if (System.Net.NetEventSource.Log.IsEnabled())
1610 {
1611 System.Net.NetEventSource.Error(this, exception.ToString(), "OnBackgroundTaskException");
1612 }
1613 Abort();
1614 }
1615 }
1616
1618 {
1620 if (ex != null)
1621 {
1622 throw new WebSocketException(WebSocketError.Faulted, ex);
1623 }
1624 }
1625
1626 private void ThrowIfDisposed()
1627 {
1628 if (_isDisposed)
1629 {
1630 throw new ObjectDisposedException(GetType().FullName);
1631 }
1632 }
1633
1638
1640 {
1642 if (WebSocket.IsStateTerminal(State) || State == WebSocketState.CloseReceived)
1643 {
1644 return false;
1645 }
1647 if (WebSocket.IsStateTerminal(State) || State == WebSocketState.CloseReceived)
1648 {
1649 return false;
1650 }
1651 if (State == WebSocketState.Open)
1652 {
1653 _state = WebSocketState.CloseReceived;
1655 {
1657 }
1658 return false;
1659 }
1660 return true;
1661 }
1662
1664 {
1665 _closeReceivedTaskCompletionSource?.TrySetResult();
1668 if (System.Net.NetEventSource.Log.IsEnabled())
1669 {
1670 System.Net.NetEventSource.Info(this, $"closeStatus: {closeStatus}, closeStatusDescription: {closeStatusDescription}, _State: {_state}", "FinishOnCloseReceived");
1671 }
1672 }
1673
1674 private static async void OnKeepAlive(object sender)
1675 {
1677 bool lockTaken = false;
1679 try
1680 {
1681 Monitor.Enter(thisPtr.SessionHandle, ref lockTaken);
1682 if (thisPtr._isDisposed || thisPtr._state != WebSocketState.Open || thisPtr._closeOutputTask != null || !thisPtr._keepAliveTracker.ShouldSendKeepAlive())
1683 {
1684 return;
1685 }
1686 bool ownsCancellationTokenSource = false;
1687 try
1688 {
1689 ownsCancellationTokenSource = thisPtr._sendOutstandingOperationHelper.TryStartOperation(CancellationToken.None, out linkedCancellationToken);
1691 {
1692 thisPtr.EnsureKeepAliveOperation();
1693 thisPtr._keepAliveTask = thisPtr._keepAliveOperation.Process(null, linkedCancellationToken);
1694 ReleaseLock(thisPtr.SessionHandle, ref lockTaken);
1695 await thisPtr._keepAliveTask.SuppressContextFlow();
1696 }
1697 }
1698 finally
1699 {
1700 if (!lockTaken)
1701 {
1702 Monitor.Enter(thisPtr.SessionHandle, ref lockTaken);
1703 }
1704 thisPtr._sendOutstandingOperationHelper.CompleteOperation(ownsCancellationTokenSource);
1705 thisPtr._keepAliveTask = null;
1706 }
1707 thisPtr._keepAliveTracker.ResetTimer();
1708 }
1709 catch (Exception exception)
1710 {
1711 try
1712 {
1713 thisPtr.ThrowIfConvertibleException("OnKeepAlive", exception, CancellationToken.None, linkedCancellationToken.IsCancellationRequested);
1714 throw;
1715 }
1716 catch (Exception exception2)
1717 {
1718 thisPtr.OnBackgroundTaskException(exception2);
1719 }
1720 }
1721 finally
1722 {
1723 ReleaseLock(thisPtr.SessionHandle, ref lockTaken);
1724 }
1725 }
1726}
static void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count)
Definition Buffer.cs:102
void Add(TKey key, TValue value)
Task FlushAsync()
Definition Stream.cs:669
virtual void Close()
Definition Stream.cs:644
Task WriteAsync(byte[] buffer, int offset, int count)
Definition Stream.cs:914
Task< int > ReadAsync(byte[] buffer, int offset, int count)
Definition Stream.cs:762
static byte Min(byte val1, byte val2)
Definition Math.cs:912
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 void Associate(object first, object second, [CallerMemberName] string memberName=null)
static void DumpBuffer(object thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string memberName=null)
static void ValidateOptions(string subProtocol, int receiveBufferSize, int sendBufferSize, TimeSpan keepAliveInterval)
static void ValidateInnerStream(Stream innerStream)
static void ThrowIfConnectionAborted(Stream connection, bool read)
static KeepAliveTracker Create(TimeSpan keepAliveInterval)
bool TryStartOperation(CancellationToken userCancellationToken, out CancellationToken linkedCancellationToken)
void CompleteOperation(bool ownsCancellationTokenSource)
CancellationToken CreateLinkedCancellationToken(CancellationToken cancellationToken)
override global::Interop.WebSocket.? Buffer CreateBuffer(ArraySegment< byte >? buffer)
override WebSocketProtocolComponent.ActionQueue ActionQueue
override void ProcessAction_IndicateReceiveComplete(ArraySegment< byte >? buffer, WebSocketProtocolComponent.BufferType bufferType, WebSocketProtocolComponent.Action action, global::Interop.WebSocket.Buffer[] dataBuffers, uint dataBufferCount, IntPtr actionContext)
override bool ShouldContinue(CancellationToken cancellationToken)
override void Initialize(ArraySegment< byte >? buffer, CancellationToken cancellationToken)
override WebSocketProtocolComponent.ActionQueue ActionQueue
override bool ShouldContinue(CancellationToken cancellationToken)
virtual global::Interop.WebSocket.? Buffer CreateBuffer(ArraySegment< byte >? buffer)
override void Initialize(ArraySegment< byte >? buffer, CancellationToken cancellationToken)
virtual void ProcessAction_IndicateReceiveComplete(ArraySegment< byte >? buffer, WebSocketProtocolComponent.BufferType bufferType, WebSocketProtocolComponent.Action action, global::Interop.WebSocket.Buffer[] dataBuffers, uint dataBufferCount, IntPtr actionContext)
void Initialize(ArraySegment< byte >? buffer, CancellationToken cancellationToken)
WebSocketProtocolComponent.ActionQueue ActionQueue
async Task< WebSocketReceiveResult > Process(ArraySegment< byte >? buffer, CancellationToken cancellationToken)
bool ShouldContinue(CancellationToken cancellationToken)
void FinishOnCloseReceived(WebSocketCloseStatus closeStatus, string closeStatusDescription)
void ResetFlagsAndTakeLocks(ref bool thisLockTaken, ref bool sessionHandleLockTaken)
readonly SemaphoreSlim _sendFrameThrottle
volatile WebSocketOperation.ReceiveOperation _receiveOperation
readonly OutstandingOperationHelper _closeOutstandingOperationHelper
readonly OutstandingOperationHelper _sendOutstandingOperationHelper
override Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
readonly OutstandingOperationHelper _closeOutputOutstandingOperationHelper
async Task CloseOutputAsyncCore(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
static void ReleaseLock(object lockObject, ref bool lockTaken)
void TakeLocks(ref bool thisLockTaken, ref bool sessionHandleLockTaken)
override Task< WebSocketReceiveResult > ReceiveAsync(ArraySegment< byte > buffer, CancellationToken cancellationToken)
static WebSocketProtocolComponent.BufferType GetBufferType(WebSocketMessageType messageType, bool endOfMessage)
override Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
static async void OnKeepAlive(object sender)
void ValidateNativeBuffers(WebSocketProtocolComponent.Action action, WebSocketProtocolComponent.BufferType bufferType, global::Interop.WebSocket.Buffer[] dataBuffers, uint dataBufferCount)
void OnBackgroundTaskException(Exception exception)
void ThrowIfConvertibleException(string methodName, Exception exception, CancellationToken cancellationToken, bool aborted)
void ReleaseLocks(ref bool thisLockTaken, ref bool sessionHandleLockTaken)
async Task< WebSocketReceiveResult > ReceiveAsyncCore(ArraySegment< byte > buffer, CancellationToken cancellationToken)
void UpdateReceiveState(int newReceiveState, int expectedReceiveState)
readonly WebSocketBuffer _internalBuffer
WebSocketBase(Stream innerStream, string subProtocol, TimeSpan keepAliveInterval, WebSocketBuffer internalBuffer)
async Task SendAsyncCore(ArraySegment< byte > buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
bool StartOnCloseReceived(ref bool thisLockTaken)
volatile WebSocketOperation.SendOperation _keepAliveOperation
async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
volatile WebSocketOperation.SendOperation _sendOperation
readonly KeepAliveTracker _keepAliveTracker
override Task SendAsync(ArraySegment< byte > buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
void ResetFlagAndTakeLock(object lockObject, ref bool thisLockTaken)
async Task SendFrameAsync(IList< ArraySegment< byte > > sendBuffers, CancellationToken cancellationToken)
bool CanHandleExceptionDuringClose(Exception error)
readonly IWebSocketStream _innerStreamAsWebSocketStream
static WebSocketMessageType GetMessageType(WebSocketProtocolComponent.BufferType bufferType)
volatile WebSocketOperation.CloseOutputOperation _closeOutputOperation
override? WebSocketCloseStatus CloseStatus
volatile TaskCompletionSource _closeReceivedTaskCompletionSource
readonly OutstandingOperationHelper _receiveOutstandingOperationHelper
void ThrowIfAborted(bool aborted, Exception innerException)
async Task< bool > StartOnCloseCompleted(bool thisLockTakenSnapshot, bool sessionHandleLockTakenSnapshot, CancellationToken cancellationToken)
void ValidateNativeBuffers(WebSocketProtocolComponent.Action action, WebSocketProtocolComponent.BufferType bufferType, global::Interop.WebSocket.Buffer[] dataBuffers, uint dataBufferCount)
bool ReceiveFromBufferedPayload(ArraySegment< byte > buffer, out WebSocketReceiveResult receiveResult)
ArraySegment< byte > ConvertPinnedSendPayloadFromNative(global::Interop.WebSocket.Buffer buffer, WebSocketProtocolComponent.BufferType bufferType)
void BufferPayload(ArraySegment< byte > payload, int unconsumedDataOffset, WebSocketMessageType messageType, bool endOfMessage)
bool IsPinnedSendPayloadBuffer(byte[] buffer, int offset, int count)
void Dispose(WebSocketState webSocketState)
void ConvertCloseBuffer(WebSocketProtocolComponent.Action action, global::Interop.WebSocket.Buffer buffer, out WebSocketCloseStatus closeStatus, out string reason)
IntPtr ConvertPinnedSendPayloadToNative(ArraySegment< byte > payload)
void PinSendBuffer(ArraySegment< byte > payload, out bool bufferHasBeenPinned)
ArraySegment< byte > ConvertNativeBuffer(WebSocketProtocolComponent.Action action, global::Interop.WebSocket.Buffer buffer, WebSocketProtocolComponent.BufferType bufferType)
static void WebSocketSend(WebSocketBase webSocket, BufferType bufferType, global::Interop.WebSocket.Buffer buffer)
static void WebSocketGetAction(WebSocketBase webSocket, ActionQueue actionQueue, global::Interop.WebSocket.Buffer[] dataBuffers, ref uint dataBufferCount, out Action action, out BufferType bufferType, out IntPtr actionContext)
static void WebSocketAbortHandle(SafeHandle webSocketHandle)
static void WebSocketSendWithoutBody(WebSocketBase webSocket, BufferType bufferType)
static void WebSocketCompleteAction(WebSocketBase webSocket, IntPtr actionContext, int bytesTransferred)
static void ValidateArraySegment(ArraySegment< byte > arraySegment, string parameterName)
static void ValidateCloseStatus(WebSocketCloseStatus closeStatus, string statusDescription)
static bool IsStateTerminal(WebSocketState state)
Definition WebSocket.cs:99
static void ThrowOnInvalidState(WebSocketState state, params WebSocketState[] validStates)
Definition WebSocket.cs:82
static string net_Websockets_AlreadyOneOutstandingOperation
Definition SR.cs:158
static string net_WebSockets_Argument_InvalidMessageType
Definition SR.cs:166
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string net_WebSockets_ReceiveAsyncDisallowedAfterCloseAsync
Definition SR.cs:156
static string net_WebSockets_InvalidMessageType
Definition SR.cs:160
static string net_WebSockets_InvalidState_ClosedOrAborted
Definition SR.cs:154
static string net_WebSockets_InvalidBufferType
Definition SR.cs:162
Definition SR.cs:7
static Encoding UTF8
Definition Encoding.cs:526
static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2)
static int CompareExchange(ref int location1, int value, int comparand)
static int Exchange(ref int location1, int value)
static void Exit(object obj)
static void Enter(object obj)
bool Dispose(WaitHandle notifyObject)
Definition Timer.cs:176
bool Change(int dueTime, int period)
Definition Timer.cs:131
Task MultipleWriteAsync(IList< ArraySegment< byte > > buffers, CancellationToken cancellationToken)
Task CloseNetworkConnectionAsync(CancellationToken cancellationToken)
void SwitchToOpaqueMode(WebSocketBase webSocket)
delegate void TimerCallback(object? state)
void ICollection< T >. Add(T item)
double TotalMilliseconds
Definition TimeSpan.cs:46