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(); } } }