bool CommunicationKDP::SendRequestPacketNoLock( const PacketStreamType &request_packet) { if (IsConnected()) { const char *packet_data = request_packet.GetData(); const size_t packet_size = request_packet.GetSize(); Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); if (log) { PacketStreamType log_strm; DumpPacket(log_strm, packet_data, packet_size); log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } ConnectionStatus status = eConnectionStatusSuccess; 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 %" PRIu64 " of %" PRIu64 " bytes sent", (uint64_t)bytes_written, (uint64_t)packet_size); } return false; }
void CommunicationKDP::MakeRequestPacketHeader(CommandType request_type, PacketStreamType &request_packet, uint16_t request_length) { request_packet.Clear(); request_packet.PutHex8(request_type | ePacketTypeRequest); // Set the request type request_packet.PutHex8(m_request_sequence_id++); // Sequence number request_packet.PutHex16( request_length); // Length of the packet including this header request_packet.PutHex32(m_session_key); // Session key }
bool CommunicationKDP::SendRequestAndGetReply (const CommandType command, const uint8_t request_sequence_id, const PacketStreamType &request_packet, DataExtractor &reply_packet) { if (IsRunning()) { LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); if (log) { PacketStreamType log_strm; DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize()); log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } return false; } Mutex::Locker locker(m_sequence_mutex); #ifdef LLDB_CONFIGURATION_DEBUG // NOTE: this only works for packets that are in native endian byte order assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2))); #endif if (SendRequestPacketNoLock(request_packet)) { if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ())) { uint32_t offset = 0; const uint8_t reply_command = reply_packet.GetU8 (&offset); const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset); if ((reply_command & eCommandTypeMask) == command) { if (request_sequence_id == reply_sequence_id) { if (command == KDP_RESUMECPUS) m_is_running.SetValue(true, eBroadcastAlways); return true; } } } } reply_packet.Clear(); return false; }
bool CommunicationKDP::SendRequestAndGetReply( const CommandType command, const PacketStreamType &request_packet, DataExtractor &reply_packet) { if (IsRunning()) { Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); if (log) { PacketStreamType log_strm; DumpPacket(log_strm, request_packet.GetData(), request_packet.GetSize()); log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } return false; } std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); #ifdef LLDB_CONFIGURATION_DEBUG // NOTE: this only works for packets that are in native endian byte order assert(request_packet.GetSize() == *((const uint16_t *)(request_packet.GetData() + 2))); #endif lldb::offset_t offset = 1; const uint32_t num_retries = 3; for (uint32_t i = 0; i < num_retries; ++i) { if (SendRequestPacketNoLock(request_packet)) { const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; while (1) { if (WaitForPacketWithTimeoutMicroSecondsNoLock( reply_packet, std::chrono::microseconds(GetPacketTimeout()).count())) { offset = 0; const uint8_t reply_command = reply_packet.GetU8(&offset); const uint8_t reply_sequence_id = reply_packet.GetU8(&offset); if (request_sequence_id == reply_sequence_id) { // The sequent ID was correct, now verify we got the response we // were looking for if ((reply_command & eCommandTypeMask) == command) { // Success if (command == KDP_RESUMECPUS) m_is_running.SetValue(true, eBroadcastAlways); return true; } else { // Failed to get the correct response, bail reply_packet.Clear(); return false; } } else if (reply_sequence_id > request_sequence_id) { // Sequence ID was greater than the sequence ID of the packet we // sent, something is really wrong... reply_packet.Clear(); return false; } else { // The reply sequence ID was less than our current packet's // sequence ID so we should keep trying to get a response because // this was a response for a previous packet that we must have // retried. } } else { // Break and retry sending the packet as we didn't get a response due // to timeout break; } } } } reply_packet.Clear(); return false; }