/// <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); }
/// <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(); }
/// <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)); } }
/// <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); }
/// <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)); } }
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); }
/// <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); } }
/// <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); } }
/// <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)); } }
/// <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); }
/// <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); }
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()); }
/// <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; } } } }
/// <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; } } } }
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); }
/// <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); }
/// <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); }
/// <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); }
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); }