public void FreeArgs(ISocketAsyncEventArgs args) { if (args.Buffer != m_buffer) { throw new ArgumentException("Can only free args allocated by this factory"); } m_freeIndexPool.Push(args.Offset); args.SetBuffer(null, 0, 0); }
private void SendNotificationToObserver(IObserver<Unit> observer, ISocketAsyncEventArgs socketEvent) { if (socketEvent.SocketError == SocketError.Success) { observer.OnNext(Unit.Default); observer.OnCompleted(); } else { observer.OnError(new RedisException(socketEvent.SocketError)); } }
private void SendNotificationToObserver(IObserver<ConnectionToken> observer, ISocketAsyncEventArgs socketEvent, ConnectionToken connectionToken) { if (socketEvent.SocketError == SocketError.Success) { observer.OnNext(connectionToken); observer.OnCompleted(); } else { observer.OnError(new RedisException(socketEvent.SocketError)); } }
private bool SendNotificationToObserver(IObserver<string> observer, ISocketAsyncEventArgs socketEvent) { if (socketEvent.SocketError == SocketError.Success) { observer.OnNext(Encoding.UTF8.GetString(socketEvent.Buffer, 0, socketEvent.BytesTransferred)); return true; } else { observer.OnError(new RedisException(socketEvent.SocketError)); return false; } }
public Connection(EndPoint endPoint, Func <EndPoint, ISocket> socketFactory, Pool <byte[]> bufferPool, Pool <ReusableMemoryStream> responsePool, int sendBufferSize, int receiveBufferSize) { _socket = socketFactory(endPoint); _socket.Blocking = false; _socket.SendBufferSize = sendBufferSize; _socket.ReceiveBufferSize = receiveBufferSize; _sendArgs = _socket.CreateEventArgs(); _sendArgs.Completed += OnSendCompleted; _receiveArgs = _socket.CreateEventArgs(); _receiveArgs.Completed += OnReceiveCompleted; _bufferPool = bufferPool; _responsePool = responsePool; }
// Async send loop body private static void OnSendCompleted(ISocket sender, ISocketAsyncEventArgs saea) { var connection = saea.UserToken as Connection; if (connection == null) { // It should not happen but it makes Sonar happy CleanAsyncArgs(saea); return; } if (saea.SocketError != SocketError.Success) { connection._sendContext.Promise.SetException(new TransportException(TransportError.WriteError, new SocketException((int)saea.SocketError))); connection.CleanSend(); return; } // Async loop if (saea.BytesTransferred != saea.Count) { connection.LoopSend(saea.Offset + saea.BytesTransferred, saea.Count - saea.BytesTransferred); } else { int read = connection._sendContext.Data.Read(connection._sendContext.Buffer, 0, connection._sendContext.Buffer.Length); if (read != 0) { connection.LoopSend(0, read); } else { connection._sendContext.Promise.SetResult(SuccessResult); connection.CleanSend(); } } }
// Just pass back the response private void HandleBodyState(ReceiveContext context, ISocket socket, ISocketAsyncEventArgs saea) { int rec = Math.Min(saea.Buffer.Length, context.RemainingExpected); context.Response.Write(saea.Buffer, 0, rec); context.RemainingExpected -= rec; if (context.RemainingExpected == 0) { context.Response.Position = 0; OnResponse(context.CorrelationId, context.Response); CleanReceive(false); StartReceive(); } else { saea.SetBuffer(0, Math.Min(context.Buffer.Length, context.RemainingExpected)); if (!socket.ReceiveAsync(saea)) { OnReceiveCompleted(socket, saea); } } }
public Task <bool> Connect(NetAddress remote, Func <ISocketAsyncEventArgs, bool> receiveCallback) { PLog.LogTrace($"Connecting to {remote}"); TaskCompletionSource <bool> src = new TaskCompletionSource <bool>(); if ( (m_isConnected) || (m_isConnecting) ) { src.SetResult(false); return(src.Task); } m_isConnecting = true; m_remote = remote; try { m_receiveCallback = receiveCallback; ISocketAsyncEventArgs args = m_factory.GetEmptyArgs(); args.UserToken = src; args.RemoteEndPoint = m_remote; args.Completed += OnConnectCompleted; if (!m_socket.ConnectAsync(args)) { OnConnectCompleted(this, args as SocketAsyncEventArgs); } } catch (Exception ex) { PLog.LogError($"Failed to connect to {m_remote}"); m_isConnecting = false; m_receiveCallback = null; src.SetException(ex); } return(src.Task); }
// Extract size and correlation Id, then start receive body loop. private void HandleHeaderState(ReceiveContext context, ISocket socket, ISocketAsyncEventArgs saea) { int responseSize = BigEndianConverter.ToInt32(saea.Buffer); int correlationId = BigEndianConverter.ToInt32(saea.Buffer, SizeLength); // TODO check absurd response size? int matching; if (!_correlationIds.TryDequeue(out matching) || matching != correlationId) { throw new CorrelationException(matching, correlationId); } context.State = ReceiveState.Body; context.CorrelationId = correlationId; // responseSize includes 4 bytes of correlation id context.RemainingExpected = responseSize - CorrelationIdLength; context.Response = _responsePool.Reserve(); saea.SetBuffer(0, Math.Min(context.Buffer.Length, context.RemainingExpected)); if (!socket.ReceiveAsync(saea)) { OnReceiveCompleted(socket, saea); } }
/// <summary> /// Cancels an asynchronous request for a remote host connection. /// </summary> /// <param name="e">The System.Net.Sockets.SocketAsyncEventArgs object used to request the connection to the remote host by calling one of the ConnectAsync methods.</param> public void CancelConnectAsync(ISocketAsyncEventArgs e) { SocketAdapter.CancelConnectAsync(e); }
/// <summary>Begins an asynchronous request for a connection to a remote host.</summary> /// <returns>Returns true if the I/O operation is pending. The <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event on the <paramref name="e" /> parameter will be raised upon completion of the operation. Returns false if the I/O operation completed synchronously. In this case, The <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event on the <paramref name="e" /> parameter will not be raised and the <paramref name="e" /> object passed as a parameter may be examined immediately after the method call returns to retrieve the result of the operation. </returns> /// <param name="socketType">One of the <see cref="T:System.Net.Sockets.SocketType" /> values.</param> /// <param name="protocolType">One of the <see cref="T:System.Net.Sockets.ProtocolType" /> values.</param> /// <param name="e">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> object to use for this asynchronous socket operation.</param> /// <exception cref="T:System.ArgumentException">An argument is not valid. This exception occurs if multiple buffers are specified, the <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.BufferList" /> property is not null. </exception> /// <exception cref="T:System.ArgumentNullException">The <paramref name="e" /> parameter cannot be null and the <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.RemoteEndPoint" /> cannot be null.</exception> /// <exception cref="T:System.InvalidOperationException">The <see cref="T:System.Net.Sockets.Socket" /> is listening or a socket operation was already in progress using the <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> object specified in the <paramref name="e" /> parameter.</exception> /// <exception cref="T:System.Net.Sockets.SocketException">An error occurred when attempting to access the socket. See the Remarks section for more information.</exception> /// <exception cref="T:System.NotSupportedException">Windows XP or later is required for this method. This exception also occurs if the local endpoint and the <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.RemoteEndPoint" /> are not the same address family.</exception> /// <exception cref="T:System.ObjectDisposedException">The <see cref="T:System.Net.Sockets.Socket" /> has been closed. </exception> /// <exception cref="T:System.Security.SecurityException">A caller higher in the call stack does not have permission for the requested operation.</exception> public bool ConnectAsync(SocketType socketType, ProtocolType protocolType, ISocketAsyncEventArgs e) { return(SocketAdapter.ConnectAsync(socketType, protocolType, e)); }
/// <summary> /// Cancels an asynchronous request for a remote host connection. /// </summary> /// <param name="e">The System.Net.Sockets.SocketAsyncEventArgs object used to request the connection to the remote host by calling one of the ConnectAsync methods.</param> public static void CancelConnectAsync(ISocketAsyncEventArgs e) { Socket.CancelConnectAsync(e.ToImplementation()); }
public void AcceptAsync(ISocketAsyncEventArgs args) { socket.AcceptAsync(((SocketAsyncEventArgsWrapper)args).WrappedArgs); }
private static void CleanAsyncArgs(ISocketAsyncEventArgs args) { args.UserToken = null; args.SetBuffer(null, 0, 0); }
public bool SendAsync(ISocketAsyncEventArgs args) { return(base.SendAsync((SocketAsyncEventArgs)args)); }
/// <inheritdoc /> public bool ConnectAsync(ISocketAsyncEventArgs e) { return(_socket.ConnectAsync(e.ToImplementation <SocketAsyncEventArgs>())); }
/// <inheritdoc /> public bool ReceiveMessageFromAsync(ISocketAsyncEventArgs e) { return(_socket.ReceiveMessageFromAsync(e.ToImplementation <SocketAsyncEventArgs>())); }
/// <inheritdoc /> public bool AcceptAsync(ISocketAsyncEventArgs e) { return(_socket.AcceptAsync(e.ToImplementation <SocketAsyncEventArgs>())); }
public override bool SendAsync(ISocketAsyncEventArgs e) { SocketAsyncEventArgs ee = (SocketAsyncEventArgs)e.SocketAsyncEventArgs; return(_socket.SendAsync(ee)); }
public override bool ReceiveAsync(ISocketAsyncEventArgs e) { SocketAsyncEventArgs ee = (SocketAsyncEventArgs)e.SocketAsyncEventArgs; return(_socket.ReceiveAsync(ee)); }
public bool SendAsync(ISocketAsyncEventArgs args) { return(SendAsync(args as SocketAsyncEventArgs)); }
public bool ReceiveAsync(ISocketAsyncEventArgs args) { return(base.ReceiveAsync((SocketAsyncEventArgs)args)); }
public bool ReceiveAsync(ISocketAsyncEventArgs args) { return(ReceiveAsync(args as SocketAsyncEventArgs)); }
public void FreeArgs(ISocketAsyncEventArgs args) { // Impl not required for test }
private int _recursiveOnReceiveCompleted; // count recursive calls when Socket.ReceiveAsync returns synchronously // Async receive loop private static void OnReceiveCompleted(ISocket sender, ISocketAsyncEventArgs saea) { var connection = saea.UserToken as Connection; if (connection == null) // This one should not happen but it makes Sonar happy { CleanAsyncArgs(saea); return; } if (saea.SocketError == SocketError.OperationAborted) { connection.CleanReceive(true); return; } if (saea.SocketError != SocketError.Success || saea.BytesTransferred == 0) { connection.CleanReceive(true); connection.OnReceiveError(new TransportException(TransportError.ReadError, new SocketException(saea.SocketError != SocketError.Success ? (int)saea.SocketError : (int)SocketError.ConnectionAborted))); return; } try { // Loop if needed if (saea.BytesTransferred != saea.Count) { saea.SetBuffer(saea.Offset + saea.BytesTransferred, saea.Count - saea.BytesTransferred); if (sender.ReceiveAsync(saea)) { return; } if (++connection._recursiveOnReceiveCompleted > 20) { // Too many recursive calls, we trampoline out of the current // stack trace using a simple Task. This should really not happen // but you never know. connection._recursiveOnReceiveCompleted = 0; Task.Run(() => OnReceiveCompleted(sender, saea)); return; } OnReceiveCompleted(sender, saea); return; } // Handle current state switch (connection._receiveContext.State) { case ReceiveState.Header: connection.HandleHeaderState(connection._receiveContext, sender, saea); break; case ReceiveState.Body: connection.HandleBodyState(connection._receiveContext, sender, saea); break; default: throw new InvalidOperationException( string.Format("Receive state should be Header or Body only (was: {0}).", connection._receiveContext.State)); } } catch (CorrelationException ex) { connection.CleanReceive(true); connection.OnReceiveError(ex); } catch (Exception ex) { connection.CleanReceive(true); connection.OnReceiveError(new TransportException(TransportError.ReadError, ex)); } }
/// <summary>Begins an asynchronous request for a connection to a remote host.</summary> /// <returns>Returns true if the I/O operation is pending. The <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event on the <paramref name="e" /> parameter will be raised upon completion of the operation. Returns false if the I/O operation completed synchronously. In this case, The <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event on the <paramref name="e" /> parameter will not be raised and the <paramref name="e" /> object passed as a parameter may be examined immediately after the method call returns to retrieve the result of the operation. </returns> /// <param name="socketType">One of the <see cref="T:System.Net.Sockets.SocketType" /> values.</param> /// <param name="protocolType">One of the <see cref="T:System.Net.Sockets.ProtocolType" /> values.</param> /// <param name="e">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> object to use for this asynchronous socket operation.</param> /// <exception cref="T:System.ArgumentException">An argument is not valid. This exception occurs if multiple buffers are specified, the <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.BufferList" /> property is not null. </exception> /// <exception cref="T:System.ArgumentNullException">The <paramref name="e" /> parameter cannot be null and the <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.RemoteEndPoint" /> cannot be null.</exception> /// <exception cref="T:System.InvalidOperationException">The <see cref="T:System.Net.Sockets.Socket" /> is listening or a socket operation was already in progress using the <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> object specified in the <paramref name="e" /> parameter.</exception> /// <exception cref="T:System.Net.Sockets.SocketException">An error occurred when attempting to access the socket. See the Remarks section for more information.</exception> /// <exception cref="T:System.NotSupportedException">Windows XP or later is required for this method. This exception also occurs if the local endpoint and the <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.RemoteEndPoint" /> are not the same address family.</exception> /// <exception cref="T:System.ObjectDisposedException">The <see cref="T:System.Net.Sockets.Socket" /> has been closed. </exception> /// <exception cref="T:System.Security.SecurityException">A caller higher in the call stack does not have permission for the requested operation.</exception> public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType, ISocketAsyncEventArgs e) { return(Socket.ConnectAsync(socketType, protocolType, e.ToImplementation())); }
/// <inheritdoc /> public bool SendToAsync(ISocketAsyncEventArgs e) { return(_socket.SendToAsync(e.ToImplementation <SocketAsyncEventArgs>())); }
public void AcceptAsync (ISocketAsyncEventArgs args) { socket.AcceptAsync (((SocketAsyncEventArgsWrapper) args).WrappedArgs); }
public static SocketAsyncEventArgs ToImplementation([CanBeNull] this ISocketAsyncEventArgs abstraction) { return(((IAbstraction <SocketAsyncEventArgs>)abstraction)?.UnsafeConvert()); }
public bool ConnectAsync(ISocketAsyncEventArgs args) { return(base.ConnectAsync((SocketAsyncEventArgs)args)); }