Add listen loop, error messages, ip4 & 6 support
This commit is contained in:
		
							parent
							
								
									cebbb1dc19
								
							
						
					
					
						commit
						3053a0b8f8
					
				| @ -24,8 +24,21 @@ namespace wc { | ||||
| 	Application::Application(std::string& appName, std::string& appVersion) | ||||
| 		: m_appName(appName.begin(), appName.end()) | ||||
| 		, m_appVersion(appVersion.begin(), appVersion.end()) | ||||
| 		, m_running(true) | ||||
| 	{ | ||||
| 		std::wcout << std::format(L"{} {}\n", m_appName, m_appVersion); | ||||
| 
 | ||||
| 		//Initialize Windows Sockets 2
 | ||||
| 		WSADATA data = { }; | ||||
| 		if (WSAStartup(MAKEWORD(2, 2), &data) != 0) { | ||||
| 			MessageBox(nullptr, L"Error: could not initialize WinSock 2!", L"Error", MB_ICONERROR); | ||||
| 			std::exit(1); | ||||
| 		} | ||||
| 
 | ||||
| 		if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2) { | ||||
| 			MessageBox(nullptr, L"Error: WinSock version 2.2 not available!", L"Error", MB_ICONERROR); | ||||
| 			std::exit(1); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	void Application::run() { | ||||
| @ -50,75 +63,68 @@ namespace wc { | ||||
| 			input = new MainDlgInput{ this, x, y }; | ||||
| 		} | ||||
| 
 | ||||
| 		m_running = false; | ||||
| 		listenThread.join(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Application::startListen() { | ||||
| 		WSADATA data = { }; | ||||
| 		if (WSAStartup(MAKEWORD(2, 2), &data) != 0) { | ||||
| 			std::cerr << std::format("Error: could not initialize WinSock 2!\n"); | ||||
| 			std::exit(1); | ||||
| 		} | ||||
| 
 | ||||
| 		if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2) { | ||||
| 			std::cerr << std::format("Error: WinSock version 2.2 not available!\n"); | ||||
| 			std::exit(1); | ||||
| 		} | ||||
| 
 | ||||
| 		addrinfo hints = { }; | ||||
| 		addrinfo* hostInfo = nullptr; | ||||
| 		hints.ai_family = AF_UNSPEC; | ||||
| 		hints.ai_socktype = SOCK_STREAM; | ||||
| 		hints.ai_flags = AI_PASSIVE; | ||||
| 		getaddrinfo(nullptr, "9430", &hints, &hostInfo); | ||||
| 		getaddrinfo("::", "9430", nullptr, &hostInfo); | ||||
| 
 | ||||
| 		SOCKET sock = socket(hostInfo->ai_family, hostInfo->ai_socktype, hostInfo->ai_protocol); | ||||
| 		SOCKET sock = socket(AF_INET6, SOCK_STREAM, NULL); | ||||
| 		if (sock == INVALID_SOCKET) { | ||||
| 			std::cerr << std::format("Error: could not create network socket!\n"); | ||||
| 			MessageBox(nullptr, L"Error: could not create network socket!", L"Error", MB_ICONERROR); | ||||
| 			std::exit(1); | ||||
| 		} | ||||
| 
 | ||||
| 		unsigned long yes = 1; | ||||
| 		unsigned long no = 0; | ||||
| 		setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<char*>(&no), sizeof(no)); | ||||
| 
 | ||||
| 		if (bind(sock, hostInfo->ai_addr, static_cast<int>(hostInfo->ai_addrlen)) != 0) { | ||||
| 			std::cerr << std::format("Error: could not bind network socket!\n"); | ||||
| 			MessageBox(nullptr, L"Error: could not bind network socket!", L"Error", MB_ICONERROR); | ||||
| 			std::exit(1); | ||||
| 		} | ||||
| 
 | ||||
| 		freeaddrinfo(hostInfo); | ||||
| 		listen(sock, 1); | ||||
| 
 | ||||
| 		sockaddr_storage remoteAddr = { }; | ||||
| 		ioctlsocket(sock, FIONBIO, &yes); | ||||
| 
 | ||||
| 		sockaddr_in6 remoteAddr = { }; | ||||
| 		int remoteSize = sizeof(remoteAddr); | ||||
| 		SOCKET conSock = accept(sock, reinterpret_cast<sockaddr*>(&remoteAddr), &remoteSize); | ||||
| 		if (conSock == INVALID_SOCKET) { | ||||
| 			std::cerr << std::format("Error: could not accept connection!\n");; | ||||
| 			std::exit(1); | ||||
| 		} | ||||
| 		SOCKET conSock = INVALID_SOCKET; | ||||
| 		int errorCode = 0; | ||||
| 		while (m_running) { | ||||
| 			conSock = accept(sock, reinterpret_cast<sockaddr*>(&remoteAddr), &remoteSize); | ||||
| 			errorCode = WSAGetLastError(); | ||||
| 			if (errorCode && errorCode != WSAEWOULDBLOCK) { | ||||
| 				MessageBox(nullptr, L"Error: could not accept connection!", L"Error", MB_ICONERROR); | ||||
| 				std::exit(1); | ||||
| 			} | ||||
| 			std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||||
| 			if (errorCode == WSAEWOULDBLOCK) | ||||
| 				continue; | ||||
| 
 | ||||
| 		std::string remoteStr; | ||||
| 		remoteStr.resize(INET6_ADDRSTRLEN); | ||||
| 		void* addrLocation = nullptr; | ||||
| 		if (remoteAddr.ss_family == AF_INET) { | ||||
| 			addrLocation = reinterpret_cast<void*>(&reinterpret_cast<sockaddr_in*>(&remoteAddr)->sin_addr); | ||||
| 		} | ||||
| 		else if (remoteAddr.ss_family = AF_INET6) { | ||||
| 			addrLocation = reinterpret_cast<void*>(&reinterpret_cast<sockaddr_in6*>(&remoteAddr)->sin6_addr); | ||||
| 		} | ||||
| 		inet_ntop(remoteAddr.ss_family, addrLocation, remoteStr.data(), INET6_ADDRSTRLEN); | ||||
| 		std::cout << std::format("Connected to: {}\n", remoteStr); | ||||
| 			ioctlsocket(conSock, FIONBIO, &no); | ||||
| 
 | ||||
| 		std::string buf(1000, 0); | ||||
| 			std::string remoteStr(INET6_ADDRSTRLEN, 0); | ||||
| 			inet_ntop(AF_INET6, &remoteAddr.sin6_addr, remoteStr.data(), INET6_ADDRSTRLEN); | ||||
| 			remoteStr.resize(remoteStr.find_first_of('\0', 0)); | ||||
| 			std::cout << std::format("Connected to: {}\n", remoteStr); | ||||
| 
 | ||||
| 		int bytesRecvd = 1; | ||||
| 		while (bytesRecvd = recv(conSock, buf.data(), 1000, 0)) { | ||||
| 			buf.resize(bytesRecvd); | ||||
| 			std::cout << std::format("Remote: {}\n", buf); | ||||
| 			buf.resize(1000); | ||||
| 			std::string buf(1000, 0); | ||||
| 			int bytesRecvd = 0; | ||||
| 			while (bytesRecvd = recv(conSock, buf.data(), 1000, NULL)) { | ||||
| 				buf.resize(bytesRecvd); | ||||
| 				std::cout << std::format("Remote: {}\n", buf); | ||||
| 				buf.resize(1000); | ||||
| 			} | ||||
| 
 | ||||
| 			closesocket(conSock); | ||||
| 		} | ||||
| 
 | ||||
| 		closesocket(conSock); | ||||
| 
 | ||||
| 		closesocket(sock); | ||||
| 		WSACleanup(); | ||||
| 	} | ||||
| 
 | ||||
| 	BOOL CALLBACK Application::mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) { | ||||
| @ -145,8 +151,7 @@ namespace wc { | ||||
| 				SetWindowPos(dlg, nullptr, xPos, yPos, 0, 0, SWP_NOSIZE | SWP_NOZORDER); | ||||
| 
 | ||||
| 				SetDlgItemText(dlg, IDC_STATICTITLE, app->m_appName.c_str()); | ||||
| 				LOGFONT lFont = { }; | ||||
| 				lFont.lfHeight = 50; | ||||
| 				LOGFONT lFont = { .lfHeight = 50 }; | ||||
| 				HFONT font = CreateFontIndirect(&lFont); | ||||
| 				SendMessage(GetDlgItem(dlg, IDC_STATICTITLE), WM_SETFONT, reinterpret_cast<LPARAM>(font), NULL); | ||||
| 
 | ||||
| @ -163,11 +168,19 @@ namespace wc { | ||||
| 			case WM_COMMAND: | ||||
| 				switch (LOWORD(wParam)) { | ||||
| 					case IDC_BUTTONCONNECT: { | ||||
| 						int addressSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITADDRESS)); | ||||
| 						int screennameSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITSCREENNAME)); | ||||
| 						if (!addressSize || !screennameSize) { | ||||
| 							EDITBALLOONTIP balloon = { .cbStruct = sizeof(balloon), .pszTitle = L"Alert", .pszText = L"You must enter an address and screenname." }; | ||||
| 							SendDlgItemMessage(dlg, addressSize ? IDC_EDITSCREENNAME : IDC_EDITADDRESS, EM_SHOWBALLOONTIP, NULL, reinterpret_cast<LPARAM>(&balloon)); | ||||
| 							return TRUE; | ||||
| 						} | ||||
| 
 | ||||
| 						std::wstring address; | ||||
| 						address.resize(GetWindowTextLength(GetDlgItem(dlg, IDC_EDITADDRESS))); | ||||
| 						address.resize(addressSize); | ||||
| 						GetDlgItemText(dlg, IDC_EDITADDRESS, address.data(), static_cast<int>(address.size() + 1)); | ||||
| 						std::wstring screenname; | ||||
| 						screenname.resize(GetWindowTextLength(GetDlgItem(dlg, IDC_EDITSCREENNAME))); | ||||
| 						screenname.resize(screennameSize); | ||||
| 						GetDlgItemText(dlg, IDC_EDITSCREENNAME, screenname.data(), static_cast<int>(screenname.size() + 1)); | ||||
| 
 | ||||
| 						RECT dlgRect = { }; | ||||
| @ -203,6 +216,6 @@ namespace wc { | ||||
| 	} | ||||
| 
 | ||||
| 	Application::~Application() { | ||||
| 
 | ||||
| 		WSACleanup(); | ||||
| 	} | ||||
| } | ||||
| @ -17,5 +17,6 @@ namespace wc { | ||||
| 
 | ||||
| 		const std::wstring m_appName; | ||||
| 		const std::wstring m_appVersion; | ||||
| 		bool m_running; | ||||
| 	}; | ||||
| } | ||||
| @ -12,21 +12,49 @@ namespace wc { | ||||
| 	} | ||||
| 
 | ||||
| 	void Chat::run() { | ||||
| 		addrinfo hints = { }; | ||||
| 		addrinfo* destInfo = nullptr; | ||||
| 		hints.ai_family = AF_UNSPEC; | ||||
| 		hints.ai_socktype = SOCK_STREAM; | ||||
| 		getaddrinfo(toStr(m_address).c_str(), "9430", &hints, &destInfo); | ||||
| 		if (getaddrinfo(toStr(m_address).c_str(), "9430", nullptr, &destInfo) != 0) { | ||||
| 			MessageBox(nullptr, L"Error: Could not resolve host or invalid address!", L"Error", MB_ICONERROR); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		SOCKET sock = socket(destInfo->ai_family, destInfo->ai_socktype, destInfo->ai_protocol); | ||||
| 		SOCKET sock = socket(destInfo->ai_family, SOCK_STREAM, NULL); | ||||
| 		if (sock == INVALID_SOCKET) { | ||||
| 			std::cerr << std::format("Error: could not create network socket!\n"); | ||||
| 			std::exit(1); | ||||
| 			MessageBox(nullptr, L"Error: could not create network socket!", L"Error", MB_ICONERROR); | ||||
| 			freeaddrinfo(destInfo); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (connect(sock, destInfo->ai_addr, static_cast<int>(destInfo->ai_addrlen)) != 0) { | ||||
| 			std::cerr << std::format("Error: could not connect to destination!\n"); | ||||
| 			std::exit(1); | ||||
| 			int errorCode = WSAGetLastError(); | ||||
| 			std::wstring errorStr; | ||||
| 			switch (errorCode) { | ||||
| 				case WSAETIMEDOUT: | ||||
| 					errorStr = L"Timed out"; | ||||
| 					break; | ||||
| 
 | ||||
| 				case WSAECONNREFUSED: | ||||
| 					errorStr = L"Connection refused (WinChat may not be running on remote host)"; | ||||
| 					break; | ||||
| 
 | ||||
| 				case WSAENETUNREACH: | ||||
| 				case WSAEHOSTUNREACH: | ||||
| 					errorStr = L"Remote host unreachable (You may not be connected to the internet)"; | ||||
| 					break; | ||||
| 
 | ||||
| 				case WSAEADDRNOTAVAIL: | ||||
| 					errorStr = L"Not a valid address to connect to"; | ||||
| 					break; | ||||
| 
 | ||||
| 				default: | ||||
| 					errorStr = std::format(L"Error Code {}", errorCode); | ||||
| 					break; | ||||
| 			} | ||||
| 
 | ||||
| 			MessageBox(nullptr, std::format(L"Error: Could not connect - {}", errorStr).c_str(), L"Error", MB_ICONERROR); | ||||
| 			freeaddrinfo(destInfo); | ||||
| 			closesocket(sock); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		freeaddrinfo(destInfo); | ||||
| @ -34,7 +62,7 @@ namespace wc { | ||||
| 		std::string data; | ||||
| 		while (data != "end") { | ||||
| 			std::getline(std::cin, data); | ||||
| 			send(sock, data.data(), static_cast<int>(data.size()), 0); | ||||
| 			send(sock, data.data(), static_cast<int>(data.size()), NULL); | ||||
| 		} | ||||
| 
 | ||||
| 		closesocket(sock); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user