Example #1
0
 /// <summary>
 /// Sends a message and blocks until the response is complete or
 /// the timeout period passes. Dispose will be called on the resulting
 /// request.
 /// </summary>
 /// <param name="msg">The message to send.</param>
 /// <param name="hasData">Whether the response has data.</param>
 /// <param name="req">The request if completed.</param>
 /// <returns>True if sent and acknowledged. False otherwise.</returns>
 private bool SendRequest(Message msg, bool hasData, out Request req)
 {
     using (req = new Request(msg, new AutoResetEvent(false), hasData))
     {
         return this.SendRequest(req);
     }
 }
Example #2
0
 /// <summary>
 /// Sends a message and blocks until the response is complete or
 /// the timeout period passes.
 /// </summary>
 /// <param name="msg">The message to send.</param>
 /// <param name="hasData">Whether the response has data.</param>
 /// <returns>True if sent and acknowledged. False otherwise.</returns>
 private bool SendRequest(Message msg, bool hasData)
 {
     Request _;
     return this.SendRequest(msg, hasData, out _);
 }
Example #3
0
        /// <summary>
        /// Synchronously sends a message to the connected GDB stub. This cannot
        /// be called while the message loop is active.
        /// </summary>
        /// <param name="msg">The message to send.</param>
        /// <returns>Receipt acknowledgemenet. True if no-ack enabled.</returns>
        private bool SendMessage(Message msg)
        {
            // Send data
            socket.Send(msg.GetMessageBytes());

            // Receive confirmation
            if (this.confirmReceipt)
            {
                lock (this.buffer)
                {
                    int recv = socket.Receive(this.buffer, 0, 1, SocketFlags.None);
                    if (recv != 1) throw new IOException();

                    switch ((char)this.buffer[0])
                    {
                        case '+': return true;
                        case '-': return false;
                        default: throw new IOException();
                    }
                }
            }
            else return true;
        }
Example #4
0
        /// <summary>
        /// Synchronously receives a message from the GDB stub. This cannot
        /// be called while the message loop is active.
        /// </summary>
        /// <returns>The received message.</returns>
        private Message ReceiveMessage()
        {
            lock (this.buffer)
            {
                try
                {
                    var msg = new Message(this.buffer, 0, socket.Receive(this.buffer));
                    socket.Send(new byte[] { (byte)'+' });

                    return msg;
                }
                catch (FormatException)
                {
                    socket.Send(new byte[] { (byte)'-' });
                    throw;
                }
            }
        }
Example #5
0
        private void MessageLoop(IAsyncResult token)
        {
            // End receive
            int received = this.socket.EndReceive(token);

            // Yup. This is a goto. For real. Deal with it.
            // If we've received nothing, skip all processing.
            if (received == 0) goto beginReceive;

            bool? ack    = null;
            int   offset = 0;

            // Look for +/- acknowledgements
            if (this.confirmReceipt)
            {
                for (int i = 0; i < received; i++)
                {
                    if (buffer[i] == '+' || buffer[i] == '-')
                    {
                        // If we've already parsed an acknowledgement
                        if (ack.HasValue)
                        {
                            throw new Exception("Double ack in GDB message loop. " +
                            "Please report this to the development team.");
                        }
                        // Set ack accordingly
                        ack = buffer[i] == '+';
                        // Increment offset
                        offset++;
                    }
                    else break;
                }
                // Missing acknowledgements should result in timeouts in requests or
                // null ack values.
            }

            // Lock request queue
            Monitor.Enter(this.requests);

            // Set the acknowledgement
            if (ack != null && this.requests.Count != 0)
            {
                this.requests.Peek().Acknowledge(ack.Value);
            }

            // Now look for response data
            if (received - offset > 0)
            {
                try
                {
                    var msg = new Message(this.buffer, offset, received);

                    // Send acknowledgement
                    if (this.confirmReceipt) { socket.Send(new byte[] { (byte)'+' }); }

                    // Check for stop replies - we handle those differently
                    if (msg.IsStopReply)
                    {
                        this.HandleStopReply(msg);
                    }
                    else // Handle request. Disconnect on error.
                    {
                        this.requests.Dequeue().HandleResponse(msg);
                    }
                }
                catch (FormatException)
                {
                    // Send acknowledgement
                    if (this.confirmReceipt) { socket.Send(new byte[] { (byte)'-' }); }

                    // Disconnect and throw
                    Monitor.Exit(this.requests);
                    this.Disconnect();
                }
                catch { Monitor.Exit(this.requests); this.Disconnect(); throw; }
            }
            // Handle requests without response datak
            else if (ack != null && this.requests.Count != 0 && !this.requests.Peek().HasResponseData)
            {
                // Handle request. Disconnect on error.
                try   { this.requests.Dequeue().HandleResponse(null); }
                catch { Monitor.Exit(this.requests); this.Disconnect(); throw; }
            }

            try
            {
                // Check for request to send
                if (requests.Count != 0 && !requests.Peek().Sent)
                {
                    this.socket.Send(requests.Peek().Message.GetMessageBytes());
                    requests.Peek().Sent = true;
                }
            }
            finally
            {
                // Unlock request queue
                Monitor.Exit(this.requests);
            }

            // Begin receiving again
            beginReceive:
            this.socket.BeginReceive(this.buffer, 0, this.buffer.Length,
                    SocketFlags.None, this.MessageLoop, null);
        }
Example #6
0
        private void HandleStopReply(Message msg)
        {
            if (msg.Data[0] == 'O')
            {
                // It's actually just console output
                if (this.ConsoleOutput != null)
                {
                    // Use ThreadPool so that we don't interrupt the message loop thread
                    ThreadPool.QueueUserWorkItem((o) =>
                        this.ConsoleOutput(msg.Data.Remove(0, 1)));
                }
            }
            else if (msg.Data[0] == 'F')
            {
                return; // Ignore system call requests
            }
            else // We have an actual stop reply
            {
                StopReply reply = new StopReply(msg.Data);

                if (reply.Reason == StopReason.Trap || reply.Reason == StopReason.Watchpoint)
                {
                    if (this.Paused != null)
                    {
                        // Use ThreadPool so that we don't interrupt the message loop thread
                        ThreadPool.QueueUserWorkItem((o) => this.Paused(reply));
                    }
                }
                else if (reply.Reason == StopReason.Termination)
                {
                    if (this.Terminated != null)
                    {
                        // Use ThreadPool so that we don't interrupt the message loop thread
                        ThreadPool.QueueUserWorkItem((o) => this.Terminated());
                    }
                }
            }
        }