src/network/socket/qlocalsocket_win.cpp
changeset 33 3e2da88830cd
parent 22 79de32ba3296
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
   190 // This is reading from the buffer
   190 // This is reading from the buffer
   191 qint64 QLocalSocket::readData(char *data, qint64 maxSize)
   191 qint64 QLocalSocket::readData(char *data, qint64 maxSize)
   192 {
   192 {
   193     Q_D(QLocalSocket);
   193     Q_D(QLocalSocket);
   194 
   194 
       
   195     if (d->pipeClosed && d->actualReadBufferSize == 0)
       
   196         return -1;  // signal EOF
       
   197 
   195     qint64 readSoFar;
   198     qint64 readSoFar;
   196     // If startAsyncRead() read data, copy it to its destination.
   199     // If startAsyncRead() read data, copy it to its destination.
   197     if (maxSize == 1 && d->actualReadBufferSize > 0) {
   200     if (maxSize == 1 && d->actualReadBufferSize > 0) {
   198         *data = d->readBuffer.getChar();
   201         *data = d->readBuffer.getChar();
   199         d->actualReadBufferSize--;
   202         d->actualReadBufferSize--;
   211             d->actualReadBufferSize -= bytesToReadFromThisBlock;
   214             d->actualReadBufferSize -= bytesToReadFromThisBlock;
   212         }
   215         }
   213     }
   216     }
   214 
   217 
   215     if (d->pipeClosed) {
   218     if (d->pipeClosed) {
   216         if (readSoFar == 0) {
   219         if (d->actualReadBufferSize == 0)
   217             QTimer::singleShot(0, this, SLOT(_q_pipeClosed()));
   220             QTimer::singleShot(0, this, SLOT(_q_pipeClosed()));
   218             return -1;  // signal EOF
       
   219         }
       
   220     } else {
   221     } else {
   221         if (!d->readSequenceStarted)
   222         if (!d->readSequenceStarted)
   222             d->startAsyncRead();
   223             d->startAsyncRead();
   223         d->checkReadyRead();
   224         d->checkReadyRead();
   224     }
   225     }
   248     Reads data from the socket into the readbuffer
   249     Reads data from the socket into the readbuffer
   249  */
   250  */
   250 void QLocalSocketPrivate::startAsyncRead()
   251 void QLocalSocketPrivate::startAsyncRead()
   251 {
   252 {
   252     do {
   253     do {
   253         DWORD bytesToRead = bytesAvailable();
   254         DWORD bytesToRead = checkPipeState();
       
   255         if (pipeClosed)
       
   256             return;
       
   257 
   254         if (bytesToRead == 0) {
   258         if (bytesToRead == 0) {
   255             // There are no bytes in the pipe but we need to
   259             // There are no bytes in the pipe but we need to
   256             // start the overlapped read with some buffer size.
   260             // start the overlapped read with some buffer size.
   257             bytesToRead = initialReadBufferSize;
   261             bytesToRead = initialReadBufferSize;
   258         }
   262         }
   274         } else {
   278         } else {
   275             switch (GetLastError()) {
   279             switch (GetLastError()) {
   276                 case ERROR_IO_PENDING:
   280                 case ERROR_IO_PENDING:
   277                     // This is not an error. We're getting notified, when data arrives.
   281                     // This is not an error. We're getting notified, when data arrives.
   278                     return;
   282                     return;
       
   283                 case ERROR_MORE_DATA:
       
   284                     // This is not an error. The synchronous read succeeded.
       
   285                     // We're connected to a message mode pipe and the message
       
   286                     // didn't fit into the pipe's system buffer.
       
   287                     completeAsyncRead();
       
   288                     break;
   279                 case ERROR_PIPE_NOT_CONNECTED:
   289                 case ERROR_PIPE_NOT_CONNECTED:
   280                     {
   290                     {
   281                         // It may happen, that the other side closes the connection directly
   291                         // It may happen, that the other side closes the connection directly
   282                         // after writing data. Then we must set the appropriate socket state.
   292                         // after writing data. Then we must set the appropriate socket state.
   283                         pipeClosed = true;
   293                         pipeClosed = true;
   303     ResetEvent(overlapped.hEvent);
   313     ResetEvent(overlapped.hEvent);
   304     readSequenceStarted = false;
   314     readSequenceStarted = false;
   305 
   315 
   306     DWORD bytesRead;
   316     DWORD bytesRead;
   307     if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
   317     if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
   308         if (GetLastError() != ERROR_PIPE_NOT_CONNECTED)
   318         switch (GetLastError()) {
       
   319         case ERROR_MORE_DATA:
       
   320             // This is not an error. We're connected to a message mode
       
   321             // pipe and the message didn't fit into the pipe's system
       
   322             // buffer. We will read the remaining data in the next call.
       
   323             break;
       
   324         case ERROR_PIPE_NOT_CONNECTED:
   309             setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead"));
   325             setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead"));
   310         return false;
   326             // fall through
       
   327         default:
       
   328             return false;
       
   329         }
   311     }
   330     }
   312 
   331 
   313     actualReadBufferSize += bytesRead;
   332     actualReadBufferSize += bytesRead;
   314     readBuffer.truncate(actualReadBufferSize);
   333     readBuffer.truncate(actualReadBufferSize);
   315     return true;
   334     return true;
   331 {
   350 {
   332     close();
   351     close();
   333 }
   352 }
   334 
   353 
   335 /*!
   354 /*!
   336     The number of bytes available from the pipe
   355     \internal
   337   */
   356     Returns the number of available bytes in the pipe.
   338 DWORD QLocalSocketPrivate::bytesAvailable()
   357     Sets QLocalSocketPrivate::pipeClosed to true if the connection is broken.
       
   358  */
       
   359 DWORD QLocalSocketPrivate::checkPipeState()
   339 {
   360 {
   340     Q_Q(QLocalSocket);
   361     Q_Q(QLocalSocket);
   341     DWORD bytes;
   362     DWORD bytes;
   342     if (PeekNamedPipe(handle, NULL, 0, NULL, &bytes, NULL)) {
   363     if (PeekNamedPipe(handle, NULL, 0, NULL, &bytes, NULL)) {
   343         return bytes;
   364         return bytes;
   344     } else {
   365     } else {
   345         if (!pipeClosed) {
   366         if (!pipeClosed) {
   346             pipeClosed = true;
   367             pipeClosed = true;
   347             emit q->readChannelFinished();
   368             emit q->readChannelFinished();
   348             QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
   369             if (actualReadBufferSize == 0)
       
   370                 QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
   349         }
   371         }
   350     }
   372     }
   351     return 0;
   373     return 0;
   352 }
   374 }
   353 
   375 
   476 {
   498 {
   477     Q_Q(QLocalSocket);
   499     Q_Q(QLocalSocket);
   478     if (!completeAsyncRead()) {
   500     if (!completeAsyncRead()) {
   479         pipeClosed = true;
   501         pipeClosed = true;
   480         emit q->readChannelFinished();
   502         emit q->readChannelFinished();
       
   503         if (actualReadBufferSize == 0)
       
   504             QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
   481         return;
   505         return;
   482     }
   506     }
   483     startAsyncRead();
   507     startAsyncRead();
   484     pendingReadyRead = false;
   508     pendingReadyRead = false;
   485     emit q->readyRead();
   509     emit q->readyRead();
   527         qWarning("QLocalSocket::waitForDisconnected isn't supported for write only pipes.");
   551         qWarning("QLocalSocket::waitForDisconnected isn't supported for write only pipes.");
   528         return false;
   552         return false;
   529     }
   553     }
   530     QIncrementalSleepTimer timer(msecs);
   554     QIncrementalSleepTimer timer(msecs);
   531     forever {
   555     forever {
   532         d->bytesAvailable();    // to check if PeekNamedPipe fails
   556         d->checkPipeState();
   533         if (d->pipeClosed)
   557         if (d->pipeClosed)
   534             close();
   558             close();
   535         if (state() == UnconnectedState)
   559         if (state() == UnconnectedState)
   536             return true;
   560             return true;
   537         Sleep(timer.nextSleepTime());
   561         Sleep(timer.nextSleepTime());
   559         return true;
   583         return true;
   560 
   584 
   561     if (d->state != QLocalSocket::ConnectedState)
   585     if (d->state != QLocalSocket::ConnectedState)
   562         return false;
   586         return false;
   563 
   587 
       
   588     // We already know that the pipe is gone, but did not enter the event loop yet.
       
   589     if (d->pipeClosed) {
       
   590         close();
       
   591         return false;
       
   592     }
       
   593 
   564     Q_ASSERT(d->readSequenceStarted);
   594     Q_ASSERT(d->readSequenceStarted);
   565     DWORD result = WaitForSingleObject(d->overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
   595     DWORD result = WaitForSingleObject(d->overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
   566     switch (result) {
   596     switch (result) {
   567         case WAIT_OBJECT_0:
   597         case WAIT_OBJECT_0:
   568             d->_q_notified();
   598             d->_q_notified();
       
   599             // We just noticed that the pipe is gone.
       
   600             if (d->pipeClosed) {
       
   601                 close();
       
   602                 return false;
       
   603             }
   569             return true;
   604             return true;
   570         case WAIT_TIMEOUT:
   605         case WAIT_TIMEOUT:
   571             return false;
   606             return false;
   572     }
   607     }
   573 
   608