Esempio n. 1
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static async Task SendAsync(this ISnmpMessage message, IPEndPoint manager, UdpClient socket, CancellationToken cancellationToken = default)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            var bytes = message.ToBytes();

            socket.Connect(manager);
            await socket.SendAsync(bytes, bytes.Length);
        }
Esempio n. 2
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        public static async Task SendAsync(this ISnmpMessage message, EndPoint manager)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            using (var socket = manager.GetSocket())
            {
                await message.SendAsync(manager, socket).ConfigureAwait(false);
            }
        }
        public static void Fill(this ISnmpMessage message, TreeView tree)
        {
            var messageNode = tree.Nodes.Add(string.Format("Version {0}", message.Version));

            if (message.Version == VersionCode.V3)
            {
                var header = messageNode.Nodes.Add("header");
                header.Nodes.Add(string.Format("message id {0}", message.Header.MessageId));
                header.Nodes.Add(string.Format("max size {0}", message.Header.MaxSize));
                header.Nodes.Add(string.Format("security level {0}", message.Header.SecurityLevel.GetString()));
            }

            var parameter = messageNode.Nodes.Add("parameters");

            if (message.Version == VersionCode.V3)
            {
                parameter.Nodes.Add(string.Format("user {0}", message.Parameters.UserName));
                parameter.Nodes.Add(string.Format("engine id {0}", message.Parameters.EngineId.ToHexString()));
                parameter.Nodes.Add(string.Format("engine boots {0}", message.Parameters.EngineBoots));
                parameter.Nodes.Add(string.Format("engine time {0}", message.Parameters.EngineTime));
                parameter.Nodes.Add(string.Format("checksum {0}", message.Parameters.AuthenticationParameters.ToHexString()));
                parameter.Nodes.Add(string.Format("checksum broken {0}", message.Parameters.IsInvalid));
                parameter.Nodes.Add(string.Format("encryption token {0}", message.Parameters.PrivacyParameters.ToHexString()));
            }
            else
            {
                parameter.Nodes.Add(string.Format("community {0}", message.Parameters.UserName));
            }

            var scope = messageNode.Nodes.Add("scope");

            if (message.TypeCode() == SnmpType.Unknown)
            {
                scope.Nodes.Add("decryption error");
            }
            else if (OctetString.IsNullOrEmpty(message.Parameters.PrivacyParameters))
            {
                if (message.Version == VersionCode.V3)
                {
                    scope.Nodes.Add(string.Format("context name {0}", message.Scope.ContextName));
                    scope.Nodes.Add(string.Format("context engine id {0}", message.Scope.ContextEngineId.ToHexString()));
                }

                var pdu = scope.Nodes.Add(string.Format("pdu type {0}", message.Scope.Pdu.TypeCode));
                pdu.Nodes.Add(string.Format("request id {0}", message.Scope.Pdu.RequestId));
                pdu.Nodes.Add(string.Format("error status {0}", message.Scope.Pdu.ErrorStatus.ToErrorCode()));
                pdu.Nodes.Add(string.Format("error index {0}", message.Scope.Pdu.ErrorIndex));
                var variables = pdu.Nodes.Add(string.Format("variable count {0}", message.Scope.Pdu.Variables.Count));
                foreach (var variable in message.Scope.Pdu.Variables)
                {
                    variables.Nodes.Add(variable.ToString());
                }
            }
            else
            {
                scope.Nodes.Add("encrypted data");
            }

            tree.ExpandAll();
        }
Esempio n. 4
0
        /// <summary>
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Port number.</param>
        /// <returns></returns>
        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            var code = request.TypeCode();

            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
            }

            using (var socket = receiver.GetSocket())
            {
#if SSHARP
                socket.Connect(receiver);
#endif
                return(request.GetResponse(timeout, receiver, socket));
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static void Send(this ISnmpMessage message, EndPoint manager, Socket socket)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            var bytes = message.ToBytes();

            socket.SendTo(bytes, 0, bytes.Length, SocketFlags.None, manager);
        }
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static async Task SendAsync(this ISnmpMessage message, EndPoint manager, Socket socket)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            var buffer = new ArraySegment <byte>(message.ToBytes());
            await socket.SendToAsync(buffer, SocketFlags.None, manager);
        }
Esempio n. 7
0
        /// <summary>
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Port number.</param>
        /// <param name="registry">User registry.</param>
        /// <returns></returns>
        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry)
        {
            // TODO: make more usage of UserRegistry.
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            var code = request.TypeCode();

            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
            }

            using (var socket = receiver.GetSocket())
            {
                return(request.GetResponse(timeout, receiver, registry, socket));
            }
        }
Esempio n. 8
0
        public void TestSendTrap()
        {
            TrapV1Message message = new TrapV1Message(VersionCode.V1,
                                                      IPAddress.Parse("127.0.0.1"),
                                                      new OctetString("public"),
                                                      new ObjectIdentifier(new uint[] { 1, 3, 6 }),
                                                      GenericCode.AuthenticationFailure,
                                                      0,
                                                      0,
                                                      new List <Variable>());

            byte[]       bytes  = message.ToBytes();
            ISnmpMessage parsed = MessageFactory.ParseMessages(bytes, new UserRegistry())[0];

            Assert.Equal(SnmpType.TrapV1Pdu, parsed.TypeCode());
            TrapV1Message m = (TrapV1Message)parsed;

            Assert.Equal(GenericCode.AuthenticationFailure, m.Generic);
            Assert.Equal(0, m.Specific);
            Assert.Equal("public", m.Community.ToString());
            Assert.Equal(IPAddress.Parse("127.0.0.1"), m.AgentAddress);
            Assert.Equal(new uint[] { 1, 3, 6 }, m.Enterprise.ToNumerical());
            Assert.Equal(0U, m.TimeStamp);
            Assert.Equal(0, m.Variables().Count);
        }
Esempio n. 9
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        public static void Send(this ISnmpMessage message, EndPoint manager)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (manager == null)
            {
                throw new ArgumentNullException("manager");
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            using (var socket = manager.GetSocket())
            {
                message.Send(manager, socket);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static async Task SendAsync(this ISnmpMessage message, EndPoint manager, Socket socket)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (socket == null)
            {
                throw new ArgumentNullException("socket");
            }

            if (manager == null)
            {
                throw new ArgumentNullException("manager");
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a trap message: {0}", code));
            }

            var bytes = message.ToBytes();
            var info  = SocketExtension.EventArgsFactory.Create();

            info.RemoteEndPoint = manager;
            info.SetBuffer(bytes, 0, bytes.Length);
            using (var awaitable1 = new SocketAwaitable(info))
            {
                await socket.SendToAsync(awaitable1);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Port number.</param>
        /// <param name="registry">User registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry)
        {
            // TODO: make more usage of UserRegistry.
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            var code = request.TypeCode();

            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
            }

            using (var socket = receiver.GetSocket())
            {
                return(await request.GetResponseAsync(receiver, registry, socket).ConfigureAwait(false));
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Begins to asynchronously send an <see cref="ISnmpMessage"/> to an <see cref="IPEndPoint"/>.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="registry">The user registry.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state object.</param>
        /// <returns></returns>
        public static IAsyncResult BeginGetResponse(
            this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, AsyncCallback callback, object state)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException("udpSocket");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            if (registry == null)
            {
                throw new ArgumentNullException("registry");
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            // Whatever you change, try to keep the Send and the Receive close to each other.
            udpSocket.SendTo(request.ToBytes(), receiver);
#if CF
            var bufferSize = 8192;
#elif SSHARP
            var bufferSize = 16384;
#else
            var bufferSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;
#endif
            var buffer = new byte[bufferSize];

            // https://sharpsnmplib.codeplex.com/workitem/7234
            if (callback != null)
            {
                AsyncCallback wrapped = callback;
                callback = asyncResult =>
                {
                    var result = new SnmpMessageAsyncResult(asyncResult, udpSocket, registry, receiver, buffer);
                    wrapped(result);
                };
            }

            var ar = udpSocket.BeginReceive(buffer, 0, bufferSize, SocketFlags.None, callback, state);
            return(new SnmpMessageAsyncResult(ar, udpSocket, registry, receiver, buffer));
        }
        /// <summary>
        /// Variables.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        public static IList <Variable> Variables(this ISnmpMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var code = message.TypeCode();

            return(code == SnmpType.Unknown ? new List <Variable>(0) : message.Scope.Pdu.Variables);
        }
Esempio n. 14
0
        /// <summary>
        /// Sends an  <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="connectionTimeout">The time-out value, in milliseconds for how long to wait for a connection</param>
        /// <param name="responseTimeout">The time-out value, in milliseconds for how long to wait for a response. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="client">The DTLS client</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetSecureResponseAsync(this ISnmpMessage request, TimeSpan connectionTimeout, TimeSpan responseTimeout, IPEndPoint receiver, Client client, UserRegistry registry)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (client is null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes = request.ToBytes();
            await client.ConnectToServerAsync(receiver, responseTimeout, connectionTimeout).ConfigureAwait(false);

            var reply = await client.SendAndGetResponseAsync(bytes, responseTimeout).ConfigureAwait(false);

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, reply.Length, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
Esempio n. 15
0
        public void Test()
        {
            byte[]       expected = Properties.Resources.get;
            ISnmpMessage message  = MessageFactory.ParseMessages(expected, new UserRegistry())[0];

            Assert.Equal(SnmpType.GetRequestPdu, message.TypeCode());
            GetRequestPdu pdu = (GetRequestPdu)message.Pdu();

            Assert.Equal(1, pdu.Variables.Count);
            Variable v = pdu.Variables[0];

            Assert.Equal(new uint[] { 1, 3, 6, 1, 2, 1, 1, 6, 0 }, v.Id.ToNumerical());
            Assert.Equal(typeof(Null), v.Data.GetType());
            Assert.True(expected.Length >= message.ToBytes().Length);
        }
        public void TestResponseV1()
        {
            ISnmpMessage message = MessageFactory.ParseMessages(File.ReadAllBytes(Path.Combine("Resources", "getresponse.dat")), new UserRegistry())[0];

            Assert.Equal(SnmpType.ResponsePdu, message.TypeCode());
            ISnmpPdu pdu = message.Pdu();

            Assert.Equal(SnmpType.ResponsePdu, pdu.TypeCode);
            ResponsePdu response = (ResponsePdu)pdu;

            Assert.Equal(Integer32.Zero, response.ErrorStatus);
            Assert.Equal(0, response.ErrorIndex.ToInt32());
            Assert.Equal(1, response.Variables.Count);
            Variable v = response.Variables[0];

            Assert.Equal(new uint[] { 1, 3, 6, 1, 2, 1, 1, 6, 0 }, v.Id.ToNumerical());
            Assert.Equal("Shanghai", v.Data.ToString());
        }
Esempio n. 17
0
        /// <summary>
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Port number.</param>
        /// <returns></returns>
        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            var code = request.TypeCode();

            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
            }

            int nRetry = 0;

            while (true)
            {
                using (var socket = receiver.GetSocket())
                {
                    try
                    {
                        return(request.GetResponse(timeout, receiver, socket));
                    }
                    catch (TimeoutException tx)
                    {
                        nRetry++;
                        if (nRetry > 3)
                        {
                            throw tx;
                        }
                    }
                    catch (Exception e)
                    {
                        throw e;
                    }
                }
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Port number.</param>
        /// <param name="registry">User registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry, int timeoutRetries = 1, CancellationToken cancellationToken = default)
        {
            // TODO: make more usage of UserRegistry.
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            var code = request.TypeCode();

            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
            }

            while (true)
            {
                try
                {
                    using (var socket = new UdpClient())
                    {
                        return(await request.GetResponseAsync(timeout, receiver, registry, socket, cancellationToken).ConfigureAwait(false));
                    }
                }
                catch (TimeoutException)
                {
                    if (timeoutRetries > 1)
                    {
                        timeoutRetries--;
                        continue;
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
Esempio n. 19
0
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, CancellationToken token)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            var code = request.TypeCode();

            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
            }

            using var socket = receiver.GetSocket();
            return(await request.GetResponseAsync(receiver, socket, token).ConfigureAwait(false));
        }
        /// <summary>
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Port number.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            var code = request.TypeCode();

            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
            }

            var tcs = new TaskCompletionSource <bool>();

            using (var cancel = cancellationToken.Register(() => tcs.SetCanceled()))
                using (var socket = receiver.GetSocket())
                {
                    var response = request.GetResponseAsync(receiver, socket);
                    var result   = await Task.WhenAny(tcs.Task, response).ConfigureAwait(false);

                    if (result == tcs.Task)
                    {
                        // This should always be true....
                        // Otherwise throw your own.
                        cancellationToken.ThrowIfCancellationRequested();
                    }
                    return(await response.ConfigureAwait(false));
                }
        }
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes   = request.ToBytes();
            var bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;

            // Whatever you change, try to keep the Send and the Receive close to each other.
            var info = SocketExtension.EventArgsFactory.Create();

            info.RemoteEndPoint = receiver;
            info.SetBuffer(bytes, 0, bytes.Length);
            using (var awaitable1 = new SocketAwaitable(info))
            {
                await udpSocket.SendToAsync(awaitable1);
            }

            int count;
            var reply = new byte[bufSize];

            // IMPORTANT: follow http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx
            var      args   = SocketExtension.EventArgsFactory.Create();
            EndPoint remote = new IPEndPoint(IPAddress.Any, 0);

            try
            {
                args.RemoteEndPoint = remote;
                args.SetBuffer(reply, 0, bufSize);
                using (var awaitable = new SocketAwaitable(args))
                {
                    count = await udpSocket.ReceiveAsync(awaitable);
                }
            }
            catch (SocketException ex)
            {
                // FIXME: If you use a Mono build without the fix for this issue (https://bugzilla.novell.com/show_bug.cgi?id=599488), please uncomment this code.

                /*
                 * if (SnmpMessageExtension.IsRunningOnMono && ex.ErrorCode == 10035)
                 * {
                 *  throw TimeoutException.Create(receiver.Address, timeout);
                 * }
                 * // */

                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, 0);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
        /// <summary>
        /// Sends an  <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry, Socket udpSocket)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes   = request.ToBytes();
            var bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;
            var reply   = new byte[bufSize];

            // Whatever you change, try to keep the Send and the Receive close to each other.
            udpSocket.SendTo(bytes, receiver);
            udpSocket.ReceiveTimeout = timeout;
            int count;

            try
            {
                count = udpSocket.Receive(reply, 0, bufSize, SocketFlags.None);
            }
            catch (SocketException ex)
            {
                // FIXME: If you use a Mono build without the fix for this issue (https://bugzilla.novell.com/show_bug.cgi?id=599488), please uncomment this code.

                /*
                 * if (SnmpMessageExtension.IsRunningOnMono && ex.ErrorCode == 10035)
                 * {
                 *  throw TimeoutException.Create(receiver.Address, timeout);
                 * }
                 * // */

                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, timeout);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
Esempio n. 23
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry, UdpClient udpSocket /*, int retries = 0*/)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes = request.ToBytes();

            udpSocket.Connect(receiver);
            var recvTask = udpSocket.ReceiveAsync();

            if (timeout > 0)
            {
                var timeoutTask = Task.Delay(timeout);
                await udpSocket.SendAsync(bytes, bytes.Length).ConfigureAwait(false);

                var r = await Task.WhenAny(new Task[] { recvTask, timeoutTask }).ConfigureAwait(false);

                if (r == timeoutTask)
                {
                    udpSocket.Close();
                    throw TimeoutException.Create(receiver.Address, timeout);
                }
            }
            var result = await recvTask.ConfigureAwait(false);

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(result.Buffer, 0, result.Buffer.Length, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
Esempio n. 24
0
        /// <summary>
        /// Sends an  <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry, Socket udpSocket)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            SnmpType requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            byte[] bytes   = request.ToBytes();
            int    bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;

            byte[] reply = new byte[bufSize];

            // Whatever you change, try to keep the Send and the Receive close to each other.
            udpSocket.SendTo(bytes, receiver);
            udpSocket.ReceiveTimeout = timeout;
            int count;

            try
            {
                count = udpSocket.Receive(reply, 0, bufSize, SocketFlags.None);
            }
            catch (SocketException ex)
            {
                // IMPORTANT: Mono behavior.
                if (IsRunningOnMono && ex.SocketErrorCode == SocketError.WouldBlock)
                {
                    throw TimeoutException.Create(receiver.Address, timeout);
                }


                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, timeout);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            ISnmpMessage response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            SnmpType     responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                int requestId  = request.MessageId();
                int responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
Esempio n. 25
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, int timeout)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var          bytes = request.ToBytes();
            ISnmpMessage response;

            // Whatever you change, try to keep the Send and the Receive close to each other.

            // fix race condition where the gc memory was corrupted
            using (var udpClient = new UdpClient())
            {
                udpClient.DontFragment = true;
                await udpClient.SendAsync(bytes, bytes.Length, receiver);

                // ReceiveAsync is an extension method implemented in class UdpClientExtension
                // it handles the timeout behavior to avoid object dispose exception when an timeout is received
                // but also - later - a valid datagram
                UdpReceiveResult receiveTask = await udpClient.ReceiveAsync(receiver, timeout);

                byte[] reply = new byte[receiveTask.Buffer.Length];
                receiveTask.Buffer.CopyTo(reply, 0);

                // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
                response = MessageFactory.ParseMessages(reply, 0, reply.Length, registry)[0];
            }

            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
Esempio n. 26
0
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, CancellationToken token)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes   = request.ToBytes();
            var bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;

            // Whatever you change, try to keep the Send and the Receive close to each other.
            var buffer = new ArraySegment <byte>(bytes);
            await udpSocket.SendToAsync(buffer, SocketFlags.None, receiver ?? throw new ArgumentNullException(nameof(receiver)), token);

            int count;

            byte[] reply = new byte[bufSize];

            // IMPORTANT: follow http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx
            var      remoteAddress = udpSocket.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any;
            EndPoint remote        = new IPEndPoint(remoteAddress, 0);

            try
            {
                var result = await udpSocket.ReceiveMessageFromAsync(new ArraySegment <byte>(reply), SocketFlags.None, remote, token);

                count = result.ReceivedBytes;
            }
            catch (SocketException ex)
            {
                // IMPORTANT: Mono behavior (https://bugzilla.novell.com/show_bug.cgi?id=599488)
                if (IsRunningOnMono() && ex.SocketErrorCode == SocketError.WouldBlock)
                {
                    throw TimeoutException.Create(receiver.Address, 0);
                }

                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, 0);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }