// /** // * File: RadiusServer.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.Net.Sockets; using System.Net; using System.Collections.Generic; using System.Threading; using System.Linq; using ln.logging; using ln.types.threads; namespace ln.radius { public delegate byte[] LookupSecretDelegate(IPEndPoint endPoint); public delegate void RadiusMessageReceived(RadiusServer radiusServer, RadiusMessage radiusMessage); public class RadiusServer : IDisposable { public LookupSecretDelegate LookupSecret { get; set; } public RadiusMessageReceived MessageReceived { get; set; } public Pool RequestPool { get; } = new Pool(16); UdpClient udp; bool contListeners = true; public RadiusServer() {} public RadiusServer(IPEndPoint endPoint) { udp = new UdpClient(endPoint); RequestPool.Enqueue(() => ListenerThread(udp)); } public void Close() { contListeners = false; udp.Close(); RequestPool.Close(); } public void Dispose() { Close(); } public void Send(RadiusMessage message) { byte[] packet = message.Authenticate(LookupSecret(message.EndPoint)); lock (udp) { int sent = udp.Send(packet, packet.Length, message.EndPoint); Logging.Log(LogLevel.DEBUG, "Radius sent {0} bytes to {1}", sent, message.EndPoint); } } private void ListenerThread(UdpClient udp) { try { while (contListeners) { IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); byte[] rx = udp.Receive(ref remoteEndPoint); try { RadiusMessage radiusMessage = RadiusMessage.FromBytes(rx, remoteEndPoint); RequestPool.Enqueue(() => MessageReceived(this, radiusMessage)); } catch (Exception e) { Logging.Log(e); } } } catch (Exception e) { Logging.Log(LogLevel.ERROR, "radius listener thread caught exception: {0}", e); Logging.Log(e); } } } }