using System; using ln.snmp.types; using System.Net; using System.Collections.Generic; using System.Linq; using ln.snmp.endpoint; using System.Reflection; using System.Threading; using ln.logging; namespace ln.snmp.endpoint { public abstract class SnmpEndpoint : SnmpInterface, IDisposable { public SNMPEngine SNMPEngine { get; } public IPEndPoint RemoteEndpoint { get; set; } public int Retries { get; set; } = 3; public SnmpEndpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint) { SNMPEngine = snmpEngine; RemoteEndpoint = remoteEndpoint; SNMPEngine.RegisterEndpoint(this); } public void Close() { Dispose(); } public virtual void Send(SnmpMessage message) { //message.MessageID = SNMPEngine.NextMessageID; //if (requestMessage.snmpPDU != null) //{ // requestMessage.snmpPDU.RequestID.LongValue = SNMPEngine.NextMessageID; //} message = Encrypt(message); message = ApplyAuthentication(message); SNMPEngine.SendMessage(RemoteEndpoint, message); } public virtual void DispatchReceived(SnmpMessage message) { lock (queuedRequests) { if (queuedRequests.ContainsKey(message.MessageID)) { SnmpMessage queuedMessage = queuedRequests[message.MessageID]; lock (queuedMessage) { queuedRequests[message.MessageID] = message; Monitor.PulseAll(queuedMessage); } } else { long dt = DateTimeOffset.Now.ToUnixTimeSeconds() - message.MessageID; Logging.Log(LogLevel.WARNING, "SNMPEndpoint: Received unqueued message id: {0} (0x{0:x8}) possibly D-T: {1}", message.MessageID,dt); } } } public virtual void Received(SnmpMessage message) { message = CheckAuthentication(message); message = Decrypt(message); DispatchReceived(message); } public virtual SnmpMessage Encrypt(SnmpMessage message) => message; public virtual SnmpMessage ApplyAuthentication(SnmpMessage message) => message; public virtual SnmpMessage CheckAuthentication(SnmpMessage message) => message; public virtual SnmpMessage Decrypt(SnmpMessage message) => message; /** * Requests **/ private Dictionary queuedRequests = new Dictionary(); public SnmpMessage EnqueueRequest(SnmpMessage requestMessage) { lock (queuedRequests) { queuedRequests.Add(requestMessage.MessageID, requestMessage); Monitor.Exit(queuedRequests); lock (requestMessage) { Send(requestMessage); Monitor.Wait(requestMessage, SNMPEngine.Timeout); } Monitor.Enter(queuedRequests); SnmpMessage responseMessage = queuedRequests[requestMessage.MessageID]; if (responseMessage == requestMessage) throw new TimeoutException(); return responseMessage; } } public override void Dispose() { SNMPEngine.UnregisterEndpoint(this); base.Dispose(); } } }