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