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");;
|
||||
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);
|
||||
ioctlsocket(conSock, FIONBIO, &no);
|
||||
|
||||
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);
|
||||
|
||||
std::string buf(1000, 0);
|
||||
|
||||
int bytesRecvd = 1;
|
||||
while (bytesRecvd = recv(conSock, buf.data(), 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(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