File indexing completed on 2025-01-05 04:37:33

0001 /*
0002     SPDX-FileCopyrightText: 2010 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "outputqueue.h"
0008 #include <QSet>
0009 #include <net/socket.h>
0010 #include <util/log.h>
0011 
0012 using namespace bt;
0013 
0014 namespace utp
0015 {
0016 OutputQueue::OutputQueue()
0017     : mutex()
0018 {
0019 }
0020 
0021 OutputQueue::~OutputQueue()
0022 {
0023 }
0024 
0025 int OutputQueue::add(const PacketBuffer &packet, Connection::WPtr conn)
0026 {
0027     QMutexLocker lock(&mutex);
0028     queue.push_back(Entry(packet, conn));
0029     return queue.size();
0030 }
0031 
0032 void OutputQueue::send(net::ServerSocket *sock)
0033 {
0034     QList<Connection::WPtr> to_close;
0035     QMutexLocker lock(&mutex);
0036     try {
0037         // Keep sending until the output queue is empty or the socket
0038         // can't handle the data anymore
0039         while (!queue.empty()) {
0040             Entry &packet = queue.front();
0041             Connection::Ptr conn = packet.conn.toStrongRef();
0042             if (!conn) {
0043                 queue.pop_front();
0044                 continue;
0045             }
0046 
0047             int ret = sock->sendTo(packet.data.data(), packet.data.bufferSize(), conn->remoteAddress());
0048             if (ret == net::SEND_WOULD_BLOCK)
0049                 break;
0050             else if (ret == net::SEND_FAILURE) {
0051                 // Kill the connection of this packet
0052                 to_close.append(packet.conn);
0053                 queue.pop_front();
0054             } else
0055                 queue.pop_front();
0056         }
0057     } catch (Connection::TransmissionError &err) {
0058         Out(SYS_UTP | LOG_NOTICE) << "UTP: " << err.location << endl;
0059     }
0060     sock->setWriteNotificationsEnabled(!queue.empty());
0061     lock.unlock(); // unlock, so we can't get deadlocked in any subsequent close calls
0062 
0063     for (const utp::Connection::WPtr &conn : std::as_const(to_close)) {
0064         Connection::Ptr c = conn.toStrongRef();
0065         if (c)
0066             c->close();
0067     }
0068 }
0069 
0070 }