Internal class holding relevant information for async requests.
예제 #1
0
        /// <summary>
        /// Begin an async SNMP request
        /// </summary>
        /// <param name="peer">Pdu to send to the agent</param>
        /// <param name="port">Callback to receive response from the agent</param>
        /// <param name="buffer">Buffer containing data to send to the peer</param>
        /// <param name="bufferLength">Length of data in the buffer</param>
        /// <param name="timeout">Request timeout in milliseconds</param>
        /// <param name="retries">Maximum retry count. 0 = single request no further retries.</param>
        /// <param name="asyncCallback">Callback that will receive the status and result of the operation</param>
        /// <returns>Returns false if another request is already in progress or if socket used by the class
        /// has been closed using Dispose() member, otherwise true</returns>
        /// <exception cref="SnmpException">Thrown when IPv4 address is passed to the v6 socket or vice versa</exception>
        internal bool RequestAsync(IPAddress peer, int port, byte[] buffer, int bufferLength, int timeout, int retries, SnmpAsyncCallback asyncCallback)
        {
            if (_busy == true)
            {
                return(false);
            }
            if (_socket == null)
            {
                return(false); // socket has been closed. no new operations are possible.
            }

            if (_socket.AddressFamily != peer.AddressFamily)
            {
                throw new SnmpException("Invalid address protocol version.");
            }
            _busy                      = true;
            _asyncCallback             = null;
            _asyncCallback            += asyncCallback;
            _requestState              = new AsyncRequestState(peer, port, retries, timeout);
            _requestState.Packet       = buffer;
            _requestState.PacketLength = bufferLength;

            // _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _requestState.Timeout);

            _inBuffer = new byte[64 * 1024]; // create incoming data buffer

            SendToBegin();                   // Send the request

            return(true);
        }
예제 #2
0
 /// <summary>
 /// Calls async version of the SendTo socket function.
 /// </summary>
 internal void SendToBegin()
 {
     if (_requestState == null)
     {
         _busy = false;
         return;
     }
     // kill the timeout timer - there shouldn't be one active when we are sending a new request
     if (_requestState.Timer != null)
     {
         _requestState.Timer.Dispose();
         _requestState.Timer = null;
     }
     if (_socket == null)
     {
         _busy         = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
         return; // socket has been closed. no new operations are possible.
     }
     try
     {
         _socket.BeginSendTo(_requestState.Packet, 0, _requestState.PacketLength, SocketFlags.None, _requestState.EndPoint, new AsyncCallback(SendToCallback), null);
     }
     catch
     {
         _busy         = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.SocketSendError, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
     }
 }
예제 #3
0
        /// <summary>
        /// Callback member called on completion of BeginSendTo send data operation.
        /// </summary>
        /// <param name="ar">Async result</param>
        internal void SendToCallback(IAsyncResult ar)
        {
            if (_socket == null)
            {
                _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
                _busy = false;
                return;                 // socket has been closed. no new operations are possible.
            }
            int sentLength = 0;

            try
            {
                sentLength = _socket.EndSendTo(ar);
            }
            catch
            {
                sentLength = 0;
            }
            if (sentLength != _requestState.PacketLength)
            {
                _busy         = false;
                _requestState = null;
                _asyncCallback(AsyncRequestResult.SocketSendError, new IPEndPoint(IPAddress.Any, 0), null, 0);
            }
            // Start receive timer
            ReceiveBegin();             // Initialize a receive call
        }
예제 #4
0
        /// <summary>
        ///     Begin async version of ReceiveFrom member of the socket class.
        /// </summary>
        internal void ReceiveBegin()
        {
            // kill the timeout timer
            if (_requestState.Timer != null)
            {
                _requestState.Timer.Dispose();
                _requestState.Timer = null;
            }
            if (_socket == null || !_busy || _requestState == null)
            {
                _busy         = false;
                _requestState = null;
                if (_socket != null)
                {
                    _asyncCallback(AsyncRequestResult.Terminated,
                                   new IPEndPoint(
                                       _socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0),
                                   null, 0);
                }
                else
                {
                    _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
                }
                return;
                // socket has been closed. no new operations are possible.
            }
            _receivePeer =
                new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any,
                               0);
            EndPoint ep = _receivePeer;

            try
            {
                _socket.BeginReceiveFrom(_inBuffer, 0, _inBuffer.Length, SocketFlags.None, ref ep, ReceiveFromCallback,
                                         null);
            }
            catch
            {
                // retry on every error. this can be done better by evaluating the returned
                // error value but it's a lot of work and for a non-acked protocol, just send it again
                // until you reach max retries.
                RetryAsyncRequest();
                return;
            }
            _requestState.Timer = new Timer(AsyncRequestTimerCallback, null, _requestState.Timeout, Timeout.Infinite);
        }
예제 #5
0
 /// <summary>
 /// Calls async version of the SendTo socket function.
 /// </summary>
 internal void SendToBegin()
 {
     if (_socket == null)
     {
         _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
         _busy = false;
         return;                 // socket has been closed. no new operations are possible.
     }
     try
     {
         _socket.BeginSendTo(_requestState.Packet, 0, _requestState.PacketLength, SocketFlags.None, _requestState.EndPoint, new AsyncCallback(SendToCallback), null);
     }
     catch
     {
         _busy         = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.SocketSendError, new IPEndPoint(IPAddress.Any, 0), null, 0);
     }
 }
예제 #6
0
        /// <summary>
        ///     Callback member called on completion of BeginSendTo send data operation.
        /// </summary>
        /// <param name="ar">Async result</param>
        internal void SendToCallback(IAsyncResult ar)
        {
            if (_socket == null || !_busy || _requestState == null)
            {
                _busy         = false;
                _requestState = null;
                _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
                return; // socket has been closed. no new operations are possible.
            }
            var sentLength = 0;

            try
            {
                sentLength = _socket.EndSendTo(ar);
            }
            catch (NullReferenceException ex)
            {
                ex.GetType();
                _busy         = false;
                _requestState = null;
                _asyncCallback(AsyncRequestResult.Terminated,
                               new IPEndPoint(
                                   _socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0),
                               null, 0);
                return;
            }
            catch
            {
                sentLength = 0;
            }
            if (sentLength != _requestState.PacketLength)
            {
                _busy         = false;
                _requestState = null;
                _asyncCallback(AsyncRequestResult.SocketSendError,
                               new IPEndPoint(
                                   _socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0),
                               null, 0);
                return;
            }
            // Start receive timer
            ReceiveBegin(); // Initialize a receive call
        }
예제 #7
0
 /// <summary>
 ///     Internal retry function. Checks if request has reached maximum number of retries and either resends the request if
 ///     not reached,
 ///     or sends request timed-out notification to the caller if maximum retry count has been reached and request has
 ///     failed.
 /// </summary>
 internal void RetryAsyncRequest()
 {
     // kill the timer if one is active
     if (_requestState.Timer != null)
     {
         _requestState.Timer.Dispose();
         _requestState.Timer = null;
     }
     if (_socket == null || !_busy || _requestState == null)
     {
         _busy         = false;
         _requestState = null;
         if (_socket != null)
         {
             _asyncCallback(AsyncRequestResult.Terminated,
                            new IPEndPoint(
                                _socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0),
                            null, 0);
         }
         else
         {
             _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
         }
         return; // socket has been closed. no new operations are possible.
     }
     // We increment the retry counter before retry count. Initial CurrentRetry value is set to -1 so that
     // MaxRetries value can be 0 (first request is not counted as a retry).
     _requestState.CurrentRetry += 1;
     if (_requestState.CurrentRetry >= _requestState.MaxRetries)
     {
         _busy         = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.Timeout,
                        new IPEndPoint(
                            _socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0),
                        null, 0);
     }
     else
     {
         SendToBegin();
     }
 }
예제 #8
0
        /// <summary>
        /// Internal callback called as part of Socket.BeginReceiveFrom. Process incoming packets and notify caller
        /// of results.
        /// </summary>
        /// <param name="ar">Async call result used by <seealso cref="Socket.EndReceiveFrom"/></param>
        internal void ReceiveFromCallback(IAsyncResult ar)
        {
            // kill the timer if one is active
            if (_requestState != null && _requestState.Timer != null)
            {
                _requestState.Timer.Dispose();
                _requestState.Timer = null;
            }
            if (_socket == null || !_busy || _requestState == null)
            {
                _busy         = false;
                _requestState = null;
                if (_socket == null)
                {
                    _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
                }
                else
                {
                    _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
                }
                return; // socket has been closed. no new operations are possible.
            }
            int      inlen = 0;
            EndPoint ep    = (EndPoint)_receivePeer;

            try
            {
                inlen = _socket.EndReceiveFrom(ar, ref ep);
            }
            catch (SocketException ex)
            {
                if (ex.ErrorCode == 10040)
                {
                    inlen = 0; // Packet too large
                }
                else if (ex.ErrorCode == 10050)
                {
                    _busy         = false;
                    _requestState = null;
                    _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
                    return;
                }
                else if (ex.ErrorCode == 10051)
                {
                    _busy         = false;
                    _requestState = null;
                    _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
                    return;
                }
                else if (ex.ErrorCode == 10054)
                {
                    _busy         = false;
                    _requestState = null;
                    _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
                    return;
                }
                else if (ex.ErrorCode == 10064)
                {
                    _busy         = false;
                    _requestState = null;
                    _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
                    return;
                }
                else if (ex.ErrorCode == 10065)
                {
                    _busy         = false;
                    _requestState = null;
                    _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
                    return;
                }
                else if (ex.ErrorCode == 10061)
                {
                    _busy         = false;
                    _requestState = null;
                    _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
                    return;
                }
                else if (ex.ErrorCode == 10060)
                {
                    inlen = 0; // Connection attempt timed out. Fall through to retry
                }
                else
                {
                    // Assume it is a timeout
                }
            }
            catch (ObjectDisposedException ex)
            {
                ex.GetType(); // this is to avoid the compilation warning
                _asyncCallback(AsyncRequestResult.Terminated, null, null, -1);
                return;
            }
            catch (NullReferenceException ex)
            {
                ex.GetType(); // this is to avoid the compilation warning
                _asyncCallback(AsyncRequestResult.Terminated, null, null, -1);
                return;
            }
            catch (Exception ex)
            {
                ex.GetType();
                // we don't care what exception happened. We only want to know if we should retry the request
                inlen = 0;
            }
            if (inlen == 0)
            {
                RetryAsyncRequest();
            }
            else
            {
                // make a copy of the data from the internal buffer
                byte[] buf = new byte[inlen];
                Buffer.BlockCopy(_inBuffer, 0, buf, 0, inlen);
                _busy         = false;
                _requestState = null;
                _asyncCallback(AsyncRequestResult.NoError, _receivePeer, buf, buf.Length);
            }
        }
예제 #9
0
 /// <summary>
 /// Callback member called on completion of BeginSendTo send data operation.
 /// </summary>
 /// <param name="ar">Async result</param>
 internal void SendToCallback(IAsyncResult ar)
 {
     if (_socket == null || ! _busy || _requestState == null)
     {
         _busy = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
         return; // socket has been closed. no new operations are possible.
     }
     int sentLength = 0;
     try
     {
         sentLength = _socket.EndSendTo(ar);
     }
     catch (NullReferenceException ex)
     {
         ex.GetType();
         _busy = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
         return;
     }
     catch
     {
         sentLength = 0;
     }
     if (sentLength != _requestState.PacketLength)
     {
         _busy = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.SocketSendError, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
         return;
     }
     // Start receive timer
     ReceiveBegin(); // Initialize a receive call
 }
예제 #10
0
 /// <summary>
 /// Calls async version of the SendTo socket function.
 /// </summary>
 internal void SendToBegin()
 {
     if (_requestState == null)
     {
         _busy = false;
         return;
     }
     // kill the timeout timer - there shouldn't be one active when we are sending a new request
     if (_requestState.Timer != null)
     {
         _requestState.Timer.Dispose();
         _requestState.Timer = null;
     }
     if (_socket == null)
     {
         _busy = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
         return; // socket has been closed. no new operations are possible.
     }
     try
     {
         _socket.BeginSendTo(_requestState.Packet, 0, _requestState.PacketLength, SocketFlags.None, _requestState.EndPoint, new AsyncCallback(SendToCallback), null);
     }
     catch
     {
         _busy = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.SocketSendError, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
     }
 }
예제 #11
0
 /// <summary>
 /// Internal retry function. Checks if request has reached maximum number of retries and either resends the request if not reached,
 /// or sends request timed-out notification to the caller if maximum retry count has been reached and request has failed.
 /// </summary>
 internal void RetryAsyncRequest()
 {
     // kill the timer if one is active
     if (_requestState.Timer != null)
     {
         _requestState.Timer.Dispose();
         _requestState.Timer = null;
     }
     if (_socket == null || !_busy || _requestState == null)
     {
         _busy = false;
         _requestState = null;
         if( _socket != null )
             _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
         else
             _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
         return; // socket has been closed. no new operations are possible.
     }
     // We increment the retry counter before retry count. Initial CurrentRetry value is set to -1 so that
     // MaxRetries value can be 0 (first request is not counted as a retry).
     _requestState.CurrentRetry += 1;
     if (_requestState.CurrentRetry >= _requestState.MaxRetries)
     {
         _busy = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.Timeout, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
         return;
     }
     else
     {
         SendToBegin();
     }
 }
예제 #12
0
        /// <summary>
        /// Begin an async SNMP request
        /// </summary>
        /// <param name="peer">Pdu to send to the agent</param>
        /// <param name="port">Callback to receive response from the agent</param>
        /// <param name="buffer">Buffer containing data to send to the peer</param>
        /// <param name="bufferLength">Length of data in the buffer</param>
        /// <param name="timeout">Request timeout in milliseconds</param>
        /// <param name="retries">Maximum retry count. 0 = single request no further retries.</param>
        /// <param name="asyncCallback">Callback that will receive the status and result of the operation</param>
        /// <returns>Returns false if another request is already in progress or if socket used by the class
        /// has been closed using Dispose() member, otherwise true</returns>
        /// <exception cref="SnmpException">Thrown when IPv4 address is passed to the v6 socket or vice versa</exception>
        internal bool RequestAsync(IPAddress peer, int port, byte[] buffer, int bufferLength, int timeout, int retries, SnmpAsyncCallback asyncCallback)
        {
            if (_busy == true)
            {
                return false;
            }
            if (_socket == null)
            {
                return false; // socket has been closed. no new operations are possible.
            }

            if (_socket.AddressFamily != peer.AddressFamily)
                throw new SnmpException("Invalid address protocol version.");
            _busy = true;
            _asyncCallback = null;
            _asyncCallback += asyncCallback;
            _requestState = new AsyncRequestState(peer, port, retries, timeout);
            _requestState.Packet = buffer;
            _requestState.PacketLength = bufferLength;

            // _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _requestState.Timeout);

            _inBuffer = new byte[64 * 1024]; // create incoming data buffer

            SendToBegin(); // Send the request

            return true;
        }
예제 #13
0
 /// <summary>
 /// Internal callback called as part of Socket.BeginReceiveFrom. Process incoming packets and notify caller
 /// of results.
 /// </summary>
 /// <param name="ar">Async call result used by <seealso cref="Socket.EndReceiveFrom"/></param>
 internal void ReceiveFromCallback(IAsyncResult ar)
 {
     // kill the timer if one is active
     if (_requestState.Timer != null)
     {
         _requestState.Timer.Dispose();
         _requestState.Timer = null;
     }
     if (_socket == null || !_busy || _requestState == null)
     {
         _busy = false;
         _requestState = null;
         if( _socket == null )
             _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
         else
             _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
         return; // socket has been closed. no new operations are possible.
     }
     int inlen = 0;
     EndPoint ep = (EndPoint)_receivePeer;
     try
     {
         inlen = _socket.EndReceiveFrom(ar, ref ep);
     }
     catch (SocketException ex)
     {
         if (ex.ErrorCode == 10040)
         {
             inlen = 0; // Packet too large
         }
         else if (ex.ErrorCode == 10050)
         {
             _busy = false;
             _requestState = null;
             _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
             return;
         }
         else if (ex.ErrorCode == 10051)
         {
             _busy = false;
             _requestState = null;
             _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
             return;
         }
         else if (ex.ErrorCode == 10054)
         {
             _busy = false;
             _requestState = null;
             _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
             return;
         }
         else if (ex.ErrorCode == 10064)
         {
             _busy = false;
             _requestState = null;
             _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
             return;
         }
         else if (ex.ErrorCode == 10065)
         {
             _busy = false;
             _requestState = null;
             _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
             return;
         }
         else if (ex.ErrorCode == 10061)
         {
             _busy = false;
             _requestState = null;
             _asyncCallback(AsyncRequestResult.SocketReceiveError, null, null, -1);
             return;
         }
         else if (ex.ErrorCode == 10060)
         {
             inlen = 0; // Connection attempt timed out. Fall through to retry
         }
         else
         {
             // Assume it is a timeout
         }
     }
     catch (ObjectDisposedException ex)
     {
         ex.GetType(); // this is to avoid the compilation warning
         _asyncCallback(AsyncRequestResult.Terminated, null, null, -1);
         return;
     }
     catch (NullReferenceException ex)
     {
         ex.GetType(); // this is to avoid the compilation warning
         _asyncCallback(AsyncRequestResult.Terminated, null, null, -1);
         return;
     }
     catch (Exception ex)
     {
         ex.GetType();
         // we don't care what exception happened. We only want to know if we should retry the request
         inlen = 0;
     }
     if (inlen == 0 )
     {
         RetryAsyncRequest();
     }
     else
     {
         // make a copy of the data from the internal buffer
         byte[] buf = new byte[inlen];
         Buffer.BlockCopy(_inBuffer, 0, buf, 0, inlen);
         _busy = false;
         _requestState = null;
         _asyncCallback(AsyncRequestResult.NoError, _receivePeer, buf, buf.Length);
     }
 }
예제 #14
0
        /// <summary>
        /// Begin async version of ReceiveFrom member of the socket class.
        /// </summary>
        internal void ReceiveBegin()
        {
            // kill the timeout timer
            if(_requestState.Timer != null)
            {
                _requestState.Timer.Dispose();
                _requestState.Timer = null;
            }
            if (_socket == null || !_busy || _requestState == null)
            {
                _busy = false;
                _requestState = null;
                if( _socket != null )
                    _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0), null, 0);
                else
                    _asyncCallback(AsyncRequestResult.Terminated, new IPEndPoint(IPAddress.Any, 0), null, 0);
                return;
                // socket has been closed. no new operations are possible.
            }
            _receivePeer = new IPEndPoint(_socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
            EndPoint ep = (EndPoint)_receivePeer;
            try
            {
                _socket.BeginReceiveFrom(_inBuffer, 0, _inBuffer.Length, SocketFlags.None, ref ep, new AsyncCallback(ReceiveFromCallback), null);
            }
            catch
            {

                // retry on every error. this can be done better by evaluating the returned
                // error value but it's a lot of work and for a non-acked protocol, just send it again
                // until you reach max retries.
                RetryAsyncRequest();
                return;
            }
            _requestState.Timer = new Timer(new TimerCallback(AsyncRequestTimerCallback), null, _requestState.Timeout, System.Threading.Timeout.Infinite);
        }