ln.snmp/SNMPEngine.cs

196 lines
6.0 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;
using ln.snmp.endpoint;
namespace ln.snmp
{
public class SNMPEngine : IDisposable
{
public static bool DEBUG = false;
private static SNMPEngine __default = null;
public static SNMPEngine DefaultEngine
{
get
{
if (__default == null)
__default = new SNMPEngine();
return __default;
}
set => __default = value;
}
public UdpClient LocalEndpoint { get; private set; }
public int Timeout { get; set; } = 750;
private Dictionary<int, SnmpMessage> queuedRequests = new Dictionary<int, SnmpMessage>();
private bool shutdown = false;
private Thread ReceiverThread { get; set; }
private Dictionary<IPEndPoint, SnmpEndpoint> currentEndpoints = new Dictionary<IPEndPoint, SnmpEndpoint>();
private int nextMessageID = (int)DateTimeOffset.Now.ToUnixTimeSeconds();
public int NextMessageID => nextMessageID++;
public SNMPEngine()
{
LocalEndpoint = new UdpClient();
ReceiverThread = new Thread(Receiver);
ReceiverThread.IsBackground = true;
ReceiverThread.Start();
}
public SNMPEngine(IPEndPoint localEndpoint)
{
LocalEndpoint = new UdpClient(localEndpoint);
ReceiverThread = new Thread(Receiver);
ReceiverThread.IsBackground = true;
ReceiverThread.Start();
}
public void Close()
{
shutdown = true;
LocalEndpoint.Close();
ReceiverThread.Interrupt();
}
private void Receiver()
{
while (!shutdown)
{
try
{
IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);
byte[] datagram = LocalEndpoint.Receive(ref remoteEndpoint);
if (DEBUG)
Logging.Log(LogLevel.DEBUGDETAIL,"SNMPClient: Received: {0}", BitConverter.ToString(datagram));
ASN1Value asn = new ASN1Value(datagram);
SnmpMessage snmpMessage = asn;
if (currentEndpoints.ContainsKey(remoteEndpoint))
{
SnmpEndpoint snmpEndpoint = currentEndpoints[remoteEndpoint];
snmpEndpoint.Received(snmpMessage);
}
else
{
Logging.Log(LogLevel.WARNING, "SnmpEngine.Receiver(): Received message from unknown endpoint ({0})",remoteEndpoint);
}
}
catch (SocketException)
{
}
catch (Exception e)
{
Logging.Log(e);
}
}
}
public void SendMessage(IPEndPoint remoteEndpoint,SnmpMessage message)
{
ASN1Value snmpMessage = message;
byte[] snmpMessageBytes = snmpMessage.AsByteArray;
lock (LocalEndpoint)
{
LocalEndpoint.Send(snmpMessageBytes, snmpMessageBytes.Length, remoteEndpoint);
}
}
//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 RegisterEndpoint(SnmpEndpoint intf)
{
lock (currentEndpoints)
{
if (currentEndpoints.ContainsKey(intf.RemoteEndpoint))
{
currentEndpoints[intf.RemoteEndpoint].Close();
}
currentEndpoints.Add(intf.RemoteEndpoint,intf);
}
}
public void UnregisterEndpoint(SnmpEndpoint intf)
{
lock (currentEndpoints)
{
currentEndpoints.Remove(intf.RemoteEndpoint);
}
}
public void Dispose()
{
if (ReceiverThread != null)
{
if (ReceiverThread.IsAlive)
{
Close();
if (!ReceiverThread.Join(250))
{
ReceiverThread.Abort();
}
}
ReceiverThread = null;
}
}
}
}