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
- InkPresenter.cs
- Pair.cs
- CompressionTransform.cs
- CompressionTracing.cs
- DropShadowEffect.cs
- PrintEvent.cs
- NetStream.cs
- AnnotationMap.cs
- Visual3DCollection.cs
- RenderOptions.cs
- TranslateTransform.cs
- XmlWrappingWriter.cs
- WebPartMenu.cs
- Animatable.cs
- AdornedElementPlaceholder.cs
- MulticastDelegate.cs
- TextEvent.cs
- TemplateControl.cs
- Msec.cs
- ShapingEngine.cs
- PageThemeCodeDomTreeGenerator.cs
- CachedFontFace.cs
- FormsAuthentication.cs
- ToolStripPanelSelectionGlyph.cs
- PasswordRecovery.cs
- ProjectionPathSegment.cs
- ClientUrlResolverWrapper.cs
- DBDataPermissionAttribute.cs
- XsdDataContractExporter.cs
- MethodRental.cs
- WindowPatternIdentifiers.cs
- StringCollectionMarkupSerializer.cs
- Substitution.cs
- ActiveDesignSurfaceEvent.cs
- PolyBezierSegmentFigureLogic.cs
- LockCookie.cs
- UrlMappingsSection.cs
- Debugger.cs
- RoutedEvent.cs
- OptimizedTemplateContentHelper.cs
- ColumnResult.cs
- OutputCacheProfileCollection.cs
- WebRequestModuleElement.cs
- ToolBarTray.cs
- MenuItem.cs
- _NtlmClient.cs
- NavigationProgressEventArgs.cs
- OpenTypeCommon.cs
- SurrogateChar.cs
- ObjectViewListener.cs
- ToolStripHighContrastRenderer.cs
- EntityCollection.cs
- SettingsAttributeDictionary.cs
- ApplicationGesture.cs
- SqlTrackingQuery.cs
- CompilationUnit.cs
- User.cs
- NaturalLanguageHyphenator.cs
- XamlInt32CollectionSerializer.cs
- CommonXSendMessage.cs
- EditCommandColumn.cs
- WindowsHyperlink.cs
- FormViewUpdatedEventArgs.cs
- SiteMembershipCondition.cs
- TimeZone.cs
- Deflater.cs
- EventToken.cs
- ActivityBuilderHelper.cs
- TimersDescriptionAttribute.cs
- HideDisabledControlAdapter.cs
- SqlDataSourceView.cs
- Base64Stream.cs
- Camera.cs
- xmlsaver.cs
- MouseGestureValueSerializer.cs
- CodeDefaultValueExpression.cs
- CollectionViewGroupInternal.cs
- TimeSpan.cs
- TextDpi.cs
- EdmMember.cs
- PointAnimationUsingKeyFrames.cs
- XmlSchemaObject.cs
- XPathEmptyIterator.cs
- KnownBoxes.cs
- unsafenativemethodstextservices.cs
- PropertyValidationContext.cs
- SQLInt64Storage.cs
- SecurityTokenResolver.cs
- TreeViewCancelEvent.cs
- ObjectSet.cs
- RC2.cs
- ListMarkerSourceInfo.cs
- ObjectStateManagerMetadata.cs
- ParallelTimeline.cs
- WindowsMenu.cs
- FileDialogCustomPlace.cs
- BaseComponentEditor.cs
- Switch.cs
- ContractListAdapter.cs
- XPathMultyIterator.cs