Пример #1
0
// --------------------------------------------------------------------------
//
// 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);
}
Пример #2
0
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;
}