885 lines · 33.5 KB · C#
RawDownload
// SNMP message extension class.// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors.// // Permission is hereby granted, free of charge, to any person obtaining a copy of this// software and associated documentation files (the "Software"), to deal in the Software// without restriction, including without limitation the rights to use, copy, modify, merge,// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons// to whom the Software is furnished to do so, subject to the following conditions:// // The above copyright notice and this permission notice shall be included in all copies or// substantial portions of the Software.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER// DEALINGS IN THE SOFTWARE. using System;using System.Collections.Generic;using System.Diagnostics.CodeAnalysis;using System.Globalization;using System.Net;using System.Net.Sockets;#if NETSTANDARD2_0using System.Runtime.InteropServices;#endifusing System.Threading;using System.Threading.Tasks;using GSF.Net.Snmp.Security; namespace GSF.Net.Snmp.Messaging{    /// <summary>    /// Extension methods for <see cref="ISnmpMessage"/>.    /// </summary>    public static class SnmpMessageExtension    {        /// <summary>        /// Gets the <see cref="SnmpType"/>.        /// </summary>        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>        /// <returns></returns>        public static SnmpType TypeCode(this ISnmpMessage message)        {            if (message == null)            {                throw new ArgumentNullException(nameof(message));            }             return message.Pdu().TypeCode;        }         /// <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));            }             SnmpType code = message.TypeCode();            return code == SnmpType.Unknown ? new List<Variable>(0) : message.Scope.Pdu.Variables;        }         /// <summary>        /// Request ID.        /// </summary>        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>        public static int RequestId(this ISnmpMessage message)        {            if (message == null)            {                throw new ArgumentNullException(nameof(message));            }             return message.Scope.Pdu.RequestId.ToInt32();        }         /// <summary>        /// Gets the message ID.        /// </summary>        /// <value>The message ID.</value>        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>        /// <remarks>For v3, message ID is different from request ID. For v1 and v2c, they are the same.</remarks>        public static int MessageId(this ISnmpMessage message)        {            if (message == null)            {                throw new ArgumentNullException(nameof(message));            }             return message.Header == Header.Empty ? message.RequestId() : message.Header.MessageId;        }         /// <summary>        /// PDU.        /// </summary>        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Pdu")]        public static ISnmpPdu Pdu(this ISnmpMessage message)        {            if (message == null)            {                throw new ArgumentNullException(nameof(message));            }             return message.Scope.Pdu;        }         /// <summary>        /// Community name.        /// </summary>        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>        public static OctetString Community(this ISnmpMessage message)        {            if (message == null)            {                throw new ArgumentNullException(nameof(message));            }             return message.Parameters.UserName;        } #region sync methods         /// <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(nameof(message));            }             if (manager == null)            {                throw new ArgumentNullException(nameof(manager));            }             SnmpType 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 (Socket socket = manager.GetSocket())            {                message.Send(manager, socket);            }        }         /// <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));            }             SnmpType 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));            }             byte[] bytes = message.ToBytes();            socket.SendTo(bytes, 0, bytes.Length, SocketFlags.None, manager);        }         /// <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(nameof(request));            }             if (receiver == null)            {                throw new ArgumentNullException(nameof(receiver));            }             SnmpType 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 (Socket socket = receiver.GetSocket())            {                return request.GetResponse(timeout, receiver, registry, socket);            }        }         /// <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(nameof(request));            }             if (receiver == null)            {                throw new ArgumentNullException(nameof(receiver));            }             SnmpType 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 (Socket socket = receiver.GetSocket())            {                return request.GetResponse(timeout, receiver, socket);            }        }         /// <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">Agent.</param>        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>        /// <returns></returns>        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver, Socket udpSocket)        {            if (request == null)            {                throw new ArgumentNullException(nameof(request));            }             if (receiver == null)            {                throw new ArgumentNullException(nameof(receiver));            }             if (udpSocket == null)            {                throw new ArgumentNullException(nameof(udpSocket));            }             UserRegistry registry = new UserRegistry();            if (request.Version == VersionCode.V3)            {                registry.Add(request.Parameters.UserName, request.Privacy);            }             return request.GetResponse(timeout, receiver, registry, udpSocket);        }         /// <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);        } #endregion #region async methods#if NET471        /// <summary>        /// Ends a pending asynchronous read.        /// </summary>        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>        /// <param name="asyncResult">An <see cref="IAsyncResult"/> that stores state information and any user defined data for this asynchronous operation.</param>        /// <returns></returns>        [Obsolete("Please use GetResponseAsync and await on it.")]        public static ISnmpMessage EndGetResponse(this ISnmpMessage request, IAsyncResult asyncResult)        {            if (asyncResult == null)            {                throw new ArgumentNullException(nameof(asyncResult));            }                        if (request == null)            {                throw new ArgumentNullException(nameof(request));            }                        SnmpMessageAsyncResult ar = (SnmpMessageAsyncResult)asyncResult;            Socket s = ar.WorkSocket;            int count = s.EndReceive(ar.Inner);                        // 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(ar.GetBuffer(), 0, count, ar.Users)[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), ar.Receiver.Address);                }                 return response;            }             throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), ar.Receiver.Address);        }         /// <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>        [Obsolete("Please use GetResponseAsync and await on it.")]        public static IAsyncResult BeginGetResponse(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, AsyncCallback callback, object state)        {            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));            }             // Whatever you change, try to keep the Send and the Receive close to each other.            udpSocket.SendTo(request.ToBytes(), receiver);            int bufferSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;            byte[] buffer = new byte[bufferSize];             // https://sharpsnmplib.codeplex.com/workitem/7234            if (callback != null)            {                AsyncCallback wrapped = callback;                callback = asyncResult =>                {                    SnmpMessageAsyncResult result = new SnmpMessageAsyncResult(asyncResult, udpSocket, registry, receiver, buffer);                    wrapped(result);                };            }             IAsyncResult ar = udpSocket.BeginReceive(buffer, 0, bufferSize, SocketFlags.None, callback, state);            return new SnmpMessageAsyncResult(ar, udpSocket, registry, receiver, buffer);        }#endif        /// <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));            }

Lines 1–500 of 885.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t