Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Discovery / System / ServiceModel / Channels / UdpSocket.cs / 1305376 / UdpSocket.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------
namespace System.ServiceModel.Channels
{
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime;
using System.Threading;
#if DEBUG
using System.Diagnostics;
#endif
using System.ServiceModel.Discovery;
class UdpSocket
{
int openCount;
int timeToLive;
int pendingReceiveCount;
Socket socket;
#if DEBUG
StackTrace disposeStack;
#endif
public UdpSocket(Socket socket, int interfaceIndex)
{
Fx.Assert(socket != null, "Socket argument cannot be null");
this.openCount = 0;
this.pendingReceiveCount = 0;
this.ThisLock = new object();
this.socket = socket;
this.InterfaceIndex = interfaceIndex;
this.timeToLive = socket.Ttl;
}
enum TransferDirection : byte
{
Send,
Receive,
}
public AddressFamily AddressFamily
{
get
{
return this.socket.AddressFamily;
}
}
public int PendingReceiveCount
{
get
{
return this.pendingReceiveCount;
}
}
//value of UdpConstants.Defaults.InterfaceIndex (-1) if not a multicast socket
internal int InterfaceIndex
{
get;
private set;
}
internal bool IsDisposed
{ get { return this.openCount < 0; } }
internal object ThisLock
{
get;
private set;
}
//must be called under a lock in receive loop
public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset, int size, ref EndPoint remoteEndPoint, AsyncCallback callback, object state)
{
UdpUtility.ValidateBufferBounds(buffer, offset, size);
ThrowIfNotOpen();
bool success = false;
IAsyncResult asyncResult = null;
try
{
this.pendingReceiveCount++;
asyncResult = new ReceiveFromAsyncResult(
this.socket,
new ArraySegment(buffer, offset, size),
remoteEndPoint,
size - offset,
this.timeToLive,
callback,
state);
success = true;
return asyncResult;
}
finally
{
if (!success)
{
this.pendingReceiveCount--;
}
}
}
public void Close()
{
bool cleanup = false;
lock (this.ThisLock)
{
if (this.IsDisposed)
{
return;
}
//UdpUtility.CreateListenSocketsOnUniquePort can create a socket and then close it without ever calling
//UdpSocket.Open() if it fails to bind on both IPv4 and IPv6. If this happens, then openCount will still be at zero.
if (this.openCount > 0)
{
this.openCount--;
}
if (this.openCount == 0)
{
cleanup = true;
this.openCount = -1;
}
}
if (cleanup)
{
#if DEBUG
if (!Fx.FastDebug)
{
disposeStack = new StackTrace();
}
#endif
//non-zero sendTimeout causes the socket to block on a receive while looking for an EOF, which will never come
this.socket.Close(0);
}
}
//must be called under a lock in receive loop
public ArraySegment EndReceiveFrom(IAsyncResult result, ref EndPoint remoteEndPoint)
{
this.pendingReceiveCount--;
return ReceiveFromAsyncResult.End(result, ref remoteEndPoint);
}
internal EndPoint CreateIPAnyEndPoint()
{
if (this.AddressFamily == AddressFamily.InterNetwork)
{
return new IPEndPoint(IPAddress.Any, 0);
}
else
{
return new IPEndPoint(IPAddress.IPv6Any, 0);
}
}
public void Open()
{
lock (this.ThisLock)
{
if (this.IsDisposed)
{
throw FxTrace.Exception.AsError(new ObjectDisposedException("UdpSocket"));
}
this.openCount++;
}
}
public int SendTo(byte[] buffer, int offset, int size, EndPoint remoteEndPoint)
{
ThrowIfNotOpen();
UdpUtility.ValidateBufferBounds(buffer, offset, size);
try
{
int count = this.socket.SendTo(buffer, offset, size, SocketFlags.None, remoteEndPoint);
Fx.Assert(count == size, "Bytes sent on the wire should be the same as the bytes specified");
return count;
}
catch (SocketException socketException)
{
throw FxTrace.Exception.AsError(ConvertNetworkError(socketException, size - offset, TransferDirection.Send, this.timeToLive));
}
}
public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, EndPoint remoteEndPoint, AsyncCallback callback, object state)
{
ThrowIfNotOpen();
UdpUtility.ValidateBufferBounds(buffer, offset, size);
return new SendToAsyncResult(this.socket, buffer, offset, size, remoteEndPoint, this.timeToLive, callback, state);
}
public int EndSendTo(IAsyncResult result)
{
return SendToAsyncResult.End(result);
}
static Exception ConvertNetworkError(SocketException socketException, ReceiveFromAsyncResult result)
{
return ConvertNetworkError(socketException, result.MessageSize, TransferDirection.Receive, result.TimeToLive);
}
// size: sending => the size of the data being sent
// Receiving => the max message size we can receive
// remoteEndPoint: remote endpoint reported when error occured
static Exception ConvertNetworkError(SocketException socketException, int size, TransferDirection direction, int timeToLive)
{
Exception result = null;
if (socketException.ErrorCode == UnsafeNativeMethods.ERROR_INVALID_HANDLE)
{
//This would likely indicate a bug in our ref-counting
//for instance, a channel is closing the socket multiple times...
Fx.Assert("The socket appears to have been closed unexpectedly. This probably indicates incorrect ref counting (i.e. a channel is closing the socket multiple times)");
result = new CommunicationObjectAbortedException(socketException.Message, socketException);
}
else
{
string errorMessage;
switch (socketException.SocketErrorCode)
{
case SocketError.MessageSize: //10040
errorMessage = (direction == TransferDirection.Send ? SR.UdpMaxMessageSendSizeExceeded(size) : SR.MaxReceivedMessageSizeExceeded(size));
Exception inner = new QuotaExceededException(errorMessage, socketException);
result = new ProtocolException(errorMessage, inner);
break;
case SocketError.NetworkReset: //10052
//ICMP: Time Exceeded (TTL expired)
//see http://tools.ietf.org/html/rfc792
result = new CommunicationException(SR.IcmpTimeExpired(timeToLive), socketException);
break;
case SocketError.ConnectionReset: //10054
//ICMP: Destination Unreachable (target host/port/etc not reachable)
//see http://tools.ietf.org/html/rfc792
result = new CommunicationException(SR.IcmpDestinationUnreachable, socketException);
break;
default:
errorMessage = (direction == TransferDirection.Send ? SR.UdpSendException : SR.UdpReceiveException);
result = new CommunicationException(errorMessage, socketException);
break;
}
}
Fx.Assert(result != null, "we should never return null");
return result;
}
void ThrowIfDisposed()
{
if (this.IsDisposed)
{
throw FxTrace.Exception.AsError(new ObjectDisposedException(this.GetType().ToString()));
}
}
void ThrowIfNotOpen()
{
ThrowIfDisposed();
if (this.openCount == 0)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ObjectNotOpen));
}
}
class SendToAsyncResult : TypedAsyncResult
{
Socket socket;
int offset;
int size;
int timeToLive;
static AsyncCallback onSendToComplete = Fx.ThunkCallback(OnSendToComplete);
public SendToAsyncResult(Socket socket, byte[] buffer, int offset, int size, EndPoint remoteEndPoint, int timeToLive, AsyncCallback callback, object state)
: base(callback, state)
{
this.socket = socket;
this.offset = offset;
this.size = size;
this.timeToLive = timeToLive;
int count = 0;
try
{
IAsyncResult socketAsyncResult = this.socket.BeginSendTo(buffer, offset, size, SocketFlags.None, remoteEndPoint, onSendToComplete, this);
if (!socketAsyncResult.CompletedSynchronously)
{
return;
}
count = this.socket.EndSendTo(socketAsyncResult);
}
catch (SocketException socketException)
{
throw FxTrace.Exception.AsError(ConvertNetworkError(socketException, this.size - this.offset, TransferDirection.Send, this.timeToLive));
}
this.Complete(count, true);
}
static void OnSendToComplete(IAsyncResult result)
{
if (result.CompletedSynchronously)
{
return;
}
SendToAsyncResult thisPtr = (SendToAsyncResult)result.AsyncState;
Exception completionException = null;
int count = 0;
try
{
count = thisPtr.socket.EndSendTo(result);
}
catch (SocketException socketException)
{
completionException = ConvertNetworkError(socketException, thisPtr.size - thisPtr.offset, TransferDirection.Send, thisPtr.timeToLive);
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
completionException = ex;
}
if (completionException != null)
{
thisPtr.Complete(false, completionException);
}
else
{
thisPtr.Complete(count, false);
}
}
}
class ReceiveFromAsyncResult : TypedAsyncResult>
{
static AsyncCallback onReceiveMessageFromCallback = Fx.ThunkCallback(new AsyncCallback(OnReceiveMessageFrom));
Socket socket;
public ReceiveFromAsyncResult(Socket socket, ArraySegment buffer, EndPoint remoteEndPoint, int messageSize, int timeToLive, AsyncCallback userCallback, object userState) :
base(userCallback, userState)
{
this.RemoteEndPoint = remoteEndPoint;
this.MessageSize = messageSize;
this.socket = socket;
this.Buffer = buffer;
this.TimeToLive = timeToLive;
ArraySegment data = default(ArraySegment);
try
{
IAsyncResult socketAsyncResult = this.socket.BeginReceiveFrom(this.Buffer.Array,
this.Buffer.Offset,
this.Buffer.Count,
SocketFlags.None,
ref remoteEndPoint,
onReceiveMessageFromCallback,
this);
if (!socketAsyncResult.CompletedSynchronously)
{
return;
}
data = EndReceiveFrom(socketAsyncResult);
}
catch (SocketException socketException)
{
throw FxTrace.Exception.AsError(UdpSocket.ConvertNetworkError(socketException, this));
}
Complete(data, true);
}
public EndPoint RemoteEndPoint
{
get;
private set;
}
public int TimeToLive
{
get;
private set;
}
//used when generating error messages for the user...
internal int MessageSize
{
get;
private set;
}
ArraySegment Buffer
{
get;
set;
}
public static ArraySegment End(IAsyncResult result, ref EndPoint remoteEndPoint)
{
ArraySegment data = TypedAsyncResult>.End(result);
ReceiveFromAsyncResult receiveFromResult = (ReceiveFromAsyncResult)result;
remoteEndPoint = receiveFromResult.RemoteEndPoint;
return data;
}
static void OnReceiveMessageFrom(IAsyncResult result)
{
if (result.CompletedSynchronously)
{
return;
}
ReceiveFromAsyncResult asyncResult = (ReceiveFromAsyncResult)result.AsyncState;
Exception completionException = null;
ArraySegment data = default(ArraySegment);
try
{
data = asyncResult.EndReceiveFrom(result);
}
catch (SocketException socketException)
{
completionException = UdpSocket.ConvertNetworkError(socketException, asyncResult);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
completionException = exception;
}
if (completionException != null)
{
asyncResult.Complete(false, completionException);
}
else
{
asyncResult.Complete(data, false);
}
}
ArraySegment EndReceiveFrom(IAsyncResult result)
{
EndPoint remoteEndPoint = this.RemoteEndPoint;
int count = this.socket.EndReceiveFrom(result, ref remoteEndPoint);
this.RemoteEndPoint = remoteEndPoint;
return new ArraySegment(this.Buffer.Array, this.Buffer.Offset, count);
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Renderer.cs
- Label.cs
- XmlUtf8RawTextWriter.cs
- ObjectResult.cs
- ValidationError.cs
- AnnotationComponentManager.cs
- AppDomainEvidenceFactory.cs
- ExpressionNormalizer.cs
- TreeViewAutomationPeer.cs
- QueryResponse.cs
- X509SecurityToken.cs
- Span.cs
- ExtentCqlBlock.cs
- SecurityResources.cs
- GiveFeedbackEventArgs.cs
- XmlSchemaResource.cs
- LoginName.cs
- ResponseBodyWriter.cs
- RequestBringIntoViewEventArgs.cs
- PeerInputChannel.cs
- CodeEntryPointMethod.cs
- MimeXmlReflector.cs
- Win32.cs
- SelectedDatesCollection.cs
- ExpressionList.cs
- Mutex.cs
- StrongNameKeyPair.cs
- URLString.cs
- QuaternionAnimationBase.cs
- XmlSchemaExternal.cs
- DtdParser.cs
- HttpListenerTimeoutManager.cs
- InputReport.cs
- DBSchemaTable.cs
- MaterialGroup.cs
- RawMouseInputReport.cs
- DispatcherObject.cs
- Array.cs
- InitializingNewItemEventArgs.cs
- DescendantBaseQuery.cs
- SqlStatistics.cs
- Exception.cs
- BezierSegment.cs
- InvalidWorkflowException.cs
- DocumentApplicationJournalEntry.cs
- NetTcpSecurity.cs
- MimeMapping.cs
- Listbox.cs
- __FastResourceComparer.cs
- IisTraceListener.cs
- PrintingPermission.cs
- XPathItem.cs
- Pair.cs
- UInt16Converter.cs
- UndoUnit.cs
- EventPrivateKey.cs
- DataFormats.cs
- ParameterCollection.cs
- CardSpaceException.cs
- DecoderBestFitFallback.cs
- EntityViewGenerationAttribute.cs
- TransactionsSectionGroup.cs
- XmlHierarchyData.cs
- StringCollectionMarkupSerializer.cs
- DataGridViewColumnCollectionDialog.cs
- RepeatInfo.cs
- VirtualDirectoryMapping.cs
- CallTemplateAction.cs
- RestClientProxyHandler.cs
- ChangeInterceptorAttribute.cs
- MobileControlsSection.cs
- CollectionEditor.cs
- MetadataPropertyCollection.cs
- DataSourceListEditor.cs
- XmlSchemaFacet.cs
- DisableDpiAwarenessAttribute.cs
- altserialization.cs
- DefinitionBase.cs
- WebControlsSection.cs
- RegistrySecurity.cs
- HttpRawResponse.cs
- Decoder.cs
- CloseCryptoHandleRequest.cs
- TogglePattern.cs
- HtmlLink.cs
- SectionInformation.cs
- PriorityChain.cs
- PrtCap_Public.cs
- ConnectionStringsExpressionBuilder.cs
- BindingElement.cs
- Point4D.cs
- TokenizerHelper.cs
- DataKeyArray.cs
- BamlLocalizer.cs
- WsdlBuildProvider.cs
- MobileControlPersister.cs
- DataGridViewTopLeftHeaderCell.cs
- GCHandleCookieTable.cs
- LinkAreaEditor.cs
- WebException.cs