Ejemplo n.º 1
0
int main(int argc, char* argv[])
{
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
	{
		printf("윈도우 소켓 초기화 실패! \n");
		return -1;
	}

	// (socket + bind + listen)
	if(!CreateListenSocket())
	{
		printf("대기 소켓 생성 실패\n");
		return -1;
	}


	//===================================================

	WSAWaitForMultipleEvents((HANDLE)_beginthreadex(0,0,ListenThread, 0,0,0), INFINITE);
	//===================================================

	WSACleanup();
	return 0;
}
Ejemplo n.º 2
0
BOOL CIocpServer::Start(LPCTSTR pszBindAddress, USHORT usPort)
{
	if(!CheckParams() || !CheckStarting())
		return FALSE;

	//创建监听套接字开始监听端口
	if(CreateListenSocket(pszBindAddress, usPort))
	{
		if(CreateCompletePort())
		{
			if(CreateWorkerThreads())
			{
				if(StartAcceptThread())
				{
					m_enState = SS_STARTED;
					return TRUE;
				}
			}
		}
	}


	Stop();

	return FALSE;
}
Ejemplo n.º 3
0
BOOL ICMPSocket::Create( LPCTSTR listenIPOrHost )
{
	tstring iporhost;
	if (NULL == listenIPOrHost)
	{
		char hostname[128] = {0};
		gethostname(hostname, 128);
		iporhost = a2t(hostname);
	}
	else
	{
		iporhost = listenIPOrHost;
	}

	Close();

	m_listenIP = INADDR_NONE;
	if (! MySocket::IPOrHostname2IP(iporhost.c_str(), m_listenIP))
	{
		errorLog(_T("invalid listeniporhost [%s]"), listenIPOrHost);
		return FALSE;
	}

	if (! CreateListenSocket(m_listenIP, m_sock))
	{
		errorLog(_T("create listen socket failed"));
		m_sock = INVALID_SOCKET;

		return FALSE;
	}

	return TRUE;
}
Ejemplo n.º 4
0
bool CServer::CreateListenSocket()
{
	CStdString ports = (m_pOptions ? m_pOptions->GetOption(OPTION_SERVERPORT) : _T("21"));
	bool success = CreateListenSocket(ports, false);

	bool ssl_enabled = m_pOptions && m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0;
	if (ssl_enabled) {
		ports = m_pOptions->GetOption(OPTION_TLSPORTS);
		success &= CreateListenSocket(ports, true);
	}

	if (success && m_ListenSocketList.empty()) {
		ShowStatus(_T("No listen ports set in settings"), 1);
	}

	return !m_ListenSocketList.empty();
}
Ejemplo n.º 5
0
bool CServer::Create()
{
	//Create window
	WNDCLASSEX wndclass{};
	wndclass.cbSize = sizeof wndclass;
	wndclass.lpfnWndProc = WindowProc;
	wndclass.hInstance = GetModuleHandle(0);
	wndclass.lpszClassName = _T("FileZilla Server Helper Window");

	RegisterClassEx(&wndclass);

	m_hWnd = CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
	if (!m_hWnd)
		return false;
	SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this);

	hMainWnd = m_hWnd;

	m_pOptions = new COptions;
	m_pFileLogger = new CFileLogger(m_pOptions);
	m_pAutoBanManager = new CAutoBanManager(m_pOptions);

	//Create the threads
	int num = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
	for (int i = 0; i < num; ++i) {
		int index = GetNextThreadNotificationID();
		CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
		m_ThreadNotificationIDs[index] = pThread;
		if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) {
			pThread->ResumeThread();
			m_ThreadArray.push_back(pThread);
		}
	}

	m_pFileLogger->Log(GetProductVersionString() + _T(" started"));
	m_pFileLogger->Log(_T("Initializing Server."));

	m_nTimerID = SetTimer(m_hWnd, 1234, 10000, NULL);
	ASSERT(m_nTimerID);

	m_nBanTimerID = SetTimer(m_hWnd, 1235, 60000, NULL);
	ASSERT(m_nBanTimerID);

	if (CreateListenSocket()) {
		m_nServerState = STATE_ONLINE;
		ShowStatus(_T("Server online."), 0);
	}
	else
		ShowStatus(_T("Server not online."), 1);

	CreateAdminListenSocket();

	m_sslLoader = make_unique<CAsyncSslSocketLayer>(0);
	m_sslLoader->InitSSL();

	return true;
}
Ejemplo n.º 6
0
int main(int argc, char* argv[])
{
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
	{
		printf("윈도우 소켓 초기화 실패! \n");
		return -1;
	}

	// (socket + bind + listen)
	if(!CreateListenSocket())
	{
		printf("대기 소켓 생성 실패\n");
		return -1;
	}

	// 서버처리
	//===================================================
	int index = 0;
	WSANETWORKEVENTS neEvents;
	
	while(1)
	{
		// 이벤트 시그널 감지
		index = WSAWaitForMultipleEvents(g_SockCnt, EventList,
			FALSE, WSA_INFINITE, FALSE);
		index -= WSA_WAIT_EVENT_0;
		// 이벤트 내용 가져오기 + EventList[index] 이벤트를 넌시그날로 변경
		WSAEnumNetworkEvents( SockList[index], EventList[index], &neEvents);
		if(neEvents.lNetworkEvents & FD_ACCEPT)
		{
			EVENTERRORCHECK(neEvents, FD_ACCEPT_BIT);
			if(AddClient(index) != true)
				continue;
		}
		else if(neEvents.lNetworkEvents & FD_READ || neEvents.lNetworkEvents & FD_WRITE)
		{
			if(neEvents.iErrorCode[FD_READ_BIT] != 0 && neEvents.iErrorCode[FD_WRITE_BIT] != 0)
			{
				DisplayMessage();
				return -1;
			}
			RecvClient(index);
			
		}
		else if(neEvents.lNetworkEvents & FD_CLOSE)
		{
			EVENTERRORCHECK(neEvents, FD_CLOSE_BIT);
				DeleteClient(index);
		}
	}
	//===================================================

	WSACleanup();
	return 0;
}
Ejemplo n.º 7
0
//=============================================================================================================================
BOOL Acceptor::StartListen( char *pIP, WORD wPort )
{	
	//创建SOCKET
	if( !CreateListenSocket( pIP, wPort ) ) return FALSE;

	// 注册IOCP和SOCKET
	CreateIoCompletionPort( (HANDLE)m_listenSocket, m_hIOCP, 1, 0 );

	//装载DLL (AcceptEx, TransmitFile)
	MsWinsockUtil::LoadExtensionFunction( m_listenSocket );

	return TRUE;
}
Ejemplo n.º 8
0
		int CMainLoop::InitListenPort()
		{
			for (int i = 0; i < m_stConfig.m_iTcpListenPortNum; i++)
			{
				int iSocketFd;
				
				iSocketFd = CreateListenSocket(m_stConfig.m_tcpListenPort[i].iIpNetOrder, m_stConfig.m_tcpListenPort[i].unPort, 20480, 20480, 0, 1024);
				if (-1 == iSocketFd)
					return -1;

				m_pSocket[i].socket_fd = iSocketFd;
				m_pSocket[i].us_listen_port = m_stConfig.m_tcpListenPort[i].unPort;
				m_epollMng.AddFd(iSocketFd, i, EPOLLIN |EPOLLHUP|EPOLLERR);
			}
			return 0;
		}
Ejemplo n.º 9
0
int EntryPoint(void) {
    SOCKET s;

    StartLogger(TEXT(LOGFILE));

    if(StartWinsock() != 0)
        return -1;

    s = CreateListenSocket(SERVER_PORT);
    if((s == SOCKET_ERROR) || (s == INVALID_SOCKET))
        return -1;
    ServerLoop(s);

    WSACleanup();

    return 1;
}
Ejemplo n.º 10
0
int main(int argc, char* argv[])
{
	/* Parse the command line arguments */
	int listenPort = -1;		// port to listen on
	char* dir = NULL;		// directory to serve
	ParseCmdLineArgs(argc, argv, dir, listenPort);
	printf("Running server in directory %s, and on port %i.\n", dir, listenPort);
	
	/* Create the listening socket for our FTP server */
	int listenSocket = CreateListenSocket( FTP_MAX_BACKLOG_CONNECTIONS, listenPort, false, true );

	/* Do this to reap zombie child processes */
	struct sigaction sa;			// need this struct for handling signals and destroying zombie child procs
	sa.sa_handler = SigChildHandler;	// function pointer
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	if ( sigaction(SIGCHLD, &sa, NULL) == -1 )
		ExitError("sigaction() failed.");
	
	while (1)
	{
		/* Accept the next connection on the backlog queue. Blocks if
		there are no connections in the queue. */
		struct sockaddr_in remoteAddr;
		int acceptSocket = AcceptConnectionFromListenSocket(listenSocket, &remoteAddr);
		printf("FTP server received connection from %s\n", inet_ntoa(remoteAddr.sin_addr));
		
		/* Each FTP session gets its own process. */
		if ( !fork() )			
		{
			// child process code
			close(listenSocket);				// child doesn't need listen socket
			FTPSession(acceptSocket, dir, remoteAddr);	// begin the FTP session
			close(acceptSocket);				// when done with the session close the socket
			exit(EXIT_SUCCESS);				// exit with success code 0
		}
		
		// parent process continues here
		close(acceptSocket);			// parent doesn't need the accept socket anymore
	}
	
	return 0;
}
Ejemplo n.º 11
0
BOOL CTcpServer::Start(LPCTSTR lpszBindAddress, USHORT usPort)
{
	if(!CheckParams() || !CheckStarting())
		return FALSE;

	PrepareStart();

	if(CreateListenSocket(lpszBindAddress, usPort))
		if(CreateCompletePort())
			if(CreateWorkerThreads())
				if(StartAccept())
				{
					m_enState = SS_STARTED;
					return TRUE;
				}

	EXECUTE_RESTORE_ERROR(Stop());

	return FALSE;
}
Ejemplo n.º 12
0
bool wxGISLocalNetworkPlugin::Start(INetService* pNetService, const wxXmlNode* pConfig)
{
    m_pNetService = pNetService;
    m_sAddr = wxString(wxT("127.0.0.1"));
    if(pConfig)
    {
        m_sAddr = pConfig->GetAttribute(wxT("addr"), m_sAddr);
	    m_nPort = wxAtoi(pConfig->GetAttribute(wxT("port"), wxT("9980")));
    }
    else
    {
        wxGISAppConfig oConfig = GetConfig();
        if(oConfig.IsOk())
        {
            m_sAddr = oConfig.Read(enumGISHKCU, wxString(wxT("wxGISTaskNamager/net/host")), m_sAddr);
            m_nPort = oConfig.ReadInt(enumGISHKCU, wxString(wxT("wxGISTaskNamager/net/port")), 9980);
        }
    }

	wxLogMessage(_("%s: Plugin is started..."), wxT("wxGISLocalNetworkPlugin"));

    return CreateListenSocket();
}
Ejemplo n.º 13
0
int main(int argc, char* argv[])
{
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
	{
		printf("윈도우 소켓 초기화 실패! \n");
		return -1;
	}

	// (socket + bind + listen
	if(!CreateListenSocket())
	{
		printf("대기 소켓 생성 실패\n");
		return -1;
	}

	unsigned int threadID;

	WaitForSingleObject((HANDLE)_beginthreadex(0,0,ListenThread, 0,0,&threadID), INFINITE);
	
	WSACleanup();
	return 0;
}
Ejemplo n.º 14
0
BOOL CTcpServer::Start(LPCTSTR lpszBindAddress, USHORT usPort)
{
	if(!CheckParams() || !CheckStarting())
		return FALSE;

	PrepareStart();

	if(CreateListenSocket(lpszBindAddress, usPort))
		if(CreateCompletePort())
			if(CreateWorkerThreads())
				if(StartAccept())
				{
					m_enState = SS_STARTED;
					return TRUE;
				}

	DWORD dwCode = ::GetLastError();

	Stop();

	::SetLastError(dwCode);

	return FALSE;
}
Ejemplo n.º 15
0
DWORD WINAPI IocpServerWorker(LPVOID p)
{
	SYSTEM_INFO SystemInfo;
	DWORD ThreadID;
	SOCKET Accept;
	int nRet;
	int ClientIndex;
	SOCKADDR_IN cAddr;
	IN_ADDR		cInAddr;
	int			cAddrlen = sizeof( cAddr );
	LPPER_SOCKET_CONTEXT lpPerSocketContext = NULL; 
	DWORD RecvBytes;
	DWORD Flags=0;
	
	InitializeCriticalSection(&criti);
	GetSystemInfo(&SystemInfo);

	g_dwThreadCount = SystemInfo.dwNumberOfProcessors * 2;
	__try
	{

		g_CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
		if ( g_CompletionPort == NULL)
		{
			LogAdd("CreateIoCompletionPort failed with error: %d", GetLastError());
			__leave;
		}
		
		for(DWORD dwCPU = 0; dwCPU < g_dwThreadCount; dwCPU++)
		{
			HANDLE ThreadHandle;
			// Create a server worker thread and pass the completion port to the thread.
			
			ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, g_CompletionPort, 0, &ThreadID);
			if ( ThreadHandle == NULL)
			{
				LogAdd("CreateThread() failed with error %d", GetLastError());
				__leave;
			}
			g_ThreadHandles[dwCPU] = ThreadHandle;
			CloseHandle(ThreadHandle);

		}

		if (!CreateListenSocket() )
			__leave;

		
		while(TRUE)		
		{
			Accept = WSAAccept(g_Listen, (LPSOCKADDR)&cAddr, &cAddrlen, NULL, 0);
			if (Accept==SOCKET_ERROR)
			{
				EnterCriticalSection(&criti);
				LogAdd("WSAAccept() failed with error %d", WSAGetLastError());
				LeaveCriticalSection(&criti);
				continue;
			}
			EnterCriticalSection(&criti);

			memcpy( &cInAddr, &cAddr.sin_addr.s_addr, 4 );

			ClientIndex = gObjAddSearch(Accept, inet_ntoa(cInAddr) );
			
			if ( ClientIndex == -1 )
			{
				LogAddL("error-L2 : ClientIndex = -1");
				closesocket(Accept);
				LeaveCriticalSection(&criti);
				continue;
			}

			if (UpdateCompletionPort(Accept, ClientIndex, 1) == 0 )
			{
				LogAddL("error-L1 : %d %d CreateIoCompletionPort failed with error %d", Accept, ClientIndex, GetLastError() );
				closesocket(Accept);
				LeaveCriticalSection(&criti);
				continue;
			}

			if (gObjAdd(Accept, inet_ntoa(cInAddr), ClientIndex) == -1 )
			{
				LogAddL("error-L1 : %d %d gObjAdd() failed with error %d", Accept, ClientIndex, GetLastError() );
				LeaveCriticalSection(&criti);
				closesocket(Accept);
				continue;
			}
				
			memset(&gObj[ClientIndex].PerSocketContext->IOContext[0].Overlapped, 0, sizeof(OVERLAPPED));
			memset(&gObj[ClientIndex].PerSocketContext->IOContext[1].Overlapped, 0, sizeof(OVERLAPPED));
			gObj[ClientIndex].PerSocketContext->IOContext[0].wsabuf.buf = gObj[ClientIndex].PerSocketContext->IOContext[0].Buffer;
			gObj[ClientIndex].PerSocketContext->IOContext[0].wsabuf.len = MAX_IO_BUFFER_SIZE;
			gObj[ClientIndex].PerSocketContext->IOContext[0].nTotalBytes = 0;
			gObj[ClientIndex].PerSocketContext->IOContext[0].nSentBytes = 0;
			gObj[ClientIndex].PerSocketContext->IOContext[0].nWaitIO    = 0;
			gObj[ClientIndex].PerSocketContext->IOContext[0].nSecondOfs = 0;
			gObj[ClientIndex].PerSocketContext->IOContext[0].IOOperation = RECV_IO;
			
			gObj[ClientIndex].PerSocketContext->IOContext[1].wsabuf.buf = gObj[ClientIndex].PerSocketContext->IOContext[0].Buffer;
			gObj[ClientIndex].PerSocketContext->IOContext[1].wsabuf.len = MAX_IO_BUFFER_SIZE;
			gObj[ClientIndex].PerSocketContext->IOContext[1].nTotalBytes= 0;
			gObj[ClientIndex].PerSocketContext->IOContext[1].nSentBytes = 0;
			gObj[ClientIndex].PerSocketContext->IOContext[1].nWaitIO    = 0;
			gObj[ClientIndex].PerSocketContext->IOContext[1].nSecondOfs = 0;
			gObj[ClientIndex].PerSocketContext->IOContext[1].IOOperation = SEND_IO;
			gObj[ClientIndex].PerSocketContext->m_socket = Accept;
			gObj[ClientIndex].PerSocketContext->nIndex   = ClientIndex;

			nRet = WSARecv(Accept, &(gObj[ClientIndex].PerSocketContext->IOContext[0].wsabuf), 1, &RecvBytes, &Flags,
				&(gObj[ClientIndex].PerSocketContext->IOContext[0].Overlapped), NULL);

			if( nRet == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING )
			{
				LogAdd("error-L1 : WSARecv() failed with error %d", WSAGetLastError());
				gObj[ClientIndex].PerSocketContext->IOContext[0].nWaitIO = 4;
				CloseClient(gObj[ClientIndex].PerSocketContext, FALSE);
				LeaveCriticalSection(&criti);
				continue;
			}

			gObj[ClientIndex].PerSocketContext->IOContext[0].nWaitIO = 1;
			gObj[ClientIndex].PerSocketContext->dwIOCount++;

			LeaveCriticalSection(&criti);
			SCPJoinResultSend(ClientIndex, 1);

		}
	}
	__finally  
	{
		if( g_CompletionPort )
		{
			for (DWORD i = 0; i < g_dwThreadCount; i++) 
					PostQueuedCompletionStatus(g_CompletionPort, 0, 0, NULL); 
		}
		if( g_CompletionPort )
		{
			CloseHandle(g_CompletionPort);
			g_CompletionPort = NULL;
		}
		if (g_Listen != INVALID_SOCKET)  
		{ 
            closesocket(g_Listen);  
            g_Listen = INVALID_SOCKET; 
		} 
	}
	return TRUE;
}
Ejemplo n.º 16
0
bool CServer::ToggleActive(int nServerState)
{
	if (nServerState & STATE_MASK_GOOFFLINE) {
		if (m_nServerState & STATE_MASK_GOOFFLINE)
			return false;

		int ftm_gooffline_arg{};
		switch (nServerState & STATE_MASK_GOOFFLINE) {
		case STATE_GOOFFLINE_LOGOUT:
			ftm_gooffline_arg = 2;
			break;
		case STATE_GOOFFLINE_WAITTRANSFER:
			ftm_gooffline_arg = 1;
			break;
		case STATE_GOOFFLINE_NOW:
			ftm_gooffline_arg = 0;
			break;
		default:
			return false;
		}

		for (auto & listenSocket : m_ListenSocketList) {
			listenSocket->Close();
			delete listenSocket;
		}
		m_ListenSocketList.clear();

		std::move(m_ThreadArray.begin(), m_ThreadArray.end(), std::back_inserter(m_ClosedThreads));
		m_ThreadArray.clear();
		for (auto & closedThread : m_ClosedThreads) {
			closedThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, ftm_gooffline_arg);
		}
		m_nServerState &= ~STATE_ONLINE;
		if (!m_ClosedThreads.empty()) {
			m_nServerState |= nServerState & STATE_MASK_GOOFFLINE;
		}
	}
	else if (nServerState & STATE_ONLINE) {
		if (m_ListenSocketList.empty()) {
			if (!CreateListenSocket()) {
				ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1);
				return true;
			}
		}

		if (!m_ListenSocketList.empty()) {
			ShowStatus(_T("Server online"), 0);
			int num = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_THREADNUM) : 2);

			//Recreate the threads
			while (m_ThreadArray.size() < num) {
				int index = GetNextThreadNotificationID();
				CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
				m_ThreadNotificationIDs[index] = pThread;
				if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) {
					m_ThreadArray.push_back(pThread);
					pThread->ResumeThread();
				}
			}
		}
		for (auto iter = m_ListenSocketList.begin(); iter != m_ListenSocketList.end(); ++iter)
			(*iter)->m_bLocked = nServerState & STATE_LOCKED;

		// Set closing threads to "wait until logout" mode.
		for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); ++iter)
			(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);

		m_nServerState = (m_ListenSocketList.empty() ? 0 : STATE_ONLINE) | (nServerState & STATE_LOCKED);
	}

	SendState();
	return true;
}
Ejemplo n.º 17
0
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength)
{
	switch (nID)
	{
	case 2:
		if (!nDataLength) {
			unsigned char buffer[2];
			buffer[0] = m_nServerState / 256;
			buffer[1] = m_nServerState % 256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else if (nDataLength == 2) {
			ToggleActive(*pData * 256 + pData[1]);
			unsigned char buffer[2];
			buffer[0] = m_nServerState / 256;
			buffer[1] = m_nServerState % 256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
		break;
	case 3:
		if (!nDataLength) {
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
		}
		else if (*pData == USERCONTROL_GETLIST) {
			int len = 4;
			std::map<int, t_connectiondata>::iterator iter;
			for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) {
				const t_connectiondata& data = iter->second;
				auto ip = ConvToNetwork(data.ip);
				auto user = ConvToNetwork(data.user);
				len += 4 + ip.size() + 2 + 4 + user.size() + 2 + 1;
				if (data.transferMode) {
					auto physicalFile = ConvToNetwork(data.physicalFile);
					auto logicalFile = ConvToNetwork(data.logicalFile);
					len += 2 + physicalFile.size() + 2 + logicalFile.size();

					if (data.currentOffset != 0)
						len += 8;
					if (data.totalSize != -1)
						len += 8;
				}
			}
			unsigned char *buffer = new unsigned char[len];
			buffer[0] = USERCONTROL_GETLIST;
			buffer[1] = ((m_UsersList.size() / 256) / 256) & 0xff;
			buffer[2] = (m_UsersList.size() / 256) & 0xff;
			buffer[3] = m_UsersList.size() % 256;
			unsigned char *p = buffer + 4;
			for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) {
				const t_connectiondata& data = iter->second;
				auto ip = ConvToNetwork(data.ip);
				auto user = ConvToNetwork(data.user);

				memcpy(p, &data.userid, 4);
				p += 4;
				*p++ = (ip.size() / 256) & 0xff;
				*p++ = ip.size() % 256;
				memcpy(p, ip.c_str(), ip.size());
				p += ip.size();

				memcpy(p, &data.port, 4);
				p += 4;

				*p++ = (user.size() / 256) & 0xff;
				*p++ = user.size() % 256;
				memcpy(p, user.c_str(), user.size());
				p += user.size();

				*p = data.transferMode;
				if (data.transferMode) {
					// Bit 5 and 6 indicate presence of currentOffset and totalSize.
					if (data.currentOffset != 0) {
						*p |= 0x20;
					}
					if (data.totalSize != -1) {
						*p |= 0x40;
					}
					p++;

					auto physicalFile = ConvToNetwork(data.physicalFile);
					*p++ = (physicalFile.size() / 256) & 0xff;
					*p++ = physicalFile.size() % 256;
					memcpy(p, physicalFile.c_str(), physicalFile.size());
					p += physicalFile.size();

					auto logicalFile = ConvToNetwork(data.logicalFile);
					*p++ = (logicalFile.size() / 256) & 0xff;
					*p++ = logicalFile.size() % 256;
					memcpy(p, logicalFile.c_str(), logicalFile.size());
					p += logicalFile.size();

					if (data.currentOffset != 0) {
						memcpy(p, &data.currentOffset, 8);
						p += 8;
					}
					if (data.totalSize != -1) {
						memcpy(p, &data.totalSize, 8);
						p += 8;
					}
				}
				else {
					p++;
				}
			}
			m_pAdminInterface->SendCommand(1, 3, buffer, len);
			delete [] buffer;
		}
		else if (*pData == USERCONTROL_KICK || *pData == USERCONTROL_BAN) {
			if (nDataLength != 5)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				int nUserID;
				memcpy(&nUserID, pData+1, 4);

				std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID);
				if (iter!=m_UsersList.end()) {
					if (*pData == USERCONTROL_BAN) {
						// Get the list of IP filter rules.
						CStdString ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
						if (ips != _T(""))
							ips += _T(" ");

						int pos = ips.Find(' ');
						while (pos != -1) {
							CStdString blockedIP = ips.Left(pos);
							ips = ips.Mid(pos + 1);
							pos = ips.Find(' ');

							if (MatchesFilter(blockedIP, iter->second.ip))
								break;
						}
						if (pos == -1) {
							ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
							if (ips != _T(""))
								ips += _T(" ");
							ips += iter->second.ip;
							m_pOptions->SetOption(OPTION_IPFILTER_DISALLOWED, ips);
						}
					}
					t_controlmessage *msg = new t_controlmessage;
					msg->command = USERCONTROL_KICK;
					msg->socketid = nUserID;
					iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg);
					char buffer[2];
					buffer[0] = *pData;
					buffer[1] = 0;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
				else {
					char buffer[2];
					buffer[0] = USERCONTROL_KICK;
					buffer[1] = 1;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
			}
		}
		else
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data")+1);
		break;
	case 5:
		if (!nDataLength) {
			unsigned char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength)) {
				pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength);
				delete [] pBuffer;
			}
		}
		else if (m_pOptions) {
			if (nDataLength < 2)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				CStdString const listenPorts = m_pOptions->GetOption(OPTION_SERVERPORT);
				CStdString const listenPortsSsl = m_pOptions->GetOption(OPTION_TLSPORTS);
				bool const enableSsl = m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0;
				CStdString const ipBindings = m_pOptions->GetOption(OPTION_IPBINDINGS);
				int const nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT);
				CStdString const adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);

				CStdString peerIP;
				UINT port = 0;
				bool bLocal = false;
				if (!pAdminSocket->GetPeerName(peerIP, port))
					return FALSE;
				else
					bLocal = IsLocalhost(peerIP);

				if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal)) {
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 5, &buffer, 1);
					break;
				}

				char buffer = 0;
				pAdminSocket->SendCommand(1, 5, &buffer, 1);

				unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
				if (m_nServerState & STATE_ONLINE) {
					if (threadnum > m_ThreadArray.size()) {
						while (threadnum > m_ThreadArray.size()) {
							int index = GetNextThreadNotificationID();
							CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
							m_ThreadNotificationIDs[index] = pThread;
							if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) {
								pThread->ResumeThread();
								m_ThreadArray.push_back(pThread);
							}
						}
						CStdString str;
						str.Format(_T("Number of threads increased to %d."), threadnum);
						ShowStatus(str, 0);
					}
					else if (threadnum < m_ThreadArray.size()) {
						CStdString str;
						str.Format(_T("Decreasing number of threads to %d."), threadnum);
						ShowStatus(str, 0);
						unsigned int i = 0;
						std::vector<CServerThread *> newList;
						for (auto iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++, i++) {
							if (i >= threadnum) {
								(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
								m_ClosedThreads.push_back(*iter);
							}
							else
								newList.push_back(*iter);
						}
						m_ThreadArray.swap(newList);
					}
				}
				if (listenPorts != m_pOptions->GetOption(OPTION_SERVERPORT) ||
					enableSsl != (m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0) ||
					(m_pOptions->GetOptionVal(OPTION_ENABLETLS) && listenPortsSsl != m_pOptions->GetOption(OPTION_TLSPORTS)) ||
					ipBindings != m_pOptions->GetOption(OPTION_IPBINDINGS))
				{
					if (!m_ListenSocketList.empty()) {
						ShowStatus(_T("Closing all listening sockets"), 0);
						for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); ++listIter) {
							(*listIter)->Close();
							delete *listIter;
						}
						m_ListenSocketList.clear();

						if (!CreateListenSocket()) {
							ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1);
							m_nServerState &= ~STATE_ONLINE;
						}
						else {
							ShowStatus(_T("Listen socket port changed"), 0);
							if (!(m_nServerState & STATE_MASK_GOOFFLINE))
								m_nServerState |= STATE_ONLINE;
						}
						SendState();
					}
				}
				if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings != m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)) {
					CreateAdminListenSocket();
				}

				VerifyTlsSettings(pAdminSocket);
				VerifyPassiveModeSettings(pAdminSocket);
			}
		}
		break;
	case 6:
		if (!nDataLength) {
			unsigned char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			CPermissions permissions = CPermissions(std::function<void()>());
			permissions.GetAsCommand(&pBuffer, &nBufferLength);
			pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength);
			delete [] pBuffer;
		}
		else {
			if (nDataLength < 2)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				CPermissions permissions = CPermissions(std::function<void()>());
				if (!permissions.ParseUsersCommand(pData, nDataLength)) {
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 6, &buffer, 1);
					break;
				}
				char buffer = 0;
				pAdminSocket->SendCommand(1, 6, &buffer, 1);
			}
		}
		break;
	case 8:
		pAdminSocket->SendCommand(1, 8, NULL, 0);
		break;
	default:
		{
			CStdStringA str;
			str.Format("\001Protocol error: Unknown command (%d).", nID);
			pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength());
		}
		break;
	}

	return TRUE;
}
Ejemplo n.º 18
0
int main(int argc, char* argv[])
{
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
	{
		printf("윈도우 소켓 초기화 실패! \n");
		return -1;
	}

	// (socket + bind + listen)
	if(!CreateListenSocket())
	{
		printf("대기 소켓 생성 실패\n");
		return -1;
	}

	// 서버처리
	//===================================================
	int index = 0;
	WSANETWORKEVENTS neEvents;
	char buf[BUFFERSIZE];
	memset(buf, 0, BUFFERSIZE);
	while(1)
	{
		// 이벤트 시그널 감지
		index = WSAWaitForMultipleEvents(g_SockCnt, EventList,
			FALSE, WSA_INFINITE, FALSE);
		index -= WSA_WAIT_EVENT_0;
		// 이벤트 내용 가져오기 + EventList[index] 이벤트를 넌시그날로 변경
		WSAEnumNetworkEvents( SockList[index], EventList[index], &neEvents);
		if(neEvents.lNetworkEvents & FD_ACCEPT)
		{
			if(neEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
			{
				DisplayMessage();
				return -1;
			}
			SOCKET ClientSocket;
			SOCKADDR_IN sockaddr;
			int addrlen = sizeof(sockaddr);
			ClientSocket = accept(SockList[index], (SOCKADDR*)&sockaddr, &addrlen);
			if(ClientSocket == SOCKET_ERROR)
			{
				DisplayMessage();	continue;
			}
			printf("\n[TCP 서버] 클라이언트 접속: IP주소=%s, 포트 번호=%d\n",
				inet_ntoa(sockaddr.sin_addr), ntohs(sockaddr.sin_port));
			WSAEVENT hClientEvent = WSACreateEvent();
			WSAEventSelect(ClientSocket, hClientEvent, FD_WRITE | FD_READ | FD_CLOSE);

			SockList[g_SockCnt] = ClientSocket;
			EventList[g_SockCnt] = hClientEvent;
			g_SockCnt++;
		}
		else if(neEvents.lNetworkEvents & FD_READ || neEvents.lNetworkEvents & FD_WRITE)
		{
			if(neEvents.iErrorCode[FD_READ_BIT] != 0 && neEvents.iErrorCode[FD_WRITE_BIT] != 0)
			{
				DisplayMessage();
				return -1;
			}
			SOCKET ClientSocket = SockList[index];
			SOCKADDR_IN senderaddr;
			int addrlen = sizeof(senderaddr);
			recv(ClientSocket, buf, BUFFERSIZE, 0);
			getpeername(ClientSocket, (SOCKADDR *)&senderaddr, &addrlen);
			printf("[%s] %s\n", inet_ntoa(senderaddr.sin_addr), buf);
			for(int i = 1; i<g_SockCnt; i++)
			{
				if(i != index)
					send(SockList[i], buf, sizeof(buf), 0);
			}
		}
		else if(neEvents.lNetworkEvents & FD_CLOSE)
		{
			if(neEvents.iErrorCode[FD_CLOSE_BIT] != 0)
			{
				DisplayMessage();
				return -1;
			}
		}
		

		

	
	}
	//===================================================

	WSACleanup();
	return 0;
}
Ejemplo n.º 19
0
int main(int argc, char** argv) {
  int c;
  int sockfd, newsockfd;
  int federated = 0, debug = 0, max_ttl = 10;
  time_t tt;
  socklen_t clilen;
  char* srcname = NULL;
  char* listenport = LISTEN_PORT;
  int conn_options = 0;

  char *ErLogFileName = BASEDIR
      "/"ERLOGFILE;
  char *AcLogFileName = BASEDIR
      "/"ACLOGFILE;
  struct sockaddr_storage cli_addr;
  I2Addr listenaddr = NULL;
  Allowed* ptr;

#ifdef AF_INET6
#define GETOPT_LONG_INET6(x) "46"x
#else
#define GETOPT_LONG_INET6(x) x
#endif

  while ((c = getopt_long(argc, argv, GETOPT_LONG_INET6("dhl:e:p:t:Ff:b:sS:v"),
                          long_options, 0)) != -1) {
    switch (c) {
      case '4':
        conn_options |= OPT_IPV4_ONLY;
        break;
      case '6':
        conn_options |= OPT_IPV6_ONLY;
        break;
      case 'd':
        debug++;
        break;
      case 'h':
        www_long_usage("ANL/Internet2 NDT version " VERSION " (fakewww)");
        break;
      case 'v':
        printf("ANL/Internet2 NDT version %s (fakewww)\n", VERSION);
        exit(0);
        break;
      case 'l':
        AcLogFileName = optarg;
        break;
      case 'e':
        ErLogFileName = optarg;
        break;
      case 'p':
        listenport = optarg;
        break;
      case 't':
        max_ttl = atoi(optarg);
        break;
      case 'F':
        federated = 1;
        break;
      case 'f':
        ptr = malloc(sizeof(Allowed));
        ptr->filename = optarg;
        ptr->next = a_root;
        a_root = ptr;
        break;
      case 'b':
        basedir = optarg;
        break;
      case 's':
        usesyslog = 1;
        break;
      case 'S':
        SysLogFacility = optarg;
        break;
      case 301:
        DefaultTree = optarg;
        break;
#ifdef AF_INET6
      case 302:
        DefaultTree6 = optarg;
        break;
#endif
      case '?':
        short_usage(argv[0], "");
        break;
    }
  }

  if (optind < argc) {
    short_usage(argv[0], "Unrecognized non-option elements");
  }

  log_init(argv[0], debug);

  if (SysLogFacility != NULL) {
    int i = 0;
    while (facilitynames[i].c_name) {
      if (strcmp(facilitynames[i].c_name, SysLogFacility) == 0) {
        syslogfacility = facilitynames[i].c_val;
        break;
      }
      ++i;
    }
    if (facilitynames[i].c_name == NULL) {
      log_println(
          0,
          "Warning: Unknown syslog facility [%s] --> using default (%d)",
          SysLogFacility, syslogfacility);
      SysLogFacility = NULL;
    }
  }

  if (DefaultTree == NULL) {
    snprintf(dtfn, sizeof(dtfn), "%s/%s", BASEDIR, DFLT_TREE);
    DefaultTree = dtfn;
  }

#ifdef AF_INET6
  if (DefaultTree6 == NULL) {
    snprintf(dt6fn, sizeof(dtfn), "%s/%s", BASEDIR, DFLT_TREE6);
    DefaultTree6 = dt6fn;
  }
#endif

  /*
   * Bind our local address so that the client can send to us.
   */
  if (srcname && !(listenaddr = I2AddrByNode(get_errhandle(), srcname))) {
    err_sys("server: Invalid source address specified");
  }
  if ((listenaddr = CreateListenSocket(listenaddr, listenport, conn_options,
                                       0)) == NULL) {
    err_sys("server: CreateListenSocket failed");
  }
  sockfd = I2AddrFD(listenaddr);

  tt = time(0);
  log_println(1, "%15.15s fakewww server started (NDT version %s)",
              ctime(&tt) + 4, VERSION);
  log_println(1, "\tport = %d", I2AddrPort(listenaddr));
  log_println(1, "\tfederated mode = %s", (federated == 1) ? "on" : "off");
  log_println(1, "\taccess log = %s\n\terror log = %s", AcLogFileName,
              ErLogFileName);
  log_println(1, "\tbasedir = %s", basedir);
  if (usesyslog) {
    log_println(1, "\tsyslog facility = %s (%d)",
                SysLogFacility ? SysLogFacility : "default", syslogfacility);
  }
  log_println(1, "\tdebug level set to %d", debug);

  logErLog(ErLogFileName, &tt, "notice",
           "fakewww server started (NDT version %s)", VERSION);
  logErLog(ErLogFileName, &tt, "notice", "\tport = %d",
           I2AddrPort(listenaddr));
  logErLog(ErLogFileName, &tt, "notice", "\tfederated mode = %s",
           (federated == 1) ? "on" : "off");
  logErLog(ErLogFileName, &tt, "notice", "\taccess log = %s", AcLogFileName);
  logErLog(ErLogFileName, &tt, "notice", "\terror log = %s", ErLogFileName);
  logErLog(ErLogFileName, &tt, "notice", "\tbasedir = %s", basedir);
  if (usesyslog) {
    logErLog(ErLogFileName, &tt, "notice", "\tsyslog facility = %s (%d)",
             SysLogFacility ? SysLogFacility : "default", syslogfacility);
  }
  logErLog(ErLogFileName, &tt, "notice", "\tdebug level set to %d", debug);

  if (usesyslog == 1)
    syslog(LOG_FACILITY | LOG_INFO, "Fakewww (ver %s) process started",
           VERSION);
  signal(SIGCHLD, reap); /* get rid of zombies */

  /*
   * Wait for a connection from a client process.
   * This is an example of a concurrent server.
   */

  for (;;) {
    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0) {
      if (errno == EINTR)
        continue; /*sig child */
      err_sys("Fakewww server: accept error");
    }

    if (fork() == 0) { /* child */
      I2Addr caddr = I2AddrBySAddr(get_errhandle(),
                                   (struct sockaddr *) &cli_addr, clilen, 0, 0);
      alarm(300); /* kill child off after 5 minutes, should never happen */
      close(sockfd);
      dowww(newsockfd, caddr, listenport, AcLogFileName, ErLogFileName,
            federated, max_ttl);
      exit(0);
    }
    close(newsockfd);
  }
}
Ejemplo n.º 20
0
void __cdecl main (int argc, char *argv[])	{

    SYSTEM_INFO systemInfo;
	WSADATA wsaData;
	DWORD dwThreadCount = 0;
	int nRet = 0;

    g_ThreadHandles[0] = (HANDLE)WSA_INVALID_EVENT;

	for( int i = 0; i < MAX_WORKER_THREAD; i++ ) {
		g_ThreadHandles[i] = INVALID_HANDLE_VALUE;
	}

	if( !ValidOptions(argc, argv) )
		return;

	if( !SetConsoleCtrlHandler(CtrlHandler, TRUE) ) {
		myprintf("SetConsoleCtrlHandler() failed to install console handler: %d\n", 
				GetLastError());
		return;
	}

	GetSystemInfo(&systemInfo);
	dwThreadCount = systemInfo.dwNumberOfProcessors * 2;

	if(WSA_INVALID_EVENT == (g_hCleanupEvent[0] = WSACreateEvent()))
	{
		myprintf("WSACreateEvent() failed: %d\n", WSAGetLastError());
		return;
	}

	if( (nRet = WSAStartup(0x202, &wsaData)) != 0 ) {
		myprintf("WSAStartup() failed: %d\n",nRet);
		SetConsoleCtrlHandler(CtrlHandler, FALSE);
		if(g_hCleanupEvent[0] != WSA_INVALID_EVENT) {
			WSACloseEvent(g_hCleanupEvent[0]);
			g_hCleanupEvent[0] = WSA_INVALID_EVENT;
		}
		return;
	}

    __try
    {
        InitializeCriticalSection(&g_CriticalSection);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        myprintf("InitializeCriticalSection raised an exception.\n");
		SetConsoleCtrlHandler(CtrlHandler, FALSE);
		if(g_hCleanupEvent[0] != WSA_INVALID_EVENT) {
			WSACloseEvent(g_hCleanupEvent[0]);
			g_hCleanupEvent[0] = WSA_INVALID_EVENT;
		}
		return;
    }

	while( g_bRestart ) {
		g_bRestart = FALSE;
		g_bEndServer = FALSE;
		WSAResetEvent(g_hCleanupEvent[0]);

		__try	{

            //
			// notice that we will create more worker threads (dwThreadCount) than 
			// the thread concurrency limit on the IOCP.
			//
			g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
            if( g_hIOCP == NULL ) {
				myprintf("CreateIoCompletionPort() failed to create I/O completion port: %d\n", 
						GetLastError());
				__leave;
			}

			for( DWORD dwCPU=0; dwCPU<dwThreadCount; dwCPU++ ) {

				//
				// Create worker threads to service the overlapped I/O requests.  The decision
				// to create 2 worker threads per CPU in the system is a heuristic.  Also,
				// note that thread handles are closed right away, because we will not need them
				// and the worker threads will continue to execute.
				//
				HANDLE  hThread;
				DWORD   dwThreadId;

				hThread = CreateThread(NULL, 0, WorkerThread, g_hIOCP, 0, &dwThreadId);
				if( hThread == NULL ) {
					myprintf("CreateThread() failed to create worker thread: %d\n", 
						   GetLastError());
					__leave;
				}
				g_ThreadHandles[dwCPU] = hThread;
				hThread = INVALID_HANDLE_VALUE;
			}

			if( !CreateListenSocket() )
				__leave;

			if( !CreateAcceptSocket(TRUE) )
				__leave;

			WSAWaitForMultipleEvents(1, g_hCleanupEvent, TRUE, WSA_INFINITE, FALSE);
		}

		__finally	{

			g_bEndServer = TRUE;

			//
			// Cause worker threads to exit
			//
			if( g_hIOCP ) {
				for( DWORD i = 0; i < dwThreadCount; i++ )
					PostQueuedCompletionStatus(g_hIOCP, 0, 0, NULL);
			}

            //
			// Make sure worker threads exits.
			//
			if( WAIT_OBJECT_0 != WaitForMultipleObjects(dwThreadCount,  g_ThreadHandles, TRUE, 1000) )
				myprintf("WaitForMultipleObjects() failed: %d\n", GetLastError());
			else
				for( DWORD i=0; i<dwThreadCount; i++ ) {
					if( g_ThreadHandles[i] != INVALID_HANDLE_VALUE )
						CloseHandle(g_ThreadHandles[i]);
					g_ThreadHandles[i] = INVALID_HANDLE_VALUE;
				}

			if( g_sdListen != INVALID_SOCKET ) {
				closesocket(g_sdListen);                                
				g_sdListen = INVALID_SOCKET;
			}

			if( g_pCtxtListenSocket ) {
				while( !HasOverlappedIoCompleted((LPOVERLAPPED)&g_pCtxtListenSocket->pIOContext->Overlapped) )
					Sleep(0);

				if( g_pCtxtListenSocket->pIOContext->SocketAccept != INVALID_SOCKET )
					closesocket(g_pCtxtListenSocket->pIOContext->SocketAccept);
				g_pCtxtListenSocket->pIOContext->SocketAccept = INVALID_SOCKET;

                //
				// We know there is only one overlapped I/O on the listening socket
				//
				if( g_pCtxtListenSocket->pIOContext )
					xfree(g_pCtxtListenSocket->pIOContext);

				if( g_pCtxtListenSocket )
					xfree(g_pCtxtListenSocket);
				g_pCtxtListenSocket = NULL;
			}

			CtxtListFree();

			if( g_hIOCP ) {
				CloseHandle(g_hIOCP);
				g_hIOCP = NULL;
			}
		} //finally

		if( g_bRestart ) {
			myprintf("\niocpserverex is restarting...\n");
		} else
			myprintf("\niocpserverex is exiting...\n");

	} //while (g_bRestart)

	DeleteCriticalSection(&g_CriticalSection);
	if(g_hCleanupEvent[0] != WSA_INVALID_EVENT) {
		WSACloseEvent(g_hCleanupEvent[0]);
		g_hCleanupEvent[0] = WSA_INVALID_EVENT;
	}
	WSACleanup();
	SetConsoleCtrlHandler(CtrlHandler, FALSE);
} //main
Ejemplo n.º 21
0
// -------------------------------------------------------------------------------------------------------------------------------------------------------
bool IOCP::StartNetwork(UINT NumberOfThreads)
{
	bool bReturn		= true;
	// -----
	if ( WSAStartup(MAKEWORD(2,2), &this->wsData) != NULL )
	{
		CLog.Error("Could't Start Up WSA Library.");
		// -----
		bReturn			= false;
	}
	// -----
	Sleep(m_DelaySNet);
	// -----
	if ((m_hCmport = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0)) == NULL )
	{
		CLog.Error("Couldn't Create Completion Port() Failed: [%d].", GetLastError());
		// -----
		bReturn			= false;
	}
	// -----
	Sleep(m_DelaySNet);
	// -----
	if(CreateListenSocket() == false)
	{
		CLog.Error("[IOCP] Couldn't Create Socket() Failed: [%d].", GetLastError());
		// -----
		bReturn = false;
	}
	// -----
	Sleep(m_DelaySNet);
	// -----
	for (int i = 0; i != 4; i++)
	{
		if ( ( m_ListThread = CreateThread(NULL, 0, (LPTHREAD)ListenWorker, (LPVOID)this, 0, &m_ThreadID) ) == NULL )
		{
			CLog.Error("Couldn't Create ListenThread() Failed: [%d].", GetLastError());
			// -----
			bReturn = false;
		}
	}
	// -----
	Sleep(m_DelaySNet);
	// -----
	for (int i = 0 ; i != NumberOfThreads; i++)
    {
        if ( ( m_hThread[i] = CreateThread(NULL, 0, RecvWorker, (LPVOID)this, 0, &m_ThreadID) ) == NULL )
        {
			CLog.Error("Couldn't Create RecvThread() Failed: [%d].", GetLastError());
            // -----
            bReturn = false;
        }
        // -----
		m_nThreadCount++;
	}
	// -----
	Sleep(m_DelaySNet);
	// -----
	CLog.Connect("%s Started! Port [%d].", m_Name, m_nPort);
	// -----
	return bReturn;
}
Ejemplo n.º 22
0
int CMainCtrl::Initialize(char* pProName,char* pConfigFile)
{
	//读配置
	strcpy(m_stConfig.m_szSvrName,pProName);
	int iRet = ReadCfgFile(pConfigFile);
	if( 0 != iRet )
	{
		return iRet;
	}

	//连接资源限制,root用户下有效
	rlimit rlim;
	rlim.rlim_cur = m_stConfig.MAX_SOCKET_NUM+10240;
	rlim.rlim_max = m_stConfig.MAX_SOCKET_NUM+10240;
	setrlimit(RLIMIT_NOFILE, &rlim);	

	//bind cpu
	if(m_stConfig.m_iBindCpu >= 0)
	{
		cpu_set_t mask;
		int iCpuId = m_stConfig.m_iBindCpu;
		printf("set cpu affinity %d.\n",iCpuId);
		
		CPU_ZERO(&mask);
		CPU_SET(iCpuId, &mask);
		sched_setaffinity(0, sizeof(mask), &mask);
	}
	
	//读so
	void* pHandle = dlopen(m_stConfig.m_szNetCompleteSo, RTLD_LAZY);
	if (!pHandle)
	{
		printf("open %s failed!\n",m_stConfig.m_szNetCompleteSo);
		printf("use ccs/src/make -f makefile.complete to make these so,and choose the one you want.\n");
		return -1;
	}	
	dlerror();  	//Clear any existing error 
	net_complete_func = (check_complete)dlsym(pHandle, "net_complete_func");
	if (dlerror() != NULL)
	{
		printf("get net_complete_func from %s failed!\n",m_stConfig.m_szNetCompleteSo);
		return -1;
	}
	msg_header_len_func = (msg_header_len)dlsym(pHandle, "msg_header_len");
	if (dlerror() != NULL)
	{
		printf("get msg_header_len from %s failed!\n",m_stConfig.m_szNetCompleteSo);
		return -1;
	}
	m_iMsgHeaderLen = msg_header_len_func();

	//初始化epoll端口
	if(m_stEPollFlow.Create(m_stConfig.MAX_SOCKET_NUM))
	{
		printf("epoll create error!");
		return -1;
	}

	//创建管道
	if(CCodeQueue::CreateMQByFile(m_stConfig.m_szMeToSvrMQ,&m_Me2SvrPipe))
	{
		printf("CreateCodeMQ %s failed!\n",m_stConfig.m_szMeToSvrMQ);
		return -1;	
	}
	
	if(CCodeQueue::CreateMQByFile(m_stConfig.m_szSvrToMeMQ,&m_Svr2MePipe))
	{
		printf("CreateCodeMQ %s failed!\n",m_stConfig.m_szSvrToMeMQ);
		return -1;	
	}
	long long ullMemCost = 0;
	
	//创建CS消息缓冲区
	int iMemSize = TIdxObjMng::CountMemSize(m_stConfig.RCV_BLOCK_SIZE,m_stConfig.RCV_BLOCK_NUM,1);
	char* pMem = new char[iMemSize];
	m_stIdxObjMngRecv.AttachMem(pMem,iMemSize,m_stConfig.RCV_BLOCK_SIZE,m_stConfig.RCV_BLOCK_NUM,emInit,1);
	ullMemCost += (long long)iMemSize;

	iMemSize = CBuffMng::CountMemSize(m_stConfig.MAX_SOCKET_NUM);
	pMem = new char[iMemSize];	
	m_stBuffMngRecv.AttachMem(pMem,iMemSize,m_stConfig.MAX_SOCKET_NUM);
	ullMemCost += (long long)iMemSize;

	m_stBuffMngRecv.AttachIdxObjMng(&m_stIdxObjMngRecv);
	
	//创建SC消息缓冲区
	iMemSize = TIdxObjMng::CountMemSize(m_stConfig.SND_BLOCK_SIZE,m_stConfig.SND_BLOCK_NUM,1);
	pMem = new char[iMemSize];
	m_stIdxObjMngSend.AttachMem(pMem,iMemSize,m_stConfig.SND_BLOCK_SIZE,m_stConfig.SND_BLOCK_NUM,emInit,1);
	ullMemCost += (long long)iMemSize;

	iMemSize = CBuffMng::CountMemSize(m_stConfig.MAX_SOCKET_NUM);
	pMem = new char[iMemSize];	
	m_stBuffMngSend.AttachMem(pMem,iMemSize,m_stConfig.MAX_SOCKET_NUM);
	ullMemCost += (long long)iMemSize;

	m_stBuffMngSend.AttachIdxObjMng(&m_stIdxObjMngSend);

	//创建socket管理区
	iMemSize = TIdxObjMng::CountMemSize(sizeof(TSocketNode),m_stConfig.MAX_SOCKET_NUM,1);
	pMem = new char[iMemSize];
	m_stSocketNodeMng.AttachMem(pMem,iMemSize,sizeof(TSocketNode),m_stConfig.MAX_SOCKET_NUM,emInit,1);
	ullMemCost += (long long)iMemSize;

	iMemSize = CHashTab::CountMemSize(m_stConfig.MAX_SOCKET_NUM);
	pMem = new char[iMemSize];
	m_stSocketNodeHash.AttachMem(pMem, iMemSize,m_stConfig.MAX_SOCKET_NUM);
	ullMemCost += (long long)iMemSize;

	m_stSocketNodeHash.AttachIdxObjMng(&m_stSocketNodeMng,SetSocketNodeKey,GetSocketNodeKey);

	//内存管道监听
	if (m_Svr2MePipe.GetReadNotifyFD() >= 0)
	{
		iRet = CreateSocketNode(m_Svr2MePipe.GetReadNotifyFD(),TSocketNode::STATUS_OK,
							0,0,"_PIPE_",TSocketNode::PIPE_SOCKET);
		if(iRet < 0)
		{
			printf("CreateSocketNode Failed!iRet=%d\n",iRet);
			return iRet;
		}		
	}

	//管理端口
	if(m_stConfig.m_iAdminPort > 0)
	{
		unsigned short usListenPort = (unsigned short)m_stConfig.m_iAdminPort;
		unsigned int unListenIP = inet_addr(m_stConfig.m_szAdminIp);
		
		int iListenSocket = CreateListenSocket(unListenIP,usListenPort,
					m_stConfig.SOCKET_RCVBUF,m_stConfig.SOCKET_SNDBUF);
		if (iListenSocket < 0)
		{
			printf("CreateListenSocket %u:%u failed!\n",unListenIP,usListenPort);
			TLib_Log_LogMsg("CreateListenSocket %u:%u failed!\n",unListenIP,usListenPort);
			return -2;		
		}
		
		//加入监听数组
		int iNewSuffix = CreateSocketNode(iListenSocket,TSocketNode::STATUS_OK,
						unListenIP,usListenPort,"_ADMIN_",TSocketNode::ADMIN_LISTEN_SOCKET);
		if (iNewSuffix < 0)
		{
			close(iListenSocket);		
			printf("add to socket array failed!\n");
			TLib_Log_LogMsg("add to socket array failed!\n");
			return -3;
		}		

		printf("Admin Listen on %s:%u Success!\n", m_stConfig.m_szAdminIp, m_stConfig.m_iAdminPort);		
	}

	printf("%s Cost Mem %llu bytes.\n",SVR_NAME,ullMemCost);
	TLib_Log_LogMsg("Cost Mem %llu bytes.\n",ullMemCost);	
	printf("Server Init Success!\n");
	TLib_Log_LogMsg("Server Init Success!\n");
	return 0;
}
Ejemplo n.º 23
0
/**
 * Perform the C2S Throughput test. This test intends to measure throughput
 * from the client to the server by performing a 10 seconds memory-to-memory
 * data transfer.
 *
 * Protocol messages are exchanged between the Client and the Server using the
 * same connection and message format as the NDTP-Control protocol.Throughput
 * packets are sent on the new connection and do not follow the NDTP-Control
 * protocol message format.
 *
 * When the Client stops streaming the test data (or the server test routine
 * times out), the Server sends the Client its calculated throughput value.
 *
 * @param ctl Client control Connection
 * @param agent Web100 agent used to track the connection
 * @param testOptions Test options
 * @param conn_options connection options
 * @param c2sspd In-out parameter to store C2S throughput value
 * @param set_buff enable setting TCP send/recv buffer size to be used (seems
 *                 unused in file)
 * @param window value of TCP send/rcv buffer size intended to be used.
 * @param autotune autotuning option. Deprecated.
 * @param device string device name inout parameter
 * @param options Test Option variables
 * @param record_reverse integer indicating whether receiver-side statistics
 *                       have to be logged
 * @param count_vars count of web100 variables
 * @param spds[] [] speed check array
 * @param spd_index  index used for speed check array
 * @param conn_options Connection options
 * @param ctx The SSL context (possibly NULL)
 * @param c2s_ThroughputSnapshots Variable used to set c2s throughput snapshots
 * @param extended indicates if extended c2s test should be performed
 * @return 0 on success, an error code otherwise
 *         Error codes:
 *           -1 - Listener socket creation failed
 *           -100 - Timeout while waiting for client to connect to server's
 *                  ephemeral port
 *           -101 - Retries exceeded while waiting for client to connect
 *           -102 - Retries exceeded while waiting for data from connected
 *                  client
 *           -errno - Other specific socket error numbers
 */
int test_c2s(Connection *ctl, tcp_stat_agent *agent, TestOptions *testOptions,
             int conn_options, double *c2sspd, int set_buff, int window,
             int autotune, char *device, Options *options, int record_reverse,
             int count_vars, char spds[4][256], int *spd_index, SSL_CTX *ctx,
             struct throughputSnapshot **c2s_ThroughputSnapshots,
             int extended) {
  tcp_stat_connection conn;
  tcp_stat_group *group = NULL;
  /* The pipe that will return packet pair results */
  int mon_pipe[2];
  int packet_trace_running = 0;
  pid_t c2s_childpid = 0;       // child process pids
  int msgretvalue, read_error;  // used during the "read"/"write" process
  int i;                  // used as loop iterator
  int conn_index, attempts;
  int retvalue = 0;
  int streamsNum = 1;
  int activeStreams = 1;
  int local_errno;

  struct sockaddr_storage cli_addr[MAX_STREAMS];
  Connection c2s_conns[MAX_STREAMS];
  struct throughputSnapshot *lastThroughputSnapshot;

  socklen_t clilen;
  char tmpstr[256];  // string array used for all sorts of temp storage purposes
  double start_time, measured_test_duration;
  double throughputSnapshotTime;  // specify the next snapshot time
  double testDuration = 10;       // default test duration
  double bytes_read = 0;    // number of bytes read during the throughput tests
  struct timeval sel_tv;    // time
  fd_set rfd;       // receive file descriptors
  int max_fd;
  char buff[BUFFSIZE + 1];  // message "payload" buffer
  PortPair pair;            // socket ports
  I2Addr c2ssrv_addr = NULL;  // c2s test's server address
  // I2Addr src_addr=NULL;  // c2s test source address
  char listenc2sport[10];  // listening port
  pthread_t workerThreadId;

  // snap related variables
  SnapArgs snapArgs;
  snapArgs.snap = NULL;
#if USE_WEB100
  snapArgs.log = NULL;
#endif
  snapArgs.delay = options->snapDelay;

  // Test ID and status descriptors
  enum TEST_ID testids = extended ? C2S_EXT : C2S;
  enum TEST_STATUS_INT teststatuses = TEST_NOT_STARTED;
  char namesuffix[256] = "c2s_snaplog";

  for (i = 0; i < MAX_STREAMS; i++) {
    c2s_conns[i].socket = 0;
    c2s_conns[i].ssl = NULL;
  }

  if (!extended && testOptions->c2sopt) {
    setCurrentTest(TEST_C2S);
  } else if (extended && testOptions->c2sextopt) {
    setCurrentTest(TEST_C2S_EXT);
  } else {
    return 0;
  }
  log_println(1, " <-- %d - C2S throughput test -->", testOptions->child0);
  strlcpy(listenc2sport, PORT2, sizeof(listenc2sport));

  // log protocol validation logs
  teststatuses = TEST_STARTED;
  protolog_status(testOptions->child0, testids, teststatuses, ctl->socket);

  // Determine port to be used. Compute based on options set earlier
  // by reading from config file, or use default port2 (3002).
  if (testOptions->c2ssockport) {
    snprintf(listenc2sport, sizeof(listenc2sport), "%d",
             testOptions->c2ssockport);
  } else if (testOptions->mainport) {
    snprintf(listenc2sport, sizeof(listenc2sport), "%d",
             testOptions->mainport + 1);
  }

  if (testOptions->multiple) {
    strlcpy(listenc2sport, "0", sizeof(listenc2sport));
  }

  // attempt to bind to a new port and obtain address structure with details
  // of listening port
  while (c2ssrv_addr == NULL) {
    c2ssrv_addr = CreateListenSocket(
        NULL, (testOptions->multiple
                   ? mrange_next(listenc2sport, sizeof(listenc2sport))
                   : listenc2sport),
        conn_options, 0);
    if (strcmp(listenc2sport, "0") == 0) {
      log_println(1, "WARNING: ephemeral port number was bound");
      break;
    }
    if (testOptions->multiple == 0) {
      break;
    }
  }
  if (c2ssrv_addr == NULL) {
    log_println(0,
                "Server (C2S throughput test): CreateListenSocket failed: %s",
                strerror(errno));
    snprintf(buff, sizeof(buff),
             "Server (C2S throughput test): CreateListenSocket failed: %s",
             strerror(errno));
    send_json_message_any(ctl, MSG_ERROR, buff, strlen(buff),
                          testOptions->connection_flags, JSON_SINGLE_VALUE);
    return -1;
  }

  // get socket FD and the ephemeral port number that client will connect to
  // run tests
  testOptions->c2ssockfd = I2AddrFD(c2ssrv_addr);
  testOptions->c2ssockport = I2AddrPort(c2ssrv_addr);
  log_println(1, "  -- c2s %d port: %d", testOptions->child0,
              testOptions->c2ssockport);
  if (extended) {
    log_println(1, "  -- c2s ext -- duration = %d", options->c2s_duration);
    log_println(1,
                "  -- c2s ext -- throughput snapshots: enabled = %s, "
                "delay = %d, offset = %d",
                options->c2s_throughputsnaps ? "true" : "false",
                options->c2s_snapsdelay, options->c2s_snapsoffset);
    log_println(1, "  -- c2s ext -- number of streams: %d",
                options->c2s_streamsnum);
  }
  pair.port1 = testOptions->c2ssockport;
  pair.port2 = -1;

  log_println(
      1, "listening for Inet connection on testOptions->c2ssockfd, fd=%d",
      testOptions->c2ssockfd);

  log_println(
      1, "Sending 'GO' signal, to tell client %d to head for the next test",
      testOptions->child0);
  snprintf(buff, sizeof(buff), "%d", testOptions->c2ssockport);
  if (extended) {
    snprintf(buff, sizeof(buff), "%d %d %d %d %d %d",
             testOptions->c2ssockport, options->c2s_duration,
             options->c2s_throughputsnaps, options->c2s_snapsdelay,
             options->c2s_snapsoffset, options->c2s_streamsnum);
    lastThroughputSnapshot = NULL;
  }

  // send TEST_PREPARE message with ephemeral port detail, indicating start
  // of tests
  if ((msgretvalue = send_json_message_any(
           ctl, TEST_PREPARE, buff, strlen(buff),
           testOptions->connection_flags, JSON_SINGLE_VALUE)) < 0) {
    log_println(2, "Child %d could not send details about ephemeral port",
                getpid());
    return msgretvalue;
  }

  // Wait on listening socket and read data once ready.
  // Retry 5 times,  waiting for activity on the socket
  clilen = sizeof(cli_addr);
  log_println(6, "child %d - sent c2s prepare to client",
              testOptions->child0);
  FD_ZERO(&rfd);
  FD_SET(testOptions->c2ssockfd, &rfd);
  sel_tv.tv_sec = 5;
  sel_tv.tv_usec = 0;
  if (extended) {
    streamsNum = options->c2s_streamsnum;
    testDuration = options->c2s_duration / 1000.0;
  }

  conn_index = 0;
  for (attempts = 0;
       attempts < RETRY_COUNT * streamsNum && conn_index < streamsNum;
       attempts++) {
    msgretvalue = select((testOptions->c2ssockfd) + 1, &rfd, NULL, NULL,
                         &sel_tv);  // TODO
    // socket interrupted. continue waiting for activity on socket
    if ((msgretvalue == -1) && (errno == EINTR)) {
      continue;
    }
    if (msgretvalue == 0)  // timeout
      retvalue = -SOCKET_CONNECT_TIMEOUT;
    if (msgretvalue < 0)  // other socket errors. exit
      retvalue = -errno;
    if (!retvalue) {
      // If a valid connection request is received, client has connected.
      // Proceed.
      c2s_conns[conn_index].socket = accept(
          testOptions->c2ssockfd,
          (struct sockaddr *)&cli_addr[conn_index],
          &clilen);
      // socket interrupted, wait some more
      if ((c2s_conns[conn_index].socket == -1) && (errno == EINTR)) {
        log_println(
            6,
            "Child %d interrupted while waiting for accept() to complete",
            testOptions->child0);
        continue;
      }
      if (c2s_conns[conn_index].socket <= 0) {
        continue;
      }
      log_println(6, "accept(%d/%d) for %d completed", conn_index + 1,
                  streamsNum, testOptions->child0);

      // log protocol validation indicating client accept
      protolog_procstatus(testOptions->child0, testids, CONNECT_TYPE,
                          PROCESS_STARTED, c2s_conns[conn_index].socket);
      if (testOptions->connection_flags & TLS_SUPPORT) {
        errno = setup_SSL_connection(&c2s_conns[conn_index], ctx);
        if (errno != 0) return -errno;
      }

      // To preserve user privacy, make sure that the HTTP header
      // processing is done prior to the start of packet capture, as many
      // browsers have headers that uniquely identify a single user.
      if (testOptions->connection_flags & WEBSOCKET_SUPPORT) {
        if (initialize_websocket_connection(&c2s_conns[conn_index], 0, "c2s") !=
            0) {
          close_all_connections(c2s_conns, streamsNum);
          return -EIO;
        }
      }

      conn_index++;
    }

    if (retvalue) {
      log_println(
          6,
          "-------     C2S connection setup for %d returned because (%d)",
          testOptions->child0, retvalue);
      close_all_connections(c2s_conns, streamsNum);
      return retvalue;
    }
  }
  // If we haven't created enough streams after the loop is over, quit.
  if (conn_index != streamsNum) {
    log_println(
        6,
        "c2s child %d, unable to open connection, return from test",
        testOptions->child0);
     close_all_connections(c2s_conns, streamsNum);
     return RETRY_EXCEEDED_WAITING_DATA;
  }

  // Get address associated with the throughput test. Used for packet tracing
  log_println(6, "child %d - c2s ready for test with fd=%d",
              testOptions->child0, c2s_conns[0].socket);

  // commenting out below to move to init_pkttrace function
  I2Addr src_addr = I2AddrByLocalSockFD(get_errhandle(), c2s_conns[0].socket, 0);

  // Get tcp_stat connection. Used to collect tcp_stat variable statistics
  conn = tcp_stat_connection_from_socket(agent, c2s_conns[0].socket);

  // set up packet tracing. Collected data is used for bottleneck link
  // calculations
  if (getuid() == 0) {
    if (pipe(mon_pipe) != 0) {
      log_println(0, "C2S test error: can't create pipe.");
    } else {
      if ((c2s_childpid = fork()) == 0) {
        close(testOptions->c2ssockfd);
        close_all_connections(c2s_conns, streamsNum);
        // Don't capture more than 14 seconds of packet traces:
        //   2 seconds of sleep + 10 seconds of test + 2 seconds of slop
        alarm(testDuration + RACE_CONDITION_WAIT_TIME + 2);
        log_println(
            5,
            "C2S test Child %d thinks pipe() returned fd0=%d, fd1=%d",
            testOptions->child0, mon_pipe[0], mon_pipe[1]);
        log_println(2, "C2S test calling init_pkttrace() with pd=%p",
                    &cli_addr[0]);
        init_pkttrace(src_addr, cli_addr, streamsNum, clilen,
                      mon_pipe, device, &pair, "c2s", options->c2s_duration / 1000.0);
        log_println(1, "c2s is exiting gracefully");
        /* Close the pipe */
        close(mon_pipe[0]);
        close(mon_pipe[1]);
        exit(0); /* Packet trace finished, terminate gracefully */
      } else if (c2s_childpid < 0) {
        log_println(0, "C2S test error: can't create child process.");
      }
    }

    packet_trace_running = wait_for_readable_fd(mon_pipe[0]);

    if (packet_trace_running) {
      // Get data collected from packet tracing into the C2S "ndttrace" file
      memset(tmpstr, 0, 256);
      for (i = 0; i < 5; i++) {
        msgretvalue = read(mon_pipe[0], tmpstr, 128);
        if ((msgretvalue == -1) && (errno == EINTR))
          continue;
        break;
      }

      if (strlen(tmpstr) > 5)
        memcpy(meta.c2s_ndttrace, tmpstr, strlen(tmpstr));
      // name of nettrace file passed back from pcap child
      log_println(3, "--tracefile after packet_trace %s",
                  meta.c2s_ndttrace);
    } else {
      log_println(0, "Packet trace was unable to be created");
      packet_trace_emergency_shutdown(mon_pipe);
    }
  }

  log_println(5, "C2S test Parent thinks pipe() returned fd0=%d, fd1=%d",
              mon_pipe[0], mon_pipe[1]);

  // experimental code, delete when finished
  setCwndlimit(conn, group, agent, options);

  // Create C->S snaplog directories, and perform some initialization based on
  // options
  create_client_logdir((struct sockaddr *) &cli_addr[0], clilen,
                       options->c2s_logname, sizeof(options->c2s_logname),
                       namesuffix, sizeof(namesuffix));
  sleep(RACE_CONDITION_WAIT_TIME);
  // Reset alarm() again. This 10 sec test should finish before this signal is
  // generated, but sleep() can render existing alarm()s invalid, and alarm() is
  // our watchdog timer.
  alarm(30);

  // send empty TEST_START indicating start of the test
  send_json_message_any(ctl, TEST_START, "", 0, testOptions->connection_flags,
                        JSON_SINGLE_VALUE);

  // If snaplog recording is enabled, update meta file to indicate the same
  // and proceed to get snapshot and log it.
  // This block is needed here since the meta file stores names without the
  // full directory but fopen needs full path. Else, it could have gone into
  // the "start_snap_worker" method
  if (options->snapshots && options->snaplog) {
    memcpy(meta.c2s_snaplog, namesuffix, strlen(namesuffix));
    /*start_snap_worker(&snapArgs, agent, options->snaplog, &workerLoop,
      &workerThreadId, meta.c2s_snaplog, options->c2s_logname,
      conn, group); */
  }
  if (options->snapshots)
    start_snap_worker(&snapArgs, agent, NULL, options->snaplog, &workerThreadId,
                      options->c2s_logname, conn, group);
  // Wait on listening socket and read data once ready.
  start_time = secs();
  throughputSnapshotTime = start_time + (options->c2s_snapsoffset / 1000.0);

  activeStreams = connections_to_fd_set(c2s_conns, streamsNum, &rfd, &max_fd);

  while (activeStreams > 0 && (secs() - start_time) < testDuration) {
    // POSIX says "Upon successful completion, the select() function may
    // modify the object pointed to by the timeout argument."
    // Therefore sel_tv is undefined afterwards and we must set it every time.
    sel_tv.tv_sec = testDuration + 1;  // time out after test duration + 1sec
    sel_tv.tv_usec = 0;
    msgretvalue = select(max_fd + 1, &rfd, NULL, NULL, &sel_tv);
    if (msgretvalue == -1) {
      if (errno == EINTR) {
        // select interrupted. Continue waiting for activity on socket
        continue;
      } else {
        log_println(1,
                    "Error while trying to wait for incoming data in c2s: %s",
                    strerror(errno));
        break;
      }
    }
    if (extended && options->c2s_throughputsnaps && secs() > throughputSnapshotTime) {
      if (lastThroughputSnapshot != NULL) {
        lastThroughputSnapshot->next = (struct throughputSnapshot*) malloc(sizeof(struct throughputSnapshot));
        lastThroughputSnapshot = lastThroughputSnapshot->next;
      } else {
        *c2s_ThroughputSnapshots = lastThroughputSnapshot = (struct throughputSnapshot*) malloc(sizeof(struct throughputSnapshot));
      }
      lastThroughputSnapshot->next = NULL;
      lastThroughputSnapshot->time = secs() - start_time;
      lastThroughputSnapshot->throughput = (8.e-3 * bytes_read) / (lastThroughputSnapshot->time);  // kbps
      log_println(6, " ---C->S: Throughput at %0.2f secs: Received %0.0f bytes, Spdin= %f",
                     lastThroughputSnapshot->time, bytes_read, lastThroughputSnapshot->throughput);
      throughputSnapshotTime += options->c2s_snapsdelay / 1000.0;
    }

    if (msgretvalue > 0) {
      read_error = read_ready_streams(&rfd, c2s_conns, streamsNum, buff, sizeof(buff), &bytes_read);
      if (read_error != 0 && read_error != EINTR) {
        // EINTR is expected, but all other errors are actually errors
        log_println(1, "Error while trying to read incoming data in c2s: %s",
                    strerror(read_error));
        break;
      }
    }

    // Set up the FD_SET and activeStreams for the next select.
    activeStreams = connections_to_fd_set(c2s_conns, streamsNum, &rfd, &max_fd);
  }
  measured_test_duration = secs() - start_time;
  // From the NDT spec:
  //  throughput in kilo bits per sec =
  //  (transmitted_byte_count * 8) / (time_duration)*(1000)
  *c2sspd = (8.0e-3 * bytes_read) / measured_test_duration;

  // As a kindness to old clients, drain their queues for a second or two.
  // TODO: Fix web100clt code to eliminate the need for this.  In general,
  //       clients that need this line should be removed from their respective
  //       gene pools and this code should be deleted.
  drain_old_clients(c2s_conns, streamsNum, buff, sizeof(buff));

  // c->s throuput value calculated and assigned ! Release resources, conclude
  // snap writing.
  if (options->snapshots)
    stop_snap_worker(&workerThreadId, options->snaplog, &snapArgs);

  // send the server calculated value of C->S throughput as result to client
  snprintf(buff, sizeof(buff), "%6.0f kbps outbound for child %d", *c2sspd,
           testOptions->child0);
  log_println(1, "%s", buff);
  snprintf(buff, sizeof(buff), "%0.0f", *c2sspd);
  if (extended && options->c2s_throughputsnaps && *c2s_ThroughputSnapshots != NULL) {
    struct throughputSnapshot *snapshotsPtr = *c2s_ThroughputSnapshots;
    while (snapshotsPtr != NULL) {
      int currBuffLength = strlen(buff);
      snprintf(&buff[currBuffLength], sizeof(buff)-currBuffLength, " %0.2f %0.2f", snapshotsPtr->time, snapshotsPtr->throughput);
      snapshotsPtr = snapshotsPtr->next;
    }
  }
  send_json_message_any(ctl, TEST_MSG, buff, strlen(buff),
                        testOptions->connection_flags, JSON_SINGLE_VALUE);

  // get receiver side Web100 stats and write them to the log file. close
  // sockets
  if (record_reverse == 1)
    tcp_stat_get_data_recv(c2s_conns[0].socket, agent, conn, count_vars);


  close_all_connections(c2s_conns, streamsNum);
  close(testOptions->c2ssockfd);

  if (packet_trace_running) {
    log_println(1, "Signal USR1(%d) sent to child [%d]", SIGUSR1,
                c2s_childpid);
    testOptions->child1 = c2s_childpid;
    kill(c2s_childpid, SIGUSR1);
    i = 0;

    for (;;) {
      FD_ZERO(&rfd);
      FD_SET(mon_pipe[0], &rfd);
      sel_tv.tv_sec = 1;
      sel_tv.tv_usec = 100000;
      msgretvalue = select(mon_pipe[0] + 1, &rfd, NULL, NULL, &sel_tv);
      if (msgretvalue <= 0) {
        local_errno = (msgretvalue == -1) ? errno : 0;
        if (local_errno == EINTR) continue;
        // Either a timeout or an error that wasn't EINTR...
        log_println(4, "Failed to read pkt-pair data from C2S flow, "
                    "retcode=%d, reason=%d", msgretvalue, local_errno);
        snprintf(spds[(*spd_index)++],
                 sizeof(spds[*spd_index]),
                 " -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0.0 0 0 0 0 0 -1");
        snprintf(spds[(*spd_index)++],
                 sizeof(spds[*spd_index]),
                 " -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0.0 0 0 0 0 0 -1");
        break;
      } else {
        /* There is something to read, so get it from the pktpair child.  If an
         * interrupt occurs, just skip the read and go on
         * RAC 2/8/10
         */
        if ((msgretvalue = read(mon_pipe[0], spds[*spd_index],
                                sizeof(spds[*spd_index]))) < 0) {
          snprintf(
              spds[*spd_index],
              sizeof(spds[*spd_index]),
              " -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0.0 0 0 0 0 0 -1");
        }
        log_println(1, "%d bytes read '%s' from C2S monitor pipe",
                    msgretvalue, spds[*spd_index]);
        (*spd_index)++;
        if (i++ == 1) break;
      }
    }
  }

  // An empty TEST_FINALIZE message is sent to conclude the test
  send_json_message_any(ctl, TEST_FINALIZE, "", 0,
                        testOptions->connection_flags, JSON_SINGLE_VALUE);

  //  Close opened resources for packet capture
  if (packet_trace_running) {
    // TODO: Determine whether this shutdown can be performed in a non-blocking
    // manner, and if so then refactor packet_trace_emergency_shutdown to have
    // better error handling and use that refactored and renamed function here.
    stop_packet_trace(mon_pipe);
    packet_trace_running = 0;
  }

  // log end of C->S test
  log_println(1, " <----------- %d -------------->", testOptions->child0);
  // protocol logs
  teststatuses = TEST_ENDED;
  protolog_status(testOptions->child0, testids, teststatuses, ctl->socket);

  // set current test status and free address
  setCurrentTest(TEST_NONE);


  return 0;
}
Ejemplo n.º 24
0
void FTPSession(int controlSocket, char* inputRootDir, struct sockaddr_in remoteAddr)
{
	
	strcpy( dir, inputRootDir ); // copy into new buffer so we can make the directory string larger if needed
	AddTrailingSlashIfNeeded( dir ); // make sure we have a trailing slash on the file
	char properRootDir[PATH_MAX];
	strcpy( properRootDir, dir );
	
	/* Test to see if the directory to serve exists */	
	if ( GetFileInfo(dir) == FILEINFO_DOESNOTEXIST )
		ExitError("Failed to open directory to serve.");
	
	/* Reply 220 to user upon connection */
	if ( send(controlSocket, replies[REPLY_220_BEGIN_SESSION], strlen(replies[REPLY_220_BEGIN_SESSION ]), 0) == -1 )
		ExitError("Error sending reply.");
	
	while (1)
	{
		printf("Serving Directory: <%s>.\n", dir);
		
		int ret;
		
		/* Receive and parse the next command
		over the socket from the user. */
		ret = GetControlConnectionCmd(
			controlSocket,
			msgBuf, msgBufLen, MSG_BUF_MAX_SIZE,
			cmdTokens, numCmdTokens
		);
		if (ret == 1) // user has closed connection
			break; // break out of loop and end session
		
		/* Do the specified command */
		
		/* USER command - We're not doing authentication. Just reply
		with a normal username okay message */
		if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_USER]) == 0)
		{
			printf("Receivied USER command.\n");
			send(controlSocket, replies[REPLY_331_USERNAME_OK], strlen(replies[REPLY_331_USERNAME_OK]), 0);
		}
		/* PASS command - Like with PASS we're not doing
		authentication. Just reply with a normal username okay
		message */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_PASS]) == 0)
		{
			printf("Receivied PASS command.\n");
			send(controlSocket, replies[REPLY_230_PASS_ACCEPT], strlen(replies[REPLY_230_PASS_ACCEPT]), 0);
		}
		/* SYST command - Give a typical UNIX system response */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_SYST]) == 0)
		{
			printf("Receivied SYST command.\n");
			send(controlSocket, replies[REPLY_215_SYST_RESPONSE], strlen(replies[REPLY_215_SYST_RESPONSE]), 0);
		}
		/* CWD command - Print out the current working directory. */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_CWD]) == 0)
		{
			printf("Receivied CWD command.\n");
			
			char* dirToChangeTo = cmdTokens[1];
			
			if ( strcmp( "." , dirToChangeTo ) == 0 )
			{
				// change to current directory, so don't change anything and reply with success
				send(controlSocket, replies[REPLY_250_DIRCHANGE_SUCCESS], strlen(replies[REPLY_250_DIRCHANGE_SUCCESS]), 0);
				continue;
			}
			
			/* handle ".." CWD command */
			if ( strcmp( ".." , dirToChangeTo ) == 0 )
			{
				int len = strlen( dir );
				assert( dir[len-1] == '/' ); // all dirs should have slash at end
				if ( strcmp( dir , properRootDir ) == 0 )
				{
					printf("User tried to go above root directory.\n");
					send(controlSocket, replies[REPLY_550_DIRCHANGE_FAILURE], strlen(replies[REPLY_550_DIRCHANGE_FAILURE]), 0);
					continue;
				}
				/* chomp the last dir off the end */
				for (int i = len - 2;  ; i--)
				{
					assert ( i > 0 );
					if (dir[i] == '/')
					{
						dir[i+1] = '\0';
						break;
					}
				}
				send(controlSocket, replies[REPLY_250_DIRCHANGE_SUCCESS], strlen(replies[REPLY_250_DIRCHANGE_SUCCESS]), 0);
				continue;
			}
			
			/* make sure dirToChange is a subdirectory of the current
			directory to prevent the user from jumping multiple directories
			with the dirToChangeTo string (this check especially important
			to the prevent the use of ".."s somewhere in the string which
			might allow the user to navigate above the root directory). */
			
			DIR *dp;
			struct dirent *ep;
			bool entryExistsInCurrentDir;
			dp = opendir(dir);
			if (dp != NULL)
			{
				while ( ep = readdir(dp) )
					if ( strcmp( ep->d_name, dirToChangeTo ) == 0)
						entryExistsInCurrentDir = true;
				closedir(dp);
			}
			else
				ExitError("For some reason the current directory doesn't exist, or opendir() failed for some other reason.");
			
			if ( entryExistsInCurrentDir == false )
			{
				send(controlSocket, replies[REPLY_550_DIRCHANGE_FAILURE], strlen(replies[REPLY_550_DIRCHANGE_FAILURE]), 0);
				continue;
			}
			
			/* Finally, we have to make sure the file entry we found
			is actually a directory, not a regular file. */
			sprintf(pathBuf, "%s%s%s", dir, dirToChangeTo, "/");
			int fileInfo = GetFileInfo( pathBuf );
			if ( fileInfo == FILEINFO_DIR )
			{
				strcpy( dir, pathBuf );
				send(controlSocket, replies[REPLY_250_DIRCHANGE_SUCCESS], strlen(replies[REPLY_250_DIRCHANGE_SUCCESS]), 0);
			}
			else
			{
				send(controlSocket, replies[REPLY_550_DIRCHANGE_FAILURE], strlen(replies[REPLY_550_DIRCHANGE_FAILURE]), 0);
			}
		}
		/* PASV command - Reply over the the control connection with
		the IP and port info of the data transfer connection listening
		IP and port, and then fork off the data transfer process (DTP)
		which will get a command from the control connection while
		listening for a connection from the user on the data transfer
		connection. Once the DTP gets the command over the control
		connectionit will do the specified command over the data
		connection once the user connects. */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_PASV]) == 0)
		{
			printf("Receivied PASV command.\n");
			
			/* Create new listening socket */
			
			const int DTP_MAX_BACKLOG_CONNECTIONS = 1;
			const uint16_t RANDOM_DTP_LISTEN_PORT = 49064; // HACK: for our random listening port we're just going to make a port number up
			int dataTransferListenSocket = CreateListenSocket( DTP_MAX_BACKLOG_CONNECTIONS, RANDOM_DTP_LISTEN_PORT, false, true );
			
			/* Say Bert.CS.UIC.edu is 131.193.40.32 to the
			outside world. We want to get that address. */
			char localHostName[MAXHOSTNAMELEN];
			gethostname(localHostName, MAXHOSTNAMELEN);
			struct hostent* hostEntry = gethostbyname(localHostName);
			struct in_addr hostIPAddr = *(struct in_addr *)*hostEntry->h_addr_list;// TODO: make sure the first item in the list isn't 127.0.0.1 or something
			char* localIPString = inet_ntoa( hostIPAddr ); // points to the first entry in the list
			
			printf("PASV found IP: %s.\n", localIPString);
			
			/* Create the port string */
			
			unsigned char h1, h2, h3, h4;
			unsigned char p1, p2;
			
			// HACK HACK: this stuff is not endian safe
			unsigned char* bytePtr = (unsigned char*)&hostIPAddr;
			h1 = bytePtr[0];
			h2 = bytePtr[1];
			h3 = bytePtr[2];
			h4 = bytePtr[3];
			
			bytePtr = (unsigned char*)&RANDOM_DTP_LISTEN_PORT;
			p2 = bytePtr[0]; // high byte
			p1 = bytePtr[1]; // low byte
			
			// port = p1 * 256 + p2 
			char pasvPortString[30]; // (xxx,yyy,zzz,www,ppp,nnn)
			sprintf(pasvPortString, "(%i,%i,%i,%i,%i,%i)", h1, h2, h3, h4, p1, p2);
			
			printf("Port value test: p1*256+p2 ?= port :: %d ?= %d.\n", p1*256+p2, RANDOM_DTP_LISTEN_PORT);
			printf("PASV string: %s.\n", pasvPortString);
			
			/* Send the PASV reply */
			
			char pasvReply[200];
			sprintf(pasvReply, replies[REPLY_227_PASSIVE_MODE], pasvPortString);
			send(controlSocket, pasvReply, strlen(pasvReply), 0);
			
			int dtp_pid = fork();
			if ( !dtp_pid )
			{
				/* Data Transfer Process (DTP) code */
				printf("Created data transfer process.\n");
				
				/* Get the next command from the control connection (RETR, STOR, LIST) */
				ret = GetControlConnectionCmd(
					controlSocket,
					msgBuf, msgBufLen, MSG_BUF_MAX_SIZE,
					cmdTokens, numCmdTokens
				);
				if (ret == 1) // control socket was closed for some reason
				{
					close(dataTransferListenSocket);	// done with the listen socket
					exit(EXIT_FAILURE);
				}
				
				/* Accept the user connection */
				struct sockaddr_in remoteAddr;
				int dataTransferSessionSocket = AcceptConnectionFromListenSocket(dataTransferListenSocket, &remoteAddr);
				printf("Data transfer process (DTP) received connection from %s\n", inet_ntoa(remoteAddr.sin_addr));
				
				FTPDataTransferSession(controlSocket, dataTransferSessionSocket);
				
				close(dataTransferSessionSocket);	// when done with the session close the socket
				close(dataTransferListenSocket);	// close the listen socket too
				
				printf("Closing data transfer process.\n");
				exit(EXIT_SUCCESS);				// exit with success code
			}
			
			/* parent continues here */
			
			close(dataTransferListenSocket); // parent doesn't need the this socket
			
			/* wait for the child process to complete */
			waitpid( dtp_pid, NULL, 0 ); // TODO: check for things other than normal termination
			printf("Server-PI resuming execution.\n");
		}
		/* TYPE command */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_TYPE]) == 0)
		{
			if ( strcmp(cmdTokens[1], "I") == 0 ) // binary
			{
				send(controlSocket, replies[REPLY_200_TYPE_SET_TO_I], strlen(replies[REPLY_200_TYPE_SET_TO_I]), 0);
			}
			else if ( strcmp(cmdTokens[1], "A") == 0 ) // ASCII
			{
				send(controlSocket, replies[REPLY_200_TYPE_SET_TO_A], strlen(replies[REPLY_200_TYPE_SET_TO_A]), 0);
			}
			else
			{
				// TODO: handle other stuff
			}
		}
		/* QUIT command */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_QUIT]) == 0)
		{
			printf("Receivied QUIT command.\n");
			send(controlSocket, replies[REPLY_221_END_SESSION], strlen(replies[REPLY_221_END_SESSION]), 0);
			break; // break out of the loop
		}
		/* Unknown command */
		else
		{
			printf("Receivied unknown command.\n");
			send(controlSocket, replies[REPLY_500_UNKNOWN_COMMAND], strlen(replies[REPLY_500_UNKNOWN_COMMAND]), 0);
		}
	}
	
	/* Done */
	printf("Ended FTP session from %s\n", inet_ntoa(remoteAddr.sin_addr));
}
Ejemplo n.º 25
0
DWORD WINAPI CEgTcpDriver::Start(IEgTcpDriverEvents * pEvents, 
								 const COINIT ThreadingModel,
								 const unsigned short usServerPort)
{
	if (pEvents == NULL)
		return ERROR_INVALID_PARAMETER;

	CAutoLock lock(&m_InitLock);

	if (m_bInited)
		return ERROR_ALREADY_INITIALIZED;

	m_ThreadingModel = ThreadingModel;

	m_pEvents = pEvents;

	m_usServerPort = usServerPort;

	for(int i = 0; i < WSATOTAL_EVENTS; i++)
	{
		m_hWsaEvents[i] = WSACreateEvent();
		if (WSA_INVALID_EVENT == m_hWsaEvents[i])
			return WSAGetLastError();
	}

	m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
    if (NULL == m_hIocp) 
		return GetLastError();

	SYSTEM_INFO	systemInfo;
    GetSystemInfo(&systemInfo);
    m_dwThreadCount = 1/*systemInfo.dwNumberOfProcessors * 2*/;


	// Create worker threads to service the overlapped I/O requests.  The decision
    // to create 1 worker threads per CPU in the system is a heuristic.  Also,
    // note that thread handles are closed right away, because we will not need them
    // and the worker threads will continue to execute.
    unsigned long  hThread;
    UINT   dwThreadId;

	for (DWORD dwCPU=0; dwCPU < m_dwThreadCount; dwCPU++) 
    {
		hThread = _beginthreadex(NULL, 0, WorkerThread, this, 0, &dwThreadId);
		if (hThread == -1) 
			return GetLastError();

		m_hThreads.push_back((HANDLE)hThread);
	}

	hThread = _beginthreadex(NULL, 0, WsaEventThread, this, 0, &dwThreadId);

	if (hThread == -1) 
			return GetLastError();

	m_hWSAEventThread = (HANDLE)hThread;

	if (m_usServerPort != CLIENT_ONLY)
	{
		DWORD dwErr = CreateListenSocket();
		if (dwErr != 0)
			return dwErr;

		dwErr = CreateAcceptSocket(TRUE);
		if (dwErr != 0)
			return dwErr;
	}
           
	m_bInited = TRUE;

	return 0;
}