/* * PROJECT: Aura Operating System Development * CONTENT: UDP Client * PROGRAMMERS: Valentin Charbonnier * Port of Cosmos Code. */ using Cosmos.System.Network.Config; using System; using System.Collections.Generic; using System.Text; namespace Cosmos.System.Network.IPv4.UDP { /// /// UdpClient class. Used to manage the UDP connection to a client. /// public class UdpClient : IDisposable { /// /// Clients dictionary. /// private static Dictionary clients; /// /// Local port. /// private int localPort; /// /// Destination address. /// internal Address destination; /// /// Destination port. /// private int destinationPort; /// /// RX buffer queue. /// internal Queue rxBuffer; /// /// Assign clients dictionary. /// /// Thrown on fatal error (contact support). static UdpClient() { clients = new Dictionary(); } /// /// Get client. /// /// Destination port. /// UdpClient internal static UdpClient GetClient(ushort destPort) { if (clients.ContainsKey((uint)destPort) == true) { return clients[(uint)destPort]; } return null; } /// /// Create new instance of the class. /// /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 0 exists. public UdpClient() : this(0) { } /// /// Create new instance of the class. /// /// Local port. /// Thrown on fatal error (contact support). /// Thrown if localPort already exists. public UdpClient(int localPort) { rxBuffer = new Queue(8); this.localPort = localPort; if (localPort > 0) { clients.Add((uint)localPort, this); } } /// /// Create new instance of the class. /// /// Destination address. /// Destination port. /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 0 exists. public UdpClient(Address dest, int destPort) : this(0) { destination = dest; destinationPort = destPort; } /// /// Connect to client. /// /// Destination address. /// Destination port. public void Connect(Address dest, int destPort) { destination = dest; destinationPort = destPort; } /// /// Close connection. /// /// Thrown on fatal error (contact support). public void Close() { if (clients.ContainsKey((uint)localPort) == true) { clients.Remove((uint)localPort); } } /// /// Send data to client. /// /// Data array to send. /// Thrown if destination is null or destinationPort is 0. /// Thrown on fatal error (contact support). /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown on IO error. public void Send(byte[] data) { if ((destination == null) || (destinationPort == 0)) { throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } Send(data, destination, destinationPort); NetworkStack.Update(); } /// /// Send data. /// /// Data array. /// Destination address. /// Destination port. /// Thrown on fatal error (contact support). /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown on IO error. public void Send(byte[] data, Address dest, int destPort) { Address source = IPConfig.FindNetwork(dest); UDPPacket packet = new UDPPacket(source, dest, (ushort)localPort, (ushort)destPort, data); OutgoingBuffer.AddPacket(packet); } /// /// Receive data from end point. /// /// Source end point. /// byte array value. /// Thrown on fatal error (contact support). public byte[] NonBlockingReceive(ref EndPoint source) { if (rxBuffer.Count < 1) { return null; } var packet = new UDPPacket(rxBuffer.Dequeue().RawData); source.address = packet.SourceIP; source.port = packet.SourcePort; return packet.UDP_Data; } /// /// Receive data from end point. /// /// Source end point. /// byte array value. /// Thrown on fatal error (contact support). public byte[] Receive(ref EndPoint source) { while (rxBuffer.Count < 1) ; var packet = new UDPPacket(rxBuffer.Dequeue().RawData); source.address = packet.SourceIP; source.port = packet.SourcePort; return packet.UDP_Data; } /// /// Receive data from packet. /// /// Packet to receive. /// Thrown on fatal error (contact support). /// Thrown on IO error. internal void ReceiveData(UDPPacket packet) { rxBuffer.Enqueue(packet); } /// /// Close Client /// public void Dispose() { Close(); } } }