equal
deleted
inserted
replaced
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 |