1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security;
using System.Threading;
namespace System.Net.Sockets
{
partial class SocketAsyncEventArgs
{
// Single buffer.
private Memory<byte> _buffer;
private int _offset;
private int _count;
private bool _bufferIsExplicitArray;
// BufferList property variables.
private IList<ArraySegment<byte>> _bufferList;
private List<ArraySegment<byte>> _bufferListInternal;
public byte[] Buffer
{
get
{
if (_bufferIsExplicitArray)
{
bool success = MemoryMarshal.TryGetArray(_buffer, out ArraySegment<byte> arraySegment);
Debug.Assert(success);
return arraySegment.Array;
}
return null;
}
}
public Memory<byte> MemoryBuffer => _buffer;
public int Offset => _offset;
public int Count => _count;
// NOTE: this property is mutually exclusive with Buffer.
// Setting this property with an existing non-null Buffer will throw.
public IList<ArraySegment<byte>> BufferList
{
get { return _bufferList; }
set
{
if (value != null)
{
if (!_buffer.Equals(default))
{
// Can't have both set
throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(Buffer)));
}
// Copy the user-provided list into our internal buffer list,
// so that we are not affected by subsequent changes to the list.
// We reuse the existing list so that we can avoid reallocation when possible.
int bufferCount = value.Count;
if (_bufferListInternal == null)
{
_bufferListInternal = new List<ArraySegment<byte>>(bufferCount);
}
else
{
_bufferListInternal.Clear();
}
for (int i = 0; i < bufferCount; i++)
{
ArraySegment<byte> buffer = value[i];
RangeValidationHelpers.ValidateSegment(buffer);
_bufferListInternal.Add(buffer);
}
}
else
{
_bufferListInternal?.Clear();
}
_bufferList = value;
}
}
public void SetBuffer(int offset, int count)
{
if (!_buffer.Equals(default))
{
if ((uint)offset > _buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if ((uint)count > (_buffer.Length - offset))
{
throw new ArgumentOutOfRangeException(nameof(count));
}
if (!_bufferIsExplicitArray)
{
throw new InvalidOperationException(SR.InvalidOperation_BufferNotExplicitArray);
}
_offset = offset;
_count = count;
}
}
internal void CopyBufferFrom(SocketAsyncEventArgs source)
{
_buffer = source._buffer;
_offset = source._offset;
_count = source._count;
_bufferIsExplicitArray = source._bufferIsExplicitArray;
}
public void SetBuffer(byte[] buffer, int offset, int count)
{
if (buffer == null)
{
// Clear out existing buffer.
_buffer = default;
_offset = 0;
_count = 0;
_bufferIsExplicitArray = false;
}
else
{
// Can't have both Buffer and BufferList.
if (_bufferList != null)
{
throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList)));
}
// Offset and count can't be negative and the
// combination must be in bounds of the array.
if ((uint)offset > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if ((uint)count > (buffer.Length - offset))
{
throw new ArgumentOutOfRangeException(nameof(count));
}
_buffer = buffer;
_offset = offset;
_count = count;
_bufferIsExplicitArray = true;
}
}
public void SetBuffer(Memory<byte> buffer)
{
if (buffer.Length != 0 && _bufferList != null)
{
throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList)));
}
_buffer = buffer;
_offset = 0;
_count = buffer.Length;
_bufferIsExplicitArray = false;
}
internal bool HasMultipleBuffers => _bufferList != null;
}
}
|