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)
|
Application::Application(std::string& appName, std::string& appVersion)
|
||||||
: m_appName(appName.begin(), appName.end())
|
: m_appName(appName.begin(), appName.end())
|
||||||
, m_appVersion(appVersion.begin(), appVersion.end())
|
, m_appVersion(appVersion.begin(), appVersion.end())
|
||||||
|
, m_running(true)
|
||||||
{
|
{
|
||||||
std::wcout << std::format(L"{} {}\n", m_appName, m_appVersion);
|
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() {
|
void Application::run() {
|
||||||
@ -50,75 +63,68 @@ namespace wc {
|
|||||||
input = new MainDlgInput{ this, x, y };
|
input = new MainDlgInput{ this, x, y };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_running = false;
|
||||||
listenThread.join();
|
listenThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::startListen() {
|
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;
|
addrinfo* hostInfo = nullptr;
|
||||||
hints.ai_family = AF_UNSPEC;
|
getaddrinfo("::", "9430", nullptr, &hostInfo);
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
hints.ai_flags = AI_PASSIVE;
|
|
||||||
getaddrinfo(nullptr, "9430", &hints, &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) {
|
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);
|
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) {
|
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);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(hostInfo);
|
freeaddrinfo(hostInfo);
|
||||||
listen(sock, 1);
|
listen(sock, 1);
|
||||||
|
|
||||||
sockaddr_storage remoteAddr = { };
|
ioctlsocket(sock, FIONBIO, &yes);
|
||||||
|
|
||||||
|
sockaddr_in6 remoteAddr = { };
|
||||||
int remoteSize = sizeof(remoteAddr);
|
int remoteSize = sizeof(remoteAddr);
|
||||||
SOCKET conSock = accept(sock, reinterpret_cast<sockaddr*>(&remoteAddr), &remoteSize);
|
SOCKET conSock = INVALID_SOCKET;
|
||||||
if (conSock == INVALID_SOCKET) {
|
int errorCode = 0;
|
||||||
std::cerr << std::format("Error: could not accept connection!\n");;
|
while (m_running) {
|
||||||
std::exit(1);
|
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;
|
ioctlsocket(conSock, FIONBIO, &no);
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
std::string buf(1000, 0);
|
||||||
while (bytesRecvd = recv(conSock, buf.data(), 1000, 0)) {
|
int bytesRecvd = 0;
|
||||||
buf.resize(bytesRecvd);
|
while (bytesRecvd = recv(conSock, buf.data(), 1000, NULL)) {
|
||||||
std::cout << std::format("Remote: {}\n", buf);
|
buf.resize(bytesRecvd);
|
||||||
buf.resize(1000);
|
std::cout << std::format("Remote: {}\n", buf);
|
||||||
|
buf.resize(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(conSock);
|
||||||
}
|
}
|
||||||
|
|
||||||
closesocket(conSock);
|
|
||||||
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
WSACleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CALLBACK Application::mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
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);
|
SetWindowPos(dlg, nullptr, xPos, yPos, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||||
|
|
||||||
SetDlgItemText(dlg, IDC_STATICTITLE, app->m_appName.c_str());
|
SetDlgItemText(dlg, IDC_STATICTITLE, app->m_appName.c_str());
|
||||||
LOGFONT lFont = { };
|
LOGFONT lFont = { .lfHeight = 50 };
|
||||||
lFont.lfHeight = 50;
|
|
||||||
HFONT font = CreateFontIndirect(&lFont);
|
HFONT font = CreateFontIndirect(&lFont);
|
||||||
SendMessage(GetDlgItem(dlg, IDC_STATICTITLE), WM_SETFONT, reinterpret_cast<LPARAM>(font), NULL);
|
SendMessage(GetDlgItem(dlg, IDC_STATICTITLE), WM_SETFONT, reinterpret_cast<LPARAM>(font), NULL);
|
||||||
|
|
||||||
@ -163,11 +168,19 @@ namespace wc {
|
|||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
switch (LOWORD(wParam)) {
|
switch (LOWORD(wParam)) {
|
||||||
case IDC_BUTTONCONNECT: {
|
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;
|
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));
|
GetDlgItemText(dlg, IDC_EDITADDRESS, address.data(), static_cast<int>(address.size() + 1));
|
||||||
std::wstring screenname;
|
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));
|
GetDlgItemText(dlg, IDC_EDITSCREENNAME, screenname.data(), static_cast<int>(screenname.size() + 1));
|
||||||
|
|
||||||
RECT dlgRect = { };
|
RECT dlgRect = { };
|
||||||
@ -203,6 +216,6 @@ namespace wc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
|
WSACleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,5 +17,6 @@ namespace wc {
|
|||||||
|
|
||||||
const std::wstring m_appName;
|
const std::wstring m_appName;
|
||||||
const std::wstring m_appVersion;
|
const std::wstring m_appVersion;
|
||||||
|
bool m_running;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -12,21 +12,49 @@ namespace wc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chat::run() {
|
void Chat::run() {
|
||||||
addrinfo hints = { };
|
|
||||||
addrinfo* destInfo = nullptr;
|
addrinfo* destInfo = nullptr;
|
||||||
hints.ai_family = AF_UNSPEC;
|
if (getaddrinfo(toStr(m_address).c_str(), "9430", nullptr, &destInfo) != 0) {
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
MessageBox(nullptr, L"Error: Could not resolve host or invalid address!", L"Error", MB_ICONERROR);
|
||||||
getaddrinfo(toStr(m_address).c_str(), "9430", &hints, &destInfo);
|
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) {
|
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);
|
freeaddrinfo(destInfo);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(sock, destInfo->ai_addr, static_cast<int>(destInfo->ai_addrlen)) != 0) {
|
if (connect(sock, destInfo->ai_addr, static_cast<int>(destInfo->ai_addrlen)) != 0) {
|
||||||
std::cerr << std::format("Error: could not connect to destination!\n");
|
int errorCode = WSAGetLastError();
|
||||||
std::exit(1);
|
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);
|
freeaddrinfo(destInfo);
|
||||||
@ -34,7 +62,7 @@ namespace wc {
|
|||||||
std::string data;
|
std::string data;
|
||||||
while (data != "end") {
|
while (data != "end") {
|
||||||
std::getline(std::cin, data);
|
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);
|
closesocket(sock);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user