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
- RegisteredDisposeScript.cs
- SQlBooleanStorage.cs
- SetStoryboardSpeedRatio.cs
- StylusDownEventArgs.cs
- DbSourceParameterCollection.cs
- CompensationDesigner.cs
- TextSpan.cs
- TextRangeSerialization.cs
- ExitEventArgs.cs
- DodSequenceMerge.cs
- ProviderUtil.cs
- SystemException.cs
- XmlCharacterData.cs
- ThrowOnMultipleAssignment.cs
- MSAAEventDispatcher.cs
- ProxyHwnd.cs
- CapabilitiesAssignment.cs
- EncryptedKeyHashIdentifierClause.cs
- SerializationStore.cs
- DBSqlParserColumn.cs
- DateTimeOffsetStorage.cs
- FormViewRow.cs
- webeventbuffer.cs
- PropertyDescriptorGridEntry.cs
- StatusBarAutomationPeer.cs
- ImageSourceConverter.cs
- UIInitializationException.cs
- GcSettings.cs
- EditorBrowsableAttribute.cs
- PeerServiceMessageContracts.cs
- Main.cs
- _DomainName.cs
- DataGridColumnCollectionEditor.cs
- ReceiveSecurityHeaderEntry.cs
- DiffuseMaterial.cs
- Soap.cs
- TypedTableBaseExtensions.cs
- OrderablePartitioner.cs
- SmtpMail.cs
- Path.cs
- FlagsAttribute.cs
- _ListenerRequestStream.cs
- XmlName.cs
- ProxyAssemblyNotLoadedException.cs
- DocumentGridPage.cs
- Rotation3DKeyFrameCollection.cs
- GatewayDefinition.cs
- ToolboxComponentsCreatedEventArgs.cs
- ProfileParameter.cs
- AlignmentYValidation.cs
- ExpressionParser.cs
- Boolean.cs
- WindowsFormsSynchronizationContext.cs
- InputGestureCollection.cs
- TextRangeEdit.cs
- ProfileSettings.cs
- SqlDataSourceRefreshSchemaForm.cs
- Pkcs7Signer.cs
- FrameworkReadOnlyPropertyMetadata.cs
- SemaphoreSecurity.cs
- XmlBaseReader.cs
- DataSourceListEditor.cs
- Run.cs
- MatrixTransform3D.cs
- Path.cs
- DbMetaDataFactory.cs
- LinkArea.cs
- ResourceExpressionBuilder.cs
- ObjectTypeMapping.cs
- AtlasWeb.Designer.cs
- VisualCollection.cs
- DataRecordInternal.cs
- OrderedDictionaryStateHelper.cs
- PaintValueEventArgs.cs
- QuaternionAnimation.cs
- WebPartTransformer.cs
- HwndProxyElementProvider.cs
- NeutralResourcesLanguageAttribute.cs
- ImageCodecInfoPrivate.cs
- IUnknownConstantAttribute.cs
- DataSourceCache.cs
- UnmanagedMemoryStreamWrapper.cs
- Brush.cs
- DomainConstraint.cs
- Menu.cs
- UrlMapping.cs
- BamlTreeMap.cs
- ImageInfo.cs
- EntityDataSourceViewSchema.cs
- ConstraintEnumerator.cs
- WebPartConnectionsConnectVerb.cs
- LinkButton.cs
- DocumentStream.cs
- GenericXmlSecurityToken.cs
- LinqDataSourceUpdateEventArgs.cs
- OleDbWrapper.cs
- StyleCollection.cs
- InternalConfigSettingsFactory.cs
- Literal.cs
- OleDbDataReader.cs