mscorlib(4.0.0.0) API with additions
_SslStream.cs
2 using System.IO;
3 using System.Net.Sockets;
4 using System.Threading;
5 
7 {
8  internal class _SslStream
9  {
10  private class SplitWriteAsyncProtocolRequest : AsyncProtocolRequest
11  {
12  internal SplitWritesState SplitWritesState;
13 
14  internal SplitWriteAsyncProtocolRequest(LazyAsyncResult userAsyncResult)
15  : base(userAsyncResult)
16  {
17  }
18 
19  internal void SetNextRequest(SplitWritesState splitWritesState, AsyncProtocolCallback callback)
20  {
21  SplitWritesState = splitWritesState;
22  SetNextRequest(null, 0, 0, callback);
23  }
24  }
25 
26  private static AsyncCallback _WriteCallback = WriteCallback;
27 
28  private static AsyncCallback _MulitpleWriteCallback = MulitpleWriteCallback;
29 
30  private static AsyncProtocolCallback _ResumeAsyncWriteCallback = ResumeAsyncWriteCallback;
31 
32  private static AsyncProtocolCallback _ResumeAsyncReadCallback = ResumeAsyncReadCallback;
33 
34  private static AsyncProtocolCallback _ReadHeaderCallback = ReadHeaderCallback;
35 
36  private static AsyncProtocolCallback _ReadFrameCallback = ReadFrameCallback;
37 
38  private const int PinnableReadBufferSize = 16416;
39 
40  private static PinnableBufferCache s_PinnableReadBufferCache = new PinnableBufferCache("System.Net.SslStream", 16416);
41 
42  private const int PinnableWriteBufferSize = 5120;
43 
44  private static PinnableBufferCache s_PinnableWriteBufferCache = new PinnableBufferCache("System.Net.SslStream", 5120);
45 
46  private SslState _SslState;
47 
48  private int _NestedWrite;
49 
50  private int _NestedRead;
51 
52  private byte[] _InternalBuffer;
53 
54  private bool _InternalBufferFromPinnableCache;
55 
56  private byte[] _PinnableOutputBuffer;
57 
58  private byte[] _PinnableOutputBufferInUse;
59 
60  private int _InternalOffset;
61 
62  private int _InternalBufferCount;
63 
64  private FixedSizeReader _Reader;
65 
66  internal bool DataAvailable => InternalBufferCount != 0;
67 
68  private byte[] InternalBuffer => _InternalBuffer;
69 
70  private int InternalOffset => _InternalOffset;
71 
72  private int InternalBufferCount => _InternalBufferCount;
73 
74  internal _SslStream(SslState sslState)
75  {
76  if (PinnableBufferCacheEventSource.Log.IsEnabled())
77  {
78  PinnableBufferCacheEventSource.Log.DebugMessage1("CTOR: In System.Net._SslStream.SslStream", GetHashCode());
79  }
80  _SslState = sslState;
81  _Reader = new FixedSizeReader(_SslState.InnerStream);
82  }
83 
84  private void FreeReadBuffer()
85  {
86  if (_InternalBufferFromPinnableCache)
87  {
88  s_PinnableReadBufferCache.FreeBuffer(_InternalBuffer);
89  _InternalBufferFromPinnableCache = false;
90  }
91  _InternalBuffer = null;
92  }
93 
94  ~_SslStream()
95  {
96  if (_InternalBufferFromPinnableCache)
97  {
98  if (PinnableBufferCacheEventSource.Log.IsEnabled())
99  {
100  PinnableBufferCacheEventSource.Log.DebugMessage2("DTOR: In System.Net._SslStream.~SslStream Freeing Read Buffer", GetHashCode(), PinnableBufferCacheEventSource.AddressOfByteArray(_InternalBuffer));
101  }
102  FreeReadBuffer();
103  }
104  if (_PinnableOutputBuffer != null)
105  {
106  if (PinnableBufferCacheEventSource.Log.IsEnabled())
107  {
108  PinnableBufferCacheEventSource.Log.DebugMessage2("DTOR: In System.Net._SslStream.~SslStream Freeing Write Buffer", GetHashCode(), PinnableBufferCacheEventSource.AddressOfByteArray(_PinnableOutputBuffer));
109  }
110  s_PinnableWriteBufferCache.FreeBuffer(_PinnableOutputBuffer);
111  }
112  }
113 
114  internal int Read(byte[] buffer, int offset, int count)
115  {
116  return ProcessRead(buffer, offset, count, null);
117  }
118 
119  internal void Write(byte[] buffer, int offset, int count)
120  {
121  ProcessWrite(buffer, offset, count, null);
122  }
123 
124  internal void Write(BufferOffsetSize[] buffers)
125  {
126  ProcessWrite(buffers, null);
127  }
128 
129  internal IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
130  {
131  BufferAsyncResult bufferAsyncResult = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback);
132  AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(bufferAsyncResult);
133  ProcessRead(buffer, offset, count, asyncRequest);
134  return bufferAsyncResult;
135  }
136 
137  internal int EndRead(IAsyncResult asyncResult)
138  {
139  if (asyncResult == null)
140  {
141  throw new ArgumentNullException("asyncResult");
142  }
143  BufferAsyncResult bufferAsyncResult = asyncResult as BufferAsyncResult;
144  if (bufferAsyncResult == null)
145  {
146  throw new ArgumentException(SR.GetString("net_io_async_result", asyncResult.GetType().FullName), "asyncResult");
147  }
148  if (Interlocked.Exchange(ref _NestedRead, 0) == 0)
149  {
150  throw new InvalidOperationException(SR.GetString("net_io_invalidendcall", "EndRead"));
151  }
152  bufferAsyncResult.InternalWaitForCompletion();
153  if (bufferAsyncResult.Result is Exception)
154  {
155  if (bufferAsyncResult.Result is IOException)
156  {
157  throw (Exception)bufferAsyncResult.Result;
158  }
159  throw new IOException(SR.GetString("net_io_read"), (Exception)bufferAsyncResult.Result);
160  }
161  return (int)bufferAsyncResult.Result;
162  }
163 
164  internal IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
165  {
166  LazyAsyncResult lazyAsyncResult = new LazyAsyncResult(this, asyncState, asyncCallback);
167  AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(lazyAsyncResult);
168  ProcessWrite(buffer, offset, count, asyncRequest);
169  return lazyAsyncResult;
170  }
171 
172  internal IAsyncResult BeginWrite(BufferOffsetSize[] buffers, AsyncCallback asyncCallback, object asyncState)
173  {
174  LazyAsyncResult lazyAsyncResult = new LazyAsyncResult(this, asyncState, asyncCallback);
175  SplitWriteAsyncProtocolRequest asyncRequest = new SplitWriteAsyncProtocolRequest(lazyAsyncResult);
176  ProcessWrite(buffers, asyncRequest);
177  return lazyAsyncResult;
178  }
179 
180  internal void EndWrite(IAsyncResult asyncResult)
181  {
182  if (asyncResult == null)
183  {
184  throw new ArgumentNullException("asyncResult");
185  }
186  LazyAsyncResult lazyAsyncResult = asyncResult as LazyAsyncResult;
187  if (lazyAsyncResult == null)
188  {
189  throw new ArgumentException(SR.GetString("net_io_async_result", asyncResult.GetType().FullName), "asyncResult");
190  }
191  if (Interlocked.Exchange(ref _NestedWrite, 0) == 0)
192  {
193  throw new InvalidOperationException(SR.GetString("net_io_invalidendcall", "EndWrite"));
194  }
195  lazyAsyncResult.InternalWaitForCompletion();
196  if (lazyAsyncResult.Result is Exception)
197  {
198  if (lazyAsyncResult.Result is IOException)
199  {
200  throw (Exception)lazyAsyncResult.Result;
201  }
202  throw new IOException(SR.GetString("net_io_write"), (Exception)lazyAsyncResult.Result);
203  }
204  }
205 
206  private void DecrementInternalBufferCount(int decrCount)
207  {
208  _InternalOffset += decrCount;
209  _InternalBufferCount -= decrCount;
210  }
211 
212  private void EnsureInternalBufferSize(int curOffset, int addSize)
213  {
214  if (_InternalBuffer == null || _InternalBuffer.Length < addSize + curOffset)
215  {
216  bool internalBufferFromPinnableCache = _InternalBufferFromPinnableCache;
217  byte[] internalBuffer = _InternalBuffer;
218  int num = addSize + curOffset;
219  if (num <= 16416)
220  {
221  if (PinnableBufferCacheEventSource.Log.IsEnabled())
222  {
223  PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.EnsureInternalBufferSize IS pinnable", GetHashCode(), num);
224  }
225  _InternalBufferFromPinnableCache = true;
226  _InternalBuffer = s_PinnableReadBufferCache.AllocateBuffer();
227  }
228  else
229  {
230  if (PinnableBufferCacheEventSource.Log.IsEnabled())
231  {
232  PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.EnsureInternalBufferSize NOT pinnable", GetHashCode(), num);
233  }
234  _InternalBufferFromPinnableCache = false;
235  _InternalBuffer = new byte[num];
236  }
237  if (internalBuffer != null && curOffset != 0)
238  {
239  Buffer.BlockCopy(internalBuffer, 0, _InternalBuffer, 0, curOffset);
240  }
241  if (internalBufferFromPinnableCache)
242  {
243  s_PinnableReadBufferCache.FreeBuffer(internalBuffer);
244  }
245  }
246  _InternalOffset = curOffset;
247  _InternalBufferCount = curOffset + addSize;
248  }
249 
250  private void ValidateParameters(byte[] buffer, int offset, int count)
251  {
252  if (buffer == null)
253  {
254  throw new ArgumentNullException("buffer");
255  }
256  if (offset < 0)
257  {
258  throw new ArgumentOutOfRangeException("offset");
259  }
260  if (count < 0)
261  {
262  throw new ArgumentOutOfRangeException("count");
263  }
264  if (count > buffer.Length - offset)
265  {
266  throw new ArgumentOutOfRangeException("count", SR.GetString("net_offset_plus_count"));
267  }
268  }
269 
270  private void ProcessWrite(BufferOffsetSize[] buffers, SplitWriteAsyncProtocolRequest asyncRequest)
271  {
272  _SslState.CheckThrow(authSuccessCheck: true, shutdownCheck: true);
273  foreach (BufferOffsetSize bufferOffsetSize in buffers)
274  {
275  ValidateParameters(bufferOffsetSize.Buffer, bufferOffsetSize.Offset, bufferOffsetSize.Size);
276  }
277  if (Interlocked.Exchange(ref _NestedWrite, 1) == 1)
278  {
279  throw new NotSupportedException(SR.GetString("net_io_invalidnestedcall", (asyncRequest != null) ? "BeginWrite" : "Write", "write"));
280  }
281  bool flag = false;
282  try
283  {
284  SplitWritesState splitWritesState = new SplitWritesState(buffers);
285  asyncRequest?.SetNextRequest(splitWritesState, _ResumeAsyncWriteCallback);
286  StartWriting(splitWritesState, asyncRequest);
287  }
288  catch (Exception ex)
289  {
290  _SslState.FinishWrite();
291  flag = true;
292  if (ex is IOException)
293  {
294  throw;
295  }
296  throw new IOException(SR.GetString("net_io_write"), ex);
297  }
298  finally
299  {
300  if ((asyncRequest == null) | flag)
301  {
302  _NestedWrite = 0;
303  }
304  }
305  }
306 
307  private void ProcessWrite(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
308  {
309  if (_SslState.LastPayload != null)
310  {
311  BufferOffsetSize[] buffers = new BufferOffsetSize[1]
312  {
313  new BufferOffsetSize(buffer, offset, count, copyBuffer: false)
314  };
315  if (asyncRequest != null)
316  {
317  ProcessWrite(buffers, new SplitWriteAsyncProtocolRequest(asyncRequest.UserAsyncResult));
318  }
319  else
320  {
321  ProcessWrite(buffers, null);
322  }
323  return;
324  }
325  ValidateParameters(buffer, offset, count);
326  _SslState.CheckThrow(authSuccessCheck: true, shutdownCheck: true);
327  if (Interlocked.Exchange(ref _NestedWrite, 1) == 1)
328  {
329  throw new NotSupportedException(SR.GetString("net_io_invalidnestedcall", (asyncRequest != null) ? "BeginWrite" : "Write", "write"));
330  }
331  bool flag = false;
332  try
333  {
334  StartWriting(buffer, offset, count, asyncRequest);
335  }
336  catch (Exception ex)
337  {
338  _SslState.FinishWrite();
339  flag = true;
340  if (ex is IOException)
341  {
342  throw;
343  }
344  throw new IOException(SR.GetString("net_io_write"), ex);
345  }
346  finally
347  {
348  if ((asyncRequest == null) | flag)
349  {
350  _NestedWrite = 0;
351  }
352  }
353  }
354 
355  private void StartWriting(SplitWritesState splitWrite, SplitWriteAsyncProtocolRequest asyncRequest)
356  {
357  while (!splitWrite.IsDone)
358  {
359  if (_SslState.CheckEnqueueWrite(asyncRequest))
360  {
361  return;
362  }
363  byte[] lastHandshakePayload = null;
364  if (_SslState.LastPayload != null)
365  {
366  lastHandshakePayload = _SslState.LastPayload;
367  _SslState.LastPayloadConsumed();
368  }
369  BufferOffsetSize[] nextBuffers = splitWrite.GetNextBuffers();
370  nextBuffers = EncryptBuffers(nextBuffers, lastHandshakePayload);
371  if (asyncRequest != null)
372  {
373  IAsyncResult asyncResult = ((NetworkStream)_SslState.InnerStream).BeginMultipleWrite(nextBuffers, _MulitpleWriteCallback, asyncRequest);
374  if (!asyncResult.CompletedSynchronously)
375  {
376  return;
377  }
378  ((NetworkStream)_SslState.InnerStream).EndMultipleWrite(asyncResult);
379  }
380  else
381  {
382  ((NetworkStream)_SslState.InnerStream).MultipleWrite(nextBuffers);
383  }
384  _SslState.FinishWrite();
385  }
386  asyncRequest?.CompleteUser();
387  }
388 
389  private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload)
390  {
391  List<BufferOffsetSize> list = null;
392  SecurityStatus securityStatus = SecurityStatus.OK;
393  BufferOffsetSize[] array = buffers;
394  foreach (BufferOffsetSize bufferOffsetSize in array)
395  {
396  int num = Math.Min(bufferOffsetSize.Size, _SslState.MaxDataSize);
397  byte[] outBuffer = null;
398  securityStatus = _SslState.EncryptData(bufferOffsetSize.Buffer, bufferOffsetSize.Offset, num, ref outBuffer, out int outSize);
399  if (securityStatus != 0)
400  {
401  break;
402  }
403  if (num != bufferOffsetSize.Size || list != null)
404  {
405  if (list == null)
406  {
407  list = new List<BufferOffsetSize>(buffers.Length * (bufferOffsetSize.Size / num + 1));
408  if (lastHandshakePayload != null)
409  {
410  list.Add(new BufferOffsetSize(lastHandshakePayload, copyBuffer: false));
411  }
412  BufferOffsetSize[] array2 = buffers;
413  foreach (BufferOffsetSize bufferOffsetSize2 in array2)
414  {
415  if (bufferOffsetSize2 == bufferOffsetSize)
416  {
417  break;
418  }
419  list.Add(bufferOffsetSize2);
420  }
421  }
422  list.Add(new BufferOffsetSize(outBuffer, 0, outSize, copyBuffer: false));
423  while ((bufferOffsetSize.Size -= num) != 0)
424  {
425  bufferOffsetSize.Offset += num;
426  num = Math.Min(bufferOffsetSize.Size, _SslState.MaxDataSize);
427  outBuffer = null;
428  securityStatus = _SslState.EncryptData(bufferOffsetSize.Buffer, bufferOffsetSize.Offset, num, ref outBuffer, out outSize);
429  if (securityStatus != 0)
430  {
431  break;
432  }
433  list.Add(new BufferOffsetSize(outBuffer, 0, outSize, copyBuffer: false));
434  }
435  }
436  else
437  {
438  bufferOffsetSize.Buffer = outBuffer;
439  bufferOffsetSize.Offset = 0;
440  bufferOffsetSize.Size = outSize;
441  }
442  if (securityStatus != 0)
443  {
444  break;
445  }
446  }
447  if (securityStatus != 0)
448  {
449  ProtocolToken protocolToken = new ProtocolToken(null, securityStatus);
450  throw new IOException(SR.GetString("net_io_encrypt"), protocolToken.GetException());
451  }
452  if (list != null)
453  {
454  buffers = list.ToArray();
455  }
456  else if (lastHandshakePayload != null)
457  {
458  BufferOffsetSize[] array3 = new BufferOffsetSize[buffers.Length + 1];
459  Array.Copy(buffers, 0, array3, 1, buffers.Length);
460  array3[0] = new BufferOffsetSize(lastHandshakePayload, copyBuffer: false);
461  buffers = array3;
462  }
463  return buffers;
464  }
465 
466  private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
467  {
468  asyncRequest?.SetNextRequest(buffer, offset, count, _ResumeAsyncWriteCallback);
469  if (count >= 0)
470  {
471  byte[] outBuffer = null;
472  if (_PinnableOutputBufferInUse == null)
473  {
474  if (_PinnableOutputBuffer == null)
475  {
476  _PinnableOutputBuffer = s_PinnableWriteBufferCache.AllocateBuffer();
477  }
478  _PinnableOutputBufferInUse = buffer;
479  outBuffer = _PinnableOutputBuffer;
480  if (PinnableBufferCacheEventSource.Log.IsEnabled())
481  {
482  PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Trying Pinnable", GetHashCode(), count, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
483  }
484  }
485  else if (PinnableBufferCacheEventSource.Log.IsEnabled())
486  {
487  PinnableBufferCacheEventSource.Log.DebugMessage2("In System.Net._SslStream.StartWriting BufferInUse", GetHashCode(), count);
488  }
489  do
490  {
491  if (_SslState.CheckEnqueueWrite(asyncRequest))
492  {
493  return;
494  }
495  int num = Math.Min(count, _SslState.MaxDataSize);
496  int outSize;
497  SecurityStatus securityStatus = _SslState.EncryptData(buffer, offset, num, ref outBuffer, out outSize);
498  if (securityStatus != 0)
499  {
500  ProtocolToken protocolToken = new ProtocolToken(null, securityStatus);
501  throw new IOException(SR.GetString("net_io_encrypt"), protocolToken.GetException());
502  }
503  if (PinnableBufferCacheEventSource.Log.IsEnabled())
504  {
505  PinnableBufferCacheEventSource.Log.DebugMessage3("In System.Net._SslStream.StartWriting Got Encrypted Buffer", GetHashCode(), outSize, PinnableBufferCacheEventSource.AddressOfByteArray(outBuffer));
506  }
507  if (asyncRequest != null)
508  {
509  asyncRequest.SetNextRequest(buffer, offset + num, count - num, _ResumeAsyncWriteCallback);
510  IAsyncResult asyncResult = _SslState.InnerStream.BeginWrite(outBuffer, 0, outSize, _WriteCallback, asyncRequest);
511  if (!asyncResult.CompletedSynchronously)
512  {
513  return;
514  }
515  _SslState.InnerStream.EndWrite(asyncResult);
516  }
517  else
518  {
519  _SslState.InnerStream.Write(outBuffer, 0, outSize);
520  }
521  offset += num;
522  count -= num;
523  _SslState.FinishWrite();
524  }
525  while (count != 0);
526  }
527  asyncRequest?.CompleteUser();
528  if (buffer == _PinnableOutputBufferInUse)
529  {
530  _PinnableOutputBufferInUse = null;
531  if (PinnableBufferCacheEventSource.Log.IsEnabled())
532  {
533  PinnableBufferCacheEventSource.Log.DebugMessage1("In System.Net._SslStream.StartWriting Freeing buffer.", GetHashCode());
534  }
535  }
536  }
537 
538  private int ProcessRead(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
539  {
540  ValidateParameters(buffer, offset, count);
541  if (Interlocked.Exchange(ref _NestedRead, 1) == 1)
542  {
543  throw new NotSupportedException(SR.GetString("net_io_invalidnestedcall", (asyncRequest != null) ? "BeginRead" : "Read", "read"));
544  }
545  bool flag = false;
546  try
547  {
548  if (InternalBufferCount != 0)
549  {
550  int num = (InternalBufferCount > count) ? count : InternalBufferCount;
551  if (num != 0)
552  {
553  Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, num);
554  DecrementInternalBufferCount(num);
555  }
556  asyncRequest?.CompleteUser(num);
557  return num;
558  }
559  return StartReading(buffer, offset, count, asyncRequest);
560  }
561  catch (Exception ex)
562  {
563  _SslState.FinishRead(null);
564  flag = true;
565  if (ex is IOException)
566  {
567  throw;
568  }
569  throw new IOException(SR.GetString("net_io_read"), ex);
570  }
571  finally
572  {
573  if ((asyncRequest == null) | flag)
574  {
575  _NestedRead = 0;
576  }
577  }
578  }
579 
580  private int StartReading(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
581  {
582  int num = 0;
583  do
584  {
585  asyncRequest?.SetNextRequest(buffer, offset, count, _ResumeAsyncReadCallback);
586  int num2 = _SslState.CheckEnqueueRead(buffer, offset, count, asyncRequest);
587  switch (num2)
588  {
589  case 0:
590  return 0;
591  case -1:
592  continue;
593  }
594  asyncRequest?.CompleteUser(num2);
595  return num2;
596  }
597  while ((num = StartFrameHeader(buffer, offset, count, asyncRequest)) == -1);
598  return num;
599  }
600 
601  private int StartFrameHeader(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
602  {
603  int num = 0;
604  EnsureInternalBufferSize(0, 5);
605  if (asyncRequest != null)
606  {
607  asyncRequest.SetNextRequest(InternalBuffer, 0, 5, _ReadHeaderCallback);
608  _Reader.AsyncReadPacket(asyncRequest);
609  if (!asyncRequest.MustCompleteSynchronously)
610  {
611  return 0;
612  }
613  num = asyncRequest.Result;
614  }
615  else
616  {
617  num = _Reader.ReadPacket(InternalBuffer, 0, 5);
618  }
619  return StartFrameBody(num, buffer, offset, count, asyncRequest);
620  }
621 
622  private int StartFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
623  {
624  if (readBytes == 0)
625  {
626  DecrementInternalBufferCount(InternalBufferCount);
627  asyncRequest?.CompleteUser(0);
628  return 0;
629  }
630  readBytes = _SslState.GetRemainingFrameSize(InternalBuffer, readBytes);
631  if (readBytes < 0)
632  {
633  throw new IOException(SR.GetString("net_frame_read_size"));
634  }
635  EnsureInternalBufferSize(5, readBytes);
636  if (asyncRequest != null)
637  {
638  asyncRequest.SetNextRequest(InternalBuffer, 5, readBytes, _ReadFrameCallback);
639  _Reader.AsyncReadPacket(asyncRequest);
640  if (!asyncRequest.MustCompleteSynchronously)
641  {
642  return 0;
643  }
644  readBytes = asyncRequest.Result;
645  }
646  else
647  {
648  readBytes = _Reader.ReadPacket(InternalBuffer, 5, readBytes);
649  }
650  return ProcessFrameBody(readBytes, buffer, offset, count, asyncRequest);
651  }
652 
653  private int ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest)
654  {
655  if (readBytes == 0)
656  {
657  throw new IOException(SR.GetString("net_io_eof"));
658  }
659  readBytes += 5;
660  int offset2 = 0;
661  SecurityStatus securityStatus = _SslState.DecryptData(InternalBuffer, ref offset2, ref readBytes);
662  if (securityStatus != 0)
663  {
664  byte[] array = null;
665  if (readBytes != 0)
666  {
667  array = new byte[readBytes];
668  Buffer.BlockCopy(InternalBuffer, offset2, array, 0, readBytes);
669  }
670  DecrementInternalBufferCount(InternalBufferCount);
671  return ProcessReadErrorCode(securityStatus, buffer, offset, count, asyncRequest, array);
672  }
673  if (readBytes == 0 && count != 0)
674  {
675  DecrementInternalBufferCount(InternalBufferCount);
676  return -1;
677  }
678  EnsureInternalBufferSize(0, offset2 + readBytes);
679  DecrementInternalBufferCount(offset2);
680  if (readBytes > count)
681  {
682  readBytes = count;
683  }
684  Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, readBytes);
685  DecrementInternalBufferCount(readBytes);
686  _SslState.FinishRead(null);
687  asyncRequest?.CompleteUser(readBytes);
688  return readBytes;
689  }
690 
691  private int ProcessReadErrorCode(SecurityStatus errorCode, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest, byte[] extraBuffer)
692  {
693  ProtocolToken protocolToken = new ProtocolToken(null, errorCode);
694  if (protocolToken.Renegotiate)
695  {
696  _SslState.ReplyOnReAuthentication(extraBuffer);
697  return -1;
698  }
699  if (protocolToken.CloseConnection)
700  {
701  _SslState.FinishRead(null);
702  asyncRequest?.CompleteUser(0);
703  return 0;
704  }
705  throw new IOException(SR.GetString("net_io_decrypt"), protocolToken.GetException());
706  }
707 
708  private static void WriteCallback(IAsyncResult transportResult)
709  {
710  if (!transportResult.CompletedSynchronously)
711  {
712  AsyncProtocolRequest asyncProtocolRequest = (AsyncProtocolRequest)transportResult.AsyncState;
713  _SslStream sslStream = (_SslStream)asyncProtocolRequest.AsyncObject;
714  try
715  {
716  sslStream._SslState.InnerStream.EndWrite(transportResult);
717  sslStream._SslState.FinishWrite();
718  if (asyncProtocolRequest.Count == 0)
719  {
720  asyncProtocolRequest.Count = -1;
721  }
722  sslStream.StartWriting(asyncProtocolRequest.Buffer, asyncProtocolRequest.Offset, asyncProtocolRequest.Count, asyncProtocolRequest);
723  }
724  catch (Exception e)
725  {
726  if (asyncProtocolRequest.IsUserCompleted)
727  {
728  throw;
729  }
730  sslStream._SslState.FinishWrite();
731  asyncProtocolRequest.CompleteWithError(e);
732  }
733  }
734  }
735 
736  private static void MulitpleWriteCallback(IAsyncResult transportResult)
737  {
738  if (!transportResult.CompletedSynchronously)
739  {
740  SplitWriteAsyncProtocolRequest splitWriteAsyncProtocolRequest = (SplitWriteAsyncProtocolRequest)transportResult.AsyncState;
741  _SslStream sslStream = (_SslStream)splitWriteAsyncProtocolRequest.AsyncObject;
742  try
743  {
744  ((NetworkStream)sslStream._SslState.InnerStream).EndMultipleWrite(transportResult);
745  sslStream._SslState.FinishWrite();
746  sslStream.StartWriting(splitWriteAsyncProtocolRequest.SplitWritesState, splitWriteAsyncProtocolRequest);
747  }
748  catch (Exception e)
749  {
750  if (splitWriteAsyncProtocolRequest.IsUserCompleted)
751  {
752  throw;
753  }
754  sslStream._SslState.FinishWrite();
755  splitWriteAsyncProtocolRequest.CompleteWithError(e);
756  }
757  }
758  }
759 
760  private static void ResumeAsyncReadCallback(AsyncProtocolRequest request)
761  {
762  try
763  {
764  ((_SslStream)request.AsyncObject).StartReading(request.Buffer, request.Offset, request.Count, request);
765  }
766  catch (Exception e)
767  {
768  if (request.IsUserCompleted)
769  {
770  throw;
771  }
772  ((_SslStream)request.AsyncObject)._SslState.FinishRead(null);
773  request.CompleteWithError(e);
774  }
775  }
776 
777  private static void ResumeAsyncWriteCallback(AsyncProtocolRequest asyncRequest)
778  {
779  try
780  {
781  SplitWriteAsyncProtocolRequest splitWriteAsyncProtocolRequest = asyncRequest as SplitWriteAsyncProtocolRequest;
782  if (splitWriteAsyncProtocolRequest != null)
783  {
784  ((_SslStream)asyncRequest.AsyncObject).StartWriting(splitWriteAsyncProtocolRequest.SplitWritesState, splitWriteAsyncProtocolRequest);
785  }
786  else
787  {
788  ((_SslStream)asyncRequest.AsyncObject).StartWriting(asyncRequest.Buffer, asyncRequest.Offset, asyncRequest.Count, asyncRequest);
789  }
790  }
791  catch (Exception e)
792  {
793  if (asyncRequest.IsUserCompleted)
794  {
795  throw;
796  }
797  ((_SslStream)asyncRequest.AsyncObject)._SslState.FinishWrite();
798  asyncRequest.CompleteWithError(e);
799  }
800  }
801 
802  private static void ReadHeaderCallback(AsyncProtocolRequest asyncRequest)
803  {
804  try
805  {
806  _SslStream sslStream = (_SslStream)asyncRequest.AsyncObject;
807  BufferAsyncResult bufferAsyncResult = (BufferAsyncResult)asyncRequest.UserAsyncResult;
808  if (-1 == sslStream.StartFrameBody(asyncRequest.Result, bufferAsyncResult.Buffer, bufferAsyncResult.Offset, bufferAsyncResult.Count, asyncRequest))
809  {
810  sslStream.StartReading(bufferAsyncResult.Buffer, bufferAsyncResult.Offset, bufferAsyncResult.Count, asyncRequest);
811  }
812  }
813  catch (Exception e)
814  {
815  if (asyncRequest.IsUserCompleted)
816  {
817  throw;
818  }
819  asyncRequest.CompleteWithError(e);
820  }
821  }
822 
823  private static void ReadFrameCallback(AsyncProtocolRequest asyncRequest)
824  {
825  try
826  {
827  _SslStream sslStream = (_SslStream)asyncRequest.AsyncObject;
828  BufferAsyncResult bufferAsyncResult = (BufferAsyncResult)asyncRequest.UserAsyncResult;
829  if (-1 == sslStream.ProcessFrameBody(asyncRequest.Result, bufferAsyncResult.Buffer, bufferAsyncResult.Offset, bufferAsyncResult.Count, asyncRequest))
830  {
831  sslStream.StartReading(bufferAsyncResult.Buffer, bufferAsyncResult.Offset, bufferAsyncResult.Count, asyncRequest);
832  }
833  }
834  catch (Exception e)
835  {
836  if (asyncRequest.IsUserCompleted)
837  {
838  throw;
839  }
840  asyncRequest.CompleteWithError(e);
841  }
842  }
843  }
844 }
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
static sbyte Min(sbyte val1, sbyte val2)
Returns the smaller of two 8-bit signed integers.
Definition: Math.cs:762
Definition: __Canon.cs:3
The exception that is thrown when the value of an argument is outside the allowable range of values a...
delegate void AsyncCallback(IAsyncResult ar)
References a method to be called when a corresponding asynchronous operation completes.
object AsyncState
Gets a user-defined object that qualifies or contains information about an asynchronous operation.
Definition: IAsyncResult.cs:34
static int Exchange(ref int location1, int value)
Sets a 32-bit signed integer to a specified value and returns the original value, as an atomic operat...
Represents the status of an asynchronous operation.
Definition: IAsyncResult.cs:9
static void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count)
Copies a specified number of bytes from a source array starting at a particular offset to a destinati...
The exception that is thrown when an I/O error occurs.
Definition: IOException.cs:10
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition: Array.cs:17
bool CompletedSynchronously
Gets a value that indicates whether the asynchronous operation completed synchronously.
Definition: IAsyncResult.cs:44
The exception that is thrown when one of the arguments provided to a method is not valid.
static void Copy(Array sourceArray, Array destinationArray, int length)
Copies a range of elements from an T:System.Array starting at the first element and pastes them into ...
Definition: Array.cs:1275
Represents a strongly typed list of objects that can be accessed by index. Provides methods to search...
Definition: List.cs:14
Represents errors that occur during application execution.To browse the .NET Framework source code fo...
Definition: Exception.cs:22
The exception that is thrown when a method call is invalid for the object's current state.
Manipulates arrays of primitive types.
Definition: Buffer.cs:11
Provides constants and static methods for trigonometric, logarithmic, and other common mathematical f...
Definition: Math.cs:10
The exception that is thrown when an invoked method is not supported, or when there is an attempt to ...
Provides atomic operations for variables that are shared by multiple threads.
Definition: Interlocked.cs:10
Provides the underlying stream of data for network access.