File indexing completed on 2024-12-01 13:02:42
0001 /* 0002 * Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Lesser General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Lesser General Public 0015 * License along with this library; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0017 * 02110-1301 USA 0018 * 0019 */ 0020 0021 // Note: if we ever enable the threaded backend, we need to protect: 0022 // QPipeDevice read and bytesAvailable 0023 // QPipeEnd finalize 0024 0025 // Note: we never use the return value for QPipeWriter::stop, but I don't 0026 // think this matters much 0027 0028 #include "qpipe.h" 0029 0030 #include <climits> 0031 #include <cstdlib> 0032 0033 // sorry, i've added this dependency for now, but it's easy enough to take 0034 // with you if you want qpipe independent of qca 0035 #include "qca_safeobj.h" 0036 0037 #ifdef Q_OS_WIN 0038 #include <QMutex> 0039 #include <QTextCodec> 0040 #include <QTextDecoder> 0041 #include <QTextEncoder> 0042 #include <QThread> 0043 #include <QWaitCondition> 0044 #else 0045 #include <QMutex> 0046 #endif 0047 0048 #ifdef Q_OS_UNIX 0049 #include <cerrno> 0050 #include <csignal> 0051 #include <fcntl.h> 0052 #include <sys/ioctl.h> 0053 #include <unistd.h> 0054 #ifdef HAVE_SYS_FILIO_H 0055 #include <sys/filio.h> 0056 #endif 0057 #endif 0058 0059 #define USE_POLL 0060 0061 #define CONSOLE_CHAREXPAND 5 0062 #define PIPEWRITER_POLL 1000 0063 #define PIPEREADER_POLL 100 0064 #define PIPEWRITER_BLOCK 8192 0065 #define PIPEEND_BLOCK 8192 0066 #define PIPEEND_READBUF 16384 0067 #define PIPEEND_READBUF_SEC 1024 0068 0069 namespace QCA { 0070 0071 #ifdef Q_OS_UNIX 0072 // adapted from qt 0073 Q_GLOBAL_STATIC(QMutex, ign_mutex) 0074 static bool ign_sigpipe = false; 0075 0076 static void ignore_sigpipe() 0077 { 0078 // Set to ignore SIGPIPE once only. 0079 QMutexLocker locker(ign_mutex()); 0080 if (!ign_sigpipe) { 0081 ign_sigpipe = true; 0082 struct sigaction noaction; 0083 memset(&noaction, 0, sizeof(noaction)); 0084 noaction.sa_handler = SIG_IGN; 0085 sigaction(SIGPIPE, &noaction, nullptr); 0086 } 0087 } 0088 #endif 0089 0090 #ifdef Q_OS_WIN 0091 static int pipe_dword_cap_to_int(DWORD dw) 0092 { 0093 if (sizeof(int) <= sizeof(DWORD)) 0094 return (int)((dw > INT_MAX) ? INT_MAX : dw); 0095 else 0096 return (int)dw; 0097 } 0098 0099 static bool pipe_dword_overflows_int(DWORD dw) 0100 { 0101 if (sizeof(int) <= sizeof(DWORD)) 0102 return (dw > INT_MAX) ? true : false; 0103 else 0104 return false; 0105 } 0106 #endif 0107 0108 #ifdef Q_OS_UNIX 0109 static int pipe_size_t_cap_to_int(size_t size) 0110 { 0111 if (sizeof(int) <= sizeof(size_t)) 0112 return (int)((size > INT_MAX) ? INT_MAX : size); 0113 else // maybe silly.. can int ever be larger than size_t? 0114 return (int)size; 0115 } 0116 #endif 0117 0118 static bool pipe_set_blocking(Q_PIPE_ID pipe, bool b) 0119 { 0120 #ifdef Q_OS_WIN 0121 DWORD flags = 0; 0122 if (!b) 0123 flags |= PIPE_NOWAIT; 0124 if (!SetNamedPipeHandleState(pipe, &flags, NULL, NULL)) 0125 return false; 0126 return true; 0127 #endif 0128 #ifdef Q_OS_UNIX 0129 int flags = fcntl(pipe, F_GETFL); 0130 if (!b) 0131 flags |= O_NONBLOCK; 0132 else 0133 flags &= ~O_NONBLOCK; 0134 if (fcntl(pipe, F_SETFL, flags) == -1) 0135 return false; 0136 return true; 0137 #endif 0138 } 0139 0140 // on windows, the pipe is closed and the new pipe is returned in newPipe 0141 static bool pipe_set_inheritable(Q_PIPE_ID pipe, bool b, Q_PIPE_ID *newPipe = nullptr) 0142 { 0143 #ifdef Q_OS_WIN 0144 // windows is required to accept a new pipe id 0145 if (!newPipe) 0146 return false; 0147 HANDLE h; 0148 if (!DuplicateHandle(GetCurrentProcess(), pipe, GetCurrentProcess(), &h, 0, b, DUPLICATE_SAME_ACCESS)) 0149 return false; 0150 *newPipe = h; 0151 return true; 0152 #endif 0153 #ifdef Q_OS_UNIX 0154 if (newPipe) 0155 *newPipe = pipe; 0156 int flags = fcntl(pipe, F_GETFD); 0157 if (!b) 0158 flags |= FD_CLOEXEC; 0159 else 0160 flags &= ~FD_CLOEXEC; 0161 if (fcntl(pipe, F_SETFD, flags) == -1) 0162 return false; 0163 return true; 0164 #endif 0165 } 0166 0167 // returns number of bytes available 0168 static int pipe_read_avail(Q_PIPE_ID pipe) 0169 { 0170 int bytesAvail = 0; 0171 #ifdef Q_OS_WIN 0172 DWORD i = 0; 0173 if (PeekNamedPipe(pipe, 0, 0, 0, &i, 0)) 0174 bytesAvail = pipe_dword_cap_to_int(i); 0175 #endif 0176 #ifdef Q_OS_UNIX 0177 size_t nbytes = 0; 0178 if (ioctl(pipe, FIONREAD, (char *)&nbytes) >= 0) 0179 bytesAvail = pipe_size_t_cap_to_int(nbytes); 0180 #endif 0181 return bytesAvail; 0182 } 0183 0184 // returns number of bytes actually read, no more than 'max'. 0185 // -1 on error. 0 means no data, NOT EOF. 0186 // note: even though this function looks like it can return data and EOF 0187 // at the same time, it never actually does. 0188 static int pipe_read(Q_PIPE_ID pipe, char *data, int max, bool *eof) 0189 { 0190 int bytesRead = 0; 0191 if (eof) 0192 *eof = false; 0193 if (max < 1) 0194 return 0; 0195 #ifdef Q_OS_WIN 0196 DWORD maxread = max; 0197 DWORD r = 0; 0198 if (!ReadFile(pipe, data, maxread, &r, 0)) { 0199 const DWORD err = GetLastError(); 0200 if (err == ERROR_HANDLE_EOF) { 0201 if (eof) 0202 *eof = true; 0203 } else if (err == ERROR_NO_DATA) { 0204 r = 0; 0205 } else 0206 return -1; 0207 } 0208 bytesRead = (int)r; // safe to cast, since 'max' is signed 0209 #endif 0210 #ifdef Q_OS_UNIX 0211 int r = 0; 0212 int ret = read(pipe, data, max); 0213 if (ret == -1) { 0214 if (errno != EAGAIN) 0215 return -1; 0216 } else if (ret == 0) { 0217 if (eof) 0218 *eof = true; 0219 } else 0220 r = ret; 0221 0222 bytesRead = r; 0223 #endif 0224 return bytesRead; 0225 } 0226 0227 // returns number of bytes actually written. 0228 // for blocking pipes, this should always be 'size'. 0229 // -1 on error. 0230 static int pipe_write(Q_PIPE_ID pipe, const char *data, int size) 0231 { 0232 #ifdef Q_OS_WIN 0233 DWORD written; 0234 if (!WriteFile(pipe, data, size, &written, 0)) 0235 return -1; 0236 return (int)written; // safe to cast, since 'size' is signed 0237 #endif 0238 #ifdef Q_OS_UNIX 0239 ignore_sigpipe(); 0240 int r = 0; 0241 int ret = write(pipe, data, size); 0242 if (ret == -1) { 0243 if (errno != EAGAIN) 0244 return -1; 0245 } else 0246 r = ret; 0247 return r; 0248 #endif 0249 } 0250 0251 // Windows Console functions 0252 0253 #ifdef Q_OS_WIN 0254 0255 static bool pipe_is_a_console(Q_PIPE_ID pipe) 0256 { 0257 DWORD mode; 0258 if (GetConsoleMode(pipe, &mode)) 0259 return true; 0260 return false; 0261 } 0262 0263 // returns the number of keypress events in the console input queue, 0264 // or -1 if there is an error (don't forget this!!) 0265 static int pipe_read_avail_console(Q_PIPE_ID pipe) 0266 { 0267 DWORD count, i; 0268 INPUT_RECORD *rec; 0269 int n, icount, total; 0270 0271 // how many events are there? 0272 if (!GetNumberOfConsoleInputEvents(pipe, &count)) 0273 return -1; 0274 0275 // peek them all 0276 rec = (INPUT_RECORD *)malloc(count * sizeof(INPUT_RECORD)); 0277 BOOL ret; 0278 ret = PeekConsoleInputW(pipe, rec, count, &i); 0279 if (!ret) { 0280 free(rec); 0281 return -1; 0282 } 0283 0284 icount = pipe_dword_cap_to_int(i); // process only the amount returned 0285 0286 // see which ones are normal keypress events 0287 total = 0; 0288 for (n = 0; n < icount; ++n) { 0289 if (rec[n].EventType == KEY_EVENT) { 0290 KEY_EVENT_RECORD *ke = &rec[n].Event.KeyEvent; 0291 if (ke->bKeyDown && ke->uChar.AsciiChar != 0) 0292 total += ke->wRepeatCount; 0293 } 0294 } 0295 0296 free(rec); 0297 return total; 0298 } 0299 0300 // pass dec to keep a long-running decoder, else 0 0301 static int pipe_read_console(Q_PIPE_ID pipe, ushort *data, int max, bool *eof, QTextDecoder *dec = 0) 0302 { 0303 int n, size, count; 0304 bool own_decoder; 0305 0306 if (eof) 0307 *eof = false; 0308 if (max < 1) 0309 return 0; 0310 0311 count = pipe_read_avail_console(pipe); 0312 if (count == -1) 0313 return -1; 0314 if (count == 0) 0315 return 0; 0316 0317 if (dec) { 0318 own_decoder = false; 0319 } else { 0320 dec = 0; 0321 own_decoder = true; 0322 } 0323 0324 size = 0; 0325 for (n = 0; n < count && size < max; ++n) { 0326 bool use_uni = true; 0327 quint16 uni = 0; 0328 quint8 ansi = 0; 0329 0330 BOOL ret; 0331 DWORD i; 0332 ret = ReadConsoleW(pipe, &uni, 1, &i, NULL); 0333 if (!ret) { 0334 // if the first read is an error, then report error 0335 if (n == 0) { 0336 delete dec; 0337 return -1; 0338 } 0339 // if we have some data, don't count this as an error. 0340 // we'll probably get it again next time around... 0341 else 0342 break; 0343 } 0344 0345 QString substr; 0346 if (use_uni) 0347 substr = QChar(uni); 0348 else 0349 substr = dec->toUnicode((const char *)&ansi, 1); 0350 0351 for (int k = 0; k < substr.length() && size < max; ++k) { 0352 QChar c = substr[k]; 0353 if (c == QChar(0x1A)) // EOF? 0354 { 0355 if (eof) 0356 *eof = true; 0357 break; 0358 } 0359 data[size++] = substr[k].unicode(); 0360 } 0361 } 0362 if (own_decoder) 0363 delete dec; 0364 0365 return size; 0366 } 0367 0368 static int pipe_write_console(Q_PIPE_ID pipe, const ushort *data, int size) 0369 { 0370 DWORD i; 0371 BOOL ret; 0372 ret = WriteConsoleW(pipe, data, size, &i, NULL); 0373 if (!ret) 0374 return -1; 0375 return (int)i; // safe to cast since 'size' is signed 0376 } 0377 #endif 0378 0379 #ifdef Q_OS_WIN 0380 0381 // Here is the multi-backend stuff for windows. QPipeWriter and QPipeReader 0382 // define a common interface, and then subclasses (like QPipeWriterThread) 0383 // are used by QPipeDevice. The base classes inherit from QThread, even 0384 // if threads aren't used, so that I can define signals without dealing 0385 // with multiple QObject inheritance in the thread subclasses (it is also 0386 // possible that I'm missing something obvious and don't need to do this). 0387 0388 // Note: 0389 // QPipeWriterThread and QPipeReaderThread require the pipes to be in 0390 // blocking mode. QPipeWriterPoll and QPipeReaderPoll require the pipes 0391 // to be in non-blocking mode. 0392 0393 //---------------------------------------------------------------------------- 0394 // QPipeWriter 0395 //---------------------------------------------------------------------------- 0396 class QPipeWriter : public QThread 0397 { 0398 Q_OBJECT 0399 public: 0400 QPipeWriter(QObject *parent = nullptr) 0401 : QThread(parent) 0402 { 0403 } 0404 0405 virtual ~QPipeWriter() 0406 { 0407 } 0408 0409 // start 0410 virtual void start() = 0; 0411 0412 // stop, and return number of bytes written so far 0413 virtual int stop() = 0; 0414 0415 // data pointer needs to remain until canWrite is emitted 0416 virtual int write(const char *data, int size) = 0; 0417 0418 Q_SIGNALS: 0419 // result values: 0420 // = 0 : success 0421 // = -1 : error 0422 void canWrite(int result, int bytesWritten); 0423 0424 protected: 0425 virtual void run() 0426 { 0427 // implement a default to satisfy the polling subclass 0428 } 0429 }; 0430 0431 //---------------------------------------------------------------------------- 0432 // QPipeReader 0433 //---------------------------------------------------------------------------- 0434 class QPipeReader : public QThread 0435 { 0436 Q_OBJECT 0437 public: 0438 QPipeReader(QObject *parent = nullptr) 0439 : QThread(parent) 0440 { 0441 } 0442 0443 virtual ~QPipeReader() 0444 { 0445 } 0446 0447 // start 0448 virtual void start() = 0; 0449 0450 // to be called after every read 0451 virtual void resume() = 0; 0452 0453 Q_SIGNALS: 0454 // result values: 0455 // >= 0 : readAhead 0456 // = -1 : atEnd 0457 // = -2 : atError 0458 // = -3 : data available, but no readAhead 0459 void canRead(int result); 0460 0461 protected: 0462 virtual void run() 0463 { 0464 // implement a default to satisfy the polling subclass 0465 } 0466 }; 0467 0468 //---------------------------------------------------------------------------- 0469 // QPipeWriterThread 0470 //---------------------------------------------------------------------------- 0471 class QPipeWriterThread : public QPipeWriter 0472 { 0473 Q_OBJECT 0474 public: 0475 Q_PIPE_ID pipe; 0476 QMutex m; 0477 QWaitCondition w; 0478 bool do_quit; 0479 const char *data; 0480 int size; 0481 0482 QPipeWriterThread(Q_PIPE_ID id, QObject *parent = nullptr) 0483 : QPipeWriter(parent) 0484 { 0485 do_quit = false; 0486 data = 0; 0487 connect(this, &QPipeWriterThread::canWrite_p, this, &QPipeWriterThread::canWrite); 0488 DuplicateHandle(GetCurrentProcess(), id, GetCurrentProcess(), &pipe, 0, false, DUPLICATE_SAME_ACCESS); 0489 } 0490 0491 virtual ~QPipeWriterThread() 0492 { 0493 stop(); 0494 CloseHandle(pipe); 0495 } 0496 0497 virtual void start() 0498 { 0499 pipe_set_blocking(pipe, true); 0500 QThread::start(); 0501 } 0502 0503 virtual int stop() 0504 { 0505 if (isRunning()) { 0506 m.lock(); 0507 do_quit = true; 0508 w.wakeOne(); 0509 m.unlock(); 0510 if (!wait(100)) 0511 terminate(); 0512 do_quit = false; 0513 data = 0; 0514 } 0515 return size; 0516 } 0517 0518 virtual int write(const char *_data, int _size) 0519 { 0520 if (!isRunning()) 0521 return -1; 0522 0523 QMutexLocker locker(&m); 0524 if (data) 0525 return 0; 0526 0527 data = _data; 0528 size = _size; 0529 w.wakeOne(); 0530 return _size; 0531 } 0532 0533 protected: 0534 virtual void run() 0535 { 0536 while (1) { 0537 m.lock(); 0538 0539 while (!data && !do_quit) 0540 w.wait(&m); 0541 0542 if (do_quit) { 0543 m.unlock(); 0544 break; 0545 } 0546 0547 const char *p = data; 0548 int len = size; 0549 0550 m.unlock(); 0551 0552 int ret = internalWrite(p, len); 0553 0554 m.lock(); 0555 data = 0; 0556 size = ret; 0557 m.unlock(); 0558 0559 emit canWrite_p(ret < len ? -1 : 0, ret); 0560 } 0561 } 0562 0563 private: 0564 // attempts to write len bytes. value returned is number of bytes written. 0565 // any return value less than len means a write error was encountered 0566 int internalWrite(const char *p, int len) 0567 { 0568 int total = 0; 0569 while (total < len) { 0570 m.lock(); 0571 if (do_quit) { 0572 m.unlock(); 0573 return 0; 0574 } 0575 m.unlock(); 0576 0577 int ret = pipe_write(pipe, p + total, qMin(PIPEWRITER_BLOCK, len - total)); 0578 if (ret == -1) { 0579 // from qt, don't know why 0580 if (GetLastError() == 0xE8) // NT_STATUS_INVALID_USER_BUFFER 0581 { 0582 // give the os a rest 0583 msleep(100); 0584 continue; 0585 } 0586 0587 // on any other error, end thread 0588 return total; 0589 } 0590 total += ret; 0591 } 0592 return total; 0593 } 0594 0595 Q_SIGNALS: 0596 void canWrite_p(int result, int bytesWritten); 0597 }; 0598 0599 //---------------------------------------------------------------------------- 0600 // QPipeWriterPoll 0601 //---------------------------------------------------------------------------- 0602 class QPipeWriterPoll : public QPipeWriter 0603 { 0604 Q_OBJECT 0605 public: 0606 Q_PIPE_ID pipe; 0607 const char *data; 0608 int size; 0609 SafeTimer timer; 0610 int total; 0611 0612 QPipeWriterPoll(Q_PIPE_ID id, QObject *parent = nullptr) 0613 : QPipeWriter(parent) 0614 , timer(this) 0615 { 0616 pipe = id; 0617 data = 0; 0618 connect(&timer, &SafeTimer::timeout, this, &QPipeWriterPoll::tryNextWrite); 0619 } 0620 0621 virtual ~QPipeWriterPoll() 0622 { 0623 } 0624 0625 virtual void start() 0626 { 0627 pipe_set_blocking(pipe, false); 0628 } 0629 0630 // return number of bytes written 0631 virtual int stop() 0632 { 0633 timer.stop(); 0634 data = 0; 0635 return total; 0636 } 0637 0638 // data pointer needs to remain until canWrite is emitted 0639 virtual int write(const char *_data, int _size) 0640 { 0641 total = 0; 0642 data = _data; 0643 size = _size; 0644 timer.start(0); // write at next event loop 0645 return _size; 0646 } 0647 0648 private Q_SLOTS: 0649 void tryNextWrite() 0650 { 0651 int written = pipe_write(pipe, data + total, size - total); 0652 bool error = false; 0653 if (written == -1) { 0654 error = true; 0655 written = 0; // no bytes written on error 0656 0657 // from qt, they don't count it as fatal 0658 if (GetLastError() == 0xE8) // NT_STATUS_INVALID_USER_BUFFER 0659 error = false; 0660 } 0661 0662 total += written; 0663 if (error || total == size) { 0664 timer.stop(); 0665 data = 0; 0666 emit canWrite(error ? -1 : 0, total); 0667 return; 0668 } 0669 0670 timer.setInterval(PIPEWRITER_POLL); 0671 } 0672 }; 0673 0674 //---------------------------------------------------------------------------- 0675 // QPipeReaderThread 0676 //---------------------------------------------------------------------------- 0677 class QPipeReaderThread : public QPipeReader 0678 { 0679 Q_OBJECT 0680 public: 0681 Q_PIPE_ID pipe; 0682 QMutex m; 0683 QWaitCondition w; 0684 bool do_quit, active; 0685 0686 QPipeReaderThread(Q_PIPE_ID id, QObject *parent = nullptr) 0687 : QPipeReader(parent) 0688 { 0689 do_quit = false; 0690 active = true; 0691 connect(this, &QPipeReaderThread::canRead_p, this, &QPipeReaderThread::canRead); 0692 DuplicateHandle(GetCurrentProcess(), id, GetCurrentProcess(), &pipe, 0, false, DUPLICATE_SAME_ACCESS); 0693 } 0694 0695 virtual ~QPipeReaderThread() 0696 { 0697 if (isRunning()) { 0698 m.lock(); 0699 do_quit = true; 0700 w.wakeOne(); 0701 m.unlock(); 0702 if (!wait(100)) 0703 terminate(); 0704 } 0705 CloseHandle(pipe); 0706 } 0707 0708 virtual void start() 0709 { 0710 pipe_set_blocking(pipe, true); 0711 QThread::start(); 0712 } 0713 0714 virtual void resume() 0715 { 0716 QMutexLocker locker(&m); 0717 pipe_set_blocking(pipe, true); 0718 active = true; 0719 w.wakeOne(); 0720 } 0721 0722 protected: 0723 virtual void run() 0724 { 0725 while (1) { 0726 m.lock(); 0727 0728 while (!active && !do_quit) 0729 w.wait(&m); 0730 0731 if (do_quit) { 0732 m.unlock(); 0733 break; 0734 } 0735 0736 m.unlock(); 0737 0738 while (1) { 0739 unsigned char c; 0740 bool done; 0741 int ret = pipe_read(pipe, (char *)&c, 1, &done); 0742 if (done || ret != 0) // eof, error, or data? 0743 { 0744 int result; 0745 0746 if (done) // we got EOF? 0747 result = -1; 0748 else if (ret == -1) // we got an error? 0749 result = -2; 0750 else if (ret >= 1) // we got some data?? queue it 0751 result = c; 0752 else // will never happen 0753 result = -2; 0754 0755 m.lock(); 0756 active = false; 0757 pipe_set_blocking(pipe, false); 0758 m.unlock(); 0759 0760 emit canRead_p(result); 0761 break; 0762 } 0763 } 0764 } 0765 } 0766 0767 Q_SIGNALS: 0768 void canRead_p(int result); 0769 }; 0770 0771 //---------------------------------------------------------------------------- 0772 // QPipeReaderPoll 0773 //---------------------------------------------------------------------------- 0774 class QPipeReaderPoll : public QPipeReader 0775 { 0776 Q_OBJECT 0777 public: 0778 Q_PIPE_ID pipe; 0779 SafeTimer timer; 0780 bool consoleMode; 0781 0782 QPipeReaderPoll(Q_PIPE_ID id, QObject *parent = nullptr) 0783 : QPipeReader(parent) 0784 , timer(this) 0785 { 0786 pipe = id; 0787 connect(&timer, &SafeTimer::timeout, this, &QPipeReaderPoll::tryRead); 0788 } 0789 0790 virtual ~QPipeReaderPoll() 0791 { 0792 } 0793 0794 virtual void start() 0795 { 0796 pipe_set_blocking(pipe, false); 0797 consoleMode = pipe_is_a_console(pipe); 0798 resume(); 0799 } 0800 0801 virtual void resume() 0802 { 0803 timer.start(0); 0804 } 0805 0806 private Q_SLOTS: 0807 void tryRead() 0808 { 0809 if (consoleMode) 0810 tryReadConsole(); 0811 else 0812 tryReadPipe(); 0813 } 0814 0815 private: 0816 void tryReadPipe() 0817 { 0818 // is there data available for reading? if so, signal. 0819 int bytes = pipe_read_avail(pipe); 0820 if (bytes > 0) { 0821 timer.stop(); 0822 emit canRead(-3); // no readAhead 0823 return; 0824 } 0825 0826 // no data available? probe for EOF/error 0827 unsigned char c; 0828 bool done; 0829 int ret = pipe_read(pipe, (char *)&c, 1, &done); 0830 if (done || ret != 0) // eof, error, or data? 0831 { 0832 int result; 0833 0834 if (done) // we got EOF? 0835 result = -1; 0836 else if (ret == -1) // we got an error? 0837 result = -2; 0838 else if (ret >= 1) // we got some data?? queue it 0839 result = c; 0840 else // will never happen 0841 result = -2; 0842 0843 timer.stop(); 0844 emit canRead(result); 0845 return; 0846 } 0847 0848 timer.setInterval(PIPEREADER_POLL); 0849 } 0850 0851 void tryReadConsole() 0852 { 0853 // is there data available for reading? if so, signal. 0854 int count = pipe_read_avail_console(pipe); 0855 if (count > 0) { 0856 timer.stop(); 0857 emit canRead(-3); // no readAhead 0858 return; 0859 } 0860 0861 timer.setInterval(PIPEREADER_POLL); 0862 } 0863 }; 0864 0865 // end of windows pipe writer/reader implementations 0866 0867 #endif 0868 0869 //---------------------------------------------------------------------------- 0870 // QPipeDevice 0871 //---------------------------------------------------------------------------- 0872 class QPipeDevice::Private : public QObject 0873 { 0874 Q_OBJECT 0875 public: 0876 QPipeDevice *q; 0877 Q_PIPE_ID pipe; 0878 QPipeDevice::Type type; 0879 bool enabled; 0880 bool blockReadNotify; 0881 bool canWrite; 0882 int writeResult; 0883 int lastTaken, lastWritten; 0884 0885 #ifdef Q_OS_WIN 0886 bool atEnd, atError, forceNotify; 0887 int readAhead; 0888 SafeTimer *readTimer; 0889 QTextDecoder *dec; 0890 bool consoleMode; 0891 QPipeWriter *pipeWriter; 0892 QPipeReader *pipeReader; 0893 #endif 0894 #ifdef Q_OS_UNIX 0895 SafeSocketNotifier *sn_read, *sn_write; 0896 #endif 0897 0898 Private(QPipeDevice *_q) 0899 : QObject(_q) 0900 , q(_q) 0901 , pipe(INVALID_Q_PIPE_ID) 0902 { 0903 #ifdef Q_OS_WIN 0904 readTimer = 0; 0905 pipeWriter = 0; 0906 pipeReader = 0; 0907 dec = 0; 0908 #endif 0909 #ifdef Q_OS_UNIX 0910 sn_read = nullptr; 0911 sn_write = nullptr; 0912 #endif 0913 } 0914 0915 ~Private() override 0916 { 0917 reset(); 0918 } 0919 0920 void reset() 0921 { 0922 #ifdef Q_OS_WIN 0923 atEnd = false; 0924 atError = false; 0925 forceNotify = false; 0926 readAhead = -1; 0927 delete readTimer; 0928 readTimer = 0; 0929 delete pipeWriter; 0930 pipeWriter = 0; 0931 delete pipeReader; 0932 pipeReader = 0; 0933 delete dec; 0934 dec = 0; 0935 consoleMode = false; 0936 #endif 0937 #ifdef Q_OS_UNIX 0938 delete sn_read; 0939 sn_read = nullptr; 0940 delete sn_write; 0941 sn_write = nullptr; 0942 #endif 0943 if (pipe != INVALID_Q_PIPE_ID) { 0944 #ifdef Q_OS_WIN 0945 CloseHandle(pipe); 0946 #endif 0947 #ifdef Q_OS_UNIX 0948 ::close(pipe); 0949 #endif 0950 pipe = INVALID_Q_PIPE_ID; 0951 } 0952 0953 enabled = false; 0954 blockReadNotify = false; 0955 canWrite = true; 0956 writeResult = -1; 0957 } 0958 0959 void setup(Q_PIPE_ID id, QPipeDevice::Type _type) 0960 { 0961 pipe = id; 0962 type = _type; 0963 } 0964 0965 void enable() 0966 { 0967 if (enabled) 0968 return; 0969 0970 enabled = true; 0971 0972 if (type == QPipeDevice::Read) { 0973 #ifdef Q_OS_WIN 0974 // for windows, the blocking mode is chosen by the QPipeReader 0975 0976 // console might need a decoder 0977 if (consoleMode) { 0978 dec = 0; 0979 } 0980 0981 // pipe reader 0982 #ifdef USE_POLL 0983 pipeReader = new QPipeReaderPoll(pipe, this); 0984 #else 0985 // console always polls, no matter what 0986 if (consoleMode) 0987 pipeReader = new QPipeReaderPoll(pipe, this); 0988 else 0989 pipeReader = new QPipeReaderThread(pipe, this); 0990 #endif 0991 connect(pipeReader, &QPipeReader::canRead, this, &Private::pr_canRead); 0992 pipeReader->start(); 0993 0994 // polling timer 0995 readTimer = new SafeTimer(this); 0996 connect(readTimer, &SafeTimer::timeout, this, &Private::t_timeout); 0997 0998 // updated: now that we have pipeReader, this no longer 0999 // polls for data. it only does delayed singleshot 1000 // notifications. 1001 readTimer->setSingleShot(true); 1002 #endif 1003 #ifdef Q_OS_UNIX 1004 pipe_set_blocking(pipe, false); 1005 1006 // socket notifier 1007 sn_read = new SafeSocketNotifier(pipe, QSocketNotifier::Read, this); 1008 connect(sn_read, &SafeSocketNotifier::activated, this, &Private::sn_read_activated); 1009 #endif 1010 } else { 1011 // for windows, the blocking mode is chosen by the QPipeWriter 1012 #ifdef Q_OS_UNIX 1013 pipe_set_blocking(pipe, false); 1014 1015 // socket notifier 1016 sn_write = new SafeSocketNotifier(pipe, QSocketNotifier::Write, this); 1017 connect(sn_write, &SafeSocketNotifier::activated, this, &Private::sn_write_activated); 1018 sn_write->setEnabled(false); 1019 #endif 1020 } 1021 } 1022 1023 public Q_SLOTS: 1024 void t_timeout() 1025 { 1026 #ifdef Q_OS_WIN 1027 if (blockReadNotify) 1028 return; 1029 1030 // were we forced to notify? this can happen if we want to 1031 // spread out results across two reads. whatever caused 1032 // the forceNotify already knows what to do, so all we do 1033 // is signal. 1034 if (forceNotify) { 1035 forceNotify = false; 1036 blockReadNotify = true; 1037 emit q->notify(); 1038 return; 1039 } 1040 #endif 1041 } 1042 1043 void pw_canWrite(int result, int bytesWritten) 1044 { 1045 #ifdef Q_OS_WIN 1046 if (result == 0) { 1047 writeResult = 0; 1048 lastWritten = lastTaken; // success means all bytes 1049 } else { 1050 writeResult = -1; 1051 lastWritten = bytesWritten; 1052 } 1053 1054 canWrite = true; 1055 emit q->notify(); 1056 #else 1057 Q_UNUSED(result); 1058 Q_UNUSED(bytesWritten); 1059 #endif 1060 } 1061 1062 void pr_canRead(int result) 1063 { 1064 #ifdef Q_OS_WIN 1065 blockReadNotify = true; 1066 if (result == -1) 1067 atEnd = true; 1068 else if (result == -2) 1069 atError = true; 1070 else if (result != -3) 1071 readAhead = result; 1072 emit q->notify(); 1073 #else 1074 Q_UNUSED(result); 1075 #endif 1076 } 1077 1078 void sn_read_activated() 1079 { 1080 #ifdef Q_OS_UNIX 1081 if (blockReadNotify) 1082 return; 1083 1084 blockReadNotify = true; 1085 emit q->notify(); 1086 #endif 1087 } 1088 1089 void sn_write_activated() 1090 { 1091 #ifdef Q_OS_UNIX 1092 writeResult = 0; 1093 lastWritten = lastTaken; 1094 1095 canWrite = true; 1096 sn_write->setEnabled(false); 1097 emit q->notify(); 1098 #endif 1099 } 1100 }; 1101 1102 QPipeDevice::QPipeDevice(QObject *parent) 1103 : QObject(parent) 1104 { 1105 d = new Private(this); 1106 } 1107 1108 QPipeDevice::~QPipeDevice() 1109 { 1110 delete d; 1111 } 1112 1113 QPipeDevice::Type QPipeDevice::type() const 1114 { 1115 return d->type; 1116 } 1117 1118 bool QPipeDevice::isValid() const 1119 { 1120 return (d->pipe != INVALID_Q_PIPE_ID); 1121 } 1122 1123 Q_PIPE_ID QPipeDevice::id() const 1124 { 1125 return d->pipe; 1126 } 1127 1128 int QPipeDevice::idAsInt() const 1129 { 1130 #ifdef Q_OS_WIN 1131 DWORD dw; 1132 memcpy(&dw, &d->pipe, sizeof(DWORD)); 1133 return (int)dw; // FIXME? assumes handle value fits in signed int 1134 #endif 1135 #ifdef Q_OS_UNIX 1136 return d->pipe; 1137 #endif 1138 } 1139 1140 void QPipeDevice::take(Q_PIPE_ID id, Type t) 1141 { 1142 close(); 1143 d->setup(id, t); 1144 } 1145 1146 void QPipeDevice::enable() 1147 { 1148 #ifdef Q_OS_WIN 1149 d->consoleMode = pipe_is_a_console(d->pipe); 1150 #endif 1151 d->enable(); 1152 } 1153 1154 void QPipeDevice::close() 1155 { 1156 d->reset(); 1157 } 1158 1159 void QPipeDevice::release() 1160 { 1161 d->pipe = INVALID_Q_PIPE_ID; 1162 d->reset(); 1163 } 1164 1165 bool QPipeDevice::setInheritable(bool enabled) 1166 { 1167 #ifdef Q_OS_WIN 1168 Q_PIPE_ID newPipe; 1169 if (!pipe_set_inheritable(d->pipe, enabled, &newPipe)) 1170 return false; 1171 d->pipe = newPipe; 1172 #ifdef USE_POLL 1173 if (d->pipeReader) 1174 static_cast<QPipeReaderPoll *>(d->pipeReader)->pipe = d->pipe; 1175 if (d->pipeWriter) 1176 static_cast<QPipeWriterPoll *>(d->pipeWriter)->pipe = d->pipe; 1177 #endif 1178 return true; 1179 #endif 1180 #ifdef Q_OS_UNIX 1181 return pipe_set_inheritable(d->pipe, enabled, nullptr); 1182 #endif 1183 } 1184 1185 int QPipeDevice::bytesAvailable() const 1186 { 1187 int n; 1188 #ifdef Q_OS_WIN 1189 if (d->consoleMode) 1190 n = pipe_read_avail_console(d->pipe); 1191 else 1192 n = pipe_read_avail(d->pipe); 1193 if (d->readAhead != -1) 1194 ++n; 1195 #else 1196 n = pipe_read_avail(d->pipe); 1197 #endif 1198 return n; 1199 } 1200 1201 int QPipeDevice::read(char *data, int maxsize) 1202 { 1203 if (d->type != QPipeDevice::Read) 1204 return -1; 1205 1206 // must read at least 1 byte 1207 if (maxsize < 1) 1208 return -1; 1209 1210 #ifdef Q_OS_WIN 1211 // for windows console: 1212 // the number of bytes in utf8 can exceed the number of actual 1213 // characters it represents. to be safe, we'll assume that 1214 // utf8 could outnumber characters X:1. this does mean that 1215 // the maxsize parameter needs to be at least X to do 1216 // anything. (X = CONSOLE_CHAREXPAND) 1217 if (d->consoleMode && maxsize < CONSOLE_CHAREXPAND) 1218 return -1; 1219 1220 // for resuming the pipeReader 1221 bool wasBlocked = d->blockReadNotify; 1222 #endif 1223 1224 d->blockReadNotify = false; 1225 1226 #ifdef Q_OS_WIN 1227 // predetermined results 1228 if (d->atEnd) { 1229 close(); 1230 return 0; 1231 } 1232 if (d->atError) { 1233 close(); 1234 return -1; 1235 } 1236 1237 int offset = 0; 1238 int size = maxsize; 1239 1240 // prepend readAhead if we have it 1241 if (d->readAhead != -1) { 1242 unsigned char c = (unsigned char)d->readAhead; 1243 d->readAhead = -1; 1244 memcpy(&data[0], &c, 1); 1245 ++offset; 1246 --size; 1247 1248 // readAhead was enough data for the caller? 1249 if (size == 0) { 1250 if (wasBlocked) 1251 d->pipeReader->resume(); 1252 return offset; 1253 } 1254 } 1255 1256 // read from the pipe now 1257 bool done; 1258 int ret; 1259 if (d->consoleMode) { 1260 // read a fraction of the number of characters as requested, 1261 // to guarantee the result fits 1262 int num = size / CONSOLE_CHAREXPAND; 1263 1264 #ifdef QPIPE_SECURE 1265 SecureArray destbuf(num * sizeof(ushort), 0); 1266 #else 1267 QByteArray destbuf(num * sizeof(ushort), 0); 1268 #endif 1269 ushort *dest = (ushort *)destbuf.data(); 1270 1271 ret = pipe_read_console(d->pipe, dest, num, &done, d->dec); 1272 if (ret != -1) { 1273 // for security, encode one character at a time without 1274 // performing a QString conversion of the whole thing 1275 QTextCodec *codec = QTextCodec::codecForMib(106); 1276 QTextCodec::ConverterState cstate(QTextCodec::IgnoreHeader); 1277 int at = 0; 1278 for (int n = 0; n < ret; ++n) { 1279 QChar c(dest[n]); 1280 QByteArray out = codec->fromUnicode(&c, 1, &cstate); 1281 memcpy(data + offset + at, out.data(), out.size()); 1282 at += out.size(); 1283 } 1284 ret = at; // change ret to actual bytes 1285 } 1286 } else 1287 ret = pipe_read(d->pipe, data + offset, size, &done); 1288 if (done || ret == -1) // eof or error 1289 { 1290 // did we already have some data? if so, defer the eof/error 1291 if (offset) { 1292 d->forceNotify = true; 1293 if (done) 1294 d->atEnd = true; 1295 else 1296 d->atError = true; 1297 1298 // readTimer is a singleshot, so we have to start it 1299 // for forceNotify to work 1300 d->readTimer->start(); 1301 } 1302 // otherwise, bail 1303 else { 1304 close(); 1305 if (done) 1306 return 0; 1307 else 1308 return -1; 1309 } 1310 } else 1311 offset += ret; 1312 1313 // pipe still active? resume the pipeReader 1314 if (wasBlocked && !d->atEnd && !d->atError) 1315 d->pipeReader->resume(); 1316 1317 // no data means error 1318 if (offset == 0) 1319 return -1; 1320 1321 return offset; 1322 #endif 1323 #ifdef Q_OS_UNIX 1324 bool done; 1325 int r = pipe_read(d->pipe, data, maxsize, &done); 1326 if (done) { 1327 close(); 1328 return 0; 1329 } 1330 if (r == -1) { 1331 close(); 1332 return -1; 1333 } 1334 1335 // no data means error 1336 if (r == 0) 1337 return -1; 1338 1339 return r; 1340 #endif 1341 } 1342 1343 int QPipeDevice::write(const char *data, int size) 1344 { 1345 if (d->type != QPipeDevice::Write) 1346 return -1; 1347 1348 // allowed to write? 1349 if (!d->canWrite) 1350 return -1; 1351 1352 // if size is zero, don't bother 1353 if (size == 0) 1354 return 0; 1355 1356 int r; 1357 #ifdef Q_OS_WIN 1358 if (!d->pipeWriter) { 1359 #ifdef USE_POLL 1360 d->pipeWriter = new QPipeWriterPoll(d->pipe, d); 1361 #else 1362 // console always polls, no matter what 1363 if (d->consoleMode) 1364 d->pipeWriter = new QPipeReaderPoll(d->pipe, d); 1365 else 1366 d->pipeWriter = new QPipeWriterThread(d->pipe, d); 1367 #endif 1368 connect(d->pipeWriter, &QPipeWriter::canWrite, d, &Private::pw_canWrite); 1369 d->pipeWriter->start(); 1370 } 1371 1372 if (d->consoleMode) { 1373 // Note: we convert to QString here, but it should not be a 1374 // security issue (see pipe_write_console comment above) 1375 1376 // for console, just write direct. we won't use pipewriter 1377 QString out = QString::fromUtf8(QByteArray(data, size)); 1378 r = pipe_write_console(d->pipe, out.utf16(), out.length()); 1379 if (r == -1) 1380 return -1; 1381 1382 // convert characters to bytes 1383 r = out.mid(0, r).toUtf8().size(); 1384 1385 // simulate. we invoke the signal of pipewriter rather than our 1386 // own slot, so that the invoke can be cancelled. 1387 d->canWrite = false; 1388 QMetaObject::invokeMethod(d->pipeWriter, "canWrite", Qt::QueuedConnection, Q_ARG(int, 0), Q_ARG(int, r)); 1389 } else { 1390 d->canWrite = false; 1391 r = d->pipeWriter->write(data, size); 1392 } 1393 1394 d->lastTaken = r; 1395 if (r == -1) { 1396 close(); 1397 return -1; 1398 } 1399 #endif 1400 #ifdef Q_OS_UNIX 1401 r = pipe_write(d->pipe, data, size); 1402 d->lastTaken = r; 1403 if (r == -1) { 1404 close(); 1405 return -1; 1406 } 1407 1408 d->canWrite = false; 1409 d->sn_write->setEnabled(true); 1410 #endif 1411 return r; 1412 } 1413 1414 int QPipeDevice::writeResult(int *written) const 1415 { 1416 if (written) 1417 *written = d->lastWritten; 1418 return d->writeResult; 1419 } 1420 1421 //---------------------------------------------------------------------------- 1422 // QPipeEnd 1423 //---------------------------------------------------------------------------- 1424 enum ResetMode 1425 { 1426 ResetSession = 0, 1427 ResetSessionAndData = 1, 1428 ResetAll = 2 1429 }; 1430 1431 class QPipeEnd::Private : public QObject 1432 { 1433 Q_OBJECT 1434 public: 1435 QPipeEnd *q; 1436 QPipeDevice pipe; 1437 QPipeDevice::Type type; 1438 QByteArray buf; 1439 QByteArray curWrite; 1440 1441 #ifdef Q_OS_WIN 1442 bool consoleMode; 1443 #endif 1444 1445 #ifdef QPIPE_SECURE 1446 bool secure; 1447 SecureArray sec_buf; 1448 SecureArray sec_curWrite; 1449 #endif 1450 SafeTimer readTrigger, writeTrigger, closeTrigger, writeErrorTrigger; 1451 bool canRead, activeWrite; 1452 int lastWrite; 1453 bool closeLater; 1454 bool closing; 1455 1456 Private(QPipeEnd *_q) 1457 : QObject(_q) 1458 , q(_q) 1459 , pipe(this) 1460 , readTrigger(this) 1461 , writeTrigger(this) 1462 , closeTrigger(this) 1463 , writeErrorTrigger(this) 1464 { 1465 readTrigger.setSingleShot(true); 1466 writeTrigger.setSingleShot(true); 1467 closeTrigger.setSingleShot(true); 1468 writeErrorTrigger.setSingleShot(true); 1469 connect(&pipe, &QPipeDevice::notify, this, &Private::pipe_notify); 1470 connect(&readTrigger, &SafeTimer::timeout, this, &Private::doRead); 1471 connect(&writeTrigger, &SafeTimer::timeout, this, &Private::doWrite); 1472 connect(&closeTrigger, &SafeTimer::timeout, this, &Private::doClose); 1473 connect(&writeErrorTrigger, &SafeTimer::timeout, this, &Private::doWriteError); 1474 reset(ResetSessionAndData); 1475 } 1476 1477 void reset(ResetMode mode) 1478 { 1479 pipe.close(); 1480 readTrigger.stop(); 1481 writeTrigger.stop(); 1482 closeTrigger.stop(); 1483 writeErrorTrigger.stop(); 1484 canRead = false; 1485 activeWrite = false; 1486 lastWrite = 0; 1487 closeLater = false; 1488 closing = false; 1489 curWrite.clear(); 1490 #ifdef QPIPE_SECURE 1491 secure = false; 1492 sec_curWrite.clear(); 1493 #endif 1494 1495 if (mode >= ResetSessionAndData) { 1496 buf.clear(); 1497 #ifdef QPIPE_SECURE 1498 sec_buf.clear(); 1499 #endif 1500 } 1501 } 1502 1503 void setup(Q_PIPE_ID id, QPipeDevice::Type _type) 1504 { 1505 type = _type; 1506 #ifdef Q_OS_WIN 1507 consoleMode = pipe_is_a_console(id); 1508 #endif 1509 pipe.take(id, type); 1510 } 1511 1512 int pendingSize() const 1513 { 1514 #ifdef QPIPE_SECURE 1515 if (secure) 1516 return sec_buf.size(); 1517 else 1518 #endif 1519 return buf.size(); 1520 } 1521 1522 int pendingFreeSize() const 1523 { 1524 #ifdef QPIPE_SECURE 1525 if (secure) 1526 return qMax(PIPEEND_READBUF_SEC - sec_buf.size(), 0); 1527 else 1528 #endif 1529 return qMax(PIPEEND_READBUF - buf.size(), 0); 1530 } 1531 1532 void appendArray(QByteArray *a, const QByteArray &b) 1533 { 1534 (*a) += b; 1535 } 1536 1537 #ifdef QPIPE_SECURE 1538 void appendArray(SecureArray *a, const SecureArray &b) 1539 { 1540 a->append(b); 1541 } 1542 #endif 1543 1544 void takeArray(QByteArray *a, int len) 1545 { 1546 char *p = a->data(); 1547 const int newsize = a->size() - len; 1548 memmove(p, p + len, newsize); 1549 a->resize(newsize); 1550 } 1551 1552 #ifdef QPIPE_SECURE 1553 void takeArray(SecureArray *a, int len) 1554 { 1555 char *p = a->data(); 1556 const int newsize = a->size() - len; 1557 memmove(p, p + len, newsize); 1558 a->resize(newsize); 1559 } 1560 #endif 1561 1562 void setupNextRead() 1563 { 1564 if (pipe.isValid() && canRead) { 1565 canRead = false; 1566 readTrigger.start(0); 1567 } 1568 } 1569 1570 void setupNextWrite() 1571 { 1572 if (!activeWrite) { 1573 activeWrite = true; 1574 writeTrigger.start(0); 1575 } 1576 } 1577 1578 QByteArray read(QByteArray *buf, int bytes) 1579 { 1580 QByteArray a; 1581 if (bytes == -1 || bytes > buf->size()) { 1582 a = *buf; 1583 } else { 1584 a.resize(bytes); 1585 memcpy(a.data(), buf->data(), a.size()); 1586 } 1587 1588 takeArray(buf, a.size()); 1589 setupNextRead(); 1590 return a; 1591 } 1592 1593 void write(QByteArray *buf, const QByteArray &a) 1594 { 1595 appendArray(buf, a); 1596 setupNextWrite(); 1597 } 1598 1599 #ifdef QPIPE_SECURE 1600 SecureArray readSecure(SecureArray *buf, int bytes) 1601 { 1602 SecureArray a; 1603 if (bytes == -1 || bytes > buf->size()) { 1604 a = *buf; 1605 } else { 1606 a.resize(bytes); 1607 memcpy(a.data(), buf->data(), a.size()); 1608 } 1609 1610 takeArray(buf, a.size()); 1611 setupNextRead(); 1612 return a; 1613 } 1614 1615 void writeSecure(SecureArray *buf, const SecureArray &a) 1616 { 1617 appendArray(buf, a); 1618 setupNextWrite(); 1619 } 1620 #endif 1621 1622 public Q_SLOTS: 1623 void pipe_notify() 1624 { 1625 if (pipe.type() == QPipeDevice::Read) { 1626 doRead(); 1627 } else { 1628 int x; 1629 int writeResult = pipe.writeResult(&x); 1630 if (writeResult == -1) 1631 lastWrite = x; // if error, we may have written less bytes 1632 1633 // remove what we just wrote 1634 bool moreData = false; 1635 #ifdef QPIPE_SECURE 1636 if (secure) { 1637 takeArray(&sec_buf, lastWrite); 1638 moreData = !sec_buf.isEmpty(); 1639 } else 1640 #endif 1641 { 1642 takeArray(&buf, lastWrite); 1643 moreData = !buf.isEmpty(); 1644 } 1645 1646 #ifdef QPIPE_SECURE 1647 sec_curWrite.clear(); 1648 #endif 1649 curWrite.clear(); 1650 1651 x = lastWrite; 1652 lastWrite = 0; 1653 1654 if (writeResult == 0) { 1655 // more to write? do it 1656 if (moreData) { 1657 writeTrigger.start(0); 1658 } 1659 // done with all writing 1660 else { 1661 activeWrite = false; 1662 if (closeLater) { 1663 closeLater = false; 1664 closeTrigger.start(0); 1665 } 1666 } 1667 } else 1668 writeErrorTrigger.start(); 1669 1670 if (x > 0) 1671 emit q->bytesWritten(x); 1672 } 1673 } 1674 1675 void doRead() 1676 { 1677 doReadActual(true); 1678 } 1679 1680 void doReadActual(bool sigs) 1681 { 1682 const int left = pendingFreeSize(); 1683 if (left == 0) { 1684 canRead = true; 1685 return; 1686 } 1687 1688 int max; 1689 #ifdef Q_OS_WIN 1690 if (consoleMode) { 1691 // need a minimum amount for console 1692 if (left < CONSOLE_CHAREXPAND) { 1693 canRead = true; 1694 return; 1695 } 1696 1697 // don't use pipe.bytesAvailable() for console mode, 1698 // as it is somewhat bogus. fortunately, there is 1699 // no problem with overreading from the console. 1700 max = qMin(left, 32); 1701 } else 1702 #endif 1703 { 1704 max = qMin(left, pipe.bytesAvailable()); 1705 } 1706 1707 int ret; 1708 #ifdef QPIPE_SECURE 1709 if (secure) { 1710 SecureArray a(max); 1711 ret = pipe.read(a.data(), a.size()); 1712 if (ret >= 1) { 1713 a.resize(ret); 1714 sec_buf.append(a); 1715 } 1716 } else 1717 #endif 1718 { 1719 QByteArray a(max, 0); 1720 ret = pipe.read(a.data(), a.size()); 1721 if (ret >= 1) { 1722 a.resize(ret); 1723 buf += a; 1724 } 1725 } 1726 1727 if (ret < 1) { 1728 reset(ResetSession); 1729 if (sigs) { 1730 if (ret == 0) 1731 emit q->error(QPipeEnd::ErrorEOF); 1732 else 1733 emit q->error(QPipeEnd::ErrorBroken); 1734 } 1735 return; 1736 } 1737 1738 if (sigs) 1739 emit q->readyRead(); 1740 } 1741 1742 void doWrite() 1743 { 1744 int ret; 1745 #ifdef QPIPE_SECURE 1746 if (secure) { 1747 sec_curWrite.resize(qMin(PIPEEND_BLOCK, sec_buf.size())); 1748 memcpy(sec_curWrite.data(), sec_buf.data(), sec_curWrite.size()); 1749 1750 ret = pipe.write(sec_curWrite.data(), sec_curWrite.size()); 1751 } else 1752 #endif 1753 { 1754 curWrite.resize(qMin(PIPEEND_BLOCK, buf.size())); 1755 memcpy(curWrite.data(), buf.data(), curWrite.size()); 1756 1757 ret = pipe.write(curWrite.data(), curWrite.size()); 1758 } 1759 1760 if (ret == -1) { 1761 reset(ResetSession); 1762 emit q->error(QPipeEnd::ErrorBroken); 1763 return; 1764 } 1765 1766 lastWrite = ret; 1767 } 1768 1769 void doClose() 1770 { 1771 reset(ResetSession); 1772 emit q->closed(); 1773 } 1774 1775 void doWriteError() 1776 { 1777 reset(ResetSession); 1778 emit q->error(QPipeEnd::ErrorBroken); 1779 } 1780 }; 1781 1782 QPipeEnd::QPipeEnd(QObject *parent) 1783 : QObject(parent) 1784 { 1785 d = new Private(this); 1786 } 1787 1788 QPipeEnd::~QPipeEnd() 1789 { 1790 delete d; 1791 } 1792 1793 void QPipeEnd::reset() 1794 { 1795 d->reset(ResetAll); 1796 } 1797 1798 QPipeDevice::Type QPipeEnd::type() const 1799 { 1800 return d->pipe.type(); 1801 } 1802 1803 bool QPipeEnd::isValid() const 1804 { 1805 return d->pipe.isValid(); 1806 } 1807 1808 Q_PIPE_ID QPipeEnd::id() const 1809 { 1810 return d->pipe.id(); 1811 } 1812 1813 int QPipeEnd::idAsInt() const 1814 { 1815 return d->pipe.idAsInt(); 1816 } 1817 1818 void QPipeEnd::take(Q_PIPE_ID id, QPipeDevice::Type t) 1819 { 1820 reset(); 1821 d->setup(id, t); 1822 } 1823 1824 #ifdef QPIPE_SECURE 1825 void QPipeEnd::setSecurityEnabled(bool secure) 1826 { 1827 // no change 1828 if (d->secure == secure) 1829 return; 1830 1831 if (secure) { 1832 d->sec_buf = d->buf; 1833 d->buf.clear(); 1834 } else { 1835 d->buf = d->sec_buf.toByteArray(); 1836 d->sec_buf.clear(); 1837 } 1838 1839 d->secure = secure; 1840 } 1841 #endif 1842 1843 void QPipeEnd::enable() 1844 { 1845 d->pipe.enable(); 1846 } 1847 1848 void QPipeEnd::close() 1849 { 1850 if (!isValid() || d->closing) 1851 return; 1852 1853 d->closing = true; 1854 1855 if (d->activeWrite) 1856 d->closeLater = true; 1857 else 1858 d->closeTrigger.start(0); 1859 } 1860 1861 void QPipeEnd::release() 1862 { 1863 if (!isValid()) 1864 return; 1865 1866 d->pipe.release(); 1867 d->reset(ResetSession); 1868 } 1869 1870 bool QPipeEnd::setInheritable(bool enabled) 1871 { 1872 return d->pipe.setInheritable(enabled); 1873 } 1874 1875 void QPipeEnd::finalize() 1876 { 1877 if (!isValid()) 1878 return; 1879 1880 if (d->pipe.bytesAvailable()) 1881 d->doReadActual(false); 1882 d->reset(ResetSession); 1883 } 1884 1885 void QPipeEnd::finalizeAndRelease() 1886 { 1887 if (!isValid()) 1888 return; 1889 1890 if (d->pipe.bytesAvailable()) 1891 d->doReadActual(false); 1892 d->pipe.release(); 1893 d->reset(ResetSession); 1894 } 1895 1896 int QPipeEnd::bytesAvailable() const 1897 { 1898 return d->pendingSize(); 1899 } 1900 1901 int QPipeEnd::bytesToWrite() const 1902 { 1903 return d->pendingSize(); 1904 } 1905 1906 QByteArray QPipeEnd::read(int bytes) 1907 { 1908 return d->read(&d->buf, bytes); 1909 } 1910 1911 void QPipeEnd::write(const QByteArray &buf) 1912 { 1913 if (!isValid() || d->closing) 1914 return; 1915 1916 if (buf.isEmpty()) 1917 return; 1918 1919 #ifdef QPIPE_SECURE 1920 if (d->secure) // call writeSecure() instead 1921 return; 1922 #endif 1923 1924 d->write(&d->buf, buf); 1925 } 1926 1927 #ifdef QPIPE_SECURE 1928 SecureArray QPipeEnd::readSecure(int bytes) 1929 { 1930 return d->readSecure(&d->sec_buf, bytes); 1931 } 1932 1933 void QPipeEnd::writeSecure(const SecureArray &buf) 1934 { 1935 if (!isValid() || d->closing) 1936 return; 1937 1938 if (buf.isEmpty()) 1939 return; 1940 1941 if (!d->secure) // call write() instead 1942 return; 1943 1944 d->writeSecure(&d->sec_buf, buf); 1945 } 1946 #endif 1947 1948 QByteArray QPipeEnd::takeBytesToWrite() 1949 { 1950 // only call this on inactive sessions 1951 if (isValid()) 1952 return QByteArray(); 1953 1954 QByteArray a = d->buf; 1955 d->buf.clear(); 1956 return a; 1957 } 1958 1959 #ifdef QPIPE_SECURE 1960 SecureArray QPipeEnd::takeBytesToWriteSecure() 1961 { 1962 // only call this on inactive sessions 1963 if (isValid()) 1964 return SecureArray(); 1965 1966 SecureArray a = d->sec_buf; 1967 d->sec_buf.clear(); 1968 return a; 1969 } 1970 #endif 1971 1972 //---------------------------------------------------------------------------- 1973 // QPipe 1974 //---------------------------------------------------------------------------- 1975 QPipe::QPipe(QObject *parent) 1976 : i(parent) 1977 , o(parent) 1978 { 1979 } 1980 1981 QPipe::~QPipe() 1982 { 1983 } 1984 1985 void QPipe::reset() 1986 { 1987 i.reset(); 1988 o.reset(); 1989 } 1990 1991 #ifdef QPIPE_SECURE 1992 bool QPipe::create(bool secure) 1993 #else 1994 bool QPipe::create() 1995 #endif 1996 { 1997 reset(); 1998 1999 #ifdef Q_OS_WIN 2000 SECURITY_ATTRIBUTES secAttr; 2001 memset(&secAttr, 0, sizeof secAttr); 2002 secAttr.nLength = sizeof secAttr; 2003 secAttr.bInheritHandle = false; 2004 2005 HANDLE r, w; 2006 if (!CreatePipe(&r, &w, &secAttr, 0)) 2007 return false; 2008 i.take(r, QPipeDevice::Read); 2009 o.take(w, QPipeDevice::Write); 2010 #endif 2011 2012 #ifdef Q_OS_UNIX 2013 int p[2]; 2014 if (pipe(p) == -1) 2015 return false; 2016 if (!pipe_set_inheritable(p[0], false, nullptr) || !pipe_set_inheritable(p[1], false, nullptr)) { 2017 close(p[0]); 2018 close(p[1]); 2019 return false; 2020 } 2021 i.take(p[0], QPipeDevice::Read); 2022 o.take(p[1], QPipeDevice::Write); 2023 #endif 2024 2025 #ifdef QPIPE_SECURE 2026 i.setSecurityEnabled(secure); 2027 o.setSecurityEnabled(secure); 2028 #endif 2029 2030 return true; 2031 } 2032 2033 } 2034 2035 #include "qpipe.moc"