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