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 (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 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 != LLDB_INVALID_HOST_THREAD) 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 if (m_read_thread == LLDB_INVALID_HOST_THREAD) 217 m_read_thread_enabled = false; 218 return m_read_thread_enabled; 219 } 220 221 bool 222 Communication::StopReadThread (Error *error_ptr) 223 { 224 if (m_read_thread == LLDB_INVALID_HOST_THREAD) 225 return true; 226 227 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 228 "%p Communication::StopReadThread ()", this); 229 230 m_read_thread_enabled = false; 231 232 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL); 233 234 Host::ThreadCancel (m_read_thread, error_ptr); 235 236 return Host::ThreadJoin (m_read_thread, NULL, error_ptr); 237 m_read_thread = LLDB_INVALID_HOST_THREAD; 238 } 239 240 241 size_t 242 Communication::GetCachedBytes (void *dst, size_t dst_len) 243 { 244 Mutex::Locker locker(m_bytes_mutex); 245 if (m_bytes.size() > 0) 246 { 247 // If DST is NULL and we have a thread, then return the number 248 // of bytes that are available so the caller can call again 249 if (dst == NULL) 250 return m_bytes.size(); 251 252 const size_t len = std::min<size_t>(dst_len, m_bytes.size()); 253 254 ::memcpy (dst, m_bytes.c_str(), len); 255 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len); 256 257 return len; 258 } 259 return 0; 260 } 261 262 void 263 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast) 264 { 265 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, 266 "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)", 267 this, bytes, len, broadcast); 268 if (bytes == NULL || len == 0) 269 return; 270 if (m_callback) 271 { 272 // If the user registered a callback, then call it and do not broadcast 273 m_callback (m_callback_baton, bytes, len); 274 } 275 else 276 { 277 Mutex::Locker locker(m_bytes_mutex); 278 m_bytes.append ((const char *)bytes, len); 279 if (broadcast) 280 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes); 281 } 282 } 283 284 size_t 285 Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr) 286 { 287 if (m_connection_ap.get()) 288 return m_connection_ap->Read (dst, dst_len, status, error_ptr); 289 return 0; 290 } 291 292 293 bool 294 Communication::ReadThreadIsRunning () 295 { 296 return m_read_thread != LLDB_INVALID_HOST_THREAD; 297 } 298 299 void * 300 Communication::ReadThread (void *p) 301 { 302 Communication *comm = (Communication *)p; 303 304 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION); 305 306 if (log) 307 log->Printf ("%p Communication::ReadThread () thread starting...", p); 308 309 uint8_t buf[1024]; 310 311 Error error; 312 ConnectionStatus status = eConnectionStatusSuccess; 313 bool done = false; 314 while (!done && comm->m_read_thread_enabled) 315 { 316 status = comm->BytesAvailable (UINT32_MAX, &error); 317 318 if (status == eConnectionStatusSuccess) 319 { 320 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error); 321 if (bytes_read > 0) 322 comm->AppendBytesToCache (buf, bytes_read, true); 323 } 324 325 switch (status) 326 { 327 case eConnectionStatusSuccess: 328 break; 329 330 case eConnectionStatusNoConnection: // No connection 331 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection 332 done = true; 333 // Fall through... 334 default: 335 case eConnectionStatusError: // Check GetError() for details 336 case eConnectionStatusTimedOut: // Request timed out 337 error.LogIfError(log, "%p Communication::BytesAvailable () => status = %i", p, status); 338 break; 339 } 340 } 341 if (log) 342 log->Printf ("%p Communication::ReadThread () thread exiting...", p); 343 344 // Let clients know that this thread is exiting 345 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit); 346 return NULL; 347 } 348 349 void 350 Communication::SetReadThreadBytesReceivedCallback 351 ( 352 ReadThreadBytesReceived callback, 353 void *callback_baton 354 ) 355 { 356 m_callback = callback; 357 m_callback_baton = callback_baton; 358 } 359 360 void 361 Communication::SetConnection (Connection *connection) 362 { 363 StopReadThread(NULL); 364 Disconnect (NULL); 365 m_connection_ap.reset(connection); 366 } 367