private int _intCleanedUp; // 0 if not completed, > 0 otherwise.
internal static volatile bool s_initialized;
- internal static readonly bool s_perfCountersEnabled = false; // TODO (#7833): Implement socket perf counters.
#region Constructors
public Socket(SocketType socketType, ProtocolType protocolType)
set
{
//
- // This implementation does not support non-IOCP-based async I/O on Windows, and this concept is
+ // This implementation does not support non-IOCP-based async I/O on Windows, and this concept is
// not even meaningful on other platforms. This option is really only functionally meaningful
// if the user calls DuplicateAndClose. Since we also don't support DuplicateAndClose,
// we can safely ignore the caller's choice here, rather than breaking compat further with something
return 0;
}
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesSent, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsSent);
- }
- }
- }
-
if (NetEventSource.IsEnabled) NetEventSource.Exit(this, bytesTransferred);
return bytesTransferred;
}
return 0;
}
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesSent, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsSent);
- }
- }
- }
-
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(this, $"Interop.Winsock.send returns:{bytesTransferred}");
public int SendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
-
+
if (CleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
_rightEndPoint = endPointSnapshot;
}
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesSent, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsSent);
- }
- }
- }
-
if (NetEventSource.IsEnabled)
{
NetEventSource.DumpBuffer(this, buffer, offset, size);
return 0;
}
- if (s_perfCountersEnabled)
- {
- bool peek = ((int)socketFlags & (int)SocketFlags.Peek) != 0;
-
- if (bytesTransferred > 0 && !peek)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesReceived, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsReceived);
- }
- }
- }
-
if (NetEventSource.IsEnabled)
{
#if TRACE_VERBOSE
return 0;
}
- if (s_perfCountersEnabled)
- {
- bool peek = ((int)socketFlags & (int)SocketFlags.Peek) != 0;
-
- if (bytesTransferred > 0 && !peek)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesReceived, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsReceived);
- }
- }
- }
-
#if TRACE_VERBOSE
if (NetEventSource.IsEnabled)
{
throw socketException;
}
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesReceived, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsReceived);
- }
- }
- }
-
if (NetEventSource.IsEnabled)
{
NetEventSource.DumpBuffer(this, buffer, offset, size);
int realOptionLength = 0;
// IOControl is used for Windows-specific IOCTL operations. If we need to add support for IOCTLs specific
- // to other platforms, we will likely need to add a new API, as the control codes may overlap with those
+ // to other platforms, we will likely need to add a new API, as the control codes may overlap with those
// from Windows. Generally it would be preferable to add new methods/properties to abstract these across
// platforms, however.
SocketError errorCode = SocketPal.WindowsIoctl(_handle, ioControlCode, optionInValue, optionOutValue, out realOptionLength);
out optionValue);
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Interop.Winsock.getsockopt returns errorCode:{errorCode}");
-
+
// Throw an appropriate SocketException if the native call fails.
if (errorCode != SocketError.Success)
{
}
// Routine Description:
- //
+ //
// BeginConnect - Does an async connect.
- //
+ //
// Arguments:
- //
+ //
// remoteEP - status line that we wish to parse
// Callback - Async Callback Delegate that is called upon Async Completion
// State - State used to track callback, set by caller, not required
- //
+ //
// Return Value:
- //
+ //
// IAsyncResult - Async result used to retrieve result
public IAsyncResult BeginConnect(EndPoint remoteEP, AsyncCallback callback, object state)
{
{
//
// On Windows, we cannot duplicate a socket that is bound to an IOCP. In this implementation, we *only*
- // support IOCPs, so this will not work.
+ // support IOCPs, so this will not work.
//
// On Unix, duplication of a socket into an arbitrary process is not supported at all.
//
}
// Routine Description:
- //
+ //
// EndConnect - Called after receiving callback from BeginConnect,
// in order to retrieve the result of async call
- //
+ //
// Arguments:
- //
+ //
// AsyncResult - the AsyncResult Returned from BeginConnect call
- //
+ //
// Return Value:
- //
+ //
// int - Return code from async Connect, 0 for success, SocketError.NotConnected otherwise
public void EndConnect(IAsyncResult asyncResult)
{
}
// Routine Description:
- //
+ //
// BeginSend - Async implementation of Send call, mirrored after BeginReceive
// This routine may go pending at which time,
// but any case the callback Delegate will be called upon completion
- //
+ //
// Arguments:
- //
+ //
// WriteBuffer - status line that we wish to parse
// Index - Offset into WriteBuffer to begin sending from
// Size - Size of Buffer to transmit
// Callback - Delegate function that holds callback, called on completion of I/O
// State - State used to track callback, set by caller, not required
- //
+ //
// Return Value:
- //
+ //
// IAsyncResult - Async result used to retrieve result
public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Interop.Winsock.WSASend returns:{errorCode} size:{size} returning AsyncResult:{asyncResult}");
- // If the call failed, update our status
+ // If the call failed, update our status
CheckErrorAndUpdateStatus(errorCode);
return errorCode;
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Interop.Winsock.WSASend returns:{errorCode} returning AsyncResult:{asyncResult}");
- // If the call failed, update our status
+ // If the call failed, update our status
CheckErrorAndUpdateStatus(errorCode);
return errorCode;
}
// Routine Description:
- //
+ //
// EndSend - Called by user code after I/O is done or the user wants to wait.
// until Async completion, needed to retrieve error result from call
- //
+ //
// Arguments:
- //
+ //
// AsyncResult - the AsyncResult Returned from BeginSend call
- //
+ //
// Return Value:
- //
+ //
// int - Number of bytes transferred
public int EndSend(IAsyncResult asyncResult)
{
int bytesTransferred = castedAsyncResult.InternalWaitForCompletionInt32Result();
castedAsyncResult.EndCalled = true;
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesSent, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsSent);
- }
- }
- }
-
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"bytesTransffered:{bytesTransferred}");
// Throw an appropriate SocketException if the native call failed asynchronously.
}
// Routine Description:
- //
+ //
// BeginSendTo - Async implementation of SendTo,
- //
+ //
// This routine may go pending at which time,
// but any case the callback Delegate will be called upon completion
- //
+ //
// Arguments:
- //
+ //
// WriteBuffer - Buffer to transmit
// Index - Offset into WriteBuffer to begin sending from
// Size - Size of Buffer to transmit
// remoteEP - EndPoint to transmit To
// Callback - Delegate function that holds callback, called on completion of I/O
// State - State used to track callback, set by caller, not required
- //
+ //
// Return Value:
- //
+ //
// IAsyncResult - Async result used to retrieve result
public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP, AsyncCallback callback, object state)
{
}
// Routine Description:
- //
+ //
// EndSendTo - Called by user code after I/O is done or the user wants to wait.
// until Async completion, needed to retrieve error result from call
- //
+ //
// Arguments:
- //
+ //
// AsyncResult - the AsyncResult Returned from BeginSend call
- //
+ //
// Return Value:
- //
+ //
// int - Number of bytes transferred
public int EndSendTo(IAsyncResult asyncResult)
{
int bytesTransferred = castedAsyncResult.InternalWaitForCompletionInt32Result();
castedAsyncResult.EndCalled = true;
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesSent, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsSent);
- }
- }
- }
-
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"bytesTransferred:{bytesTransferred}");
// Throw an appropriate SocketException if the native call failed asynchronously.
}
// Routine Description:
- //
+ //
// BeginReceive - Async implementation of Recv call,
- //
+ //
// Called when we want to start an async receive.
// We kick off the receive, and if it completes synchronously we'll
// call the callback. Otherwise we'll return an IASyncResult, which
// the caller can use to wait on or retrieve the final status, as needed.
- //
+ //
// Uses Winsock 2 overlapped I/O.
- //
+ //
// Arguments:
- //
+ //
// ReadBuffer - status line that we wish to parse
// Index - Offset into ReadBuffer to begin reading from
// Size - Size of Buffer to recv
// Callback - Delegate function that holds callback, called on completion of I/O
// State - State used to track callback, set by caller, not required
- //
+ //
// Return Value:
- //
+ //
// IAsyncResult - Async result used to retrieve result
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
{
SocketError errorCode = SocketPal.ReceiveAsync(_handle, buffers, socketFlags, asyncResult);
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Interop.Winsock.WSARecv returns:{errorCode} returning AsyncResult:{asyncResult}");
-
+
if (!CheckErrorAndUpdateStatus(errorCode))
{
}
#endif
// Routine Description:
- //
+ //
// EndReceive - Called when I/O is done or the user wants to wait. If
// the I/O isn't done, we'll wait for it to complete, and then we'll return
// the bytes of I/O done.
- //
+ //
// Arguments:
- //
+ //
// AsyncResult - the AsyncResult Returned from BeginSend call
- //
+ //
// Return Value:
- //
+ //
// int - Number of bytes transferred
public int EndReceive(IAsyncResult asyncResult)
{
int bytesTransferred = castedAsyncResult.InternalWaitForCompletionInt32Result();
castedAsyncResult.EndCalled = true;
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesReceived, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsReceived);
- }
- }
- }
-
#if TRACE_VERBOSE
if (NetEventSource.IsEnabled)
{
}
}
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesReceived, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsReceived);
- }
- }
- }
-
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"bytesTransferred:{bytesTransferred}");
// Throw an appropriate SocketException if the native call failed asynchronously.
}
// Routine Description:
- //
+ //
// BeginReceiveFrom - Async implementation of RecvFrom call,
- //
+ //
// Called when we want to start an async receive.
// We kick off the receive, and if it completes synchronously we'll
// call the callback. Otherwise we'll return an IASyncResult, which
// the caller can use to wait on or retrieve the final status, as needed.
- //
+ //
// Uses Winsock 2 overlapped I/O.
- //
+ //
// Arguments:
- //
+ //
// ReadBuffer - status line that we wish to parse
// Index - Offset into ReadBuffer to begin reading from
// Request - Size of Buffer to recv
// remoteEP - EndPoint that are to receive from
// Callback - Delegate function that holds callback, called on completion of I/O
// State - State used to track callback, set by caller, not required
- //
+ //
// Return Value:
- //
+ //
// IAsyncResult - Async result used to retrieve result
public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
{
}
// Routine Description:
- //
+ //
// EndReceiveFrom - Called when I/O is done or the user wants to wait. If
// the I/O isn't done, we'll wait for it to complete, and then we'll return
// the bytes of I/O done.
- //
+ //
// Arguments:
- //
+ //
// AsyncResult - the AsyncResult Returned from BeginReceiveFrom call
- //
+ //
// Return Value:
- //
+ //
// int - Number of bytes transferred
public int EndReceiveFrom(IAsyncResult asyncResult, ref EndPoint endPoint)
{
}
}
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesReceived, bytesTransferred);
- if (Transport == TransportType.Udp)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketDatagramsReceived);
- }
- }
- }
-
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"bytesTransferred:{bytesTransferred}");
// Throw an appropriate SocketException if the native call failed asynchronously.
}
// Routine Description:
- //
+ //
// BeginAccept - Does an async winsock accept, creating a new socket on success
- //
+ //
// Works by creating a pending accept request the first time,
// and subsequent calls are queued so that when the first accept completes,
// the next accept can be resubmitted in the callback.
// this routine may go pending at which time,
// but any case the callback Delegate will be called upon completion
- //
+ //
// Arguments:
- //
+ //
// Callback - Async Callback Delegate that is called upon Async Completion
// State - State used to track callback, set by caller, not required
- //
+ //
// Return Value:
- //
+ //
// IAsyncResult - Async result used to retrieve resultant new socket
public IAsyncResult BeginAccept(AsyncCallback callback, object state)
{
}
// Routine Description:
- //
+ //
// EndAccept - Called by user code after I/O is done or the user wants to wait.
// until Async completion, so it provides End handling for async Accept calls,
// and retrieves new Socket object
- //
+ //
// Arguments:
- //
+ //
// AsyncResult - the AsyncResult Returned from BeginAccept call
- //
+ //
// Return Value:
- //
+ //
// Socket - a valid socket if successful
public Socket EndAccept(IAsyncResult asyncResult)
{
castedAsyncResult.EndCalled = true;
- if (s_perfCountersEnabled)
- {
- if (bytesTransferred > 0)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketBytesReceived, bytesTransferred);
- }
- }
-
// Throw an appropriate SocketException if the native call failed asynchronously.
if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success)
{
}
}
- // Save the old RightEndPoint and prep new RightEndPoint.
+ // Save the old RightEndPoint and prep new RightEndPoint.
EndPoint oldEndPoint = _rightEndPoint;
if (_rightEndPoint == null)
{
{
_rightEndPoint = oldEndPoint;
- // Clear in-use flag on event args object.
+ // Clear in-use flag on event args object.
e.Complete();
throw;
}
MultipleConnectAsync multipleConnectAsync = null;
if (dnsEP.AddressFamily == AddressFamily.Unspecified)
{
- // This is the only *Connect* API that fully supports multiple endpoint attempts, as it's responsible
+ // This is the only *Connect* API that fully supports multiple endpoint attempts, as it's responsible
// for creating each Socket instance and can create one per attempt.
multipleConnectAsync = new DualSocketMultipleConnectAsync(socketType, protocolType);
#pragma warning restore
}
catch
{
- // clear in-use on event arg object
+ // clear in-use on event arg object
e.Complete();
throw;
}
}
catch
{
- // Clear in-use flag on event args object.
+ // Clear in-use flag on event args object.
e.Complete();
throw;
}
EndPoint endPointSnapshot = e.RemoteEndPoint;
e._socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
- // DualMode sockets may have updated the endPointSnapshot, and it has to have the same AddressFamily as
+ // DualMode sockets may have updated the endPointSnapshot, and it has to have the same AddressFamily as
// e.m_SocketAddres for Create to work later.
e.RemoteEndPoint = endPointSnapshot;
}
catch
{
- // Clear in-use flag on event args object.
+ // Clear in-use flag on event args object.
e.Complete();
throw;
}
EndPoint endPointSnapshot = e.RemoteEndPoint;
e._socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
- // DualMode may have updated the endPointSnapshot, and it has to have the same AddressFamily as
+ // DualMode may have updated the endPointSnapshot, and it has to have the same AddressFamily as
// e.m_SocketAddres for Create to work later.
e.RemoteEndPoint = endPointSnapshot;
}
catch
{
- // Clear in-use flag on event args object.
+ // Clear in-use flag on event args object.
e.Complete();
throw;
}
}
catch
{
- // Clear in-use flag on event args object.
+ // Clear in-use flag on event args object.
e.Complete();
throw;
}
}
catch (Exception)
{
- // Clear in-use flag on event args object.
+ // Clear in-use flag on event args object.
e.Complete();
throw;
}
}
catch
{
- // Clear in-use flag on event args object.
+ // Clear in-use flag on event args object.
e.Complete();
throw;
}
{
private EndPoint _endPoint;
- internal ConnectAsyncResult(object myObject, EndPoint endPoint, object myState, AsyncCallback myCallBack) :
+ internal ConnectAsyncResult(object myObject, EndPoint endPoint, object myState, AsyncCallback myCallBack) :
base(myObject, myState, myCallBack)
{
_endPoint = endPoint;
_isConnected = true;
_isDisconnected = false;
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "now connected");
- if (s_perfCountersEnabled)
- {
- SocketPerfCounter.Instance.Increment(SocketPerfCounterName.SocketConnectionsEstablished);
- }
}
internal void SetToDisconnected()