// -------------------------------------------------------------------------- // // Function // Name: NiceSocketStream::Write(const void *pBuffer, int NBytes) // Purpose: Writes bytes to the underlying stream, adjusting window size // using a TcpNice calculator. // Created: 2012/02/11 // // -------------------------------------------------------------------------- void NiceSocketStream::Write(const void *pBuffer, int NBytes) { #if HAVE_DECL_SO_SNDBUF && HAVE_DECL_TCP_INFO if(mEnabled && mapTimer.get() && mapTimer->HasExpired()) { box_time_t newPeriodStart = GetCurrentBoxTime(); box_time_t elapsed = newPeriodStart - mPeriodStartTime; int socket = mapSocket->GetSocketHandle(); int rtt = 50; // WAG # if HAVE_DECL_SOL_TCP && HAVE_DECL_TCP_INFO && HAVE_STRUCT_TCP_INFO_TCPI_RTT struct tcp_info info; socklen_t optlen = sizeof(info); if(getsockopt(socket, SOL_TCP, TCP_INFO, &info, &optlen) == -1) { BOX_LOG_SYS_WARNING("getsockopt(" << socket << ", SOL_TCP, " "TCP_INFO) failed"); } else if(optlen < sizeof(info)) { BOX_WARNING("getsockopt(" << socket << ", SOL_TCP, " "TCP_INFO) return structure size " << optlen << ", " "expected " << sizeof(info)); } else { rtt = info.tcpi_rtt; } # endif int newWindow = mTcpNice.GetNextWindowSize(mBytesWrittenThisPeriod, elapsed, rtt); if(setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &newWindow, sizeof(newWindow)) == -1) { BOX_LOG_SYS_WARNING("getsockopt(" << socket << ", SOL_SOCKET, " "SO_SNDBUF, " << newWindow << ") failed"); } StopTimer(); } if(mEnabled && !mapTimer.get()) { // Don't start the timer until we receive the first data to write, // as diffing might take a long time and we don't want to bias // the TcpNice algorithm by running while we don't have bulk data // to send. StartTimer(); mPeriodStartTime = GetCurrentBoxTime(); mBytesWrittenThisPeriod = 0; } mBytesWrittenThisPeriod += NBytes; #endif // HAVE_DECL_SO_SNDBUF mapSocket->Write(pBuffer, NBytes); }
void NiceSocketStream::SetEnabled(bool enabled) { mEnabled = enabled; if(!enabled) { StopTimer(); #if HAVE_DECL_SO_SNDBUF int socket = mapSocket->GetSocketHandle(); int newWindow = 1<<17; if(setsockopt(socket, SOL_SOCKET, SO_SNDBUF, # ifdef WIN32 // optval is a const char * on Windows, even // though the argument is a boolean or integer, // for reasons best known to Microsoft! (const char *)&newWindow, # else &newWindow, # endif sizeof(newWindow)) == -1) { BOX_LOG_SYS_WARNING("getsockopt(" << socket << ", SOL_SOCKET, " "SO_SNDBUF, " << newWindow << ") failed"); } #endif } }
bool check_filedes(bool report) { bool allOk = true; // See how many file descriptors there are with values < 256. // In order to avoid disturbing things, we scan the file descriptors // first, marking the ones that were OPEN at startup (report == FALSE) // as STILLOPEN and the ones that were not as LEAKED. Then we run // through again and print the results. for(int d = 0; d < FILEDES_MAX; ++d) { if(::fcntl(d, F_GETFD) != -1) { // File descriptor obviously exists, but is it /dev/log? // Mark it as OPEN for now, and we'll find out later. if(report) { if(filedes_open[d] == OPEN) { filedes_open[d] = STILLOPEN; } else { filedes_open[d] = LEAKED; } } else { filedes_open[d] = OPEN; } } else { filedes_open[d] = CLOSED; } } if(!report) { filedes_initialised = true; return true; } // Now loop again, reporting differences. for(int d = 0; d < FILEDES_MAX; ++d) { if(filedes_open[d] != LEAKED) { continue; } bool stat_success = false; struct stat st; if(fstat(d, &st) == 0) { stat_success = true; if(st.st_mode & S_IFSOCK) { char buffer[256]; socklen_t addrlen = sizeof(buffer); #ifdef HAVE_GETPEERNAME if(getpeername(d, (sockaddr*)buffer, &addrlen) != 0) { BOX_LOG_SYS_WARNING("Failed to getpeername(" << d << "), cannot identify /dev/log"); } else { struct sockaddr_un *sa = (struct sockaddr_un *)buffer; if(sa->sun_family == PF_UNIX && !strcmp(sa->sun_path, "/dev/log")) { // it's a syslog socket, ignore it filedes_open[d] = SYSLOG; } } #endif // HAVE_GETPEERNAME } } if(filedes_open[d] == SYSLOG) { // Different libcs have different ideas // about when to open and close this // socket, and it's not a leak, so // ignore it. } else if(stat_success) { int m = st.st_mode; #define flag(x) ((m & x) ? #x " " : "") BOX_FATAL("File descriptor " << d << " left open (type == " << flag(S_IFIFO) << flag(S_IFCHR) << flag(S_IFDIR) << flag(S_IFBLK) << flag(S_IFREG) << flag(S_IFLNK) << flag(S_IFSOCK) << " or " << m << ")"); allOk = false; } else { BOX_FATAL("File descriptor " << d << " left open (and stat failed)"); allOk = false; } } if (!report && allOk) { filedes_initialised = true; } return allOk; }