ln.snmp/SNMPEngine.cs

157 lines
4.9 KiB
C#

// /**
// * File: MyClass.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Collections.Generic;
using ln.snmp.types;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using ln.snmp.asn1;
using ln.logging;
namespace ln.snmp
{
public class SNMPEngine : IDisposable
{
public static bool DEBUG = false;
public UdpClient LocalEndpoint { get; private set; }
public int Timeout { get; set; } = 1000;
private Dictionary<int, SnmpMessage> queuedRequests = new Dictionary<int, SnmpMessage>();
private bool shutdown = false;
private Thread ReceiverThread { get; set; }
private int nextMessageID = (int)DateTimeOffset.Now.ToUnixTimeSeconds();
public int NextMessageID => nextMessageID++;
public SNMPEngine()
{
LocalEndpoint = new UdpClient();
ReceiverThread = new Thread(Receiver);
ReceiverThread.Start();
}
public SNMPEngine(IPEndPoint localEndpoint)
{
LocalEndpoint = new UdpClient(localEndpoint);
ReceiverThread = new Thread(Receiver);
ReceiverThread.Start();
}
public void Close()
{
shutdown = true;
LocalEndpoint.Close();
}
private void Receiver()
{
while (!shutdown)
{
try
{
IPEndPoint remoteEndpoint = null;
byte[] datagram = LocalEndpoint.Receive(ref remoteEndpoint);
Logging.Log(LogLevel.DEBUG,"SNMPClient: Received: {0}", BitConverter.ToString(datagram));
ASN1Value asn = new ASN1Value(datagram);
asn.Dump();
SnmpMessage snmpMessage = asn;
snmpMessage.Dump();
lock (queuedRequests)
{
if (queuedRequests.ContainsKey(snmpMessage.MessageID))
{
SnmpMessage snmpRequestMessage = queuedRequests[snmpMessage.MessageID];
lock (snmpRequestMessage)
{
queuedRequests[snmpMessage.MessageID] = snmpMessage;
Monitor.PulseAll(snmpRequestMessage);
}
}
else
{
Logging.Log(LogLevel.WARNING, "SnmpEngine.Receiver(): Can't find pending request with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID);
}
}
}
catch (SocketException se)
{
Logging.Log(se);
}
catch (Exception e)
{
Logging.Log(e);
}
}
}
public SnmpMessage SNMPRequest(IPEndPoint remoteEndpoint,SnmpMessage snmpMessage,int timeout)
{
lock (queuedRequests)
{
ASN1Value snmpRequest = snmpMessage;
byte[] snmpRequestBytes = snmpRequest.AsByteArray;
queuedRequests.Add(snmpMessage.MessageID, snmpMessage);
Logging.Log(LogLevel.DEBUG,"SNMPClient: Send: {0}", BitConverter.ToString(snmpRequestBytes));
Logging.Log(LogLevel.DEBUG,"sent snmpMessage with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID);
snmpMessage.Dump();
LocalEndpoint.Send(snmpRequestBytes, snmpRequestBytes.Length, remoteEndpoint);
lock (snmpMessage)
{
Monitor.Exit(queuedRequests);
bool success = Monitor.Wait(snmpMessage, timeout);
Monitor.Enter(queuedRequests);
if (!success)
{
queuedRequests.Remove(snmpMessage.MessageID);
throw new TimeoutException();
}
}
SnmpMessage responseMessage = queuedRequests[snmpMessage.MessageID];
queuedRequests.Remove(snmpMessage.MessageID);
return responseMessage;
}
}
public void Dispose()
{
if (ReceiverThread != null)
{
if (ReceiverThread.IsAlive)
{
Close();
if (!ReceiverThread.Join(250))
{
ReceiverThread.Abort();
}
}
ReceiverThread = null;
}
}
}
}