using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace CrestronSearch.Network
{
internal class TelnetClient : IDisposable
{
private readonly TcpClient _tcpClient;
private NetworkStream _tcpStream;
public int DefaultTelnetPort => 23;
public IPAddress IP { get; }
public event ConnectedEventHandler Connected;
public delegate void ConnectedEventHandler(IPEndPoint ip);
public event DisconnectedEventHandler Disconnected;
public delegate void DisconnectedEventHandler(IPEndPoint ip);
public event ReceivedDataEventHandler ReceivedData;
public delegate void ReceivedDataEventHandler(byte[] buffer, int receivedBytes);
public event SentDataEventHandler SentData;
public delegate void SentDataEventHandler(byte[] buffer, int receivedBytes);
public TelnetClient(IPAddress ip)
{
IP = ip;
_tcpClient = new TcpClient(AddressFamily.InterNetwork);
}
public async Task ConnectAsync()
{
await _tcpClient.ConnectAsync(IP, DefaultTelnetPort);
_tcpStream = _tcpClient.GetStream();
OnConnected(new IPEndPoint(IP, DefaultTelnetPort));
}
public async void ListenAsync()
{
while (_tcpStream != null)
{
var buffer = new byte[4096];
var receivedBytes = await _tcpStream.ReadAsync(buffer, 0, buffer.Length);
if (receivedBytes > 0)
{
OnDataReceived(buffer, receivedBytes);
}
}
}
public async Task SendBytesAsync(byte[] buffer)
{
await _tcpStream.WriteAsync(buffer, 0, buffer.Length);
await _tcpStream.FlushAsync();
OnDataSent(buffer, buffer.Length);
}
private void OnConnected(IPEndPoint ip)
{
Connected?.Invoke(ip);
}
private void OnDisconnected(IPEndPoint ip)
{
Disconnected?.Invoke(ip);
}
private void OnDataReceived(byte[] buffer, int numBytes)
{
ReceivedData?.Invoke(buffer, numBytes);
}
private void OnDataSent(byte[] buffer, int numBytes)
{
SentData?.Invoke(buffer, numBytes);
}
private void Cleanup()
{
OnDisconnected(new IPEndPoint(IP, DefaultTelnetPort));
_tcpClient.Close();
_tcpStream?.Dispose();
_tcpStream = null;
}
public void Dispose()
{
Cleanup();
}
}
}