/// <summary> /// Creates a <see cref="TimeoutException"/>. /// </summary> /// <param name="agent">Agent address</param> /// <param name="timeout">Timeout</param> /// <returns></returns> public static TimeoutException Create(IPAddress agent, int timeout) { if (agent == null) { throw new ArgumentNullException("agent"); } TimeoutException ex = new TimeoutException { Agent = agent, Timeout = timeout }; return(ex); }
/// <summary> /// Creates a <see cref="TimeoutException"/>. /// </summary> /// <param name="agent">Agent address</param> /// <param name="timeout">Timeout</param> /// <returns></returns> public static TimeoutException Create(IPAddress agent, int timeout) { if (agent == null) { throw new ArgumentNullException(nameof(agent)); } var ex = new TimeoutException($"Request timed out after {timeout}-ms.") { Agent = agent, Timeout = timeout }; return(ex); }
/// <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); }
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); }
/// <summary> /// Sends an SNMP message and wait for its responses. /// </summary> /// <param name="receiver">The IP address and port of the target to talk to.</param> /// <param name="bytes">The byte array representing the SNMP message.</param> /// <param name="number">The <see cref="ResponseMessage.MessageId"/> of the SNMP message.</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="registry">The registry.</param> /// <param name="socket">The UDP <see cref="Socket"/> to use to send/receive.</param> /// <returns> /// The response message (<see cref="ISnmpMessage"/>). /// </returns> /// <exception cref="TimeoutException">Timeout happens.</exception> internal static ISnmpMessage GetResponse(IPEndPoint receiver, byte[] bytes, int number, int timeout, UserRegistry registry, Socket socket) { if (bytes == null) { throw new ArgumentNullException("bytes"); } if (registry == null) { throw new ArgumentNullException("registry"); } if (receiver == null) { throw new ArgumentNullException("receiver"); } if (socket == null) { throw new ArgumentNullException("socket"); } #if CF int bufSize = 8192; #else int bufSize = socket.ReceiveBufferSize; #endif byte[] reply = new byte[bufSize]; // Whatever you change, try to keep the Send and the Receive close to each other. #if !SILVERLIGHT //mc++ socket.SendTo(bytes, receiver); #endif //mc++ #if !SILVERLIGHT //mc++ #if !(CF) socket.ReceiveTimeout = timeout; #endif #endif // mc++ int count = 0; //mc++ try { #if !SILVERLIGHT //mc++ count = socket.Receive(reply, 0, bufSize, SocketFlags.None); #endif } catch (SocketException ex) { // FIXME: If you use a Mono build without the fix for this bug (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.ErrorCode == WSAETIMEDOUT) { 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 a bug if parsing >1 response). ISnmpMessage message = ParseMessages(reply, 0, count, registry)[0]; var code = message.Pdu.TypeCode; if (code == SnmpType.ResponsePdu || code == SnmpType.ReportPdu) { var id = message.MessageId; if (id != number) { throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", number, id), receiver.Address); } return(message); } throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", code), 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 = ArrayPool <byte> .Shared.Rent(bufSize); try { // 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). 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); } finally { ArrayPool <byte> .Shared.Return(reply); } }