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