Added the ability to connect using "tcp://<host>:<port>" which is the
same as the old "connect://<host>:<port>". Also added the ability to
connect using "udp://<host>:<port>" which will open a connected
datagram socket. I need to find a way to specify a non connected
datagram socket as well.
We might need to start setting some settings in the URL itself,
maybe something like:
udp://<host>:<port>?connected=yes
udp://<host>:<port>?connected=no
I am open to suggestions for URL settings.
Also did more work on the KDP darwin kernel plug-in.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@135277 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
index c3ac577..1790ee7 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
@@ -16,6 +16,7 @@
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
@@ -41,7 +42,9 @@
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
m_private_is_running (false),
- m_send_acks (true)
+ m_session_key (0),
+ m_request_sequence_id (0),
+ m_exception_sequence_id (0)
{
}
@@ -56,110 +59,68 @@
}
}
-char
-CommunicationKDP::CalculcateChecksum (const char *payload, size_t payload_length)
-{
- int checksum = 0;
-
- // We only need to compute the checksum if we are sending acks
- if (GetSendAcks ())
- {
- for (size_t i = 0; i < payload_length; ++i)
- checksum += payload[i];
- }
- return checksum & 255;
-}
-
-size_t
-CommunicationKDP::SendAck ()
-{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
- if (log)
- log->Printf ("send packet: +");
- ConnectionStatus status = eConnectionStatusSuccess;
- char ack_char = '+';
- return Write (&ack_char, 1, status, NULL);
-}
-
-size_t
-CommunicationKDP::SendNack ()
-{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
- if (log)
- log->Printf ("send packet: -");
- ConnectionStatus status = eConnectionStatusSuccess;
- char nack_char = '-';
- return Write (&nack_char, 1, status, NULL);
-}
-
-size_t
-CommunicationKDP::SendPacket (lldb_private::StreamString &payload)
+bool
+CommunicationKDP::SendRequestPacket (const StreamString &request_packet)
{
Mutex::Locker locker(m_sequence_mutex);
- const std::string &p (payload.GetString());
- return SendPacketNoLock (p.c_str(), p.size());
+ return SendRequestPacketNoLock (request_packet);
}
-size_t
-CommunicationKDP::SendPacket (const char *payload)
+void
+CommunicationKDP::MakeRequestPacketHeader (RequestType request_type,
+ StreamString &request_packet)
{
- Mutex::Locker locker(m_sequence_mutex);
- return SendPacketNoLock (payload, ::strlen (payload));
+ request_packet.Clear();
+ request_packet.PutHex32 (request_type); // Set the request type
+ request_packet.PutHex8 (ePacketTypeRequest); // Set the packet type
+ request_packet.PutHex8 (++m_request_sequence_id); // Sequence number
+ request_packet.PutHex16 (0); // Pad1 and Pad2 bytes
+ request_packet.PutHex32 (m_session_key); // Session key
}
-size_t
-CommunicationKDP::SendPacket (const char *payload, size_t payload_length)
-{
- Mutex::Locker locker(m_sequence_mutex);
- return SendPacketNoLock (payload, payload_length);
-}
-size_t
-CommunicationKDP::SendPacketNoLock (const char *payload, size_t payload_length)
+bool
+CommunicationKDP::SendRequestPacketNoLock (const StreamString &request_packet)
{
if (IsConnected())
{
- StreamString packet(0, 4, eByteOrderBig);
-
- packet.PutChar('$');
- packet.Write (payload, payload_length);
- packet.PutChar('#');
- packet.PutHex8(CalculcateChecksum (payload, payload_length));
+ const char *packet_data = request_packet.GetData();
+ const size_t packet_size = request_packet.GetSize();
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
if (log)
- log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData());
+ {
+ StreamString log_strm;
+ DataExtractor data (packet_data,
+ packet_size,
+ request_packet.GetByteOrder(),
+ request_packet.GetAddressByteSize());
+ data.Dump (&log_strm,
+ 0,
+ eFormatBytes,
+ 1,
+ packet_size,
+ 32, // Num bytes per line
+ 0, // Base address
+ 0,
+ 0);
+
+ log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetString().c_str());
+ }
ConnectionStatus status = eConnectionStatusSuccess;
- size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
- if (bytes_written == packet.GetSize())
- {
- if (GetSendAcks ())
- {
- if (GetAck () != '+')
- {
- printf("get ack failed...");
- return 0;
- }
- }
- }
- else
- {
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
- if (log)
- log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
- }
- return bytes_written;
- }
- return 0;
-}
-char
-CommunicationKDP::GetAck ()
-{
- StringExtractor packet;
- if (WaitForPacketWithTimeoutMicroSeconds (packet, GetPacketTimeoutInMicroSeconds ()) == 1)
- return packet.GetChar();
- return 0;
+ size_t bytes_written = Write (packet_data,
+ packet_size,
+ status,
+ NULL);
+
+ if (bytes_written == packet_size)
+ return true;
+
+ if (log)
+ log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
+ }
+ return false;
}
bool
@@ -262,142 +223,30 @@
// Parse up the packets into gdb remote packets
if (!m_bytes.empty())
{
- // end_idx must be one past the last valid packet byte. Start
- // it off with an invalid value that is the same as the current
- // index.
- size_t content_start = 0;
- size_t content_length = 0;
- size_t total_length = 0;
- size_t checksum_idx = std::string::npos;
-
- switch (m_bytes[0])
- {
- case '+': // Look for ack
- case '-': // Look for cancel
- case '\x03': // ^C to halt target
- content_length = total_length = 1; // The command is one byte long...
- break;
-
- case '$':
- // Look for a standard gdb packet?
- {
- size_t hash_pos = m_bytes.find('#');
- if (hash_pos != std::string::npos)
- {
- if (hash_pos + 2 < m_bytes.size())
- {
- checksum_idx = hash_pos + 1;
- // Skip the dollar sign
- content_start = 1;
- // Don't include the # in the content or the $ in the content length
- content_length = hash_pos - 1;
-
- total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes
- }
- else
- {
- // Checksum bytes aren't all here yet
- content_length = std::string::npos;
- }
- }
- }
- break;
-
- default:
- {
- // We have an unexpected byte and we need to flush all bad
- // data that is in m_bytes, so we need to find the first
- // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
- // or '$' character (start of packet header) or of course,
- // the end of the data in m_bytes...
- const size_t bytes_len = m_bytes.size();
- bool done = false;
- uint32_t idx;
- for (idx = 1; !done && idx < bytes_len; ++idx)
- {
- switch (m_bytes[idx])
- {
- case '+':
- case '-':
- case '\x03':
- case '$':
- done = true;
- break;
-
- default:
- break;
- }
- }
- if (log)
- log->Printf ("CommunicationKDP::%s tossing %u junk bytes: '%.*s'",
- __FUNCTION__, idx, idx, m_bytes.c_str());
- m_bytes.erase(0, idx);
- }
- break;
- }
-
- if (content_length == std::string::npos)
- {
- packet.Clear();
- return false;
- }
- else if (total_length > 0)
- {
-
- // We have a valid packet...
- assert (content_length <= m_bytes.size());
- assert (total_length <= m_bytes.size());
- assert (content_length <= total_length);
-
- bool success = true;
- std::string &packet_str = packet.GetStringRef();
- packet_str.assign (m_bytes, content_start, content_length);
- if (m_bytes[0] == '$')
- {
- assert (checksum_idx < m_bytes.size());
- if (::isxdigit (m_bytes[checksum_idx+0]) ||
- ::isxdigit (m_bytes[checksum_idx+1]))
- {
- if (GetSendAcks ())
- {
- const char *packet_checksum_cstr = &m_bytes[checksum_idx];
- char packet_checksum = strtol (packet_checksum_cstr, NULL, 16);
- char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size());
- success = packet_checksum == actual_checksum;
- if (!success)
- {
- if (log)
- log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x",
- (int)(total_length),
- m_bytes.c_str(),
- (uint8_t)packet_checksum,
- (uint8_t)actual_checksum);
- }
- // Send the ack or nack if needed
- if (!success)
- SendNack();
- else
- SendAck();
- }
- if (success)
- {
- if (log)
- log->Printf ("read packet: %.*s", (int)(total_length), m_bytes.c_str());
- }
- }
- else
- {
- success = false;
- if (log)
- log->Printf ("error: invalid checksum in packet: '%s'\n", (int)(total_length), m_bytes.c_str());
- }
- }
- m_bytes.erase(0, total_length);
- packet.SetFilePos(0);
- return success;
- }
+ // TODO: Figure out if we have a full packet reply
}
packet.Clear();
return false;
}
+
+CommunicationKDP::ErrorType
+CommunicationKDP::Connect (uint16_t reply_port,
+ uint16_t exc_port,
+ const char *greeting)
+{
+ StreamString request_packet (Stream::eBinary, 4, eByteOrderLittle);
+ MakeRequestPacketHeader (eRequestTypeConnect, request_packet);
+ request_packet.PutHex16(reply_port);
+ request_packet.PutHex16(exc_port);
+ request_packet.PutCString(greeting);
+
+ return eErrorUnimplemented;
+}
+
+CommunicationKDP::ErrorType
+CommunicationKDP::Disconnect ()
+{
+ return eErrorUnimplemented;
+}
+