diff --git a/lib/tcprelay.cpp b/lib/tcprelay.cpp index 515969d..2c7b1dd 100644 --- a/lib/tcprelay.cpp +++ b/lib/tcprelay.cpp @@ -77,11 +77,18 @@ TcpRelay::TcpRelay(QTcpSocket *localSocket, timer, static_cast (&QTimer::start)); connect(remote, &QTcpSocket::bytesWritten, this, &TcpRelay::bytesSend); - local->setReadBufferSize(RecvSize); + // To make sure datagram doesn't exceed remote server's maximum, we can + // limit how many bytes we take from local socket at a time. This is due + // the overhead introduced by OTA. + quint64 localRecvSize = RemoteRecvSize; + if (auth && isLocal) { + localRecvSize -= (Cipher::AUTH_LEN + 2); + } + local->setReadBufferSize(localRecvSize); local->setSocketOption(QAbstractSocket::LowDelayOption, 1); local->setSocketOption(QAbstractSocket::KeepAliveOption, 1); - remote->setReadBufferSize(RecvSize); + remote->setReadBufferSize(RemoteRecvSize); remote->setSocketOption(QAbstractSocket::LowDelayOption, 1); remote->setSocketOption(QAbstractSocket::KeepAliveOption, 1); } diff --git a/lib/tcprelay.h b/lib/tcprelay.h index a270455..66b5841 100644 --- a/lib/tcprelay.h +++ b/lib/tcprelay.h @@ -64,7 +64,7 @@ class QSS_EXPORT TcpRelay : public QObject void finished(); private: - static const qint64 RecvSize = 65536; + static const qint64 RemoteRecvSize = 65536; STAGE stage; Address remoteAddress; diff --git a/lib/udprelay.cpp b/lib/udprelay.cpp index ea6bb21..f02fc3e 100644 --- a/lib/udprelay.cpp +++ b/lib/udprelay.cpp @@ -40,7 +40,14 @@ UdpRelay::UdpRelay(const EncryptorPrivate &ep, { encryptor = new Encryptor(ep, this); - listenSocket.setReadBufferSize(RecvSize); + // To make sure datagram doesn't exceed remote server's maximum, we can + // limit how many bytes we take from local socket at a time. This is due + // the overhead introduced by OTA. + quint64 localRecvSize = RemoteRecvSize; + if (auth && isLocal) { + localRecvSize -= (Cipher::AUTH_LEN + 2); + } + listenSocket.setReadBufferSize(localRecvSize); listenSocket.setSocketOption(QAbstractSocket::LowDelayOption, 1); connect(&listenSocket, &QUdpSocket::stateChanged, @@ -104,7 +111,7 @@ void UdpRelay::onListenStateChanged(QAbstractSocket::SocketState s) void UdpRelay::onServerUdpSocketReadyRead() { - if (listenSocket.pendingDatagramSize() > RecvSize) { + if (listenSocket.pendingDatagramSize() > RemoteRecvSize) { emit info("[UDP] Datagram is too large. discarded."); return; } @@ -114,7 +121,7 @@ void UdpRelay::onServerUdpSocketReadyRead() QHostAddress r_addr; quint16 r_port; qint64 readSize = listenSocket.readDatagram(data.data(), - RecvSize, + RemoteRecvSize, &r_addr, &r_port); emit bytesRead(readSize); @@ -152,7 +159,7 @@ void UdpRelay::onServerUdpSocketReadyRead() QString dbg; if (!client) { client = new QUdpSocket(this); - client->setReadBufferSize(RecvSize); + client->setReadBufferSize(RemoteRecvSize); client->setSocketOption(QAbstractSocket::LowDelayOption, 1); cache.insert(remoteAddr, client); connect(client, &QUdpSocket::readyRead, @@ -210,7 +217,7 @@ void UdpRelay::onClientUdpSocketReadyRead() return; } - if (sock->pendingDatagramSize() > RecvSize) { + if (sock->pendingDatagramSize() > RemoteRecvSize) { emit info("[UDP] Datagram is too large. Discarded."); return; } @@ -219,7 +226,7 @@ void UdpRelay::onClientUdpSocketReadyRead() data.resize(sock->pendingDatagramSize()); QHostAddress r_addr; quint16 r_port; - sock->readDatagram(data.data(), RecvSize, &r_addr, &r_port); + sock->readDatagram(data.data(), RemoteRecvSize, &r_addr, &r_port); QByteArray response; if (isLocal) { diff --git a/lib/udprelay.h b/lib/udprelay.h index df8d4ca..5fa0243 100644 --- a/lib/udprelay.h +++ b/lib/udprelay.h @@ -65,7 +65,7 @@ public slots: private: //64KB, same as shadowsocks-python (udprelay) - static const qint64 RecvSize = 65536; + static const qint64 RemoteRecvSize = 65536; const Address &serverAddress; const bool &isLocal;