00001 #include <qapplication.h>
00002 #include <qstring.h>
00003 #include <unistd.h>
00004 #include <stdlib.h>
00005 #include "mythcontext.h"
00006 #include "util.h"
00007 #include "mythsocket.h"
00008 #ifdef USING_MINGW
00009 #include <winsock2.h>
00010 #include "compat.h"
00011 #else
00012 #include <sys/select.h>
00013 #endif
00014 #include <cassert>
00015
00016 #define SLOC(a) QString("MythSocket(%1:%2): ").arg((unsigned long)a, 0, 16)\
00017 .arg(a->socket())
00018 #define LOC SLOC(this)
00019
00020 const uint MythSocket::kSocketBufferSize = 128000;
00021
00022 #ifndef USING_MINGW
00023 pthread_t MythSocket::m_readyread_thread = (pthread_t)0;
00024 #else
00025 pthread_t MythSocket::m_readyread_thread = {0, 0};
00026 #endif
00027
00028 bool MythSocket::m_readyread_run = false;
00029 QMutex MythSocket::m_readyread_lock;
00030 QPtrList<MythSocket> MythSocket::m_readyread_list;
00031 QPtrList<MythSocket> MythSocket::m_readyread_dellist;
00032 QPtrList<MythSocket> MythSocket::m_readyread_addlist;
00033
00034 #ifdef USING_MINGW
00035 HANDLE readyreadevent = NULL;
00036 #else
00037 int MythSocket::m_readyread_pipe[2] = {-1, -1};
00038 #endif
00039
00040 MythSocket::MythSocket(int socket, MythSocketCBs *cb)
00041 : QSocketDevice(QSocketDevice::Stream), m_cb(cb),
00042 m_state(Idle), m_addr(), m_port(0),
00043 m_ref_count(0), m_notifyread(0)
00044 {
00045 VERBOSE(VB_SOCKET, LOC + "new socket");
00046 if (socket > -1)
00047 setSocket(socket);
00048
00049 if (m_cb)
00050 AddToReadyRead(this);
00051 }
00052
00053 MythSocket::~MythSocket()
00054 {
00055 close();
00056 VERBOSE(VB_SOCKET, LOC + "delete socket");
00057 }
00058
00059 void MythSocket::setCallbacks(MythSocketCBs *cb)
00060 {
00061 if (m_cb && cb)
00062 {
00063 m_cb = cb;
00064 return;
00065 }
00066
00067 m_cb = cb;
00068
00069 if (m_cb)
00070 AddToReadyRead(this);
00071 else
00072 RemoveFromReadyRead(this);
00073 }
00074
00075 void MythSocket::UpRef(void)
00076 {
00077 m_ref_lock.lock();
00078 m_ref_count++;
00079 m_ref_lock.unlock();
00080 VERBOSE(VB_SOCKET, LOC + QString("UpRef: %1").arg(m_ref_count));
00081 }
00082
00083 bool MythSocket::DownRef(void)
00084 {
00085 m_ref_lock.lock();
00086 int ref = --m_ref_count;
00087 m_ref_lock.unlock();
00088
00089 VERBOSE(VB_SOCKET, LOC + QString("DownRef: %1").arg(m_ref_count));
00090
00091 if (m_cb && ref == 0)
00092 {
00093 m_cb = NULL;
00094 RemoveFromReadyRead(this);
00095
00096 return true;
00097 }
00098 else if (ref < 0)
00099 {
00100 delete this;
00101 return true;
00102 }
00103
00104 return false;
00105 }
00106
00107 MythSocket::State MythSocket::state(void)
00108 {
00109 return m_state;
00110 }
00111
00112 void MythSocket::setState(const State state)
00113 {
00114 if (state != m_state)
00115 {
00116 VERBOSE(VB_SOCKET, LOC + QString("state change %1 -> %2")
00117 .arg(stateToString(m_state)).arg(stateToString(state)));
00118
00119 m_state = state;
00120 }
00121 }
00122
00123 QString MythSocket::stateToString(const State state)
00124 {
00125 switch(state)
00126 {
00127 case Connected:
00128 return "Connected";
00129 case Connecting:
00130 return "Connecting";
00131 case HostLookup:
00132 return "HostLookup";
00133 case Idle:
00134 return "Idle";
00135 default:
00136 return QString("Invalid State: %1").arg(state);
00137 }
00138 }
00139
00140 QString MythSocket::errorToString(const Error error)
00141 {
00142 switch(error)
00143 {
00144 case NoError:
00145 return "NoError";
00146 case AlreadyBound:
00147 return "AlreadyBound";
00148 case Inaccessible:
00149 return "Inaccessible";
00150 case NoResources:
00151 return "NoResources";
00152 case InternalError:
00153 return "InternalError";
00154 case Impossible:
00155 return "Impossible";
00156 case NoFiles:
00157 return "NoFiles";
00158 case ConnectionRefused:
00159 return "ConnectionRefused";
00160 case NetworkFailure:
00161 return "NetworkFailure";
00162 case UnknownError:
00163 return "UnknownError";
00164 default:
00165 return QString("Invalid error: %1").arg(error);
00166 }
00167 }
00168
00169 void MythSocket::setSocket(int socket, Type type)
00170 {
00171 VERBOSE(VB_SOCKET, LOC + QString("setSocket: %1").arg(socket));
00172 if (socket < 0)
00173 {
00174 VERBOSE(VB_SOCKET, LOC + "setSocket called with invalid socket");
00175 return;
00176 }
00177
00178 if (state() == Connected)
00179 {
00180 VERBOSE(VB_SOCKET, LOC +
00181 "setSocket called while in Connected state, closing");
00182 close();
00183 }
00184
00185 QSocketDevice::setSocket(socket, type);
00186 setBlocking(false);
00187 setState(Connected);
00188 }
00189
00190 void MythSocket::close(void)
00191 {
00192 setState(Idle);
00193 QSocketDevice::close();
00194 }
00195
00196 Q_LONG MythSocket::readBlock(char *data, Q_ULONG len)
00197 {
00198
00199 if (state() != Connected)
00200 {
00201 VERBOSE(VB_SOCKET, LOC + "readBlock called while not in "
00202 "connected state");
00203 return -1;
00204 }
00205
00206 m_notifyread = false;
00207
00208 Q_LONG rval = QSocketDevice::readBlock(data, len);
00209 if (rval == 0)
00210 {
00211 close();
00212 if (m_cb)
00213 {
00214 m_cb->connectionClosed(this);
00215 VERBOSE(VB_SOCKET, LOC + "calling cb->connectionClosed()");
00216 }
00217 }
00218 return rval;
00219 }
00220
00225 Q_LONG MythSocket::writeBlock(const char *data, Q_ULONG len)
00226 {
00227
00228 if (state() != Connected)
00229 {
00230 VERBOSE(VB_SOCKET, LOC + "writeBlock called while not in "
00231 "connected state");
00232 return -1;
00233 }
00234
00235 Q_LONG rval = QSocketDevice::writeBlock(data, len);
00236
00237
00238 if (!isValid() || error() != QSocketDevice::NoError)
00239 {
00240 close();
00241 if (m_cb)
00242 {
00243 VERBOSE(VB_SOCKET, LOC + "cb->connectionClosed()");
00244 m_cb->connectionClosed(this);
00245 }
00246 return -1;
00247 }
00248 return rval;
00249 }
00250
00251 bool MythSocket::writeStringList(QStringList &list)
00252 {
00253 if (list.size() <= 0)
00254 {
00255 VERBOSE(VB_IMPORTANT, LOC +
00256 "writeStringList: Error, invalid string list.");
00257 return false;
00258 }
00259
00260 if (state() != Connected)
00261 {
00262 VERBOSE(VB_IMPORTANT, LOC +
00263 "writeStringList: Error, called with unconnected socket.");
00264 return false;
00265 }
00266
00267 QString str = list.join("[]:[]");
00268 if (str == QString::null)
00269 {
00270 VERBOSE(VB_IMPORTANT, LOC +
00271 "writeStringList: Error, joined null string.");
00272 return false;
00273 }
00274
00275 QCString utf8 = str.utf8();
00276 int size = utf8.length();
00277 int written = 0;
00278
00279 QCString payload;
00280 payload = payload.setNum(size);
00281 payload += " ";
00282 payload.truncate(8);
00283 payload += utf8;
00284 size = payload.length();
00285
00286 if ((print_verbose_messages & VB_NETWORK) != 0)
00287 {
00288 QString msg = QString("write -> %1 %2")
00289 .arg(socket(), 2).arg(payload);
00290
00291 if ((print_verbose_messages != VB_ALL) && msg.length() > 88)
00292 {
00293 msg.truncate(85);
00294 msg += "...";
00295 }
00296 VERBOSE(VB_NETWORK, msg);
00297 }
00298
00299 unsigned int errorcount = 0;
00300 while (size > 0)
00301 {
00302 if (state() != Connected)
00303 {
00304 VERBOSE(VB_IMPORTANT, LOC +
00305 "writeStringList: Error, socket went unconnected.");
00306 return false;
00307 }
00308
00309 int temp = writeBlock(payload.data() + written, size);
00310 if (temp > 0)
00311 {
00312 written += temp;
00313 size -= temp;
00314 }
00315 else if (temp < 0 && error() != QSocketDevice::NoError)
00316 {
00317 VERBOSE(VB_IMPORTANT, LOC +
00318 QString("writeStringList: Error, writeBlock failed. (%1)")
00319 .arg(errorToString()));
00320 return false;
00321 }
00322 else if (temp <= 0)
00323 {
00324 errorcount++;
00325 if (errorcount > 5000)
00326 {
00327 VERBOSE(VB_GENERAL, LOC +
00328 "writeStringList: No data written on writeBlock");
00329 return false;
00330 }
00331 usleep(1000);
00332 }
00333 }
00334 return true;
00335 }
00336
00341 bool MythSocket::writeData(const char *data, Q_ULONG len)
00342 {
00343 if (state() != Connected)
00344 {
00345 VERBOSE(VB_IMPORTANT, LOC +
00346 "writeData: Error, called with unconnected socket.");
00347 return false;
00348 }
00349
00350 Q_ULONG written = 0;
00351 uint zerocnt = 0;
00352
00353 while (written < len)
00354 {
00355 Q_LONG btw = len - written >= kSocketBufferSize ?
00356 kSocketBufferSize : len - written;
00357 Q_LONG sret = writeBlock(data + written, btw);
00358 if (sret > 0)
00359 {
00360 zerocnt = 0;
00361 written += sret;
00362 }
00363 else if (!isValid())
00364 {
00365 VERBOSE(VB_IMPORTANT, LOC +
00366 "writeData: Error, socket went unconnected");
00367 close();
00368 return false;
00369 }
00370 else if (sret < 0 && error() != QSocketDevice::NoError)
00371 {
00372 VERBOSE(VB_IMPORTANT, LOC +
00373 QString("writeData: Error, writeBlock: %1")
00374 .arg(errorToString()));
00375 close();
00376 return false;
00377 }
00378 else
00379 {
00380 zerocnt++;
00381 if (zerocnt > 5000)
00382 {
00383 VERBOSE(VB_IMPORTANT, LOC +
00384 "writeData: Error, zerocnt timeout");
00385 return false;
00386 }
00387 usleep(1000);
00388 }
00389 }
00390 return true;
00391 }
00392
00393 bool MythSocket::readStringList(QStringList &list, bool quickTimeout)
00394 {
00395 list.clear();
00396
00397 if (state() != Connected)
00398 {
00399 VERBOSE(VB_IMPORTANT, LOC +
00400 "readStringList: Error, called with unconnected socket.");
00401 return false;
00402 }
00403
00404 MythTimer timer;
00405 timer.start();
00406 int elapsed = 0;
00407
00408 while (waitForMore(5) < 8)
00409 {
00410 elapsed = timer.elapsed();
00411 if (!quickTimeout && elapsed >= 30000)
00412 {
00413 VERBOSE(VB_GENERAL, LOC + "readStringList: Error, timeout.");
00414 close();
00415 if (m_cb)
00416 {
00417 m_cb->connectionClosed(this);
00418 VERBOSE(VB_SOCKET, LOC + "calling cb->connectionClosed()");
00419 }
00420 return false;
00421 }
00422 else if (quickTimeout && elapsed >= 7000)
00423 {
00424 VERBOSE(VB_GENERAL, LOC +
00425 "readStringList: Error, timeout (quick).");
00426 close();
00427 if (m_cb)
00428 {
00429 m_cb->connectionClosed(this);
00430 VERBOSE(VB_SOCKET, LOC + "calling cb->connectionClosed()");
00431 }
00432 return false;
00433 }
00434
00435 if (state() != Connected)
00436 {
00437 VERBOSE(VB_IMPORTANT, LOC +
00438 "readStringList: Connection died.");
00439 return false;
00440 }
00441
00442 {
00443 struct timeval tv;
00444 int maxfd;
00445 fd_set rfds;
00446
00447 FD_ZERO(&rfds);
00448 FD_SET(socket(), &rfds);
00449 maxfd = socket();
00450
00451 tv.tv_sec = 0;
00452 tv.tv_usec = 0;
00453
00454 int rval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
00455 if (rval)
00456 {
00457 if (bytesAvailable() == 0)
00458 {
00459 VERBOSE(VB_IMPORTANT, LOC +
00460 "readStringList: Connection died (select).");
00461 return false;
00462 }
00463 }
00464 }
00465 }
00466
00467 QCString sizestr(8 + 1);
00468 if (readBlock(sizestr.data(), 8) < 0)
00469 {
00470 VERBOSE(VB_GENERAL, LOC +
00471 QString("readStringList: Error, readBlock return error (%1)")
00472 .arg(errorToString()));
00473 close();
00474 return false;
00475 }
00476
00477 sizestr = sizestr.stripWhiteSpace();
00478 Q_LONG btr = sizestr.toInt();
00479
00480 if (btr < 1)
00481 {
00482 int pending = bytesAvailable();
00483 QCString dump(pending + 1);
00484 readBlock(dump.data(), pending);
00485 VERBOSE(VB_IMPORTANT, LOC +
00486 QString("Protocol error: '%1' is not a valid size "
00487 "prefix. %2 bytes pending.")
00488 .arg(sizestr).arg(pending));
00489 return false;
00490 }
00491
00492 QCString utf8(btr + 1);
00493
00494 Q_LONG read = 0;
00495 int errmsgtime = 0;
00496 timer.start();
00497
00498 while (btr > 0)
00499 {
00500 Q_LONG sret = readBlock(utf8.data() + read, btr);
00501 if (sret > 0)
00502 {
00503 read += sret;
00504 btr -= sret;
00505 if (btr > 0)
00506 {
00507 timer.start();
00508 }
00509 }
00510 else if (sret < 0 && error() != QSocketDevice::NoError)
00511 {
00512 VERBOSE(VB_GENERAL, LOC +
00513 QString("readStringList: Error, readBlock %1")
00514 .arg(errorToString()));
00515 close();
00516 return false;
00517 }
00518 else if (!isValid())
00519 {
00520 VERBOSE(VB_IMPORTANT, LOC +
00521 "readStringList: Error, socket went unconnected");
00522 close();
00523 return false;
00524 }
00525 else
00526 {
00527 elapsed = timer.elapsed();
00528 if (elapsed > 10000)
00529 {
00530 if ((elapsed - errmsgtime) > 10000)
00531 {
00532 errmsgtime = elapsed;
00533 VERBOSE(VB_GENERAL, LOC +
00534 QString("readStringList: Waiting for data: %1 %2")
00535 .arg(read).arg(btr));
00536 }
00537 }
00538
00539 if (elapsed > 100000)
00540 {
00541 VERBOSE(VB_GENERAL, LOC +
00542 "Error, readStringList timeout (readBlock)");
00543 return false;
00544 }
00545
00546 usleep(500);
00547 }
00548 }
00549
00550 QString str = QString::fromUtf8(utf8.data());
00551
00552 QCString payload;
00553 payload = payload.setNum(str.length());
00554 payload += " ";
00555 payload.truncate(8);
00556 payload += str;
00557
00558 if ((print_verbose_messages & VB_NETWORK) != 0)
00559 {
00560 QString msg = QString("read <- %1 %2").arg(socket(), 2)
00561 .arg(payload);
00562
00563 if ((print_verbose_messages != VB_ALL) && msg.length() > 88)
00564 {
00565 msg.truncate(85);
00566 msg += "...";
00567 }
00568 VERBOSE(VB_NETWORK, msg);
00569 }
00570
00571 list = QStringList::split("[]:[]", str, true);
00572
00573 m_notifyread = false;
00574 WakeReadyReadThread();
00575 return true;
00576 }
00577
00578 void MythSocket::Lock(void)
00579 {
00580 m_lock.lock();
00581 WakeReadyReadThread();
00582 }
00583
00584 void MythSocket::Unlock(void)
00585 {
00586 m_lock.unlock();
00587 WakeReadyReadThread();
00588 }
00589
00594 bool MythSocket::connect(const QString &host, Q_UINT16 port)
00595 {
00596 QHostAddress hadr;
00597 hadr.setAddress(host);
00598 return MythSocket::connect(hadr, port);
00599 }
00600
00605 bool MythSocket::connect(const QHostAddress &addr, Q_UINT16 port)
00606 {
00607 if (state() == Connected)
00608 {
00609 VERBOSE(VB_SOCKET, LOC +
00610 "connect() called with already open socket, closing");
00611 close();
00612 }
00613
00614 VERBOSE(VB_SOCKET, LOC + QString("attempting connect() to (%1:%2)")
00615 .arg(addr.toString()).arg(port));
00616
00617 if (!QSocketDevice::connect(addr, port))
00618 {
00619 VERBOSE(VB_SOCKET, LOC + QString("connect() failed (%1)")
00620 .arg(errorToString()));
00621 setState(Idle);
00622 return false;
00623 }
00624
00625 setReceiveBufferSize(kSocketBufferSize);
00626 setAddressReusable(true);
00627 if (state() == Connecting)
00628 {
00629 setState(Connected);
00630 if (m_cb)
00631 {
00632 VERBOSE(VB_SOCKET, LOC + "cb->connected()");
00633 m_cb->connected(this);
00634 WakeReadyReadThread();
00635 }
00636 }
00637 else
00638 {
00639 setState(Connected);
00640 }
00641
00642 return true;
00643 }
00644
00645 void MythSocket::ShutdownReadyReadThread(void)
00646 {
00647 m_readyread_run = false;
00648 WakeReadyReadThread();
00649 pthread_join(m_readyread_thread, NULL);
00650
00651 #ifdef USING_MINGW
00652 if (readyreadevent) {
00653 ::CloseHandle(readyreadevent);
00654 readyreadevent = NULL;
00655 }
00656 #else
00657 ::close(m_readyread_pipe[0]);
00658 ::close(m_readyread_pipe[1]);
00659 #endif
00660 }
00661
00662 void MythSocket::StartReadyReadThread(void)
00663 {
00664 if (m_readyread_run == false)
00665 {
00666 QMutexLocker locker(&m_readyread_lock);
00667 if (m_readyread_run == false)
00668 {
00669 #ifdef USING_MINGW
00670 readyreadevent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
00671 assert(readyreadevent);
00672 #else
00673 int ret = pipe(m_readyread_pipe);
00674 (void) ret;
00675 assert(ret >= 0);
00676 #endif
00677
00678 m_readyread_run = true;
00679 pthread_create(&m_readyread_thread, NULL, readyReadThread, NULL);
00680
00681 atexit(ShutdownReadyReadThread);
00682 }
00683 }
00684 }
00685
00686 void MythSocket::AddToReadyRead(MythSocket *sock)
00687 {
00688 if (sock->socket() == -1)
00689 {
00690 VERBOSE(VB_SOCKET, "MythSocket: attempted to insert invalid socket to ReadyRead");
00691 return;
00692 }
00693 StartReadyReadThread();
00694
00695 sock->UpRef();
00696 m_readyread_lock.lock();
00697 m_readyread_addlist.append(sock);
00698 m_readyread_lock.unlock();
00699
00700 WakeReadyReadThread();
00701 }
00702
00703 void MythSocket::RemoveFromReadyRead(MythSocket *sock)
00704 {
00705 m_readyread_lock.lock();
00706 m_readyread_dellist.append(sock);
00707 m_readyread_lock.unlock();
00708
00709 WakeReadyReadThread();
00710 }
00711
00712 void MythSocket::WakeReadyReadThread(void)
00713 {
00714 #ifdef USING_MINGW
00715 if (readyreadevent) ::SetEvent(readyreadevent);
00716 #else
00717 if (m_readyread_pipe[1] >= 0)
00718 {
00719 char buf[1] = { '0' };
00720 write(m_readyread_pipe[1], &buf, 1);
00721 }
00722 #endif
00723 }
00724
00725 void readyReadThread_iffound(MythSocket *sock)
00726 {
00727 VERBOSE(VB_SOCKET, SLOC(sock) + "socket is readable");
00728 if (sock->bytesAvailable() == 0)
00729 {
00730 VERBOSE(VB_SOCKET, SLOC(sock) + "socket closed");
00731 sock->close();
00732
00733 if (sock->m_cb)
00734 {
00735 VERBOSE(VB_SOCKET, SLOC(sock) + "cb->connectionClosed()");
00736 sock->m_cb->connectionClosed(sock);
00737 }
00738 }
00739 else if (sock->m_cb)
00740 {
00741 sock->m_notifyread = true;
00742 VERBOSE(VB_SOCKET, SLOC(sock) + "cb->readyRead()");
00743 sock->m_cb->readyRead(sock);
00744 }
00745 }
00746
00747 void *MythSocket::readyReadThread(void *)
00748 {
00749 VERBOSE(VB_SOCKET, "MythSocket: readyread thread start");
00750 fd_set rfds;
00751 MythSocket *sock;
00752 int maxfd;
00753 bool found;
00754
00755 while (m_readyread_run)
00756 {
00757 m_readyread_lock.lock();
00758 while (m_readyread_dellist.count() > 0)
00759 {
00760 sock = m_readyread_dellist.take();
00761 bool del = m_readyread_list.removeRef(sock);
00762
00763 if (del)
00764 {
00765 m_readyread_lock.unlock();
00766 sock->DownRef();
00767 m_readyread_lock.lock();
00768 }
00769 }
00770
00771 while (m_readyread_addlist.count() > 0)
00772 {
00773 sock = m_readyread_addlist.take();
00774
00775 m_readyread_list.append(sock);
00776 }
00777 m_readyread_lock.unlock();
00778
00779 #ifdef USING_MINGW
00780
00781 int n = m_readyread_list.count() + 1;
00782 HANDLE *hEvents = new HANDLE[n];
00783 memset(hEvents, 0, sizeof(HANDLE) * n);
00784 unsigned *idx = new unsigned[n];
00785 n = 0;
00786
00787 for (unsigned i = 0; i < m_readyread_list.count(); i++)
00788 {
00789 sock = m_readyread_list.at(i);
00790 if (sock->state() == Connected && !sock->m_notifyread &&
00791 !sock->m_lock.locked())
00792 {
00793 HANDLE hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
00794 if (!hEvent)
00795 {
00796 VERBOSE(VB_IMPORTANT, "MythSocket: CreateEvent failed");
00797 }
00798 else
00799 {
00800 if (SOCKET_ERROR != ::WSAEventSelect(
00801 sock->socket(), hEvent,
00802 FD_READ | FD_CONNECT | FD_ACCEPT |
00803 FD_OOB | FD_CLOSE))
00804 {
00805 hEvents[n] = hEvent;
00806 idx[n++] = i;
00807 }
00808 else
00809 {
00810 VERBOSE(VB_IMPORTANT, QString(
00811 "MythSocket: CreateEvent, "
00812 "WSAEventSelect(%1, %2) failed")
00813 .arg(sock->socket()));
00814 ::CloseHandle(hEvent);
00815 }
00816 }
00817 }
00818 }
00819
00820 hEvents[n++] = readyreadevent;
00821 int rval = ::WaitForMultipleObjects(n, hEvents, FALSE, INFINITE);
00822
00823 for (int i = 0; i < (n - 1); i++)
00824 ::CloseHandle(hEvents[i]);
00825
00826 delete[] hEvents;
00827
00828 if (rval == WAIT_FAILED)
00829 {
00830 VERBOSE(VB_IMPORTANT,
00831 "MythSocket: WaitForMultipleObjects returned error");
00832 delete[] idx;
00833 }
00834 else if (rval >= WAIT_OBJECT_0 && rval < (WAIT_OBJECT_0 + n))
00835 {
00836 rval -= WAIT_OBJECT_0;
00837
00838 if (rval < (n - 1))
00839 {
00840 rval = idx[rval];
00841 sock = m_readyread_list.at(rval);
00842 found = (sock->state() == Connected) && !sock->m_lock.locked();
00843 }
00844 else
00845 {
00846 found = false;
00847 }
00848
00849 delete[] idx;
00850
00851 if (found)
00852 readyReadThread_iffound(sock);
00853
00854 ::ResetEvent(readyreadevent);
00855 }
00856 else if (rval >= WAIT_ABANDONED_0 && rval < (WAIT_ABANDONED_0 + n))
00857 {
00858 VERBOSE(VB_SOCKET, "MythSocket: abandoned");
00859 }
00860 else
00861 {
00862
00863 }
00864
00865 #else
00866
00867
00868 FD_ZERO(&rfds);
00869 maxfd = m_readyread_pipe[0];
00870
00871 FD_SET(m_readyread_pipe[0], &rfds);
00872
00873 QPtrListIterator<MythSocket> it(m_readyread_list);
00874 while ((sock = it.current()) != 0)
00875 {
00876 if (sock->state() == Connected &&
00877 sock->m_notifyread == false &&
00878 !sock->m_lock.locked())
00879 {
00880 FD_SET(sock->socket(), &rfds);
00881 maxfd = max(sock->socket(), maxfd);
00882 }
00883 ++it;
00884 }
00885
00886 int rval = select(maxfd + 1, &rfds, NULL, NULL, NULL);
00887 if (rval == -1)
00888 {
00889 VERBOSE(VB_SOCKET, "MythSocket: select returned error");
00890 }
00891 else if (rval)
00892 {
00893 found = false;
00894 QPtrListIterator<MythSocket> it(m_readyread_list);
00895 while ((sock = it.current()) != 0)
00896 {
00897 if (sock->state() == Connected &&
00898 FD_ISSET(sock->socket(), &rfds) &&
00899 !sock->m_lock.locked())
00900 {
00901 found = true;
00902 break;
00903 }
00904 ++it;
00905 }
00906
00907 if (found)
00908 readyReadThread_iffound(sock);
00909
00910 if (FD_ISSET(m_readyread_pipe[0], &rfds))
00911 {
00912 char buf[128];
00913 read(m_readyread_pipe[0], buf, 128);
00914 }
00915 }
00916 else
00917 {
00918
00919 }
00920
00921 #endif
00922
00923 }
00924
00925 VERBOSE(VB_SOCKET, "MythSocket: readyread thread exit");
00926
00927 return NULL;
00928 }
00929