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
- Part.cs
- ProtectedConfigurationSection.cs
- PatternMatcher.cs
- HtmlHead.cs
- FormViewInsertEventArgs.cs
- Compiler.cs
- UrlPath.cs
- TranslateTransform3D.cs
- ScriptingRoleServiceSection.cs
- DataGridViewCellConverter.cs
- LineSegment.cs
- DisableDpiAwarenessAttribute.cs
- MonthChangedEventArgs.cs
- StylusPointProperties.cs
- HTMLTagNameToTypeMapper.cs
- PrimitiveType.cs
- TransactionOptions.cs
- QilVisitor.cs
- ToolStripItemRenderEventArgs.cs
- SingleResultAttribute.cs
- SyntaxCheck.cs
- ProgressChangedEventArgs.cs
- SqlDataSourceQueryConverter.cs
- AuthenticateEventArgs.cs
- Font.cs
- GroupItem.cs
- TreeNodeCollection.cs
- WindowsRebar.cs
- ProcessModelSection.cs
- ActionNotSupportedException.cs
- XhtmlBasicListAdapter.cs
- URLString.cs
- OpenFileDialog.cs
- AliasGenerator.cs
- PublisherMembershipCondition.cs
- ParserStreamGeometryContext.cs
- CompilerCollection.cs
- counter.cs
- DesignerActionTextItem.cs
- Visual3D.cs
- IndividualDeviceConfig.cs
- IItemContainerGenerator.cs
- SHA1CryptoServiceProvider.cs
- VerificationAttribute.cs
- FolderBrowserDialog.cs
- PointLightBase.cs
- MetadataSource.cs
- InvalidateEvent.cs
- ComAwareEventInfo.cs
- MenuItemStyleCollectionEditor.cs
- TcpTransportSecurity.cs
- VideoDrawing.cs
- XmlUrlResolver.cs
- TypeExtension.cs
- EqualityComparer.cs
- FileCodeGroup.cs
- LinearQuaternionKeyFrame.cs
- NodeLabelEditEvent.cs
- ScrollChrome.cs
- UrlPropertyAttribute.cs
- PrintingPermission.cs
- OdbcStatementHandle.cs
- DataControlImageButton.cs
- Bits.cs
- SoapInteropTypes.cs
- _SSPIWrapper.cs
- ControlIdConverter.cs
- TypedReference.cs
- InputLanguageManager.cs
- ImageAutomationPeer.cs
- VisualStyleRenderer.cs
- BindingsCollection.cs
- PowerStatus.cs
- PropertyTabAttribute.cs
- Globals.cs
- PrintDocument.cs
- AdapterSwitches.cs
- GeneralTransform2DTo3DTo2D.cs
- HttpErrorTraceRecord.cs
- AsyncOperationManager.cs
- ToolStripOverflowButton.cs
- Geometry.cs
- IconBitmapDecoder.cs
- CodeGenHelper.cs
- DescendantOverDescendantQuery.cs
- XamlWriter.cs
- TriggerActionCollection.cs
- LayoutInformation.cs
- SchemaCollectionCompiler.cs
- EditingCommands.cs
- RelationalExpressions.cs
- PeerNearMe.cs
- TreeView.cs
- TempEnvironment.cs
- TransformerTypeCollection.cs
- FlowThrottle.cs
- LineServicesRun.cs
- Matrix3DConverter.cs
- ResourceDictionaryCollection.cs
- KerberosTokenFactoryCredential.cs