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;
+}
+