using System;
using System.Collections.Generic;
using System.Text;
namespace Cosmos.GdbClient
{
///
/// Controls the Gdp Protocol.
///
public class GdbController
{
private static GdbController _instance;
///
/// Gets or sets the default GdbConnection instance.
///
public static GdbController Instance
{
get { return _instance; }
set { _instance = value; }
}
private GdbConnection _connection;
///
/// The parser queue.
///
private Queue _parserQueue = new Queue();
///
/// The sender queue.
///
private Queue _sendQueue = new Queue();
///
/// The current packet.
///
private StringBuilder _currentPacket = new StringBuilder();
///
/// When a packet is received.
///
public event EventHandler PacketReceived;
///
/// When an acknowledgement is received.
///
public event EventHandler AcknowledgementReceived;
///
/// Creates a new instance of the class.
///
///
public GdbController(GdbConnection connection)
{
_connection = connection;
connection.DataReceived += new EventHandler(connection_DataReceived);
}
///
/// Called when data is received.
///
///
///
void connection_DataReceived(object sender, DataReceivedEventArgs e)
{
lock (_parserQueue)
{
for (int i = 0; i < e.Data.Length; i++)
_parserQueue.Enqueue(e.Data[i]);
Parse();
}
}
///
/// Parses the current data stream.
///
private void Parse()
{
lock (_parserQueue)
{
while (_parserQueue.Count != 0)
{
char c = _parserQueue.Dequeue();
if (c == '+' || c == '-' || c == '#')
{
if (c == '#')
{
_currentPacket.Append(c);
_currentPacket.Append(_parserQueue.Dequeue());
_currentPacket.Append(_parserQueue.Dequeue());
}
// I don't get this.
if (_currentPacket.ToString() == "#")
_currentPacket = new StringBuilder();
if (_currentPacket.Length != 0)
{
GdbPacket packet;
try
{
packet = GdbPacket.FromString(_currentPacket.ToString());
}
catch
{
_currentPacket = new StringBuilder();
SendFail();
continue;
}
OnPacketReceived(packet);
SendAcknowledge();
GotAcknowledge();
_currentPacket = new StringBuilder();
}
if (c == '+')
{
GotAcknowledge(); // Okay, next packet.
continue;
}
else if (c == '-')
{
SendPacket(); // Resend last please.
continue;
}
}
_currentPacket.Append(c);
}
}
}
private void OnPacketReceived(GdbPacket packet)
{
if (packet.PacketData.StartsWith("S"))
return;
if (this.PacketReceived != null)
PacketReceived(this, new GdbPacketEventArgs(packet));
}
private void OnAcknowledgementReceived()
{
if (this.AcknowledgementReceived != null)
AcknowledgementReceived(this, EventArgs.Empty);
}
private void SendFail()
{
_connection.Send("-");
}
private void SendAcknowledge()
{
_connection.Send("+");
}
///
/// Occurs when an acknowledge is received.
///
private void GotAcknowledge()
{
lock (_sendQueue)
{
if (_sendQueue.Count != 0)
_sendQueue.Dequeue();
SendPacket();
}
OnAcknowledgementReceived();
}
///
/// Acknowledges the packet.
///
private void SendPacket()
{
lock (_sendQueue)
{
if(_sendQueue.Count != 0)
_connection.Send(_sendQueue.Peek().ToString());
}
}
///
/// Sends data.
///
public void Enqueue(GdbPacket packet)
{
lock (_sendQueue)
{
_sendQueue.Enqueue(packet);
if (_sendQueue.Count == 1)
SendPacket();
}
}
///
/// Opens up normal commands.
///
public void Open()
{
_connection.Open();
}
public void Close()
{
_connection.Close();
}
}
}