We bumped incorrectly a few times, so in order to make it right again, merge master into 2019-08
This commit is contained in:
Steve Pfister 2019-11-01 09:42:00 -04:00 коммит произвёл GitHub
Родитель 8524b2bfca
Коммит ce3063888d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
23 изменённых файлов: 653 добавлений и 186 удалений

Просмотреть файл

@ -15,9 +15,14 @@ internal static partial class Interop
{
private readonly Status _minorStatus;
public Status MajorStatus
{
get { return (Status)HResult; }
}
public Status MinorStatus
{
get { return _minorStatus;}
get { return _minorStatus; }
}
public GssApiException(string message) : base(message)
@ -25,20 +30,44 @@ internal static partial class Interop
}
public GssApiException(Status majorStatus, Status minorStatus)
: base(GetGssApiDisplayStatus(majorStatus, minorStatus))
: base(GetGssApiDisplayStatus(majorStatus, minorStatus, null))
{
HResult = (int)majorStatus;
_minorStatus = minorStatus;
}
private static string GetGssApiDisplayStatus(Status majorStatus, Status minorStatus)
public GssApiException(Status majorStatus, Status minorStatus, string helpText)
: base(GetGssApiDisplayStatus(majorStatus, minorStatus, helpText))
{
HResult = (int)majorStatus;
_minorStatus = minorStatus;
}
private static string GetGssApiDisplayStatus(Status majorStatus, Status minorStatus, string helpText)
{
string majorError = GetGssApiDisplayStatus(majorStatus, isMinor: false);
string minorError = GetGssApiDisplayStatus(minorStatus, isMinor: true);
string errorMessage;
return (majorError != null && minorError != null) ?
SR.Format(SR.net_gssapi_operation_failed_detailed, majorError, minorError) :
SR.Format(SR.net_gssapi_operation_failed, majorStatus.ToString("x"), minorStatus.ToString("x"));
if (minorStatus != Status.GSS_S_COMPLETE)
{
string minorError = GetGssApiDisplayStatus(minorStatus, isMinor: true);
errorMessage = (majorError != null && minorError != null) ?
SR.Format(SR.net_gssapi_operation_failed_detailed, majorError, minorError) :
SR.Format(SR.net_gssapi_operation_failed, majorStatus.ToString("x"), minorStatus.ToString("x"));
}
else
{
errorMessage = (majorError != null) ?
SR.Format(SR.net_gssapi_operation_failed_detailed_majoronly, majorError) :
SR.Format(SR.net_gssapi_operation_failed_majoronly, majorStatus.ToString("x"));
}
if (!string.IsNullOrEmpty(helpText))
{
return errorMessage + " " + helpText;
}
return errorMessage;
}
private static string GetGssApiDisplayStatus(Status status, bool isMinor)
@ -60,4 +89,4 @@ internal static partial class Interop
}
}
}
}
}

Просмотреть файл

@ -14,7 +14,7 @@ internal static partial class Interop
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct GssBuffer : IDisposable
{
internal UInt64 _length;
internal ulong _length;
internal IntPtr _data;
internal int Copy(byte[] destination, int offset)
@ -66,11 +66,11 @@ internal static partial class Interop
#if DEBUG
static GssBuffer()
{
// Verify managed size on both 32-bit and 64-bit matches the PAL_GssBuffer
// Verify managed size on both 32-bit and 64-bit matches the PAL_GssBuffer
// native struct size, which is also padded on 32-bit.
Debug.Assert(Marshal.SizeOf<GssBuffer>() == 16);
}
#endif
}
}
}
}

Просмотреть файл

@ -38,4 +38,4 @@ internal static partial class Interop
// No-op that exists to provide a hook for other static constructors
}
}
}
}

Просмотреть файл

@ -12,11 +12,120 @@ internal static partial class Interop
{
internal static partial class NetSecurityNative
{
#if ENABLE_GSS
#if !ENABLE_GSS
internal static void ReleaseGssBuffer(
IntPtr bufferPtr,
ulong length) => throw new PlatformNotSupportedException ();
internal static Status DisplayMinorStatus(
out Status minorStatus,
Status statusValue,
ref GssBuffer buffer) => throw new PlatformNotSupportedException ();
internal static Status DisplayMajorStatus(
out Status minorStatus,
Status statusValue,
ref GssBuffer buffer) => throw new PlatformNotSupportedException ();
internal static Status ImportUserName(
out Status minorStatus,
string inputName,
int inputNameByteCount,
out SafeGssNameHandle outputName) => throw new PlatformNotSupportedException ();
internal static Status ImportPrincipalName(
out Status minorStatus,
string inputName,
int inputNameByteCount,
out SafeGssNameHandle outputName) => throw new PlatformNotSupportedException ();
internal static Status ReleaseName(
out Status minorStatus,
ref IntPtr inputName) => throw new PlatformNotSupportedException ();
internal static Status InitiateCredSpNego(
out Status minorStatus,
SafeGssNameHandle desiredName,
out SafeGssCredHandle outputCredHandle) => throw new PlatformNotSupportedException ();
internal static Status InitiateCredWithPassword(
out Status minorStatus,
bool isNtlm,
SafeGssNameHandle desiredName,
string password,
int passwordLen,
out SafeGssCredHandle outputCredHandle) => throw new PlatformNotSupportedException ();
internal static Status ReleaseCred(
out Status minorStatus,
ref IntPtr credHandle) => throw new PlatformNotSupportedException ();
internal static Status InitSecContext(
out Status minorStatus,
SafeGssCredHandle initiatorCredHandle,
ref SafeGssContextHandle contextHandle,
bool isNtlmOnly,
SafeGssNameHandle targetName,
uint reqFlags,
byte[] inputBytes,
int inputLength,
ref GssBuffer token,
out uint retFlags,
out int isNtlmUsed) => throw new PlatformNotSupportedException ();
internal static Status InitSecContext(
out Status minorStatus,
SafeGssCredHandle initiatorCredHandle,
ref SafeGssContextHandle contextHandle,
bool isNtlmOnly,
IntPtr cbt,
int cbtSize,
SafeGssNameHandle targetName,
uint reqFlags,
byte[] inputBytes,
int inputLength,
ref GssBuffer token,
out uint retFlags,
out int isNtlmUsed) => throw new PlatformNotSupportedException ();
internal static Status AcceptSecContext(
out Status minorStatus,
ref SafeGssContextHandle acceptContextHandle,
byte[] inputBytes,
int inputLength,
ref GssBuffer token,
out uint retFlags) => throw new PlatformNotSupportedException ();
internal static Status DeleteSecContext(
out Status minorStatus,
ref IntPtr contextHandle) => throw new PlatformNotSupportedException ();
internal static Status GetUser(
out Status minorStatus,
SafeGssContextHandle acceptContextHandle,
ref GssBuffer token) => throw new PlatformNotSupportedException ();
private static Status Wrap(
out Status minorStatus,
SafeGssContextHandle contextHandle,
bool isEncrypt,
byte[] inputBytes,
int offset,
int count,
ref GssBuffer outBuffer) => throw new PlatformNotSupportedException ();
private static Status Unwrap(
out Status minorStatus,
SafeGssContextHandle contextHandle,
byte[] inputBytes,
int offset,
int count,
ref GssBuffer outBuffer) => throw new PlatformNotSupportedException ();
#else
[DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ReleaseGssBuffer")]
internal static extern void ReleaseGssBuffer(
IntPtr bufferPtr,
UInt64 length);
ulong length);
[DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_DisplayMinorStatus")]
internal static extern Status DisplayMinorStatus(
@ -83,19 +192,42 @@ internal static partial class Interop
out uint retFlags,
out int isNtlmUsed);
[DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitSecContextEx")]
internal static extern Status InitSecContext(
out Status minorStatus,
SafeGssCredHandle initiatorCredHandle,
ref SafeGssContextHandle contextHandle,
bool isNtlmOnly,
IntPtr cbt,
int cbtSize,
SafeGssNameHandle targetName,
uint reqFlags,
byte[] inputBytes,
int inputLength,
ref GssBuffer token,
out uint retFlags,
out int isNtlmUsed);
[DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_AcceptSecContext")]
internal static extern Status AcceptSecContext(
out Status minorStatus,
ref SafeGssContextHandle acceptContextHandle,
byte[] inputBytes,
int inputLength,
ref GssBuffer token);
ref GssBuffer token,
out uint retFlags);
[DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_DeleteSecContext")]
internal static extern Status DeleteSecContext(
out Status minorStatus,
ref IntPtr contextHandle);
[DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_GetUser")]
internal static extern Status GetUser(
out Status minorStatus,
SafeGssContextHandle acceptContextHandle,
ref GssBuffer token);
[DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_Wrap")]
private static extern Status Wrap(
out Status minorStatus,
@ -114,6 +246,7 @@ internal static partial class Interop
int offset,
int count,
ref GssBuffer outBuffer);
#endif
internal static Status WrapBuffer(
out Status minorStatus,
@ -145,117 +278,33 @@ internal static partial class Interop
return Unwrap(out minorStatus, contextHandle, inputBytes, offset, count, ref outBuffer);
}
#else
internal static void ReleaseGssBuffer (
IntPtr bufferPtr,
UInt64 length) => throw new NotSupportedException ();
internal static Status DisplayMinorStatus (
out Status minorStatus,
Status statusValue,
ref GssBuffer buffer) => throw new NotSupportedException ();
internal static Status DisplayMajorStatus (
out Status minorStatus,
Status statusValue,
ref GssBuffer buffer) => throw new NotSupportedException ();
internal static Status ImportUserName (
out Status minorStatus,
string inputName,
int inputNameByteCount,
out SafeGssNameHandle outputName) => throw new NotSupportedException ();
internal static Status ImportPrincipalName (
out Status minorStatus,
string inputName,
int inputNameByteCount,
out SafeGssNameHandle outputName) => throw new NotSupportedException ();
internal static Status ReleaseName (
out Status minorStatus,
ref IntPtr inputName) => throw new NotSupportedException ();
internal static Status InitiateCredSpNego (
out Status minorStatus,
SafeGssNameHandle desiredName,
out SafeGssCredHandle outputCredHandle) => throw new NotSupportedException ();
internal static Status InitiateCredWithPassword (
out Status minorStatus,
bool isNtlm,
SafeGssNameHandle desiredName,
string password,
int passwordLen,
out SafeGssCredHandle outputCredHandle) => throw new NotSupportedException ();
internal static Status ReleaseCred (
out Status minorStatus,
ref IntPtr credHandle) => throw new NotSupportedException ();
internal static Status InitSecContext (
out Status minorStatus,
SafeGssCredHandle initiatorCredHandle,
ref SafeGssContextHandle contextHandle,
bool isNtlmOnly,
SafeGssNameHandle targetName,
uint reqFlags,
byte[] inputBytes,
int inputLength,
ref GssBuffer token,
out uint retFlags,
out int isNtlmUsed) => throw new NotSupportedException ();
internal static Status AcceptSecContext (
out Status minorStatus,
ref SafeGssContextHandle acceptContextHandle,
byte[] inputBytes,
int inputLength,
ref GssBuffer token) => throw new NotSupportedException ();
internal static Status DeleteSecContext (
out Status minorStatus,
ref IntPtr contextHandle) => throw new NotSupportedException ();
static Status Wrap(
out Status minorStatus,
SafeGssContextHandle contextHandle,
bool isEncrypt,
byte[] inputBytes,
int offset,
int count,
ref GssBuffer outBuffer) => throw new NotSupportedException ();
static Status Unwrap (
out Status minorStatus,
SafeGssContextHandle contextHandle,
byte[] inputBytes,
int offset,
int count,
ref GssBuffer outBuffer) => throw new NotSupportedException ();
internal static Status WrapBuffer (
out Status minorStatus,
SafeGssContextHandle contextHandle,
bool isEncrypt,
byte[] inputBytes,
int offset,
int count,
ref GssBuffer outBuffer) => throw new NotSupportedException ();
internal static Status UnwrapBuffer (
out Status minorStatus,
SafeGssContextHandle contextHandle,
byte[] inputBytes,
int offset,
int count,
ref GssBuffer outBuffer) => throw new NotSupportedException ();
#endif
// https://www.gnu.org/software/gss/reference/gss.pdf Page 65
internal const int GSS_C_ROUTINE_ERROR_OFFSET = 16;
// https://www.gnu.org/software/gss/reference/gss.pdf Page 9
internal enum Status : uint
{
GSS_S_COMPLETE = 0,
GSS_S_CONTINUE_NEEDED = 1
GSS_S_CONTINUE_NEEDED = 1,
GSS_S_BAD_MECH = 1 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_BAD_NAME = 2 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_BAD_NAMETYPE = 3 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_BAD_BINDINGS = 4 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_BAD_STATUS = 5 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_BAD_SIG = 6 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_NO_CRED = 7 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_NO_CONTEXT = 8 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_DEFECTIVE_TOKEN = 9 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_DEFECTIVE_CREDENTIAL = 10 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_CREDENTIALS_EXPIRED = 11 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_CONTEXT_EXPIRED = 12 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_FAILURE = 13 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_BAD_QOP = 14 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_UNAUTHORIZED = 15 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_UNAVAILABLE = 16 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_DUPLICATE_ELEMENT = 17 << GSS_C_ROUTINE_ERROR_OFFSET,
GSS_S_NAME_NOT_MN = 18 << GSS_C_ROUTINE_ERROR_OFFSET,
}
[Flags]
@ -276,4 +325,4 @@ internal static partial class Interop
GSS_C_DELEG_POLICY_FLAG = 0x8000
}
}
}
}

Просмотреть файл

@ -146,4 +146,4 @@ namespace Microsoft.Win32.SafeHandles
return status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE;
}
}
}
}

Просмотреть файл

@ -413,4 +413,4 @@ namespace System.Net.Security
return resultSize + 4;
}
}
}
}

Просмотреть файл

@ -77,4 +77,4 @@ namespace System.Net.Security
base.Dispose(disposing);
}
}
}
}

Просмотреть файл

@ -97,6 +97,7 @@ BEGIN_EXTERN_C
typedef int errno_t;
#ifndef HAVE_MEMCPY_S
inline static errno_t memcpy_s(void* dst, size_t sizeInBytes, const void* src, size_t count)
{
if (count > 0)
@ -124,5 +125,6 @@ inline static errno_t memcpy_s(void* dst, size_t sizeInBytes, const void* src, s
return 0;
}
#endif
END_EXTERN_C

Просмотреть файл

@ -1257,15 +1257,30 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd)
int ret;
struct stat_ sourceStat;
bool copied = false;
#if HAVE_SENDFILE_4
// If sendfile is available (Linux), try to use it, as the whole copy
// can be performed in the kernel, without lots of unnecessary copying.
// First, stat the source file.
while ((ret = fstat_(inFd, &sourceStat)) < 0 && errno == EINTR);
if (ret != 0)
{
// If we can't stat() it, then we likely don't have permission to read it.
return -1;
}
// Copy permissions. This fchmod() needs to happen prior to writing anything into
// the file to avoid possibly leaking any private data.
while ((ret = fchmod(outFd, sourceStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) < 0 && errno == EINTR);
#if !TARGET_ANDROID
// On Android, we are not allowed to modify permissions, but the copy should still succeed;
// see https://github.com/mono/mono/issues/17133 for details.
if (ret != 0)
{
return -1;
}
#endif
#if HAVE_SENDFILE_4
// If sendfile is available (Linux), try to use it, as the whole copy
// can be performed in the kernel, without lots of unnecessary copying.
// On 32-bit, if you use 64-bit offsets, the last argument of `sendfile' will be a
// `size_t' a 32-bit integer while the `st_size' field of the stat structure will be off64_t.
@ -1313,37 +1328,30 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd)
// from the source file. First copy the file times.
// If futimes nor futimes are available on this platform, file times will
// not be copied over.
while ((ret = fstat_(inFd, &sourceStat)) < 0 && errno == EINTR);
if (ret == 0)
{
#if HAVE_FUTIMENS
// futimens is prefered because it has a higher resolution.
struct timespec origTimes[2];
origTimes[0].tv_sec = (time_t)sourceStat.st_atime;
origTimes[0].tv_nsec = ST_ATIME_NSEC(&sourceStat);
origTimes[1].tv_sec = (time_t)sourceStat.st_mtime;
origTimes[1].tv_nsec = ST_MTIME_NSEC(&sourceStat);
while ((ret = futimens(outFd, origTimes)) < 0 && errno == EINTR);
// futimens is prefered because it has a higher resolution.
struct timespec origTimes[2];
origTimes[0].tv_sec = (time_t)sourceStat.st_atime;
origTimes[0].tv_nsec = ST_ATIME_NSEC(&sourceStat);
origTimes[1].tv_sec = (time_t)sourceStat.st_mtime;
origTimes[1].tv_nsec = ST_MTIME_NSEC(&sourceStat);
while ((ret = futimens(outFd, origTimes)) < 0 && errno == EINTR);
#elif HAVE_FUTIMES
struct timeval origTimes[2];
origTimes[0].tv_sec = sourceStat.st_atime;
origTimes[0].tv_usec = ST_ATIME_NSEC(&sourceStat) / 1000;
origTimes[1].tv_sec = sourceStat.st_mtime;
origTimes[1].tv_usec = ST_MTIME_NSEC(&sourceStat) / 1000;
while ((ret = futimes(outFd, origTimes)) < 0 && errno == EINTR);
struct timeval origTimes[2];
origTimes[0].tv_sec = sourceStat.st_atime;
origTimes[0].tv_usec = ST_ATIME_NSEC(&sourceStat) / 1000;
origTimes[1].tv_sec = sourceStat.st_mtime;
origTimes[1].tv_usec = ST_MTIME_NSEC(&sourceStat) / 1000;
while ((ret = futimes(outFd, origTimes)) < 0 && errno == EINTR);
#endif
}
if (ret != 0)
{
return -1;
}
// Then copy permissions.
while ((ret = fchmod(outFd, sourceStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) < 0 && errno == EINTR);
#if !TARGET_ANDROID
// On Android, the copy should still succeed even if copying the file times didn't.
if (ret != 0)
{
return -1;
}
#endif
return 0;
#endif // HAVE_FCOPYFILE

Просмотреть файл

@ -816,6 +816,7 @@ static int32_t GetIPv4PacketInformation(struct cmsghdr* controlMessage, struct I
return 1;
}
#ifdef IPV6_PKTINFO
static int32_t GetIPv6PacketInformation(struct cmsghdr* controlMessage, struct IPPacketInformation* packetInfo)
{
assert(controlMessage != NULL);
@ -834,6 +835,7 @@ static int32_t GetIPv6PacketInformation(struct cmsghdr* controlMessage, struct I
return 1;
}
#endif
static struct cmsghdr* GET_CMSG_NXTHDR(struct msghdr* mhdr, struct cmsghdr* cmsg)
{
@ -1474,9 +1476,11 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO
*optName = SO_DEBUG;
return true;
#ifdef SO_ACCEPTCONN
case SocketOptionName_SO_ACCEPTCONN:
*optName = SO_ACCEPTCONN;
return true;
#endif
case SocketOptionName_SO_REUSEADDR:
*optName = SO_REUSEADDR;
@ -1638,9 +1642,11 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO
// case SocketOptionName_SO_IPV6_PROTECTION_LEVEL:
#ifdef IPV6_V6ONLY
case SocketOptionName_SO_IPV6_V6ONLY:
*optName = IPV6_V6ONLY;
return true;
#endif
#ifdef IPV6_RECVPKTINFO
case SocketOptionName_SO_IP_PKTINFO:
@ -1901,9 +1907,11 @@ static bool TryConvertProtocolTypePalToPlatform(int32_t palProtocolType, int* pl
*platformProtocolType = IPPROTO_UDP;
return true;
#ifdef IPPROTO_ICMPV6
case ProtocolType_PT_ICMPV6:
*platformProtocolType = IPPROTO_ICMPV6;
return true;
#endif
default:
*platformProtocolType = (int)palProtocolType;

Просмотреть файл

@ -111,7 +111,7 @@ static uint32_t NetSecurityNative_DisplayStatus(uint32_t* minorStatus,
assert(minorStatus != NULL);
assert(outBuffer != NULL);
uint32_t messageContext;
uint32_t messageContext = 0; // Must initialize to 0 before calling gss_display_status.
GssBuffer gssBuffer = {.length = 0, .value = NULL};
uint32_t majorStatus =
gss_display_status(minorStatus, statusValue, statusType, GSS_C_NO_OID, &messageContext, &gssBuffer);
@ -154,19 +154,36 @@ uint32_t NetSecurityNative_ImportPrincipalName(uint32_t* minorStatus,
assert(outputName != NULL);
assert(*outputName == NULL);
gss_OID nameType;
if (strchr(inputName, '/') != NULL)
// Principal name will usually be in the form SERVICE/HOST. But SPNEGO protocol prefers
// GSS_C_NT_HOSTBASED_SERVICE format. That format uses '@' separator instead of '/' between
// service name and host name. So convert input string into that format.
char* ptrSlash = memchr(inputName, '/', inputNameLen);
char* inputNameCopy = NULL;
if (ptrSlash != NULL)
{
nameType = GSS_KRB5_NT_PRINCIPAL_NAME;
}
else
{
nameType = GSS_C_NT_HOSTBASED_SERVICE;
inputNameCopy = (char*) malloc(inputNameLen);
if (inputNameCopy != NULL)
{
memcpy(inputNameCopy, inputName, inputNameLen);
inputNameCopy[ptrSlash - inputName] = '@';
inputName = inputNameCopy;
}
else
{
*minorStatus = 0;
return GSS_S_BAD_NAME;
}
}
GssBuffer inputNameBuffer = {.length = inputNameLen, .value = inputName};
return gss_import_name(minorStatus, &inputNameBuffer, nameType, outputName);
uint32_t result = gss_import_name(minorStatus, &inputNameBuffer, GSS_C_NT_HOSTBASED_SERVICE, outputName);
if (inputNameCopy != NULL)
{
free(inputNameCopy);
}
return result;
}
uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
@ -180,6 +197,35 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
PAL_GssBuffer* outBuffer,
uint32_t* retFlags,
int32_t* isNtlmUsed)
{
return NetSecurityNative_InitSecContextEx(minorStatus,
claimantCredHandle,
contextHandle,
isNtlm,
NULL,
0,
targetName,
reqFlags,
inputBytes,
inputLength,
outBuffer,
retFlags,
isNtlmUsed);
}
uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus,
GssCredId* claimantCredHandle,
GssCtxId** contextHandle,
uint32_t isNtlm,
void* cbt,
int32_t cbtSize,
GssName* targetName,
uint32_t reqFlags,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer,
uint32_t* retFlags,
int32_t* isNtlmUsed)
{
assert(minorStatus != NULL);
assert(contextHandle != NULL);
@ -189,12 +235,13 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
assert(outBuffer != NULL);
assert(retFlags != NULL);
assert(isNtlmUsed != NULL);
assert(inputBytes != NULL || inputLength == 0);
assert(cbt != NULL || cbtSize == 0);
// Note: claimantCredHandle can be null
// Note: *contextHandle is null only in the first call and non-null in the subsequent calls
#if HAVE_GSS_SPNEGO_MECHANISM
gss_OID krbMech = GSS_KRB5_MECHANISM;
gss_OID desiredMech;
if (isNtlm)
{
@ -204,9 +251,8 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
{
desiredMech = GSS_SPNEGO_MECHANISM;
}
gss_OID krbMech = GSS_KRB5_MECHANISM;
#else
gss_OID krbMech = (gss_OID)(unsigned long)gss_mech_krb5;
gss_OID_desc gss_mech_OID_desc;
if (isNtlm)
{
@ -218,14 +264,20 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
}
gss_OID desiredMech = &gss_mech_OID_desc;
gss_OID krbMech = gss_mech_krb5;
#endif
*isNtlmUsed = 1;
GssBuffer inputToken = {.length = inputLength, .value = inputBytes};
GssBuffer gssBuffer = {.length = 0, .value = NULL};
gss_OID_desc* outmech;
struct gss_channel_bindings_struct gssCbt;
if (cbt != NULL)
{
memset(&gssCbt, 0, sizeof(struct gss_channel_bindings_struct));
gssCbt.application_data.length = (size_t)cbtSize;
gssCbt.application_data.value = cbt;
}
uint32_t majorStatus = gss_init_sec_context(minorStatus,
claimantCredHandle,
contextHandle,
@ -233,18 +285,14 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
desiredMech,
reqFlags,
0,
GSS_C_NO_CHANNEL_BINDINGS,
(cbt != NULL) ? &gssCbt : GSS_C_NO_CHANNEL_BINDINGS,
&inputToken,
&outmech,
&gssBuffer,
retFlags,
NULL);
// Outmech can be null when gssntlmssp lib uses NTLM mechanism
if (outmech != NULL && gss_oid_equal(outmech, krbMech) != 0)
{
*isNtlmUsed = 0;
}
*isNtlmUsed = (isNtlm || majorStatus != GSS_S_COMPLETE || gss_oid_equal(outmech, krbMech) == 0) ? 1 : 0;
NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
return majorStatus;
@ -254,7 +302,8 @@ uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
GssCtxId** contextHandle,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer)
PAL_GssBuffer* outBuffer,
uint32_t* retFlags)
{
assert(minorStatus != NULL);
assert(contextHandle != NULL);
@ -273,7 +322,7 @@ uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
NULL,
NULL,
&gssBuffer,
0,
retFlags,
NULL,
NULL);
@ -281,6 +330,44 @@ uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
return majorStatus;
}
uint32_t NetSecurityNative_GetUser(uint32_t* minorStatus,
GssCtxId* contextHandle,
PAL_GssBuffer* outBuffer)
{
assert(minorStatus != NULL);
assert(contextHandle != NULL);
assert(outBuffer != NULL);
gss_name_t srcName = GSS_C_NO_NAME;
uint32_t majorStatus = gss_inquire_context(minorStatus,
contextHandle,
&srcName,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (majorStatus == GSS_S_COMPLETE)
{
GssBuffer gssBuffer = {.length = 0, .value = NULL};
majorStatus = gss_display_name(minorStatus, srcName, &gssBuffer, NULL);
if (majorStatus == GSS_S_COMPLETE)
{
NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
}
}
if (srcName != NULL)
{
majorStatus = gss_release_name(minorStatus, &srcName);
}
return majorStatus;
}
uint32_t NetSecurityNative_ReleaseCred(uint32_t* minorStatus, GssCredId** credHandle)
{
assert(minorStatus != NULL);
@ -416,4 +503,37 @@ uint32_t NetSecurityNative_InitiateCredWithPassword(uint32_t* minorStatus,
{
return NetSecurityNative_AcquireCredWithPassword(
minorStatus, isNtlm, desiredName, password, passwdLen, GSS_C_INITIATE, outputCredHandle);
}
uint32_t NetSecurityNative_IsNtlmInstalled()
{
#if HAVE_GSS_SPNEGO_MECHANISM
gss_OID ntlmOid = GSS_NTLM_MECHANISM;
#else
gss_OID ntlmOid = &gss_mech_ntlm_OID_desc;
#endif
uint32_t majorStatus;
uint32_t minorStatus;
gss_OID_set mechSet;
gss_OID_desc oid;
uint32_t foundNtlm = 0;
majorStatus = gss_indicate_mechs(&minorStatus, &mechSet);
if (majorStatus == GSS_S_COMPLETE)
{
for (size_t i = 0; i < mechSet->count; i++)
{
oid = mechSet->elements[i];
if ((oid.length == ntlmOid->length) && (memcmp(oid.elements, ntlmOid->elements, oid.length) == 0))
{
foundNtlm = 1;
break;
}
}
gss_release_oid_set(&minorStatus, &mechSet);
}
return foundNtlm;
}

Просмотреть файл

@ -115,6 +115,20 @@ DLLEXPORT uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
uint32_t* retFlags,
int32_t* isNtlmUsed);
DLLEXPORT uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus,
GssCredId* claimantCredHandle,
GssCtxId** contextHandle,
uint32_t isNtlm,
void* cbt,
int32_t cbtSize,
GssName* targetName,
uint32_t reqFlags,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer,
uint32_t* retFlags,
int32_t* isNtlmUsed);
/*
Shims the gss_accept_sec_context method.
*/
@ -122,7 +136,8 @@ DLLEXPORT uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
GssCtxId** contextHandle,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer);
PAL_GssBuffer* outBuffer,
uint32_t* retFlags);
/*
@ -159,4 +174,16 @@ DLLEXPORT uint32_t NetSecurityNative_InitiateCredWithPassword(uint32_t* minorSta
GssName* desiredName,
char* password,
uint32_t passwdLen,
GssCredId** outputCredHandle);
GssCredId** outputCredHandle);
/*
Shims the gss_indicate_mechs method to detect if NTLM mech is installed.
*/
DLLEXPORT uint32_t NetSecurityNative_IsNtlmInstalled(void);
/*
Shims gss_inquire_context and gss_display_name to get the remote user principal name.
*/
DLLEXPORT uint32_t NetSecurityNative_GetUser(uint32_t* minorStatus,
GssCtxId* contextHandle,
PAL_GssBuffer* outBuffer);

Просмотреть файл

@ -1145,7 +1145,7 @@ namespace System.Data.SqlClient
Task task = null;
// only send over SQL Batch command if we are not a stored proc and have no parameters and not in batch RPC mode
if ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters)))
if (!BatchRPCMode && (System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters)))
{
Debug.Assert(!sendToPipe, "trying to send non-context command to pipe");
if (null != statistics)
@ -2534,7 +2534,15 @@ namespace System.Data.SqlClient
GetStateObject();
Task writeTask = null;
if ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters)))
if (BatchRPCMode)
{
Debug.Assert(inSchema == false, "Batch RPC does not support schema only command beahvior");
Debug.Assert(!IsPrepared, "Batch RPC should not be prepared!");
Debug.Assert(!IsDirty, "Batch RPC should not be marked as dirty!");
Debug.Assert(_SqlRPCBatchArray != null, "RunExecuteReader rpc array not provided");
writeTask = _stateObj.Parser.TdsExecuteRPC( _SqlRPCBatchArray, timeout, inSchema, this.Notification, _stateObj, CommandType.StoredProcedure == CommandType, sync: !asyncWrite);
}
else if ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters)))
{
// Send over SQL Batch command if we are not a stored proc and have no parameters
Debug.Assert(!IsUserPrepared, "CommandType.Text with no params should not be prepared!");

Просмотреть файл

@ -231,6 +231,8 @@ namespace System.Data.SqlClient
destination._sourceVersion = _sourceVersion;
destination._sourceColumnNullMapping = _sourceColumnNullMapping;
destination._isNullable = _isNullable;
destination._parameterName = _parameterName;
destination._isNull = _isNull;
}
}
}

Просмотреть файл

@ -0,0 +1,107 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using Xunit;
namespace System.Data.SqlClient.ManualTesting.Tests
{
public class SqlAdapterUpdateBatch
{
[CheckConnStrSetupFact]
public void SqlAdapterTest()
{
string tableName = "BatchDemoTable";
try
{
var createTableQuery = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='BatchDemoTable' AND xtype='U')" +
" CREATE TABLE [dbo].[" + tableName + "]([TransactionNumber][int] IDENTITY(1, 1) NOT NULL,[Level] [nvarchar] (50) NOT NULL," +
"[Message] [nvarchar] (500) NOT NULL,[EventTime] [datetime]NOT NULL,CONSTRAINT[PK_BatchDemoTable] " +
"PRIMARY KEY CLUSTERED([TransactionNumber] ASC)WITH(PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF, " +
"IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON,FILLFACTOR = 90) ON[PRIMARY]) ON[PRIMARY]";
using (var connection = new SqlConnection(DataTestUtility.TcpConnStr))
using (var cmd = new SqlCommand(createTableQuery, connection))
{
connection.Open();
cmd.ExecuteNonQuery();
}
ExecuteNonQueries();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
finally
{
var dropTableQuery = "DROP TABLE IF EXISTS " + tableName;
using (var connection = new SqlConnection(DataTestUtility.TcpConnStr))
using (var cmd = new SqlCommand(dropTableQuery, connection))
{
connection.Open();
cmd.ExecuteNonQuery();
}
}
}
public class EventInfo
{
public string Level { get; set; }
public string Message { get; set; }
public DateTime EventTime { get; set; }
public EventInfo()
{
EventTime = DateTime.Now;
}
}
public static void ExecuteNonQueries()
{
List<EventInfo> entities = new List<EventInfo>
{
new EventInfo {Level = "L1", Message = "Message 1"},
new EventInfo {Level = "L2", Message = "Message 2"},
new EventInfo {Level = "L3", Message = "Message 3"},
new EventInfo {Level = "L4", Message = "Message 4"},
};
var sql = "INSERT INTO BatchDemoTable(Level, Message, EventTime) VALUES(@Level, @Message, @EventTime)";
using (var connection = new SqlConnection(DataTestUtility.TcpConnStr))
using (var adapter = new SqlDataAdapter())
using (var cmd = new SqlCommand(sql, connection))
{
cmd.Parameters.Add(new SqlParameter("@Level", System.Data.SqlDbType.NVarChar, 50, "Level"));
cmd.Parameters.Add(new SqlParameter("@Message", SqlDbType.NVarChar, 500, "Message"));
cmd.Parameters.Add(new SqlParameter("@EventTime", SqlDbType.DateTime, 0, "EventTime"));
cmd.UpdatedRowSource = UpdateRowSource.None;
adapter.InsertCommand = cmd;
adapter.UpdateBatchSize = 2;
adapter.Update(ConvertToTable(entities));
}
}
private static DataTable ConvertToTable(List<EventInfo> entities)
{
var table = new DataTable(typeof(EventInfo).Name);
table.Columns.Add("Level", typeof(string));
table.Columns.Add("Message", typeof(string));
table.Columns.Add("EventTime", typeof(DateTime));
foreach (var entity in entities)
{
var row = table.NewRow();
row["Level"] = entity.Level;
row["Message"] = entity.Message;
row["EventTime"] = entity.EventTime;
table.Rows.Add(row);
}
return table;
}
}
}

Просмотреть файл

@ -33,6 +33,7 @@
<Compile Include="SQL\ParameterTest\DateTimeVariantTest.cs" />
<Compile Include="SQL\ParameterTest\OutputParameter.cs" />
<Compile Include="SQL\ParameterTest\ParametersTest.cs" />
<Compile Include="SQL\ParameterTest\SqlAdapterUpdateBatch.cs" />
<Compile Include="SQL\ParameterTest\SqlVariantParam.cs" />
<Compile Include="SQL\ParameterTest\SteAttribute.cs" />
<Compile Include="SQL\ParameterTest\SteParam.cs" />

Просмотреть файл

@ -280,6 +280,8 @@ namespace System.IO
finally
{
StaticWatcherRunLoopManager.UnscheduleFromRunLoop(_eventStream);
_eventStream.Close();
_eventStream = null;
}
}
}

Просмотреть файл

@ -8,6 +8,7 @@ using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace System.Linq
{
@ -212,6 +213,63 @@ namespace System.Linq
private static ILookup<string, MethodInfo> s_seqMethods;
[PreserveDependency ("Aggregate`1", "System.Linq.Enumerable")]
[PreserveDependency ("Aggregate`2", "System.Linq.Enumerable")]
[PreserveDependency ("Aggregate`3", "System.Linq.Enumerable")]
[PreserveDependency ("All`1", "System.Linq.Enumerable")]
[PreserveDependency ("Any`1", "System.Linq.Enumerable")]
[PreserveDependency ("Append`1", "System.Linq.Enumerable")]
[PreserveDependency ("Average", "System.Linq.Enumerable")]
[PreserveDependency ("Average`1", "System.Linq.Enumerable")]
[PreserveDependency ("Cast`1", "System.Linq.Enumerable")]
[PreserveDependency ("Concat`1", "System.Linq.Enumerable")]
[PreserveDependency ("Contains`1", "System.Linq.Enumerable")]
[PreserveDependency ("Count`1", "System.Linq.Enumerable")]
[PreserveDependency ("DefaultIfEmpty`1", "System.Linq.Enumerable")]
[PreserveDependency ("Distinct`1", "System.Linq.Enumerable")]
[PreserveDependency ("ElementAt`1", "System.Linq.Enumerable")]
[PreserveDependency ("ElementAtOrDefault`1", "System.Linq.Enumerable")]
[PreserveDependency ("Except`1", "System.Linq.Enumerable")]
[PreserveDependency ("First`1", "System.Linq.Enumerable")]
[PreserveDependency ("FirstOrDefault`1", "System.Linq.Enumerable")]
[PreserveDependency ("GroupBy`2", "System.Linq.Enumerable")]
[PreserveDependency ("GroupBy`3", "System.Linq.Enumerable")]
[PreserveDependency ("GroupBy`4", "System.Linq.Enumerable")]
[PreserveDependency ("GroupJoin`4", "System.Linq.Enumerable")]
[PreserveDependency ("Intersect`1", "System.Linq.Enumerable")]
[PreserveDependency ("Join`4", "System.Linq.Enumerable")]
[PreserveDependency ("Last`1", "System.Linq.Enumerable")]
[PreserveDependency ("LastOrDefault`1", "System.Linq.Enumerable")]
[PreserveDependency ("LongCount`1", "System.Linq.Enumerable")]
[PreserveDependency ("Max`1", "System.Linq.Enumerable")]
[PreserveDependency ("Max`2", "System.Linq.Enumerable")]
[PreserveDependency ("Min`1", "System.Linq.Enumerable")]
[PreserveDependency ("Min`2", "System.Linq.Enumerable")]
[PreserveDependency ("OfType`1", "System.Linq.Enumerable")]
[PreserveDependency ("OrderBy`2", "System.Linq.Enumerable")]
[PreserveDependency ("OrderByDescending`2", "System.Linq.Enumerable")]
[PreserveDependency ("Prepend`1", "System.Linq.Enumerable")]
[PreserveDependency ("Reverse`1", "System.Linq.Enumerable")]
[PreserveDependency ("Select`2", "System.Linq.Enumerable")]
[PreserveDependency ("SelectMany`2", "System.Linq.Enumerable")]
[PreserveDependency ("SelectMany`3", "System.Linq.Enumerable")]
[PreserveDependency ("SequenceEqual`1", "System.Linq.Enumerable")]
[PreserveDependency ("Single`1", "System.Linq.Enumerable")]
[PreserveDependency ("SingleOrDefault`1", "System.Linq.Enumerable")]
[PreserveDependency ("Skip`1", "System.Linq.Enumerable")]
[PreserveDependency ("SkipLast`1", "System.Linq.Enumerable")]
[PreserveDependency ("SkipWhile`1", "System.Linq.Enumerable")]
[PreserveDependency ("Sum", "System.Linq.Enumerable")]
[PreserveDependency ("Sum`1", "System.Linq.Enumerable")]
[PreserveDependency ("Take`1", "System.Linq.Enumerable")]
[PreserveDependency ("TakeLast`1", "System.Linq.Enumerable")]
[PreserveDependency ("TakeWhile`1", "System.Linq.Enumerable")]
[PreserveDependency ("ThenBy`2", "System.Linq.Enumerable")]
[PreserveDependency ("ThenByDescending`2", "System.Linq.Enumerable")]
[PreserveDependency ("Union`1", "System.Linq.Enumerable")]
[PreserveDependency ("Where`1", "System.Linq.Enumerable")]
[PreserveDependency ("Zip`3", "System.Linq.Enumerable")]
private static MethodInfo FindEnumerableMethod(string name, ReadOnlyCollection<Expression> args, params Type[] typeArgs)
{
if (s_seqMethods == null)

Просмотреть файл

@ -81,15 +81,23 @@ namespace System.Net.Http
}
}
public Uri RequestUri
{
get { return _requestUri; }
set
{
#if MONO
if ((value != null) && (!IsAllowedAbsoluteUri(value)))
{
throw new ArgumentException(SR.net_http_client_http_baseaddress_required, nameof(value));
}
#else
if ((value != null) && (value.IsAbsoluteUri) && (!HttpUtilities.IsHttpUri(value)))
{
throw new ArgumentException(SR.net_http_client_http_baseaddress_required, nameof(value));
}
#endif
CheckDisposed();
// It's OK to set 'null'. HttpClient will add the 'BaseAddress'. If there is no 'BaseAddress'

Просмотреть файл

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Net;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
@ -76,7 +77,44 @@ namespace System.Net.Http
string challengeData = challenge.ChallengeData;
string spn = "HTTP/" + authUri.IdnHost;
// Calculate SPN (Service Principal Name) using the host name of the request.
// Use the request's 'Host' header if available. Otherwise, use the request uri.
// Ignore the 'Host' header if this is proxy authentication since we need to use
// the host name of the proxy itself for SPN calculation.
string hostName;
if (!isProxyAuth && request.HasHeaders && request.Headers.Host != null)
{
// Use the host name without any normalization.
hostName = request.Headers.Host;
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(connection, $"Authentication: {challenge.AuthenticationType}, Host: {hostName}");
}
}
else
{
// Need to use FQDN normalized host so that CNAME's are traversed.
// Use DNS to do the forward lookup to an A (host) record.
// But skip DNS lookup on IP literals. Otherwise, we would end up
// doing an unintended reverse DNS lookup.
UriHostNameType hnt = authUri.HostNameType;
if (hnt == UriHostNameType.IPv6 || hnt == UriHostNameType.IPv4)
{
hostName = authUri.IdnHost;
}
else
{
IPHostEntry result = await Dns.GetHostEntryAsync(authUri.IdnHost).ConfigureAwait(false);
hostName = result.HostName;
}
}
string spn = "HTTP/" + hostName;
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(connection, $"Authentication: {challenge.AuthenticationType}, SPN: {spn}");
}
ChannelBinding channelBinding = connection.TransportContext?.GetChannelBinding(ChannelBindingKind.Endpoint);
NTAuthentication authContext = new NTAuthentication(isServer:false, challenge.SchemeName, challenge.Credential, spn, ContextFlagsPal.Connection, channelBinding);
try
@ -135,4 +173,3 @@ namespace System.Net.Http
}
}
}

Просмотреть файл

@ -12,7 +12,7 @@ using System.Threading.Tasks;
namespace System.Net.Sockets
{
// Provides the underlying stream of data for network access.
public class NetworkStream : Stream
public partial class NetworkStream : Stream
{
// Used by the class to hold the underlying socket the stream uses.
private readonly Socket _streamSocket;

Просмотреть файл

@ -52,7 +52,7 @@ namespace System.Net.Sockets
internal Task<Socket> AcceptAsync(Socket acceptSocket)
{
// Get any cached SocketAsyncEventArg we may have.
TaskSocketAsyncEventArgs<Socket> saea = Interlocked.Exchange(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs).TaskAccept, s_rentedSocketSentinel);
TaskSocketAsyncEventArgs<Socket> saea = Interlocked.Exchange(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs, () => { return new CachedEventArgs(); }).TaskAccept, s_rentedSocketSentinel);
if (saea == s_rentedSocketSentinel)
{
// An instance was once created (or is currently being created elsewhere), but some other
@ -194,7 +194,7 @@ namespace System.Net.Sockets
return new ValueTask<int>(Task.FromCanceled<int>(cancellationToken));
}
AwaitableSocketAsyncEventArgs saea = LazyInitializer.EnsureInitialized(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs).ValueTaskReceive);
AwaitableSocketAsyncEventArgs saea = LazyInitializer.EnsureInitialized(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs, () => { return new CachedEventArgs(); } ).ValueTaskReceive, () => { return new AwaitableSocketAsyncEventArgs(); });
if (saea.Reserve())
{
Debug.Assert(saea.BufferList == null);
@ -343,7 +343,7 @@ namespace System.Net.Sockets
return new ValueTask<int>(Task.FromCanceled<int>(cancellationToken));
}
AwaitableSocketAsyncEventArgs saea = LazyInitializer.EnsureInitialized(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs).ValueTaskSend);
AwaitableSocketAsyncEventArgs saea = LazyInitializer.EnsureInitialized(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs, () => { return new CachedEventArgs(); } ).ValueTaskSend, () => { return new AwaitableSocketAsyncEventArgs(); });
if (saea.Reserve())
{
Debug.Assert(saea.BufferList == null);
@ -367,7 +367,7 @@ namespace System.Net.Sockets
return new ValueTask(Task.FromCanceled(cancellationToken));
}
AwaitableSocketAsyncEventArgs saea = LazyInitializer.EnsureInitialized(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs).ValueTaskSend);
AwaitableSocketAsyncEventArgs saea = LazyInitializer.EnsureInitialized(ref LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs, () => { return new CachedEventArgs(); } ).ValueTaskSend, () => { return new AwaitableSocketAsyncEventArgs(); });
if (saea.Reserve())
{
Debug.Assert(saea.BufferList == null);
@ -644,7 +644,7 @@ namespace System.Net.Sockets
private Int32TaskSocketAsyncEventArgs RentSocketAsyncEventArgs(bool isReceive)
{
// Get any cached SocketAsyncEventArg we may have.
CachedEventArgs cea = LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs);
CachedEventArgs cea = LazyInitializer.EnsureInitialized(ref _cachedTaskEventArgs, () => { return new CachedEventArgs(); });
Int32TaskSocketAsyncEventArgs saea = isReceive ?
Interlocked.Exchange(ref cea.TaskReceive, s_rentedInt32Sentinel) :
Interlocked.Exchange(ref cea.TaskSend, s_rentedInt32Sentinel);

Просмотреть файл

@ -215,6 +215,7 @@ namespace System.Net.Sockets.Tests
[Theory]
[MemberData(nameof(ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData))]
[SkipOnTargetFramework(TargetFrameworkMonikers.Mono, "Mono does not yet support `continueOnCapturedContext`.")]
public async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDesired(
bool flowExecutionContext, bool? continueOnCapturedContext)
{