// Implements ConnectEx - this provides completion port IO and support for disconnect and reconnects. // Since this is private, the unsafe mode is specified with a flag instead of an overload. private IAsyncResult BeginConnectEx(EndPoint remoteEP, bool flowContext, AsyncCallback callback, object state) { if (s_loggingEnabled) { Logging.Enter(Logging.Sockets, this, "BeginConnectEx", ""); } // This will check the permissions for connect. EndPoint endPointSnapshot = remoteEP; Internals.SocketAddress socketAddress = flowContext ? CheckCacheRemote(ref endPointSnapshot, true) : SnapshotAndSerialize(ref endPointSnapshot); // The socket must be bound first. // The calling method--BeginConnect--will ensure that this method is only // called if _rightEndPoint is not null, of that the endpoint is an IPEndPoint. if (_rightEndPoint == null) { GlobalLog.Assert(endPointSnapshot.GetType() == typeof(IPEndPoint), "Socket#{0}::BeginConnectEx()|Socket not bound and endpoint not IPEndPoint.", Logging.HashString(this)); if (endPointSnapshot.AddressFamily == AddressFamily.InterNetwork) { InternalBind(new IPEndPoint(IPAddress.Any, 0)); } else { InternalBind(new IPEndPoint(IPAddress.IPv6Any, 0)); } } // Allocate the async result and the event we'll pass to the thread pool. ConnectOverlappedAsyncResult asyncResult = new ConnectOverlappedAsyncResult(this, endPointSnapshot, state, callback); // If context flowing is enabled, set it up here. No need to lock since the context isn't used until the callback. if (flowContext) { asyncResult.StartPostingAsyncOp(false); } EndPoint oldEndPoint = _rightEndPoint; if (_rightEndPoint == null) { _rightEndPoint = endPointSnapshot; } SocketError errorCode; try { errorCode = SocketPal.ConnectAsync(this, _handle, socketAddress.Buffer, socketAddress.Size, asyncResult); } catch { // If ConnectEx throws we need to unpin the socketAddress buffer. // _rightEndPoint will always equal oldEndPoint. asyncResult.InternalCleanup(); _rightEndPoint = oldEndPoint; throw; } if (errorCode == SocketError.Success) { SetToConnected(); } GlobalLog.Print("Socket#" + Logging.HashString(this) + "::BeginConnectEx() Interop.Winsock.connect returns:" + errorCode.ToString()); errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode); // Throw an appropriate SocketException if the native call fails synchronously. if (errorCode != SocketError.Success) { // Update the internal state of this socket according to the error before throwing. _rightEndPoint = oldEndPoint; SocketException socketException = new SocketException((int)errorCode); UpdateStatusAfterSocketError(socketException); if (s_loggingEnabled) { Logging.Exception(Logging.Sockets, this, "BeginConnectEx", socketException); } throw socketException; } // We didn't throw, so indicate that we're returning this result to the user. This may call the callback. // This is a nop if the context isn't being flowed. asyncResult.FinishPostingAsyncOp(ref Caches.ConnectClosureCache); GlobalLog.Print("Socket#" + Logging.HashString(this) + "::BeginConnectEx() to:" + endPointSnapshot.ToString() + " returning AsyncResult:" + Logging.HashString(asyncResult)); if (s_loggingEnabled) { Logging.Exit(Logging.Sockets, this, "BeginConnectEx", asyncResult); } return asyncResult; }
private IAsyncResult BeginConnectEx(EndPoint remoteEP, bool flowContext, AsyncCallback callback, object state) { if (Socket.s_LoggingEnabled) Logging.Enter(Logging.Sockets, (object) this, "BeginConnectEx", ""); EndPoint remoteEP1 = remoteEP; SocketAddress socketAddress = flowContext ? this.CheckCacheRemote(ref remoteEP1, true) : this.SnapshotAndSerialize(ref remoteEP1); if (this.m_RightEndPoint == null) { if (remoteEP1.AddressFamily == AddressFamily.InterNetwork) this.InternalBind((EndPoint) new IPEndPoint(IPAddress.Any, 0)); else this.InternalBind((EndPoint) new IPEndPoint(IPAddress.IPv6Any, 0)); } ConnectOverlappedAsyncResult overlappedAsyncResult = new ConnectOverlappedAsyncResult(this, remoteEP1, state, callback); if (flowContext) overlappedAsyncResult.StartPostingAsyncOp(false); overlappedAsyncResult.SetUnmanagedStructures((object) socketAddress.m_Buffer); EndPoint endPoint = this.m_RightEndPoint; if (this.m_RightEndPoint == null) this.m_RightEndPoint = remoteEP1; SocketError errorCode = SocketError.Success; try { int bytesSent; if (!this.ConnectEx(this.m_Handle, Marshal.UnsafeAddrOfPinnedArrayElement((Array) socketAddress.m_Buffer, 0), socketAddress.m_Size, IntPtr.Zero, 0, out bytesSent, overlappedAsyncResult.OverlappedHandle)) errorCode = (SocketError) Marshal.GetLastWin32Error(); } catch { overlappedAsyncResult.InternalCleanup(); this.m_RightEndPoint = endPoint; throw; } if (errorCode == SocketError.Success) this.SetToConnected(); SocketError socketError = overlappedAsyncResult.CheckAsyncCallOverlappedResult(errorCode); if (socketError != SocketError.Success) { this.m_RightEndPoint = endPoint; SocketException socketException = new SocketException(socketError); this.UpdateStatusAfterSocketError(socketException); if (Socket.s_LoggingEnabled) Logging.Exception(Logging.Sockets, (object) this, "BeginConnectEx", (Exception) socketException); throw socketException; } else { overlappedAsyncResult.FinishPostingAsyncOp(ref this.Caches.ConnectClosureCache); if (Socket.s_LoggingEnabled) Logging.Exit(Logging.Sockets, (object) this, "BeginConnectEx", (object) overlappedAsyncResult); return (IAsyncResult) overlappedAsyncResult; } }
//Implements ConnectEx - this provides completion port IO and support for //disconnect and reconnects // Since this is private, the unsafe mode is specified with a flag instead of an overload. private IAsyncResult BeginConnectEx(EndPoint remoteEP, bool flowContext, AsyncCallback callback, object state) { if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginConnectEx", ""); // This will check the permissions for connect. EndPoint endPointSnapshot = remoteEP; SocketAddress socketAddress = flowContext ? CheckCacheRemote(ref endPointSnapshot, true) : SnapshotAndSerialize(ref endPointSnapshot); //socket must be bound first //the calling method BeginConnect will ensure that this method is only //called if m_RightEndPoint is not null, of that the endpoint is an ipendpoint if (m_RightEndPoint==null){ GlobalLog.Assert(endPointSnapshot.GetType() == typeof(IPEndPoint), "Socket#{0}::BeginConnectEx()|Socket not bound and endpoint not IPEndPoint.", ValidationHelper.HashString(this)); if (endPointSnapshot.AddressFamily == AddressFamily.InterNetwork) InternalBind(new IPEndPoint(IPAddress.Any, 0)); else InternalBind(new IPEndPoint(IPAddress.IPv6Any, 0)); } // // Allocate the async result and the event we'll pass to the // thread pool. // ConnectOverlappedAsyncResult asyncResult = new ConnectOverlappedAsyncResult(this, endPointSnapshot, state, callback); // If context flowing is enabled, set it up here. No need to lock since the context isn't used until the callback. if (flowContext) { asyncResult.StartPostingAsyncOp(false); } // This will pin socketAddress buffer asyncResult.SetUnmanagedStructures(socketAddress.m_Buffer); //we should fix this in Whidbey. EndPoint oldEndPoint = m_RightEndPoint; if (m_RightEndPoint == null) { m_RightEndPoint = endPointSnapshot; } SocketError errorCode=SocketError.Success; int ignoreBytesSent; try { if (!ConnectEx( m_Handle, Marshal.UnsafeAddrOfPinnedArrayElement(socketAddress.m_Buffer, 0), socketAddress.m_Size, IntPtr.Zero, 0, out ignoreBytesSent, asyncResult.OverlappedHandle)) { errorCode = (SocketError)Marshal.GetLastWin32Error(); } } catch { // // Bug 152350: If ConnectEx throws we need to unpin the socketAddress buffer. // m_RightEndPoint will always equal oldEndPoint anyways... // asyncResult.InternalCleanup(); m_RightEndPoint = oldEndPoint; throw; } if (errorCode == SocketError.Success) { SetToConnected(); } GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginConnectEx() UnsafeNclNativeMethods.OSSOCK.connect returns:" + errorCode.ToString()); errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode); // // if the asynchronous native call fails synchronously // we'll throw a SocketException // if (errorCode != SocketError.Success) { // // update our internal state after this socket error and throw // m_RightEndPoint = oldEndPoint; SocketException socketException = new SocketException(errorCode); UpdateStatusAfterSocketError(socketException); if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginConnectEx", socketException); throw socketException; } // We didn't throw, so indicate that we're returning this result to the user. This may call the callback. // This is a nop if the context isn't being flowed. asyncResult.FinishPostingAsyncOp(ref Caches.ConnectClosureCache); GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginConnectEx() to:" + endPointSnapshot.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult)); if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginConnectEx", asyncResult); return asyncResult; }
private IAsyncResult BeginConnectEx(EndPoint remoteEP, bool flowContext, AsyncCallback callback, object state) { if (s_LoggingEnabled) { Logging.Enter(Logging.Sockets, this, "BeginConnectEx", ""); } EndPoint point = remoteEP; SocketAddress address = flowContext ? this.CheckCacheRemote(ref point, true) : this.SnapshotAndSerialize(ref point); if (this.m_RightEndPoint == null) { if (point.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { this.InternalBind(new IPEndPoint(IPAddress.Any, 0)); } else { this.InternalBind(new IPEndPoint(IPAddress.IPv6Any, 0)); } } ConnectOverlappedAsyncResult retObject = new ConnectOverlappedAsyncResult(this, point, state, callback); if (flowContext) { retObject.StartPostingAsyncOp(false); } retObject.SetUnmanagedStructures(address.m_Buffer); EndPoint rightEndPoint = this.m_RightEndPoint; if (this.m_RightEndPoint == null) { this.m_RightEndPoint = point; } SocketError success = SocketError.Success; try { int num; if (!this.ConnectEx(this.m_Handle, Marshal.UnsafeAddrOfPinnedArrayElement(address.m_Buffer, 0), address.m_Size, IntPtr.Zero, 0, out num, retObject.OverlappedHandle)) { success = (SocketError) Marshal.GetLastWin32Error(); } } catch { retObject.InternalCleanup(); this.m_RightEndPoint = rightEndPoint; throw; } if (success == SocketError.Success) { this.SetToConnected(); } success = retObject.CheckAsyncCallOverlappedResult(success); if (success != SocketError.Success) { this.m_RightEndPoint = rightEndPoint; SocketException socketException = new SocketException(success); this.UpdateStatusAfterSocketError(socketException); if (s_LoggingEnabled) { Logging.Exception(Logging.Sockets, this, "BeginConnectEx", socketException); } throw socketException; } retObject.FinishPostingAsyncOp(ref this.Caches.ConnectClosureCache); if (s_LoggingEnabled) { Logging.Exit(Logging.Sockets, this, "BeginConnectEx", retObject); } return retObject; }