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 }