File indexing completed on 2024-05-12 04:58:51

0001 /**
0002  * SPDX-FileCopyrightText: 2019 Matthijs Tijink <matthijstijink@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "multiplexchannel.h"
0008 #include "core_debug.h"
0009 #include "multiplexchannelstate.h"
0010 
0011 MultiplexChannel::MultiplexChannel(QSharedPointer<MultiplexChannelState> state)
0012     : state{state}
0013 {
0014     QIODevice::open(QIODevice::ReadWrite);
0015 
0016     connect(this, &QIODevice::aboutToClose, state.data(), &MultiplexChannelState::requestClose);
0017     connect(state.data(), &MultiplexChannelState::readyRead, this, &QIODevice::readyRead);
0018     connect(state.data(), &MultiplexChannelState::bytesWritten, this, &QIODevice::bytesWritten);
0019     connect(state.data(), &MultiplexChannelState::disconnected, this, &MultiplexChannel::disconnect);
0020 }
0021 
0022 MultiplexChannel::~MultiplexChannel()
0023 {
0024 }
0025 
0026 bool MultiplexChannel::atEnd() const
0027 {
0028     return !isOpen() || (!state->connected && state->read_buffer.isEmpty());
0029 }
0030 
0031 void MultiplexChannel::disconnect()
0032 {
0033     state->connected = false;
0034     setOpenMode(QIODevice::ReadOnly);
0035     Q_EMIT state->readyRead();
0036     Q_EMIT state->requestClose();
0037     if (state->read_buffer.isEmpty()) {
0038         close();
0039     }
0040 }
0041 
0042 qint64 MultiplexChannel::bytesAvailable() const
0043 {
0044     return state->read_buffer.size() + QIODevice::bytesAvailable();
0045 }
0046 
0047 qint64 MultiplexChannel::bytesToWrite() const
0048 {
0049     return state->write_buffer.size() + QIODevice::bytesToWrite();
0050 }
0051 
0052 qint64 MultiplexChannel::readData(char *data, qint64 maxlen)
0053 {
0054     if (maxlen <= state->read_buffer.size()) {
0055         for (int i = 0; i < maxlen; ++i) {
0056             data[i] = state->read_buffer[i];
0057         }
0058         state->read_buffer.remove(0, maxlen);
0059         Q_EMIT state->readAvailable();
0060         if (!state->connected && state->read_buffer.isEmpty()) {
0061             close();
0062         }
0063         return maxlen;
0064     } else if (state->read_buffer.size() > 0) {
0065         auto num_to_read = state->read_buffer.size();
0066         for (int i = 0; i < num_to_read; ++i) {
0067             data[i] = state->read_buffer[i];
0068         }
0069         state->read_buffer.remove(0, num_to_read);
0070         Q_EMIT state->readAvailable();
0071         if (!state->connected && state->read_buffer.isEmpty()) {
0072             close();
0073         }
0074         return num_to_read;
0075     } else if (isOpen() && state->connected) {
0076         if (state->requestedReadAmount < BUFFER_SIZE) {
0077             Q_EMIT state->readAvailable();
0078         }
0079         return 0;
0080     } else {
0081         close();
0082         return -1;
0083     }
0084 }
0085 
0086 qint64 MultiplexChannel::writeData(const char *data, qint64 len)
0087 {
0088     state->write_buffer.append(data, len);
0089     Q_EMIT state->writeAvailable();
0090     return len;
0091 }
0092 
0093 bool MultiplexChannel::canReadLine() const
0094 {
0095     return isReadable() && (QIODevice::canReadLine() || state->read_buffer.contains('\n'));
0096 }
0097 
0098 bool MultiplexChannel::isSequential() const
0099 {
0100     return true;
0101 }
0102 
0103 #include "moc_multiplexchannel.cpp"