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

0001 /*
0002     SPDX-FileCopyrightText: 2011 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "trafficshapedsocket.h"
0008 
0009 #include "socket.h"
0010 #include "speed.h"
0011 #include <QStringList>
0012 #include <util/functions.h>
0013 
0014 const bt::Uint32 OUTPUT_BUFFER_SIZE = 16393;
0015 
0016 using namespace bt;
0017 
0018 namespace net
0019 {
0020 TrafficShapedSocket::TrafficShapedSocket(SocketDevice *sock)
0021     : rdr(nullptr)
0022     , up_gid(0)
0023     , down_gid(0)
0024     , sock(sock)
0025     , mutex()
0026 {
0027     down_speed = new Speed();
0028     up_speed = new Speed();
0029 }
0030 
0031 TrafficShapedSocket::TrafficShapedSocket(int fd, int ip_version)
0032     : rdr(nullptr)
0033     , up_gid(0)
0034     , down_gid(0)
0035     , mutex()
0036 {
0037     sock = new Socket(fd, ip_version);
0038     down_speed = new Speed();
0039     up_speed = new Speed();
0040 }
0041 
0042 TrafficShapedSocket::TrafficShapedSocket(bool tcp, int ip_version)
0043     : rdr(nullptr)
0044     , up_gid(0)
0045     , down_gid(0)
0046     , mutex()
0047 {
0048     Socket *socket = new Socket(tcp, ip_version);
0049 
0050     QString iface = NetworkInterface();
0051     QStringList ips = NetworkInterfaceIPAddresses(iface);
0052     if (ips.size() > 0)
0053         socket->bind(ips.front(), 0, false);
0054 
0055     sock = socket;
0056     down_speed = new Speed();
0057     up_speed = new Speed();
0058 }
0059 
0060 TrafficShapedSocket::~TrafficShapedSocket()
0061 {
0062     delete up_speed;
0063     delete down_speed;
0064     delete sock;
0065 }
0066 
0067 void TrafficShapedSocket::setGroupID(Uint32 gid, bool upload)
0068 {
0069     if (upload)
0070         up_gid = gid;
0071     else
0072         down_gid = gid;
0073 }
0074 
0075 int TrafficShapedSocket::getDownloadRate() const
0076 {
0077     // getRate is atomic
0078     return down_speed->getRate();
0079 }
0080 
0081 int TrafficShapedSocket::getUploadRate() const
0082 {
0083     // getRate is atomic
0084     return up_speed->getRate();
0085 }
0086 
0087 void TrafficShapedSocket::updateSpeeds(bt::TimeStamp now)
0088 {
0089     mutex.lock();
0090     up_speed->update(now);
0091     down_speed->update(now);
0092     mutex.unlock();
0093 }
0094 
0095 static bt::Uint8 input_buffer[OUTPUT_BUFFER_SIZE];
0096 
0097 Uint32 TrafficShapedSocket::read(bt::Uint32 max_bytes_to_read, bt::TimeStamp now)
0098 {
0099     Uint32 br = 0;
0100     bool no_limit = (max_bytes_to_read == 0);
0101     Uint32 ba = sock->bytesAvailable();
0102     if (ba == 0) {
0103         // For some strange reason, sometimes bytesAvailable returns 0, while there are
0104         // bytes to read, so give ba the maximum value it can be
0105         ba = max_bytes_to_read > 0 ? max_bytes_to_read : OUTPUT_BUFFER_SIZE;
0106     }
0107 
0108     while ((br < max_bytes_to_read || no_limit) && ba > 0) {
0109         Uint32 tr = ba;
0110         if (tr > OUTPUT_BUFFER_SIZE)
0111             tr = OUTPUT_BUFFER_SIZE;
0112         if (!no_limit && tr + br > max_bytes_to_read)
0113             tr = max_bytes_to_read - br;
0114 
0115         int ret = sock->recv(input_buffer, tr);
0116         if (ret > 0) {
0117             mutex.lock();
0118             down_speed->onData(ret, now);
0119             mutex.unlock();
0120             if (rdr) {
0121                 postProcess(input_buffer, ret);
0122                 rdr->onDataReady(input_buffer, ret);
0123             }
0124             br += ret;
0125             ba -= ret;
0126         } else if (ret < 0) {
0127             return br;
0128         } else {
0129             sock->close();
0130             return br;
0131         }
0132     }
0133     return br;
0134 }
0135 
0136 void TrafficShapedSocket::postProcess(Uint8 *data, Uint32 size)
0137 {
0138     Q_UNUSED(data);
0139     Q_UNUSED(size);
0140 }
0141 }