1 //===-- Communication.cpp ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "lldb/lldb-private-log.h" 15 #include "lldb/Core/Communication.h" 16 #include "lldb/Core/Connection.h" 17 #include "lldb/Core/Log.h" 18 #include "lldb/Core/Timer.h" 19 #include "lldb/Core/Event.h" 20 #include "lldb/Host/Host.h" 21 #include <string.h> 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 //---------------------------------------------------------------------- 27 // Constructor 28 //---------------------------------------------------------------------- 29 Communication::Communication(const char *name) : 30 Broadcaster (name), 31 m_connection_sp (), 32 m_read_thread (LLDB_INVALID_HOST_THREAD), 33 m_read_thread_enabled (false), 34 m_bytes(), 35 m_bytes_mutex (Mutex::eMutexTypeRecursive), 36 m_write_mutex (Mutex::eMutexTypeNormal), 37 m_callback (NULL), 38 m_callback_baton (NULL), 39 m_close_on_eof (true) 40 41 { 42 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, 43 "%p Communication::Communication (name = %s)", 44 this, name); 45 46 SetEventName (eBroadcastBitDisconnected, "disconnected"); 47 SetEventName (eBroadcastBitReadThreadGotBytes, "got bytes"); 48 SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit"); 49 SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit"); 50 SetEventName (eBroadcastBitPacketAvailable, "packet available"); 51 } 52 53 //---------------------------------------------------------------------- 54 // Destructor 55 //---------------------------------------------------------------------- 56 Communication::~Communication() 57 { 58 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, 59 "%p Communication::~Communication (name = %s)", 60 this, m_broadcaster_name.AsCString("")); 61 Clear(); 62 } 63 64 void 65 Communication::Clear() 66 { 67 StopReadThread (NULL); 68 Disconnect (NULL); 69 } 70 71 ConnectionStatus 72 Communication::Connect (const char *url, Error *error_ptr) 73 { 74 Clear(); 75 76 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url); 77 78 lldb::ConnectionSP connection_sp (m_connection_sp); 79 if (connection_sp.get()) 80 return connection_sp->Connect (url, error_ptr); 81 if (error_ptr) 82 error_ptr->SetErrorString("Invalid connection."); 83 return eConnectionStatusNoConnection; 84 } 85 86 ConnectionStatus 87 Communication::Disconnect (Error *error_ptr) 88 { 89 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this); 90 91 lldb::ConnectionSP connection_sp (m_connection_sp); 92 if (connection_sp.get()) 93 { 94 ConnectionStatus status = connection_sp->Disconnect (error_ptr); 95 // We currently don't protect connection_sp with any mutex for 96 // multi-threaded environments. So lets not nuke our connection class 97 // without putting some multi-threaded protections in. We also probably 98 // don't want to pay for the overhead it might cause if every time we 99 // access the connection we have to take a lock. 100 // 101 // This auto_ptr will cleanup after itself when this object goes away, 102 // so there is no need to currently have it destroy itself immediately 103 // upon disconnnect. 104 //connection_sp.reset(); 105 return status; 106 } 107 return eConnectionStatusNoConnection; 108 } 109 110 bool 111 Communication::IsConnected () const 112 { 113 lldb::ConnectionSP connection_sp (m_connection_sp); 114 if (connection_sp.get()) 115 return connection_sp->IsConnected (); 116 return false; 117 } 118 119 bool 120 Communication::HasConnection () const 121 { 122 return m_connection_sp.get() != NULL; 123 } 124 125 size_t 126 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) 127 { 128 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 129 "%p Communication::Read (dst = %p, dst_len = %zu, timeout = %u usec) connection = %p", 130 this, 131 dst, 132 dst_len, 133 timeout_usec, 134 m_connection_sp.get()); 135 136 if (m_read_thread_enabled) 137 { 138 // We have a dedicated read thread that is getting data for us 139 size_t cached_bytes = GetCachedBytes (dst, dst_len); 140 if (cached_bytes > 0 || timeout_usec == 0) 141 { 142 status = eConnectionStatusSuccess; 143 return cached_bytes; 144 } 145 146 if (m_connection_sp.get() == NULL) 147 { 148 if (error_ptr) 149 error_ptr->SetErrorString("Invalid connection."); 150 status = eConnectionStatusNoConnection; 151 return 0; 152 } 153 // Set the timeout appropriately 154 TimeValue timeout_time; 155 if (timeout_usec != UINT32_MAX) 156 { 157 timeout_time = TimeValue::Now(); 158 timeout_time.OffsetWithMicroSeconds (timeout_usec); 159 } 160 161 Listener listener ("Communication::Read"); 162 listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit); 163 EventSP event_sp; 164 while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp)) 165 { 166 const uint32_t event_type = event_sp->GetType(); 167 if (event_type & eBroadcastBitReadThreadGotBytes) 168 { 169 return GetCachedBytes (dst, dst_len); 170 } 171 172 if (event_type & eBroadcastBitReadThreadDidExit) 173 { 174 Disconnect (NULL); 175 break; 176 } 177 } 178 return 0; 179 } 180 181 // We aren't using a read thread, just read the data synchronously in this 182 // thread. 183 lldb::ConnectionSP connection_sp (m_connection_sp); 184 if (connection_sp.get()) 185 { 186 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr); 187 } 188 189 if (error_ptr) 190 error_ptr->SetErrorString("Invalid connection."); 191 status = eConnectionStatusNoConnection; 192 return 0; 193 } 194 195 196 size_t 197 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) 198 { 199 lldb::ConnectionSP connection_sp (m_connection_sp); 200 201 Mutex::Locker (m_write_mutex); 202 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 203 "%p Communication::Write (src = %p, src_len = %zu) connection = %p", 204 this, 205 src, 206 src_len, 207 connection_sp.get()); 208 209 if (connection_sp.get()) 210 return connection_sp->Write (src, src_len, status, error_ptr); 211 212 if (error_ptr) 213 error_ptr->SetErrorString("Invalid connection."); 214 status = eConnectionStatusNoConnection; 215 return 0; 216 } 217 218 219 bool 220 Communication::StartReadThread (Error *error_ptr) 221 { 222 if (error_ptr) 223 error_ptr->Clear(); 224 225 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread)) 226 return true; 227 228 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 229 "%p Communication::StartReadThread ()", this); 230 231 232 char thread_name[1024]; 233 snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString()); 234 235 m_read_thread_enabled = true; 236 m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr); 237 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread)) 238 m_read_thread_enabled = false; 239 return m_read_thread_enabled; 240 } 241 242 bool 243 Communication::StopReadThread (Error *error_ptr) 244 { 245 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread)) 246 return true; 247 248 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 249 "%p Communication::StopReadThread ()", this); 250 251 m_read_thread_enabled = false; 252 253 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL); 254 255 Host::ThreadCancel (m_read_thread, error_ptr); 256 257 bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr); 258 m_read_thread = LLDB_INVALID_HOST_THREAD; 259 return status; 260 } 261 262 263 size_t 264 Communication::GetCachedBytes (void *dst, size_t dst_len) 265 { 266 Mutex::Locker locker(m_bytes_mutex); 267 if (m_bytes.size() > 0) 268 { 269 // If DST is NULL and we have a thread, then return the number 270 // of bytes that are available so the caller can call again 271 if (dst == NULL) 272 return m_bytes.size(); 273 274 const size_t len = std::min<size_t>(dst_len, m_bytes.size()); 275 276 ::memcpy (dst, m_bytes.c_str(), len); 277 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len); 278 279 return len; 280 } 281 return 0; 282 } 283 284 void 285 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status) 286 { 287 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 288 "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)", 289 this, bytes, len, broadcast); 290 if ((bytes == NULL || len == 0) 291 && (status != lldb::eConnectionStatusEndOfFile)) 292 return; 293 if (m_callback) 294 { 295 // If the user registered a callback, then call it and do not broadcast 296 m_callback (m_callback_baton, bytes, len); 297 } 298 else 299 { 300 Mutex::Locker locker(m_bytes_mutex); 301 m_bytes.append ((const char *)bytes, len); 302 if (broadcast) 303 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes); 304 } 305 } 306 307 size_t 308 Communication::ReadFromConnection (void *dst, 309 size_t dst_len, 310 uint32_t timeout_usec, 311 ConnectionStatus &status, 312 Error *error_ptr) 313 { 314 lldb::ConnectionSP connection_sp (m_connection_sp); 315 if (connection_sp.get()) 316 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr); 317 return 0; 318 } 319 320 bool 321 Communication::ReadThreadIsRunning () 322 { 323 return m_read_thread_enabled; 324 } 325 326 void * 327 Communication::ReadThread (void *p) 328 { 329 Communication *comm = (Communication *)p; 330 331 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); 332 333 if (log) 334 log->Printf ("%p Communication::ReadThread () thread starting...", p); 335 336 uint8_t buf[1024]; 337 338 Error error; 339 ConnectionStatus status = eConnectionStatusSuccess; 340 bool done = false; 341 while (!done && comm->m_read_thread_enabled) 342 { 343 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error); 344 if (bytes_read > 0) 345 comm->AppendBytesToCache (buf, bytes_read, true, status); 346 else if ((bytes_read == 0) 347 && status == eConnectionStatusEndOfFile) 348 { 349 if (comm->GetCloseOnEOF ()) 350 comm->Disconnect (); 351 comm->AppendBytesToCache (buf, bytes_read, true, status); 352 } 353 354 switch (status) 355 { 356 case eConnectionStatusSuccess: 357 break; 358 359 case eConnectionStatusEndOfFile: 360 if (comm->GetCloseOnEOF()) 361 done = true; 362 break; 363 case eConnectionStatusNoConnection: // No connection 364 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection 365 done = true; 366 // Fall through... 367 default: 368 case eConnectionStatusError: // Check GetError() for details 369 case eConnectionStatusTimedOut: // Request timed out 370 if (log) 371 error.LogIfError(log.get(), 372 "%p Communication::ReadFromConnection () => status = %s", 373 p, 374 Communication::ConnectionStatusAsCString (status)); 375 break; 376 } 377 } 378 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION); 379 if (log) 380 log->Printf ("%p Communication::ReadThread () thread exiting...", p); 381 382 // Let clients know that this thread is exiting 383 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit); 384 comm->m_read_thread_enabled = false; 385 comm->Disconnect(); 386 return NULL; 387 } 388 389 void 390 Communication::SetReadThreadBytesReceivedCallback 391 ( 392 ReadThreadBytesReceived callback, 393 void *callback_baton 394 ) 395 { 396 m_callback = callback; 397 m_callback_baton = callback_baton; 398 } 399 400 void 401 Communication::SetConnection (Connection *connection) 402 { 403 StopReadThread(NULL); 404 Disconnect (NULL); 405 m_connection_sp.reset(connection); 406 } 407 408 const char * 409 Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status) 410 { 411 switch (status) 412 { 413 case eConnectionStatusSuccess: return "success"; 414 case eConnectionStatusError: return "error"; 415 case eConnectionStatusTimedOut: return "timed out"; 416 case eConnectionStatusNoConnection: return "no connection"; 417 case eConnectionStatusLostConnection: return "lost connection"; 418 case eConnectionStatusEndOfFile: return "end of file"; 419 } 420 421 static char unknown_state_string[64]; 422 snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status); 423 return unknown_state_string; 424 } 425