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
- Number.cs
- TypeBrowser.xaml.cs
- Misc.cs
- ForEachAction.cs
- DBDataPermission.cs
- TextEditorMouse.cs
- TableLayoutColumnStyleCollection.cs
- TextEditor.cs
- ControlHelper.cs
- ToolStripStatusLabel.cs
- entityreference_tresulttype.cs
- MasterPageBuildProvider.cs
- XmlValidatingReaderImpl.cs
- InstanceData.cs
- securestring.cs
- GestureRecognizer.cs
- ReachDocumentPageSerializer.cs
- TypedDataSetSchemaImporterExtensionFx35.cs
- EventArgs.cs
- RegisteredArrayDeclaration.cs
- RuntimeHelpers.cs
- EntityParameter.cs
- MobileRedirect.cs
- CustomWebEventKey.cs
- GlyphInfoList.cs
- EntityDataSourceView.cs
- COM2FontConverter.cs
- ResourceDescriptionAttribute.cs
- DataGridViewTextBoxColumn.cs
- ExeConfigurationFileMap.cs
- HtmlElementCollection.cs
- XPathMessageContext.cs
- SqlParameterCollection.cs
- DoubleAnimationBase.cs
- XmlnsPrefixAttribute.cs
- ConfigurationPropertyAttribute.cs
- SamlAssertionKeyIdentifierClause.cs
- dbenumerator.cs
- SafeRightsManagementPubHandle.cs
- AsyncCompletedEventArgs.cs
- DefaultValueConverter.cs
- MaskDesignerDialog.cs
- MultipleViewProviderWrapper.cs
- SignedPkcs7.cs
- ToolStripPanelCell.cs
- InputManager.cs
- RijndaelManaged.cs
- Errors.cs
- ValidationSummary.cs
- FixedSOMSemanticBox.cs
- ControlAdapter.cs
- Figure.cs
- SelectionService.cs
- PingReply.cs
- DoubleStorage.cs
- GatewayDefinition.cs
- TextPatternIdentifiers.cs
- DataSourceCacheDurationConverter.cs
- Overlapped.cs
- SortableBindingList.cs
- JsonMessageEncoderFactory.cs
- TransformerConfigurationWizardBase.cs
- SqlReferenceCollection.cs
- PropertyInformationCollection.cs
- GreaterThanOrEqual.cs
- CollectionsUtil.cs
- EnumValAlphaComparer.cs
- StateMachineWorkflowDesigner.cs
- Rights.cs
- PathFigureCollection.cs
- SafeNativeMethods.cs
- RowTypeElement.cs
- Tuple.cs
- FormsAuthenticationUserCollection.cs
- DetailsViewModeEventArgs.cs
- EdmFunctions.cs
- HwndSource.cs
- SchemaMapping.cs
- SafeNativeMethods.cs
- SafeHandle.cs
- HttpResponseInternalWrapper.cs
- TypeDescriptionProviderAttribute.cs
- XmlChildEnumerator.cs
- BindingListCollectionView.cs
- SpeechDetectedEventArgs.cs
- Activity.cs
- IsolatedStoragePermission.cs
- ToolTipService.cs
- ToolStripSeparator.cs
- BooleanStorage.cs
- DBConnectionString.cs
- JapaneseLunisolarCalendar.cs
- TypeExtension.cs
- IssuerInformation.cs
- DataControlFieldCell.cs
- TrackingMemoryStream.cs
- PeerContact.cs
- ParsedAttributeCollection.cs
- FixedNode.cs
- TextCompositionManager.cs