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 }