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