/// <summary> /// Sends provided bytes. /// </summary> /// <param name="buf">Serialized message bytes to send.</param> /// <returns>Whether the send was successful.</returns> protected override async Task <bool> SendBytesAsync(byte[] buf) { if (this.socket == null) { Debug.WriteLine("Cannot write to a disconnected link"); return(false); } // Await-able task for waiting on send completion var asyncSendSource = new TaskCompletionSource <int>(); // Callback when send completes AsyncCallback sendCallback = result => { int bytesSent = 0; // Retrieve the NewCtrlConnectorImpl instance from the state object CtrlConnectorImpl instance = ( CtrlConnectorImpl )result.AsyncState; try { // Complete the send if the socket hasn't been closed if (instance.socket != null) { bytesSent = instance.socket.EndSend(result); } } catch (ObjectDisposedException) { // If we're being stopped, the socket may already have // been disposed before the callback runs } asyncSendSource.SetResult(bytesSent); }; #if DEBUG2 Debug.WriteLine("Sending " + buf.Length + " bytes"); #endif // Wait for send this.socket.BeginSend(buf, 0, buf.Length, 0, sendCallback, this); await asyncSendSource.Task; #if DEBUG2 Debug.WriteLine("Sent " + buf.Length + " bytes"); #endif return(true); }
/// <summary> /// Disconnect from the protocol server /// </summary> /// <returns>Await-able task.</returns> protected override async Task DisconnectAsync() { if (this.socket != null && this.socket.Connected) { // Await-able task for waiting on connect completion var asyncDisconnectSource = new TaskCompletionSource <object>(); // Callback when connect completes AsyncCallback disconnectCallback = result => { // Retrieve the NewCtrlConnectorImpl instance from the state object CtrlConnectorImpl instance = ( CtrlConnectorImpl )result.AsyncState; try { // Complete the connection if the socket hasn't been closed if (instance.socket != null) { instance.socket.EndDisconnect(result); } } catch (ObjectDisposedException) { // If we're being stopped, the socket may already have // been disposed before the callback runs } // Finish connect task asyncDisconnectSource.SetResult(null); }; #if DEBUG Debug.WriteLine("Disconnecting"); #endif // Wait for disconnect this.socket.BeginDisconnect(false, disconnectCallback, this); await asyncDisconnectSource.Task; #if DEBUG Debug.WriteLine("Disconnected"); #endif } this.CleanupConnectorImpl(); }
/// <summary> /// Connect to the protocol server. /// </summary> /// <returns>A value indicating whether the connect was successful.</returns> protected override async Task <bool> ConnectAsync() { IPEndPoint endpoint = new IPEndPoint( Dns.GetHostAddresses(this.HostName) .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).First(), int.Parse(this.Port)); this.socket = new Socket(SocketType.Stream, ProtocolType.Tcp); this.socket.NoDelay = true; // Await-able task for waiting on connect completion var asyncConnectSource = new TaskCompletionSource <object>(); // Callback when connect completes AsyncCallback connectCallback = result => { // Retrieve the NewCtrlConnectorImpl instance from the state object CtrlConnectorImpl instance = ( CtrlConnectorImpl )result.AsyncState; try { // Complete the connection if the socket hasn't been closed if (instance.socket != null) { instance.socket.EndConnect(result); } } catch (SocketException) { asyncConnectSource.SetResult(false); return; } catch (ObjectDisposedException) { // If we're being stopped, the socket may already have // been disposed before the callback runs } // Finish connect task asyncConnectSource.SetResult(instance.socket != null && instance.socket.Connected); }; #if DEBUG Debug.WriteLine("Connecting to " + endpoint.ToString()); #endif // Wait for connect this.socket.BeginConnect(endpoint, connectCallback, this); bool success = ( bool )await asyncConnectSource.Task; if (!success) { #if DEBUG Debug.WriteLine("Failed to connect to " + endpoint.ToString()); #endif return(false); } #if DEBUG Debug.WriteLine("Connected to " + endpoint.ToString()); #endif // Start link once connected await this.StartLinkAsync(new CtrlReaderImpl ( this.socket )); return(true); }