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_ap (), 31 m_read_thread (NULL), 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 38 { 39 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, 40 "%p Communication::Communication (name = %s)", 41 this, name); 42 } 43 44 //---------------------------------------------------------------------- 45 // Destructor 46 //---------------------------------------------------------------------- 47 Communication::~Communication() 48 { 49 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, 50 "%p Communication::~Communication (name = %s)", 51 this, m_broadcaster_name.AsCString("")); 52 Clear(); 53 } 54 55 void 56 Communication::Clear() 57 { 58 StopReadThread (NULL); 59 Disconnect (NULL); 60 } 61 62 ConnectionStatus 63 Communication::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) 64 { 65 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::BytesAvailable (timeout_usec = %u)", this, timeout_usec); 66 67 if (m_connection_ap.get()) 68 return m_connection_ap->BytesAvailable (timeout_usec, error_ptr); 69 if (error_ptr) 70 error_ptr->SetErrorString("Invalid connection."); 71 return eConnectionStatusNoConnection; 72 } 73 74 ConnectionStatus 75 Communication::Connect (const char *url, Error *error_ptr) 76 { 77 Clear(); 78 79 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url); 80 81 if (m_connection_ap.get()) 82 return m_connection_ap->Connect (url, error_ptr); 83 if (error_ptr) 84 error_ptr->SetErrorString("Invalid connection."); 85 return eConnectionStatusNoConnection; 86 } 87 88 ConnectionStatus 89 Communication::Disconnect (Error *error_ptr) 90 { 91 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this); 92 93 if (m_connection_ap.get()) 94 { 95 ConnectionStatus status = m_connection_ap->Disconnect (error_ptr); 96 m_connection_ap.reset(); 97 return status; 98 } 99 return eConnectionStatusNoConnection; 100 } 101 102 bool 103 Communication::IsConnected () const 104 { 105 if (m_connection_ap.get()) 106 return m_connection_ap->IsConnected (); 107 return false; 108 } 109 110 bool 111 Communication::HasConnection () const 112 { 113 return m_connection_ap.get() != NULL; 114 } 115 116 size_t 117 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) 118 { 119 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 120 "%p Communication::Write (dst = %p, dst_len = %zu, timeout_usec = %u) connection = %p", 121 this, dst, dst_len, timeout_usec, m_connection_ap.get()); 122 123 if (m_read_thread != NULL) 124 { 125 // We have a dedicated read thread that is getting data for us 126 size_t cached_bytes = GetCachedBytes (dst, dst_len); 127 if (cached_bytes > 0 || timeout_usec == 0) 128 { 129 status = eConnectionStatusSuccess; 130 return cached_bytes; 131 } 132 133 if (m_connection_ap.get() == NULL) 134 { 135 if (error_ptr) 136 error_ptr->SetErrorString("Invalid connection."); 137 status = eConnectionStatusNoConnection; 138 return 0; 139 } 140 // Set the timeout appropriately 141 TimeValue timeout_time; 142 if (timeout_usec != UINT32_MAX) 143 { 144 timeout_time = TimeValue::Now(); 145 timeout_time.OffsetWithMicroSeconds (timeout_usec); 146 } 147 148 Listener listener ("Communication::Read"); 149 listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit); 150 EventSP event_sp; 151 while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp)) 152 { 153 const uint32_t event_type = event_sp->GetType(); 154 if (event_type & eBroadcastBitReadThreadGotBytes) 155 { 156 return GetCachedBytes (dst, dst_len); 157 } 158 159 if (event_type & eBroadcastBitReadThreadDidExit) 160 { 161 Disconnect (NULL); 162 break; 163 } 164 } 165 return 0; 166 } 167 168 // We aren't using a read thread, just read the data synchronously in this 169 // thread. 170 if (m_connection_ap.get()) 171 { 172 status = m_connection_ap->BytesAvailable (timeout_usec, error_ptr); 173 if (status == eConnectionStatusSuccess) 174 return m_connection_ap->Read (dst, dst_len, status, error_ptr); 175 } 176 177 if (error_ptr) 178 error_ptr->SetErrorString("Invalid connection."); 179 status = eConnectionStatusNoConnection; 180 return 0; 181 } 182 183 184 size_t 185 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) 186 { 187 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 188 "%p Communication::Write (src = %p, src_len = %zu) connection = %p", 189 this, src, src_len, m_connection_ap.get()); 190 191 if (m_connection_ap.get()) 192 return m_connection_ap->Write (src, src_len, status, error_ptr); 193 194 if (error_ptr) 195 error_ptr->SetErrorString("Invalid connection."); 196 status = eConnectionStatusNoConnection; 197 return 0; 198 } 199 200 201 bool 202 Communication::StartReadThread (Error *error_ptr) 203 { 204 if (m_read_thread != LLDB_INVALID_HOST_THREAD) 205 return true; 206 207 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 208 "%p Communication::StartReadThread ()", this); 209 210 211 char thread_name[1024]; 212 snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString()); 213 214 m_read_thread_enabled = true; 215 m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr); 216 return m_read_thread != LLDB_INVALID_HOST_THREAD; 217 } 218 219 bool 220 Communication::StopReadThread (Error *error_ptr) 221 { 222 if (m_read_thread == NULL) 223 return true; 224 225 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 226 "%p Communication::StopReadThread ()", this); 227 228 m_read_thread_enabled = false; 229 230 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL); 231 232 Host::ThreadCancel (m_read_thread, error_ptr); 233 234 return Host::ThreadJoin (m_read_thread, NULL, error_ptr); 235 } 236 237 238 size_t 239 Communication::GetCachedBytes (void *dst, size_t dst_len) 240 { 241 Mutex::Locker locker(m_bytes_mutex); 242 if (m_bytes.size() > 0) 243 { 244 // If DST is NULL and we have a thread, then return the number 245 // of bytes that are available so the caller can call again 246 if (dst == NULL) 247 return m_bytes.size(); 248 249 const size_t len = std::min<size_t>(dst_len, m_bytes.size()); 250 251 ::memcpy (dst, m_bytes.data(), len); 252 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len); 253 254 return len; 255 } 256 return 0; 257 } 258 259 void 260 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast) 261 { 262 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 263 "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)", 264 this, bytes, len, broadcast); 265 if (bytes == NULL || len == 0) 266 return; 267 if (m_callback) 268 { 269 // If the user registered a callback, then call it and do not broadcast 270 m_callback (m_callback_baton, bytes, len); 271 } 272 else 273 { 274 Mutex::Locker locker(m_bytes_mutex); 275 m_bytes.append ((const char *)bytes, len); 276 if (broadcast) 277 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes); 278 } 279 } 280 281 size_t 282 Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr) 283 { 284 if (m_connection_ap.get()) 285 return m_connection_ap->Read (dst, dst_len, status, error_ptr); 286 return 0; 287 } 288 289 290 bool 291 Communication::ReadThreadIsRunning () 292 { 293 return m_read_thread != NULL; 294 } 295 296 void * 297 Communication::ReadThread (void *p) 298 { 299 Communication *comm = (Communication *)p; 300 301 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION); 302 303 if (log) 304 log->Printf ("%p Communication::ReadThread () thread starting...", p); 305 306 uint8_t buf[1024]; 307 308 Error error; 309 ConnectionStatus status = eConnectionStatusSuccess; 310 bool done = false; 311 while (!done && comm->m_read_thread_enabled) 312 { 313 status = comm->BytesAvailable (UINT32_MAX, &error); 314 315 if (status == eConnectionStatusSuccess) 316 { 317 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error); 318 if (bytes_read > 0) 319 comm->AppendBytesToCache (buf, bytes_read, true); 320 } 321 322 switch (status) 323 { 324 case eConnectionStatusSuccess: 325 break; 326 327 case eConnectionStatusNoConnection: // No connection 328 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection 329 done = true; 330 // Fall through... 331 default: 332 case eConnectionStatusError: // Check GetError() for details 333 case eConnectionStatusTimedOut: // Request timed out 334 error.LogIfError(log, "%p Communication::BytesAvailable () => status = %i", p, status); 335 break; 336 } 337 } 338 if (log) 339 log->Printf ("%p Communication::ReadThread () thread exiting...", p); 340 341 // Let clients know that this thread is exiting 342 comm->m_read_thread = LLDB_INVALID_HOST_THREAD; 343 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit); 344 return NULL; 345 } 346 347 void 348 Communication::SetReadThreadBytesReceivedCallback 349 ( 350 ReadThreadBytesReceived callback, 351 void *callback_baton 352 ) 353 { 354 m_callback = callback; 355 m_callback_baton = callback_baton; 356 } 357 358 void 359 Communication::SetConnection (Connection *connection) 360 { 361 StopReadThread(NULL); 362 Disconnect (NULL); 363 m_connection_ap.reset(connection); 364 } 365