www.pudn.com > ntshell.rar > portproxy.cpp


// portproxy.cpp: implementation of the CPortProxy class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "resource.h" 
#include "common.h" 
 
#include "ntshell.h" 
#include "inputdlg.h" 
#include "portproxy.h" 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CPortProxy::CPortProxy() 
{ 
	ppl = NULL; 
} 
 
CPortProxy::~CPortProxy() 
{ 
	while (ppl != NULL) 
	{ 
		PPROXY_LIST p = ppl; 
		ppl = ppl->pNext; 
 
		SetEvent(p->hCtrlEvent1); 
		CloseHandle(p->hWorkThread); 
		CloseHandle(p->hCtrlEvent1); 
		CloseHandle(p->hCtrlEvent2); 
 
		delete p; 
	} 
} 
 
LRESULT CPortProxy::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) 
{ 
	pwip = (PWND_INIT_PARAM)lParam; 
	connwait = false; 
 
	m_hAddProxyDlg.Create(m_hWnd); 
	m_hAddProxyDlg.ShowWindow(SW_HIDE); 
 
	m_hProxyList.Attach(GetDlgItem(IDC_PROXYLIST)); 
	m_hProxyList.InsertColumn(0, "远程端口", LVCFMT_LEFT, 70, 0); 
	m_hProxyList.InsertColumn(1, "对应端口", LVCFMT_LEFT, 70, 0); 
	m_hProxyList.InsertColumn(2, "发送次数", LVCFMT_LEFT, 70, 0); 
	m_hProxyList.InsertColumn(3, "接收次数", LVCFMT_LEFT, 70, 0); 
	m_hProxyList.InsertColumn(4, "发送数据量", LVCFMT_LEFT, 100, 0); 
	m_hProxyList.InsertColumn(5, "接收数据量", LVCFMT_LEFT, 100, 0); 
 
	DWORD dwStyle = m_hProxyList.GetExtendedListViewStyle(); 
	dwStyle |= LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP; 
	m_hProxyList.SetExtendedListViewStyle(dwStyle); 
 
	return TRUE; 
} 
 
LRESULT CPortProxy::OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) 
{ 
	::MoveWindow(GetDlgItem(IDC_PROXYLIST), 7, 7, LOWORD(lParam) - 14, HIWORD(lParam) - 14, TRUE); 
	return TRUE; 
} 
 
LRESULT CPortProxy::OnSocket(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) 
{ 
	SOCKET slave_sock = (SOCKET)wParam; 
 
	if (WSAGETSELECTERROR(lParam)) 
	{ 
		closesocket(slave_sock); 
		slave_sock = INVALID_SOCKET; 
		return 0; 
	} 
 
	switch (WSAGETSELECTEVENT(lParam)) 
	{ 
	case FD_ACCEPT: 
		break; 
	} 
 
	return 0; 
} 
 
SOCKET CPortProxy::OpenLocalPort(USHORT nPort) 
{ 
	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
 
	if (s == INVALID_SOCKET) 
	{ 
		MessageBox("创建套接字失败"); 
		return INVALID_SOCKET; 
	} 
 
	struct sockaddr_in local; 
 
	local.sin_family		= AF_INET; 
	local.sin_port			= htons(nPort); 
	local.sin_addr.s_addr	= htonl(INADDR_ANY); 
 
	if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR) 
	{ 
		MessageBox("绑定本机端口失败"); 
		closesocket(s); 
		return INVALID_SOCKET; 
	} 
 
	if (listen(s, PORT_MAX_CONNECT) == SOCKET_ERROR) //最大连接数量 
	{ 
		MessageBox("监听端口失败"); 
		closesocket(s); 
		return INVALID_SOCKET; 
	} 
 
	return s; 
} 
 
SOCKET CPortProxy::OpenRemotePort(char *lpHost, USHORT nPort) 
{ 
	OPEN_REMOTE_PORT orp; 
	connwait = true; 
 
	orp.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
 
	if (orp.hEvent == NULL) 
		return INVALID_SOCKET; 
 
	rc.hAcceptWnd = m_hWnd; 
	rc.funBack = OpenPortSuccess; 
	rc.lpParam = &orp; 
	rc.dwWorkType = WORK_SOCKPROXY; 
	rc.lpCtrlHandle = pwip->lpCtrlHandle; 
 
	SendMessage(pwip->hConnMgrWnd, WM_REQUEST_CONNECT, 0, (LPARAM)&rc); 
 
	DWORD ret = WaitForSingleObject(orp.hEvent, INFINITE); 
 
	if (ret == WAIT_FAILED) 
	{ 
		SendMessage(pwip->hConnMgrWnd, WM_CANCEL_REQUEST, 0, (LPARAM)&rc); 
		CloseHandle(orp.hEvent); 
		return INVALID_SOCKET; 
	} 
 
	CloseHandle(orp.hEvent); 
 
	return orp.s; 
} 
 
void CPortProxy::OpenPortSuccess(SOCKET s, LPVOID param) 
{ 
	((POPEN_REMOTE_PORT)param)->s = s; 
	SetEvent(((POPEN_REMOTE_PORT)param)->hEvent); 
} 
 
BOOL CPortProxy::SockProxyStart(USHORT ListenPort, char *RemoteHost, USHORT RemotePort) 
{ 
	PPROXY_LIST p = new PROXY_LIST; 
 
	p->nLocalPort = ListenPort; 
	p->nTargetPort = RemotePort; 
	p->nSend = 0; 
	p->nRecv = 0; 
	p->nSendBytes = 0; 
	p->nRecvBytes = 0; 
 
	p->dwTargetHost = inet_addr(RemoteHost); 
 
	if (p->dwTargetHost == INADDR_NONE) 
	{ 
		struct hostent *host = gethostbyname(RemoteHost);				//解析主机域名 
 
		if (host == NULL) 
		{ 
			CString str = "无法解析域名"; 
			MessageBox(str + RemoteHost); 
			delete p; 
			return FALSE; 
		} 
		else 
		{ 
			p->dwTargetHost = *(DWORD *)(host->h_addr_list[0]); 
		} 
	} 
 
	p->sListen = OpenLocalPort(p->nLocalPort); 
 
	if (p->sListen == INVALID_SOCKET) 
	{ 
		delete p; 
		return FALSE; 
	} 
 
	WSAAsyncSelect(p->sListen, m_hWnd, WM_SOCKET, FD_ACCEPT); 
 
	DWORD dwThreadId; 
 
	p->hWorkThread = CreateThread(NULL, 0, SockProxyThread, p, 0, &dwThreadId); 
 
	p->pNext = ppl; 
	ppl = p; 
 
	return TRUE; 
} 
 
DWORD WINAPI CPortProxy::SockProxyThread(LPVOID lpParam) 
{ 
	PPROXY_LIST p = (PPROXY_LIST)lpParam; 
	SOCKET socks[PORT_MAX_CONNECT * 2]; 
	HANDLE events[PORT_MAX_CONNECT * 2 + 2]; 
	PHANDLE sock_events = &events[2]; 
	char *sock_buffer[PORT_MAX_CONNECT * 2]; 
	DWORD buffer_length[PORT_MAX_CONNECT * 2]; 
	DWORD send_pointer[PORT_MAX_CONNECT * 2]; 
	DWORD recv_pointer[PORT_MAX_CONNECT * 2]; 
	int ret, sock_total = 0; 
	DWORD index; 
	BOOL done = TRUE; 
	WSANETWORKEVENTS ns; 
 
	events[0] = p->hCtrlEvent1; 
	events[1] = p->hCtrlEvent2; 
 
	while (done) 
	{ 
		index = WaitForMultipleObjectsEx(sock_total + 2, events, FALSE, INFINITE, FALSE); 
 
		switch (index) 
		{ 
		case WAIT_FAILED: 
			goto cleanup; 
		 
		case WAIT_OBJECT_0: 
			goto cleanup; 
 
		case WAIT_OBJECT_0 + 1: 
			socks[sock_total] = p->local_sock; 
			socks[sock_total + 1] = p->remote_sock; 
			sock_events[sock_total] = WSACreateEvent(); 
 
			if (sock_events[sock_total] == WSA_INVALID_EVENT) 
				continue; 
 
			sock_events[sock_total + 1] = WSACreateEvent(); 
 
			if (sock_events[sock_total + 1] == WSA_INVALID_EVENT) 
			{ 
				WSACloseEvent(sock_events[sock_total]); 
				continue; 
			} 
 
			sock_buffer[sock_total] = (char *)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READWRITE); 
 
			if (sock_buffer[sock_total] == NULL) 
			{ 
				WSACloseEvent(sock_events[sock_total]); 
				WSACloseEvent(sock_events[sock_total + 1]); 
				continue; 
			} 
 
			sock_buffer[sock_total + 1] = sock_buffer[sock_total] + 2048; 
			buffer_length[sock_total] = 0; 
			buffer_length[sock_total + 1] = 0; 
			send_pointer[sock_total] = 0; 
			send_pointer[sock_total + 1] = 0; 
			recv_pointer[sock_total] = 0; 
			recv_pointer[sock_total + 1] = 0; 
			sock_total += 2; 
			p->nTotal = sock_total / 2; 
			continue; 
 
		default: 
			index -= 2; 
			break; 
		} 
 
		ret = WSAEnumNetworkEvents(socks[index], sock_events[index], &ns); 
 
		if (ret == SOCKET_ERROR) 
			goto cleanup; 
 
		int src = index; 
		int dst = index & 1 ? index - 1 : index + 1; 
 
		if (ns.lNetworkEvents & FD_READ) 
		{ 
			if (ns.iErrorCode[FD_READ_BIT]) 
				goto close_sock; 
 
			ret = recv(socks[src], sock_buffer[src] + recv_pointer[src], 2048 - recv_pointer[src], 0); 
 
			recv_pointer[src] += ret; 
			buffer_length[src] += ret; 
			p->nRecv++; 
			p->nRecvBytes += ret; 
 
			ret = send(socks[dst], sock_buffer[src] + send_pointer[src], buffer_length[src] - send_pointer[src], 0); 
 
			if (ret != SOCKET_ERROR) 
			{ 
				send_pointer[src] += ret; 
				p->nSend++; 
				p->nSendBytes += ret; 
			} 
 
			if (send_pointer[src] == buffer_length[src]) 
			{ 
				recv_pointer[src] = 0; 
				send_pointer[src] = 0; 
				buffer_length[src] = 0; 
			} 
		} 
 
		if (ns.lNetworkEvents & FD_WRITE) 
		{ 
			if (ns.iErrorCode[FD_WRITE_BIT]) 
				goto close_sock; 
 
			ret = send(socks[src], sock_buffer[dst] + send_pointer[dst], buffer_length[dst] - send_pointer[dst], 0); 
 
			send_pointer[dst] += ret; 
			p->nSend++; 
			p->nSendBytes += ret; 
 
			if (send_pointer[dst] == buffer_length[dst]) 
			{ 
				recv_pointer[dst] = 0; 
				send_pointer[dst] = 0; 
				buffer_length[dst] = 0; 
			} 
		} 
 
		if (ns.lNetworkEvents & FD_CLOSE) 
		{ 
close_sock: 
			int m = index & 0xfffffffe, n = m + 1; 
			closesocket(socks[m]); 
			closesocket(socks[n]); 
			WSACloseEvent(sock_events[m]); 
			WSACloseEvent(sock_events[n]); 
			VirtualFree(sock_buffer[m], 0, MEM_RELEASE); 
 
			sock_total -= 2; 
			p->nTotal = sock_total / 2; 
			socks[m] = socks[sock_total]; 
			socks[n] = socks[sock_total + 1]; 
			sock_events[m] = sock_events[sock_total]; 
			sock_events[n] = sock_events[sock_total + 1]; 
			sock_buffer[m] = sock_buffer[sock_total]; 
			sock_buffer[n] = sock_buffer[sock_total + 1]; 
			buffer_length[m] = buffer_length[sock_total]; 
			buffer_length[n] = buffer_length[sock_total + 1]; 
			send_pointer[m] = send_pointer[sock_total]; 
			send_pointer[n] = send_pointer[sock_total + 1]; 
			recv_pointer[m] = recv_pointer[sock_total]; 
			recv_pointer[n] = recv_pointer[sock_total + 1]; 
		} 
	} 
 
cleanup: 
	for (int i = 0; i < sock_total; i += 2) 
	{ 
		closesocket(socks[i]); 
		closesocket(socks[i + 1]); 
		WSACloseEvent(sock_events[i]); 
		WSACloseEvent(sock_events[i + 1]); 
		VirtualFree(sock_buffer[i], 0, MEM_RELEASE); 
	} 
 
	p->nTotal = 0; 
 
	return 0; 
} 
 
LRESULT CPortProxy::OnProxyList(int wParam, LPNMHDR pNMHDR, BOOL& /*bHandled*/) 
{ 
	NMLISTVIEW *pNMListView = (NMLISTVIEW *)pNMHDR; 
	int nItem = pNMListView->iItem; 
	HMENU hMenu, hPopupMenu; 
	POINT point; 
 
	switch (pNMHDR->code) 
	{ 
	case NM_RCLICK: 
		hMenu = LoadMenu(GetModuleHandle(NULL), (LPCTSTR)IDR_SUBMENU); 
		hPopupMenu = GetSubMenu(hMenu, 0); 
 
		if (nItem == -1) 
			EnableMenuItem(hPopupMenu, IDM_DELPROXY, MF_GRAYED); 
		else 
			EnableMenuItem(hPopupMenu, IDM_DELPROXY, MF_ENABLED); 
 
		GetCursorPos(&point); 
		TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN, point.x, point.y, 0, m_hWnd, NULL); 
 
		DestroyMenu(hMenu); 
		break; 
	} 
 
	return 0; 
} 
 
LRESULT CPortProxy::OnAddProxy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 
{ 
	CInputDlg dlg; 
	TCHAR szMap[INPUT_BUFFER_SIZE] = "127.0.0.1:80-81"; 
 
	if (dlg.DoModal(m_hWnd, (LPARAM)szMap) == FALSE) 
		return 0; 
 
	return 0; 
} 
 
LRESULT CPortProxy::OnAddProxyBtn(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 
{ 
	return 0; 
}