File indexing completed on 2025-01-05 04:37:34
0001 /* 0002 SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "utpsocket.h" 0008 #include "connection.h" 0009 #include "utpserver.h" 0010 #include <torrent/globals.h> 0011 0012 namespace utp 0013 { 0014 UTPSocket::UTPSocket() 0015 : net::SocketDevice(bt::UTP) 0016 , blocking(true) 0017 , polled_for_reading(false) 0018 , polled_for_writing(false) 0019 { 0020 } 0021 0022 UTPSocket::UTPSocket(Connection::WPtr conn) 0023 : net::SocketDevice(bt::UTP) 0024 , conn(conn) 0025 , blocking(true) 0026 , polled_for_reading(false) 0027 , polled_for_writing(false) 0028 { 0029 Connection::Ptr ptr = conn.toStrongRef(); 0030 if (ptr) { 0031 setRemoteAddress(ptr->remoteAddress()); 0032 ptr->setBlocking(blocking); 0033 m_state = CONNECTED; 0034 } 0035 } 0036 0037 UTPSocket::~UTPSocket() 0038 { 0039 close(); 0040 reset(); 0041 } 0042 0043 bt::Uint32 UTPSocket::bytesAvailable() const 0044 { 0045 Connection::Ptr ptr = conn.toStrongRef(); 0046 if (ptr) 0047 return ptr->bytesAvailable(); 0048 else 0049 return 0; 0050 } 0051 0052 void UTPSocket::close() 0053 { 0054 Connection::Ptr ptr = conn.toStrongRef(); 0055 if (ptr) { 0056 try { 0057 ptr->close(); 0058 } catch (Connection::TransmissionError) { 0059 reset(); 0060 } 0061 } 0062 } 0063 0064 bool UTPSocket::connectSuccesFull() 0065 { 0066 Connection::Ptr ptr = conn.toStrongRef(); 0067 if (ptr && ptr->connectionState() == CS_CONNECTED) { 0068 setRemoteAddress(ptr->remoteAddress()); 0069 m_state = CONNECTED; 0070 return true; 0071 } else 0072 return false; 0073 } 0074 0075 bool UTPSocket::connectTo(const net::Address &addr) 0076 { 0077 if (!bt::Globals::instance().isUTPEnabled()) 0078 return false; 0079 0080 UTPServer &srv = bt::Globals::instance().getUTPServer(); 0081 reset(); 0082 0083 conn = srv.connectTo(addr); 0084 Connection::Ptr ptr = conn.toStrongRef(); 0085 if (!ptr) 0086 return false; 0087 0088 m_state = CONNECTING; 0089 ptr->setBlocking(blocking); 0090 if (blocking) { 0091 bool ret = ptr->waitUntilConnected(); 0092 if (ret) 0093 m_state = CONNECTED; 0094 0095 return ret; 0096 } 0097 0098 return ptr->connectionState() == CS_CONNECTED; 0099 } 0100 0101 int UTPSocket::fd() const 0102 { 0103 return -1; 0104 } 0105 0106 const net::Address &UTPSocket::getPeerName() const 0107 { 0108 Connection::Ptr ptr = conn.toStrongRef(); 0109 if (remote_addr_override) 0110 return addr; 0111 else if (ptr) 0112 return ptr->remoteAddress(); 0113 else { 0114 static net::Address null; 0115 return null; 0116 } 0117 } 0118 0119 net::Address UTPSocket::getSockName() const 0120 { 0121 return net::Address(); 0122 } 0123 0124 bool UTPSocket::ok() const 0125 { 0126 Connection::Ptr ptr = conn.toStrongRef(); 0127 return ptr && ptr->connectionState() != CS_CLOSED; 0128 } 0129 0130 int UTPSocket::recv(bt::Uint8 *buf, int max_len) 0131 { 0132 Connection::Ptr ptr = conn.toStrongRef(); 0133 if (!ptr || ptr->connectionState() == CS_CLOSED) 0134 return 0; 0135 0136 try { 0137 if (ptr->bytesAvailable() == 0) { 0138 if (blocking) { 0139 if (ptr->waitForData()) 0140 return ptr->recv(buf, max_len); 0141 else 0142 return 0; // connection should be closed now 0143 } else 0144 return -1; // No data ready and not blocking so return -1 0145 } else 0146 return ptr->recv(buf, max_len); 0147 } catch (Connection::TransmissionError &err) { 0148 close(); 0149 return -1; 0150 } 0151 } 0152 0153 void UTPSocket::reset() 0154 { 0155 conn.clear(); 0156 } 0157 0158 int UTPSocket::send(const bt::Uint8 *buf, int len) 0159 { 0160 Connection::Ptr ptr = conn.toStrongRef(); 0161 if (!ptr) 0162 return -1; 0163 0164 try { 0165 return ptr->send(buf, len); 0166 } catch (Connection::TransmissionError &err) { 0167 close(); 0168 return -1; 0169 } 0170 } 0171 0172 void UTPSocket::setBlocking(bool on) 0173 { 0174 blocking = on; 0175 Connection::Ptr ptr = conn.toStrongRef(); 0176 if (ptr) 0177 ptr->setBlocking(on); 0178 } 0179 0180 bool UTPSocket::setTOS(unsigned char type_of_service) 0181 { 0182 Q_UNUSED(type_of_service); 0183 return true; 0184 } 0185 0186 void UTPSocket::prepare(net::Poll *p, net::Poll::Mode mode) 0187 { 0188 Connection::Ptr ptr = conn.toStrongRef(); 0189 if (ptr && ptr->connectionState() != CS_CLOSED) { 0190 UTPServer &srv = bt::Globals::instance().getUTPServer(); 0191 srv.preparePolling(p, mode, ptr); 0192 if (mode == net::Poll::OUTPUT) 0193 polled_for_writing = true; 0194 else 0195 polled_for_reading = true; 0196 } 0197 } 0198 0199 bool UTPSocket::ready(const net::Poll *p, net::Poll::Mode mode) const 0200 { 0201 Q_UNUSED(p); 0202 Connection::Ptr ptr = conn.toStrongRef(); 0203 if (!ptr) 0204 return false; 0205 0206 if (mode == net::Poll::OUTPUT) { 0207 if (polled_for_writing) { 0208 polled_for_writing = false; 0209 return ptr->isWriteable(); 0210 } 0211 } else { 0212 if (polled_for_reading) { 0213 polled_for_reading = false; 0214 return bytesAvailable() > 0 || ptr->connectionState() == CS_CLOSED; 0215 } 0216 } 0217 0218 return false; 0219 } 0220 0221 }