ln.snmp/SNMPClient.cs

155 lines
4.7 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;
namespace ln.snmp
{
public class SNMPClient : IDisposable
{
public static bool DEBUG = false;
public UdpClient LocalEndpoint { get; private set; }
public int Timeout { get; set; } = 1000;
private Dictionary<IPEndPoint, InternalRequest> queuedRequests = new Dictionary<IPEndPoint, InternalRequest>();
private bool shutdown = false;
private Thread ReceiverThread { get; set; }
public SNMPClient(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);
lock (queuedRequests)
{
if (queuedRequests.ContainsKey(remoteEndpoint))
{
InternalRequest internalRequest = queuedRequests[remoteEndpoint];
internalRequest.Response = datagram;
lock (internalRequest)
{
Monitor.PulseAll(internalRequest);
}
}
}
}
catch (SocketException se)
{
}
catch (Exception e)
{
Console.WriteLine("Receiver(): {0}", e);
}
}
}
private byte[] SendRequest(IPEndPoint remoteEndpoint,byte[] request,int timeout)
{
InternalRequest internalRequest = new InternalRequest();
internalRequest.RemoteEndpoint = remoteEndpoint;
lock(queuedRequests)
{
if (queuedRequests.ContainsKey(remoteEndpoint))
throw new ArgumentException("Already pending request exists for this remote endpoint", nameof(remoteEndpoint));
queuedRequests.Add(remoteEndpoint,internalRequest);
if (DEBUG)
Console.WriteLine("SNMPClient: Send: {0}", BitConverter.ToString(request));
LocalEndpoint.Send(request, request.Length, remoteEndpoint);
lock (internalRequest)
{
Monitor.Exit(queuedRequests);
bool success = Monitor.Wait(internalRequest, timeout);
Monitor.Enter(queuedRequests);
if (!success)
{
throw new TimeoutException();
}
}
queuedRequests.Remove(remoteEndpoint);
}
return internalRequest.Response;
}
public Variable SNMPRequest(IPEndPoint remoteEndpoint,Sequence request)
{
byte[] response = SendRequest(remoteEndpoint, request.ToBytes(), Timeout);
if (DEBUG)
Console.WriteLine("SNMPClient: Received: {0}", BitConverter.ToString(response));
Variable vreply = Variable.Read(response);
return vreply;
}
//public abstract List<Variable> Walk(ObjectIdentifier baseOID);
//public abstract List<Variable> Get(List<ObjectIdentifier> baseOID);
//public virtual Variable Get(ObjectIdentifier oid)
//{
// return Get(new List<ObjectIdentifier>(new ObjectIdentifier[] { oid }))[0];
//}
public void Dispose()
{
if (ReceiverThread != null)
{
if (ReceiverThread.IsAlive)
{
Close();
if (!ReceiverThread.Join(250))
{
ReceiverThread.Abort();
}
}
ReceiverThread = null;
}
}
class InternalRequest
{
public IPEndPoint RemoteEndpoint;
public byte[] Response;
}
}
}