void Win32Network::attachUDPSocket(SOCKET s,const char* netInterface,int port){ sockaddr_in address; setSocketOption(s,ESocketOption::ESO_NONBLOCK,true); setSocketOption(s,ESocketOption::ESO_SOCKOPT_BROADCAST,true); if(!netInterface || !netInterface[0] || !strcmp(netInterface,"localhost")){ //use any available interface address.sin_addr.s_addr=htonl(INADDR_ANY); }else{ NetAddress addr; inner_getHostAddress(netInterface,addr); toSockaddr(addr,(sockaddr*)&address); } if(!port){ address.sin_port=0; }else{ address.sin_port=htons((short)port); } address.sin_family=AF_INET; int len=sizeof(address); //bind address to the socket if(::bind(s,(sockaddr*)&address,len)==-1){ messages::logMessage(messages::HMSG_BIND,ELL_ERROR); return; } }
/*! Construct the hardware resource UpnpDiscovery with the given \a parent. */ UpnpDiscovery::UpnpDiscovery(QObject *parent) : QUdpSocket(parent) { // bind udp socket and join multicast group m_port = 1900; m_host = QHostAddress("239.255.255.250"); setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1)); setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1)); if(!bind(QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress)){ qCWarning(dcHardware) << "UPnP discovery could not bind to port" << m_port; return; } if(!joinMulticastGroup(m_host)){ qCWarning(dcHardware) << "UPnP discovery could not join multicast group" << m_host; return; } // network access manager for requesting device information m_networkAccessManager = new QNetworkAccessManager(this); connect(m_networkAccessManager, &QNetworkAccessManager::finished, this, &UpnpDiscovery::replyFinished); connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError))); connect(this, &UpnpDiscovery::readyRead, this, &UpnpDiscovery::readData); qCDebug(dcHardware) << "--> UPnP discovery created successfully."; }
bool ProtocolUDP::init_derived() { int optval = 1; char buf[SOCKADDR_SIZE]; struct sockaddr *sa = (struct sockaddr *)buf; socklen_t sa_len; SocketAddress *addr = NULL; if (!localIface) { HAGGLE_ERR("%s Could not create UDP socket, no local interface\n", getName()); return false; } #if defined(ENABLE_IPv6) addr = localIface->getAddress<IPv6Address>(); #endif if (!addr) addr = localIface->getAddress<IPv4Address>(); if (!addr) { HAGGLE_ERR("%s Could not create UDP socket, no IP address\n", getName()); return false; } sa_len = addr->fillInSockaddr(sa); if (!openSocket(AF_INET, SOCK_DGRAM, 0, true)) { HAGGLE_ERR("%s Could not open UDP socket\n", getName()); return false; } // For application IPC socket we need a large receive buffer. if (!multiplyReceiveBufferSize(2)) { HAGGLE_ERR("%s Could not increase receive buffer size.\n", getName()); } if (!setSocketOption(SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) { closeSocket(); HAGGLE_ERR("%s setsockopt SO_REUSEADDR failed\n", getName()); return false; } if (!setSocketOption(SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval))) { closeSocket(); HAGGLE_ERR("%s setsockopt SO_BROADCAST failed\n", getName()); return false; } if (!bind(sa, sa_len)) { closeSocket(); return false; } return true; }
int TcpSocketImpl::attachFd(SOCKET_FD fd, uint32_t flags) { KUMA_INFOXTRACE("attachFd, fd="<<fd<<", flags="<<flags<<", state="<<getState()); if(getState() != ST_IDLE) { KUMA_ERRXTRACE("attachFd, invalid state, state="<<getState()); return KUMA_ERROR_INVALID_STATE; } flags_ = flags; #ifndef KUMA_HAS_OPENSSL if (SslEnabled()) { KUMA_ERRXTRACE("attachFd, OpenSSL is disabled"); return KUMA_ERROR_UNSUPPORT; } #endif fd_ = fd; setSocketOption(); setState(ST_OPEN); #ifdef KUMA_HAS_OPENSSL if(SslEnabled()) { int ret = startSslHandshake(true); if(ret != KUMA_ERROR_NOERR) { return ret; } } #endif loop_->registerFd(fd_, KUMA_EV_NETWORK, [this] (uint32_t ev) { ioReady(ev); }); registered_ = true; return KUMA_ERROR_NOERR; }
void Socket::setLinger(bool activate, USHORT timeout) { linger ln; ln.l_linger = timeout; ln.l_onoff = activate ? 1 : 0; setSocketOption(SO_LINGER, ln); }
int TcpSocketImpl::attachFd(SOCKET_FD fd, SSL* ssl, uint32_t flags) { KUMA_INFOXTRACE("attachFd, with ssl, fd="<<fd<<", flags="<<flags<<", state="<<getState()); if(getState() != ST_IDLE) { KUMA_ERRXTRACE("attachFd, invalid state, state="<<getState()); return KUMA_ERROR_INVALID_STATE; } fd_ = fd; flags_ = flags; setSocketOption(); setState(ST_OPEN); if(SslEnabled()) { if (ssl) { ssl_handler_ = new SslHandler(); ssl_handler_->attachSsl(ssl); } else { int ret = startSslHandshake(true); if(ret != KUMA_ERROR_NOERR) { return ret; } } } loop_->registerFd(fd_, KUMA_EV_NETWORK, [this] (uint32_t ev) { ioReady(ev); }); registered_ = true; return KUMA_ERROR_NOERR; }
bool CPPTcpServerSocket::listen(short port, int maxConnections){ std::lock_guard<std::mutex> lockR(recvLock), lockS(sendLock); struct sockaddr_in local; memset(&local, 0, sizeof(sockaddr_in)); m_port = port; local.sin_family = AF_INET; local.sin_port = htons(port); local.sin_addr.s_addr = htonl(INADDR_ANY); if (!open()) return false; int on=1; if (!setSocketOption(SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on), false)) return false; // Bind socket to local address if(::bind(m_sock, (struct sockaddr *)&local, sizeof(struct sockaddr_in))==-1) { return false; } // Create queue for client connection requests if(::listen(m_sock, maxConnections)==-1) { return false; } m_port = port; return true; }
void Socket::enableNagleAlgorithm() { // enable nagle's algorithm for TCP if ((*m_Socket).getSockType() == TCP) { int n = 1; setSocketOption(TCP_NODELAY, n, IPPROTO_TCP); } }
CGroupClient::CGroupClient(QObject *parent) : QTcpSocket(parent) { connectionState = Closed; protocolState = Idle; setSocketOption(QAbstractSocket::KeepAliveOption, true); linkSignals(); }
// socket to server // for WinSock 1 SOCKET NetThread::socketToServer() { SOCKET sock = INVALID_SOCKET; struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; char server[512]; HOSTENT *host; unsigned int address; int result; // server name result = snprintf(server, 256, "%s", qPrintable(settings->getServerName())); if (result <= 0 || result > 255){ if (settings->getOutputLog()){ const QString text = QString("socketToServer() : snprintf() error! for server"); emit outputLogMessage(PHASE_DEBUG, text); } return INVALID_SOCKET; } host = gethostbyname(server); if (host == 0){ address = inet_addr(server); host = gethostbyaddr((char*)&address, 4, AF_INET); } if (host == 0){ return INVALID_SOCKET; } addr.sin_port = htons(settings->getPortNo()); addr.sin_addr.s_addr = *((u_long*)host->h_addr); sock = socket(AF_INET, SOCK_STREAM, 0); result = connect_int(sock, (struct sockaddr *)&addr, sizeof(addr)); if (result == SOCKET_ERROR){ sock = INVALID_SOCKET; } // for socket option if (sock != INVALID_SOCKET){ // set socket option setSocketOption(sock); // check socket option if (outputLog) checkSocketOption(sock); } else { // INVALID_SOCKET if (settings->getOutputLog()){ const QString text = "socketToServer() : sock = INVALID_SOCKET"; emit outputLogMessage(PHASE_DEBUG, text); } } return sock; }
CGroupClient::CGroupClient(QByteArray host, int remotePort, QObject *parent) : _host(host), _remotePort(remotePort), QTcpSocket(parent) { linkSignals(); setSocketOption(QAbstractSocket::KeepAliveOption, true); setConnectionState(Connecting); protocolState = AwaitingLogin; connectToHost(host, remotePort); }
unsigned NetClient::sendData(const void *d, unsigned dataSize) throw (const SocketException &) { unsigned sent = 0; const char *dataBuf = static_cast<const char *>(d); bool prev_tcpNDelay = m_tcpNDelay; // turn on nagle for large transfers if (dataSize > (unsigned)m_sendBuf) { prev_tcpNDelay = m_tcpNDelay; setSocketOption(TCPNoDelay, false); // modifies m_tcpNDelay } while (sent < dataSize) sent += Socket::sendData(dataBuf + sent, dataSize - sent); // reenable previous no nagle if required if (prev_tcpNDelay != m_tcpNDelay) setSocketOption(TCPNoDelay, prev_tcpNDelay); return sent; }
int Socket::bind(const char* host, const int port) { int res = -1; if(!isValid()) return res; if (-1 == setSocketOption()) { return -1; } memset(&_address, 0, sizeof _address); _address.sin_family = AF_INET; _address.sin_addr.s_addr = host ? inet_addr(host) : htonl(INADDR_ANY);//域名 _address.sin_port = port ? htons(port) : htons(DEFAULT_PORT);//端口 res = ::bind(_fd, (struct sockaddr*)&_address, sizeof(_address)); return res; }
bool ProtocolTCP::initbase() { int optval = 1; char buf[SOCKADDR_SIZE]; struct sockaddr *local_addr = (struct sockaddr *)buf; socklen_t addrlen = 0; int af = AF_INET; unsigned short port = isClient() ? 0 : localport; char ip_str[50]; if (!localIface) { HAGGLE_ERR("Local interface is NULL\n"); return false; } // Check if we are already connected, i.e., we are a client // that was created from acceptClient() if (isConnected()) { // Nothing to initialize return true; } // Figure out the address type based on the local interface #if defined(ENABLE_IPv6) if (localIface->getAddress<IPv6Address>() && peerIface && peerIface->getAddress<IPv6Address>()) af = AF_INET6; #endif /* Configure a sockaddr for binding to the given port. Do not * bind to a specific interface. */ if (af == AF_INET) { struct sockaddr_in *sa = (struct sockaddr_in *)local_addr; sa->sin_family = AF_INET; sa->sin_addr.s_addr = htonl(INADDR_ANY); sa->sin_port = htons(port); addrlen = sizeof(struct sockaddr_in); } #if defined(ENABLE_IPv6) else if (af == AF_INET6) { struct sockaddr_in6 *sa = (struct sockaddr_in6 *)local_addr; sa->sin6_family = AF_INET6; sa->sin6_len = SOCKADDR_SIZE; sa->sin6_addr = in6addr_any; sa->sin6_port = htons(port); addrlen = sizeof(struct sockaddr_in6); } #endif if (!openSocket(local_addr->sa_family, SOCK_STREAM, IPPROTO_TCP, isServer())) { HAGGLE_ERR("Could not create TCP socket\n"); return false; } if (!setSocketOption(SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) { closeSocket(); HAGGLE_ERR("setsockopt SO_REUSEADDR failed\n"); return false; } if (!setSocketOption(SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval))) { closeSocket(); HAGGLE_ERR("setsockopt SO_KEEPALIVE failed\n"); return false; } if (!bind(local_addr, addrlen)) { closeSocket(); HAGGLE_ERR("Could not bind TCP socket\n"); return false; } if (inet_ntop(af, &((struct sockaddr_in *)local_addr)->sin_addr, ip_str, sizeof(ip_str))) { HAGGLE_DBG("%s Created %s TCP socket - %s:%d\n", getName(), af == AF_INET ? "AF_INET" : "AF_INET6", ip_str, port); } return true; }
// socket to server SOCKET NetThread::socketToServer() { SOCKET sock = INVALID_SOCKET; ADDRINFO *addrinfo; ADDRINFO addrinfo_hints; memset(&addrinfo_hints, 0, sizeof(ADDRINFO)); #if 0 // for TEST addrinfo_hints.ai_family = AF_INET; // for IP v4 #else // for TEST addrinfo_hints.ai_family = AF_UNSPEC; #endif // for TEST addrinfo_hints.ai_socktype = SOCK_STREAM; char server[512]; char port[16]; int error; int result; result = snprintf(server, 256, "%s", qPrintable(settings->getServerName())); if (result <= 0 || result > 255){ if (settings->getOutputLog()){ const QString text = QString("socketToServer() : snprintf() error! for server"); emit outputLogMessage(PHASE_DEBUG, text); } return INVALID_SOCKET; } result = snprintf(port, 10, "%d", settings->getPortNo()); if (result <= 0 || result > 9){ if (settings->getOutputLog()){ const QString text = QString("socketToServer() : snprintf() error! for port"); emit outputLogMessage(PHASE_DEBUG, text); } return INVALID_SOCKET; } error = getaddrinfo(server, port, &addrinfo_hints, &addrinfo); if (error != 0){ #if defined(QTB_NET_WIN) if (settings->getOutputLog()){ const QString text = QString("socketToServer() : getaddrinfo(): error = ") + QString::number(error); emit outputLogMessage(PHASE_DEBUG, text); } #elif defined(QTB_NET_UNIX) if (settings->getOutputLog()){ const QString text = QString("socketToServer() : getaddrinfo(): strerror = ") + gai_strerror(error); emit outputLogMessage(PHASE_DEBUG, text); } #endif // defined(QTB_NET_UNIX) return INVALID_SOCKET; } ADDRINFO *topAddrinfo = addrinfo; for (; addrinfo != NULL; addrinfo = addrinfo->ai_next){ #if !defined(Q_OS_WIN) // Portable Vresion (for MacOSX, FreeBSD...) sock = connect_retry(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol, addrinfo->ai_addr, (int)addrinfo->ai_addrlen); if (sock == INVALID_SOCKET){ continue; } #else sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); if (sock == INVALID_SOCKET){ continue; } if (connect_retry(sock, addrinfo->ai_addr, (int)addrinfo->ai_addrlen) == SOCKET_ERROR){ closesocket(sock); sock = INVALID_SOCKET; continue; } #endif break; } // free all addrinfo while(topAddrinfo != NULL){ addrinfo = topAddrinfo; topAddrinfo = addrinfo->ai_next; freeaddrinfo(addrinfo); } // for socket option if (sock != INVALID_SOCKET){ // set socket option setSocketOption(sock); // check socket option if (outputLog) checkSocketOption(sock); } else { // INVALID_SOCKET if (settings->getOutputLog()){ const QString text = "socketToServer() : sock = INVALID_SOCKET"; emit outputLogMessage(PHASE_DEBUG, text); } } return sock; }
void Socket::enableRouting() { DWORD routing = 1; setSocketOption(SO_DONTROUTE, routing); }
static void OSNetworkSystem_setSocketOption(JNIEnv* env, jobject, jobject fileDescriptor, jint option, jobject optVal) { NetFd fd(env, fileDescriptor); if (fd.isClosed()) { return; } int intVal; bool wasBoolean = false; if (env->IsInstanceOf(optVal, JniConstants::integerClass)) { intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value); } else if (env->IsInstanceOf(optVal, JniConstants::booleanClass)) { intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value); wasBoolean = true; } else if (env->IsInstanceOf(optVal, JniConstants::inetAddressClass)) { // We use optVal directly as an InetAddress for IP_MULTICAST_IF. } else if (env->IsInstanceOf(optVal, JniConstants::multicastGroupRequestClass)) { // We use optVal directly as a MulticastGroupRequest for MCAST_JOIN_GROUP/MCAST_LEAVE_GROUP. } else { jniThrowSocketException(env, EINVAL); return; } int family = getSocketAddressFamily(fd.get()); if (family != AF_INET && family != AF_INET6) { jniThrowSocketException(env, EAFNOSUPPORT); return; } // Since we expect to have a AF_INET6 socket even if we're communicating via IPv4, we always // set the IPPROTO_IP options. As long as we fall back to creating IPv4 sockets if creating // an IPv6 socket fails, we need to make setting the IPPROTO_IPV6 options conditional. switch (option) { case JAVASOCKOPT_IP_TOS: setSocketOption(env, fd, IPPROTO_IP, IP_TOS, &intVal); if (family == AF_INET6) { setSocketOption(env, fd, IPPROTO_IPV6, IPV6_TCLASS, &intVal); } return; case JAVASOCKOPT_SO_BROADCAST: setSocketOption(env, fd, SOL_SOCKET, SO_BROADCAST, &intVal); return; case JAVASOCKOPT_SO_KEEPALIVE: setSocketOption(env, fd, SOL_SOCKET, SO_KEEPALIVE, &intVal); return; case JAVASOCKOPT_SO_LINGER: { linger l; l.l_onoff = !wasBoolean; l.l_linger = intVal <= 65535 ? intVal : 65535; setSocketOption(env, fd, SOL_SOCKET, SO_LINGER, &l); return; } case JAVASOCKOPT_SO_OOBINLINE: setSocketOption(env, fd, SOL_SOCKET, SO_OOBINLINE, &intVal); return; case JAVASOCKOPT_SO_RCVBUF: setSocketOption(env, fd, SOL_SOCKET, SO_RCVBUF, &intVal); return; case JAVASOCKOPT_SO_REUSEADDR: setSocketOption(env, fd, SOL_SOCKET, SO_REUSEADDR, &intVal); return; case JAVASOCKOPT_SO_SNDBUF: setSocketOption(env, fd, SOL_SOCKET, SO_SNDBUF, &intVal); return; case JAVASOCKOPT_SO_TIMEOUT: { timeval timeout(toTimeval(intVal)); setSocketOption(env, fd, SOL_SOCKET, SO_RCVTIMEO, &timeout); return; } case JAVASOCKOPT_TCP_NODELAY: setSocketOption(env, fd, IPPROTO_TCP, TCP_NODELAY, &intVal); return; #ifdef ENABLE_MULTICAST case JAVASOCKOPT_MCAST_JOIN_GROUP: mcastJoinLeaveGroup(env, fd.get(), optVal, true); return; case JAVASOCKOPT_MCAST_LEAVE_GROUP: mcastJoinLeaveGroup(env, fd.get(), optVal, false); return; case JAVASOCKOPT_IP_MULTICAST_IF: { sockaddr_storage sockVal; if (!env->IsInstanceOf(optVal, JniConstants::inetAddressClass) || !inetAddressToSocketAddress(env, optVal, 0, &sockVal)) { return; } // This call is IPv4 only. The socket may be IPv6, but the address // that identifies the interface to join must be an IPv4 address. if (sockVal.ss_family != AF_INET) { jniThrowSocketException(env, EAFNOSUPPORT); return; } ip_mreqn mcast_req; memset(&mcast_req, 0, sizeof(mcast_req)); mcast_req.imr_address = reinterpret_cast<sockaddr_in*>(&sockVal)->sin_addr; setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &mcast_req); return; } case JAVASOCKOPT_IP_MULTICAST_IF2: // TODO: is this right? should we unconditionally set the IPPROTO_IP state in case // we have an IPv6 socket communicating via IPv4? if (family == AF_INET) { // IP_MULTICAST_IF expects a pointer to an ip_mreqn struct. ip_mreqn multicastRequest; memset(&multicastRequest, 0, sizeof(multicastRequest)); multicastRequest.imr_ifindex = intVal; setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &multicastRequest); } else { // IPV6_MULTICAST_IF expects a pointer to an integer. setSocketOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &intVal); } return; case JAVASOCKOPT_MULTICAST_TTL: { // Although IPv6 was cleaned up to use int, and IPv4 non-multicast TTL uses int, // IPv4 multicast TTL uses a byte. u_char ttl = intVal; setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl); if (family == AF_INET6) { setSocketOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &intVal); } return; } case JAVASOCKOPT_IP_MULTICAST_LOOP: { // Although IPv6 was cleaned up to use int, IPv4 multicast loopback uses a byte. u_char loopback = intVal; setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loopback); if (family == AF_INET6) { setSocketOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &intVal); } return; } #else case JAVASOCKOPT_MULTICAST_TTL: case JAVASOCKOPT_MCAST_JOIN_GROUP: case JAVASOCKOPT_MCAST_LEAVE_GROUP: case JAVASOCKOPT_IP_MULTICAST_IF: case JAVASOCKOPT_IP_MULTICAST_IF2: case JAVASOCKOPT_IP_MULTICAST_LOOP: jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); return; #endif // def ENABLE_MULTICAST default: jniThrowSocketException(env, ENOPROTOOPT); } }
int TcpSocketImpl::connect_i(const char* host, uint16_t port, uint32_t timeout) { KUMA_INFOXTRACE("connect_i, host="<<host<<", port="<<port<<", this="<<this); #ifndef KUMA_HAS_OPENSSL if (SslEnabled()) { KUMA_ERRXTRACE("connect_i, OpenSSL is disabled"); return KUMA_ERROR_UNSUPPORT; } #endif sockaddr_storage ss_addr = {0}; struct addrinfo hints = {0}; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; // will block 10 seconds in some case if not set AI_ADDRCONFIG if(km_set_sock_addr(host, port, &hints, (struct sockaddr*)&ss_addr, sizeof(ss_addr)) != 0) { return KUMA_ERROR_INVALID_PARAM; } if(INVALID_FD == fd_) { fd_ = ::socket(ss_addr.ss_family, SOCK_STREAM, 0); if(INVALID_FD == fd_) { KUMA_ERRXTRACE("connect_i, socket failed, err="<<getLastError()); return KUMA_ERROR_FAILED; } } setSocketOption(); int addr_len = sizeof(ss_addr); #ifdef KUMA_OS_MAC if(AF_INET == ss_addr.ss_family) addr_len = sizeof(sockaddr_in); else addr_len = sizeof(sockaddr_in6); #endif int ret = ::connect(fd_, (struct sockaddr *)&ss_addr, addr_len); if(0 == ret) { setState(ST_CONNECTING); // wait for writable event } else if(ret < 0 && #ifdef KUMA_OS_WIN WSAEWOULDBLOCK #else EINPROGRESS #endif == getLastError()) { setState(ST_CONNECTING); } else { KUMA_ERRXTRACE("connect_i, error, fd="<<fd_<<", err="<<getLastError()); cleanup(); setState(ST_CLOSED); return KUMA_ERROR_FAILED; } #if defined(KUMA_OS_LINUX) || defined(KUMA_OS_MAC) socklen_t len = sizeof(ss_addr); #else int len = sizeof(ss_addr); #endif char local_ip[128] = {0}; uint16_t local_port = 0; ret = getsockname(fd_, (struct sockaddr*)&ss_addr, &len); if(ret != -1) { km_get_sock_addr((struct sockaddr*)&ss_addr, sizeof(ss_addr), local_ip, sizeof(local_ip), &local_port); } KUMA_INFOXTRACE("connect_i, fd="<<fd_<<", local_ip="<<local_ip <<", local_port="<<local_port<<", state="<<getState()); loop_->registerFd(fd_, KUMA_EV_NETWORK, [this] (uint32_t ev) { ioReady(ev); }); registered_ = true; return KUMA_ERROR_NOERR; }
void Socket::disableKeepalive() { DWORD keepAlive = 0; setSocketOption(SO_KEEPALIVE, keepAlive); }
void Socket::setOutputTimeout(DWORD timeout) { setSocketOption(SO_SNDTIMEO, timeout); }
void TMultiplexingServer::run() { // Listen socket quint16 port = Tf::app()->appSettings().value("ListenPort").toUInt(); int sock = TApplicationServerBase::nativeListen(QHostAddress::Any, port); if (sock > 0) { tSystemDebug("listen successfully. port:%d", port); } else { tSystemError("Failed to set socket descriptor: %d", sock); TApplicationServerBase::nativeClose(sock); return; } listenSocket = sock; setSocketOption(listenSocket); maxWorkers = Tf::app()->maxNumberOfServers(10); tSystemDebug("MaxWorkers: %d", maxWorkers); // Get send buffer size and recv buffer size int res, sendBufSize, recvBufSize; socklen_t optlen = sizeof(int); res = getsockopt(listenSocket, SOL_SOCKET, SO_SNDBUF, &sendBufSize, &optlen); if (res < 0) tSystemDebug("SO_SNDBUF: %d", sendBufSize); res = getsockopt(listenSocket, SOL_SOCKET, SO_RCVBUF, &recvBufSize, &optlen); if (res < 0) tSystemDebug("SO_RCVBUF: %d", recvBufSize); const int MaxEvents = 128; struct epoll_event events[MaxEvents]; sendBufSize *= 0.8; char *sndbuffer = new char[sendBufSize]; char *rcvbuffer = new char[recvBufSize]; // Create epoll epollFd = epoll_create(1); if (epollFd < 0) { tSystemError("Failed epoll_create()"); goto socket_error; } if (epollAdd(listenSocket, EPOLLIN) < 0) { tSystemError("Failed epoll_ctl()"); goto epoll_error; } for (;;) { // Get send-request getSendRequest(); // Check pending requests while (!pendingRequests.isEmpty() && (int)threadCounter < maxWorkers) { int fd = pendingRequests.takeFirst(); THttpBuffer &recvbuf = recvBuffers[fd]; emitIncomingRequest(fd, recvbuf); } // Poll Sending/Receiving/Incoming int timeout = ((int)threadCounter > 0) ? 1 : 100; int nfd = tf_epoll_wait(epollFd, events, MaxEvents, timeout); int err = errno; if (nfd < 0) { tSystemError("Failed epoll_wait() : errno:%d", err); break; } for (int i = 0; i < nfd; ++i) { if (events[i].data.fd == listenSocket) { if (!pendingRequests.isEmpty()) continue; // Incoming connection struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); int clt = ::accept(events[i].data.fd, (sockaddr *)&addr, &addrlen); if (clt < 0) { tSystemWarn("Failed accept"); continue; } setNonBlocking(clt); if (epollAdd(clt, EPOLLIN) == 0) { THttpBuffer &recvbuf = recvBuffers[clt]; recvbuf.clear(); recvbuf.setClientAddress(QHostAddress((sockaddr *)&addr)); } } else { int cltfd = events[i].data.fd; if ( (events[i].events & EPOLLIN) ) { // Receive data int len = ::recv(cltfd, rcvbuffer, recvBufSize, 0); err = errno; if (len > 0) { // Read successfully THttpBuffer &recvbuf = recvBuffers[cltfd]; recvbuf.write(rcvbuffer, len); if (recvbuf.canReadHttpRequest()) { // Incoming a request if ((int)threadCounter >= maxWorkers) { pendingRequests << cltfd; } else { emitIncomingRequest(cltfd, recvbuf); } } } else { if (len < 0 && err != ECONNRESET) { tSystemError("Failed recv : errno:%d", err); } // Disconnect epollClose(cltfd); continue; } } if ( (events[i].events & EPOLLOUT) ) { // Send data THttpSendBuffer *sendbuf = sendBuffers[cltfd].first(); if (!sendbuf) { tSystemError("Not found send-buffer"); epollClose(cltfd); continue; } int len = sendbuf->read(sndbuffer, sendBufSize); int sentlen = ::send(cltfd, sndbuffer, len, 0); err = errno; TAccessLogger &logger = sendbuf->accessLogger(); if (sentlen <= 0) { if (err != ECONNRESET) { tSystemError("Failed send : errno:%d", err); } // Access log logger.setResponseBytes(-1); logger.write(); epollClose(cltfd); continue; } else { logger.setResponseBytes(logger.responseBytes() + sentlen); if (len > sentlen) { tSystemDebug("sendbuf prepend: len:%d", len - sentlen); sendbuf->prepend(sndbuffer + sentlen, len - sentlen); } if (sendbuf->atEnd()) { logger.write(); // Writes access log sendbuf->release(); QQueue<THttpSendBuffer*> &que = sendBuffers[cltfd]; delete que.dequeue(); // delete send-buffer obj // Prepare recv if (que.isEmpty()) epollModify(cltfd, EPOLLIN); } } } } } // Check stop flag if (stopped) { if (listenSocket > 0) { // Close the listen-socket epollClose(listenSocket); listenSocket = 0; } if (!recvBuffers.isEmpty()) { for (QMapIterator<int, THttpBuffer> it(recvBuffers); it.hasNext(); ) { it.next(); epollClose(it.key()); } } if (recvBuffers.isEmpty() && sendBuffers.isEmpty()) { break; } } } epoll_error: TF_CLOSE(epollFd); epollFd = 0; socket_error: if (listenSocket > 0) TF_CLOSE(listenSocket); listenSocket = 0; delete sndbuffer; delete rcvbuffer; }
void Socket::setInputTimeout(DWORD timeout) { setSocketOption(SO_RCVTIMEO, timeout); }