File indexing completed on 2025-01-05 04:37:20
0001 /* 0002 SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "socket.h" 0008 #include <QtGlobal> 0009 0010 #include <arpa/inet.h> 0011 #include <errno.h> 0012 #include <netdb.h> 0013 #include <netinet/in.h> 0014 #include <netinet/tcp.h> 0015 #include <string.h> 0016 #include <sys/ioctl.h> 0017 #include <sys/socket.h> 0018 #include <sys/types.h> 0019 #include <unistd.h> 0020 0021 #if defined(Q_OS_LINUX) && !defined(__FreeBSD_kernel__) 0022 #include <asm/ioctls.h> 0023 #endif 0024 0025 #ifdef Q_OS_SOLARIS 0026 #include <sys/filio.h> 0027 #endif 0028 0029 #ifndef MSG_NOSIGNAL 0030 #define MSG_NOSIGNAL 0 0031 #endif 0032 0033 #include <fcntl.h> 0034 0035 #include <util/log.h> 0036 0037 #ifdef Q_WS_WIN 0038 #include <util/win32.h> 0039 #define SHUT_RDWR SD_BOTH 0040 #undef errno 0041 #define errno WSAGetLastError() 0042 #endif 0043 using namespace bt; 0044 0045 namespace net 0046 { 0047 Socket::Socket(int fd, int ip_version) 0048 : SocketDevice(bt::TCP) 0049 , m_fd(fd) 0050 , m_ip_version(ip_version) 0051 , r_poll_index(-1) 0052 , w_poll_index(-1) 0053 { 0054 // check if the IP version is 4 or 6 0055 if (m_ip_version != 4 && m_ip_version != 6) 0056 m_ip_version = 4; 0057 0058 #if defined(Q_OS_MACX) || defined(Q_OS_DARWIN) 0059 int val = 1; 0060 if (setsockopt(m_fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(int)) < 0) { 0061 Out(SYS_CON | LOG_NOTICE) << QStringLiteral("Failed to set the NOSIGPIPE option : %1").arg(QString::fromUtf8(strerror(errno))) << endl; 0062 } 0063 #endif 0064 cacheAddress(); 0065 } 0066 0067 Socket::Socket(bool tcp, int ip_version) 0068 : SocketDevice(bt::TCP) 0069 , m_fd(-1) 0070 , m_ip_version(ip_version) 0071 , r_poll_index(-1) 0072 , w_poll_index(-1) 0073 { 0074 // check if the IP version is 4 or 6 0075 if (m_ip_version != 4 && m_ip_version != 6) 0076 m_ip_version = 4; 0077 0078 int fd = socket(m_ip_version == 4 ? PF_INET : PF_INET6, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); 0079 if (fd < 0) 0080 Out(SYS_GEN | LOG_IMPORTANT) << QStringLiteral("Cannot create socket : %1").arg(QString::fromUtf8(strerror(errno))) << endl; 0081 m_fd = fd; 0082 0083 #if defined(Q_OS_MACX) || defined(Q_OS_DARWIN) 0084 int val = 1; 0085 if (setsockopt(m_fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(int)) < 0) { 0086 Out(SYS_CON | LOG_NOTICE) << QStringLiteral("Failed to set the NOSIGPIPE option : %1").arg(QString::fromUtf8(strerror(errno))) << endl; 0087 } 0088 #endif 0089 } 0090 0091 Socket::~Socket() 0092 { 0093 if (m_fd >= 0) { 0094 shutdown(m_fd, SHUT_RDWR); 0095 #ifdef Q_WS_WIN 0096 ::closesocket(m_fd); 0097 #else 0098 ::close(m_fd); 0099 #endif 0100 } 0101 } 0102 0103 void Socket::reset() 0104 { 0105 close(); 0106 int fd = socket(m_ip_version == 4 ? PF_INET : PF_INET6, SOCK_STREAM, 0); 0107 if (fd < 0) 0108 Out(SYS_GEN | LOG_IMPORTANT) << QStringLiteral("Cannot create socket : %1").arg(QString::fromUtf8(strerror(errno))) << endl; 0109 m_fd = fd; 0110 0111 #if defined(Q_OS_MACX) || defined(Q_OS_DARWIN) 0112 int val = 1; 0113 if (setsockopt(m_fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(int)) < 0) { 0114 Out(SYS_CON | LOG_NOTICE) << QString("Failed to set the NOSIGPIPE option : %1").arg(QString::fromUtf8(strerror(errno))) << endl; 0115 } 0116 #endif 0117 m_state = IDLE; 0118 } 0119 0120 void Socket::close() 0121 { 0122 if (m_fd >= 0) { 0123 shutdown(m_fd, SHUT_RDWR); 0124 #ifdef Q_WS_WIN 0125 ::closesocket(m_fd); 0126 #else 0127 ::close(m_fd); 0128 #endif 0129 m_fd = -1; 0130 m_state = CLOSED; 0131 } 0132 } 0133 0134 void Socket::setBlocking(bool on) 0135 { 0136 #ifndef Q_WS_WIN 0137 int flag = fcntl(m_fd, F_GETFL, 0); 0138 if (!on) 0139 fcntl(m_fd, F_SETFL, flag | O_NONBLOCK); 0140 else 0141 fcntl(m_fd, F_SETFL, flag & ~O_NONBLOCK); 0142 #else 0143 u_long b = on ? 1 : 0; 0144 ioctlsocket(m_fd, FIONBIO, &b); 0145 #endif 0146 } 0147 0148 bool Socket::connectTo(const Address &a) 0149 { 0150 int len = 0; 0151 struct sockaddr_storage ss; 0152 a.toSocketAddress(&ss, len); 0153 if (::connect(m_fd, (struct sockaddr *)&ss, len) < 0) { 0154 #ifndef Q_WS_WIN 0155 if (errno == EINPROGRESS) 0156 #else 0157 if (errno == WSAEINVAL || errno == WSAEALREADY || errno == WSAEWOULDBLOCK) 0158 #endif 0159 { 0160 // Out(SYS_CON|LOG_DEBUG) << "Socket is connecting" << endl; 0161 m_state = CONNECTING; 0162 return false; 0163 } else { 0164 Out(SYS_CON | LOG_NOTICE) << QStringLiteral("Cannot connect to host %1 : %2").arg(a.toString()).arg(QString::fromUtf8(strerror(errno))) << endl; 0165 return false; 0166 } 0167 } 0168 m_state = CONNECTED; 0169 cacheAddress(); 0170 return true; 0171 } 0172 0173 bool Socket::bind(const QString &ip, Uint16 port, bool also_listen) 0174 { 0175 return bind(net::Address(ip, port), also_listen); 0176 } 0177 0178 bool Socket::bind(const net::Address &addr, bool also_listen) 0179 { 0180 int val = 1; 0181 #ifndef Q_WS_WIN 0182 if (setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)) < 0) 0183 #else 0184 if (setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(int)) < 0) 0185 #endif 0186 { 0187 Out(SYS_CON | LOG_NOTICE) << QStringLiteral("Failed to set the reuseaddr option : %1").arg(QString::fromUtf8(strerror(errno))) << endl; 0188 } 0189 0190 int len = 0; 0191 struct sockaddr_storage ss; 0192 addr.toSocketAddress(&ss, len); 0193 if (::bind(m_fd, (struct sockaddr *)&ss, len) != 0) { 0194 Out(SYS_CON | LOG_IMPORTANT) 0195 << QStringLiteral("Cannot bind to port %1:%2 : %3").arg(addr.toString()).arg(addr.port()).arg(QString::fromUtf8(strerror(errno))) << endl; 0196 return false; 0197 } 0198 0199 if (also_listen && listen(m_fd, SOMAXCONN) < 0) { 0200 Out(SYS_CON | LOG_IMPORTANT) 0201 << QStringLiteral("Cannot listen to port %1:%2 : %3").arg(addr.toString()).arg(addr.port()).arg(QString::fromUtf8(strerror(errno))) << endl; 0202 return false; 0203 } 0204 0205 m_state = BOUND; 0206 return true; 0207 } 0208 0209 int Socket::send(const bt::Uint8 *buf, int len) 0210 { 0211 #ifndef Q_WS_WIN 0212 int ret = ::send(m_fd, buf, len, MSG_NOSIGNAL); 0213 #else 0214 int ret = ::send(m_fd, (char *)buf, len, MSG_NOSIGNAL); 0215 #endif 0216 if (ret < 0) { 0217 if (errno != EAGAIN && errno != EWOULDBLOCK) { 0218 // Out(SYS_CON|LOG_DEBUG) << "Send error : " << QString::fromUtf8(strerror(errno)) << endl; 0219 close(); 0220 } 0221 return 0; 0222 } 0223 return ret; 0224 } 0225 0226 int Socket::recv(bt::Uint8 *buf, int max_len) 0227 { 0228 #ifndef Q_WS_WIN 0229 int ret = ::recv(m_fd, buf, max_len, 0); 0230 #else 0231 int ret = ::recv(m_fd, (char *)buf, max_len, 0); 0232 #endif 0233 if (ret < 0) { 0234 if (errno != EAGAIN && errno != EWOULDBLOCK) { 0235 // Out(SYS_CON|LOG_DEBUG) << "Receive error : " << QString::fromUtf8(strerror(errno)) << endl; 0236 close(); 0237 return 0; 0238 } 0239 0240 return ret; 0241 } else if (ret == 0) { 0242 // connection closed 0243 close(); 0244 return 0; 0245 } 0246 return ret; 0247 } 0248 0249 int Socket::sendTo(const bt::Uint8 *buf, int len, const Address &a) 0250 { 0251 int alen = 0; 0252 struct sockaddr_storage ss; 0253 a.toSocketAddress(&ss, alen); 0254 int ret = ::sendto(m_fd, (char *)buf, len, 0, (struct sockaddr *)&ss, alen); 0255 if (ret < 0) { 0256 if (errno == EAGAIN || errno == EWOULDBLOCK) 0257 return SEND_WOULD_BLOCK; 0258 0259 Out(SYS_CON | LOG_DEBUG) << "Send error : " << QString::fromUtf8(strerror(errno)) << endl; 0260 return SEND_FAILURE; 0261 } 0262 0263 return ret; 0264 } 0265 0266 int Socket::recvFrom(bt::Uint8 *buf, int max_len, Address &a) 0267 { 0268 struct sockaddr_storage ss; 0269 socklen_t slen = sizeof(ss); 0270 #ifndef Q_WS_WIN 0271 int ret = ::recvfrom(m_fd, buf, max_len, 0, (struct sockaddr *)&ss, &slen); 0272 #else 0273 int ret = ::recvfrom(m_fd, (char *)buf, max_len, 0, (struct sockaddr *)&ss, &slen); 0274 #endif 0275 if (ret < 0) { 0276 Out(SYS_CON | LOG_DEBUG) << "Receive error : " << QString::fromUtf8(strerror(errno)) << endl; 0277 return 0; 0278 } 0279 a = ss; 0280 return ret; 0281 } 0282 0283 int Socket::accept(Address &a) 0284 { 0285 struct sockaddr_storage ss; 0286 socklen_t slen = sizeof(ss); 0287 int sfd = ::accept(m_fd, (struct sockaddr *)&ss, &slen); 0288 0289 if (sfd < 0) { 0290 Out(SYS_CON | LOG_DEBUG) << "Accept error : " << QString::fromUtf8(strerror(errno)) << endl; 0291 return -1; 0292 } 0293 a = net::Address(&ss); 0294 0295 Out(SYS_CON | LOG_DEBUG) << "Accepted connection from " << a.toString() << endl; 0296 return sfd; 0297 } 0298 0299 bool Socket::setTOS(unsigned char type_of_service) 0300 { 0301 // If type of service is 0, do nothing 0302 if (type_of_service == 0) 0303 return true; 0304 0305 if (m_ip_version == 4) { 0306 #if defined(Q_OS_MACX) || defined(Q_OS_DARWIN) || defined(Q_OS_NETBSD) || defined(Q_OS_BSD4) 0307 unsigned int c = type_of_service; 0308 #else 0309 unsigned char c = type_of_service; 0310 #endif 0311 #ifndef Q_WS_WIN 0312 if (setsockopt(m_fd, IPPROTO_IP, IP_TOS, &c, sizeof(c)) < 0) 0313 #else 0314 if (setsockopt(m_fd, IPPROTO_IP, IP_TOS, (char *)&c, sizeof(c)) < 0) 0315 #endif 0316 { 0317 Out(SYS_CON | LOG_NOTICE) << QStringLiteral("Failed to set TOS to %1 : %2").arg((int)type_of_service).arg(QString::fromUtf8(strerror(errno))) 0318 << endl; 0319 return false; 0320 } 0321 } else { 0322 #if defined(IPV6_TCLASS) 0323 int c = type_of_service; 0324 if (setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &c, sizeof(c)) < 0) { 0325 Out(SYS_CON | LOG_NOTICE) 0326 << QStringLiteral("Failed to set traffic class to %1 : %2").arg((int)type_of_service).arg(QString::fromUtf8(strerror(errno))) << endl; 0327 return false; 0328 } 0329 #endif 0330 } 0331 0332 return true; 0333 } 0334 0335 Uint32 Socket::bytesAvailable() const 0336 { 0337 int ret = 0; 0338 #ifndef Q_WS_WIN 0339 if (ioctl(m_fd, FIONREAD, &ret) < 0) 0340 #else 0341 if (ioctlsocket(m_fd, FIONREAD, (u_long *)&ret) < 0) 0342 #endif 0343 return 0; 0344 0345 return ret; 0346 } 0347 0348 bool Socket::connectSuccesFull() 0349 { 0350 if (m_state != CONNECTING) 0351 return false; 0352 0353 int err = 0; 0354 socklen_t len = sizeof(int); 0355 #ifndef Q_WS_WIN 0356 if (getsockopt(m_fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) 0357 #else 0358 if (getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char *)&err, &len) < 0) 0359 #endif 0360 return false; 0361 0362 if (err == 0) { 0363 m_state = CONNECTED; 0364 cacheAddress(); 0365 } 0366 0367 return err == 0; 0368 } 0369 0370 void Socket::cacheAddress() 0371 { 0372 struct sockaddr_storage ss; /* Where the peer adr goes. */ 0373 socklen_t sslen = sizeof(ss); 0374 0375 if (getpeername(m_fd, (struct sockaddr *)&ss, &sslen) == 0) { 0376 addr = net::Address(&ss); 0377 } 0378 } 0379 0380 Address Socket::getSockName() const 0381 { 0382 struct sockaddr_storage ss; /* Where the peer adr goes. */ 0383 socklen_t sslen = sizeof(ss); 0384 0385 if (getsockname(m_fd, (struct sockaddr *)&ss, &sslen) == 0) 0386 return net::Address(&ss); 0387 else 0388 return Address(); 0389 } 0390 0391 int Socket::take() 0392 { 0393 int ret = m_fd; 0394 m_fd = -1; 0395 return ret; 0396 } 0397 0398 void Socket::prepare(Poll *p, Poll::Mode mode) 0399 { 0400 if (m_fd >= 0) { 0401 if (mode == Poll::OUTPUT) 0402 w_poll_index = p->add(m_fd, mode); 0403 else 0404 r_poll_index = p->add(m_fd, mode); 0405 } 0406 } 0407 0408 bool Socket::ready(const Poll *p, Poll::Mode mode) const 0409 { 0410 return p->ready(mode == Poll::OUTPUT ? w_poll_index : r_poll_index, mode); 0411 } 0412 0413 }