Example #1
0
/*-------------------------------------------------------------------------*\
* Error translation functions
\*-------------------------------------------------------------------------*/
const char *socket_hoststrerror(int err) {
    if (err <= 0) return io_strerror(err);
    switch (err) {
        case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND;
        default: return wstrerror(err); 
    }
}
Example #2
0
const char *socket_strerror(int err) {
    if (err <= 0) return io_strerror(err);
    switch (err) {
        case WSAEADDRINUSE: return PIE_ADDRINUSE;
        case WSAECONNREFUSED : return PIE_CONNREFUSED;
        case WSAEISCONN: return PIE_ISCONN;
        case WSAEACCES: return PIE_ACCESS;
        case WSAECONNABORTED: return PIE_CONNABORTED;
        case WSAECONNRESET: return PIE_CONNRESET;
        case WSAETIMEDOUT: return PIE_TIMEDOUT;
        default: return wstrerror(err);
    }
}
Example #3
0
const char *socket_strerror(int err) {
    if (err <= 0) return io_strerror(err);
    switch (err) {
        case WSAEADDRINUSE: return "address already in use";
        case WSAECONNREFUSED: return "connection refused";
        case WSAEISCONN: return "already connected";
        case WSAEACCES: return "permission denied";
        case WSAECONNABORTED: return "closed";
        case WSAECONNRESET: return "closed";
        case WSAETIMEDOUT: return "timeout";
        default: return wstrerror(err);
    }
}
Example #4
0
File: qarma.cpp Project: yrro/qarma
int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPWSTR /*lpCmdLine*/, int nCmdShow) {
	INITCOMMONCONTROLSEX icc = INITCOMMONCONTROLSEX ();
	icc.dwSize = sizeof icc;
	icc.dwICC = ICC_STANDARD_CLASSES | ICC_PROGRESS_CLASS;
	InitCommonControlsEx (&icc);

	winsock_wrapper winsock;
	if (winsock.error ()) {
		explain (L"WSAStartup failed", winsock.error ());
		return 1;
	}

	WNDCLASSEX wcex = WNDCLASSEX ();
	wcex.cbSize = sizeof wcex;
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = main_window_wndproc;
	wcex.hInstance = hInstance;
	//wcex.hIcon = something;
	wcex.hCursor = LoadCursor (nullptr, IDC_ARROW);
	wcex.hbrBackground = GetSysColorBrush (COLOR_3DFACE);
	wcex.lpszClassName = main_window_class;
	if (!RegisterClassEx (&wcex)) {
		explain (L"RegisterClassEx failed");
		return 1;
	}

	window_data wd;
	HWND hWnd = CreateWindow (main_window_class, L"Qarma",
		WS_OVERLAPPEDWINDOW /*WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX */,
		CW_USEDEFAULT, CW_USEDEFAULT, 1024, 720,
		0, 0, hInstance, &wd);
	if (!hWnd) {
		explain (L"CreateWindow failed");
		return 1;
	}

	ShowWindow (hWnd, nCmdShow);
	UpdateWindow (hWnd);

	std::vector<HANDLE> handles;
	while (true) {
		handles.clear ();
		if (wd.mpt)
			handles.push_back (wd.mpt.get ());
		DWORD r = MsgWaitForMultipleObjects (handles.size (), &handles[0], false, INFINITE, QS_ALLINPUT);
		if (r == WAIT_FAILED) {
			explain (L"MsgWaitForMultipleObjects failed");
			return 1;
		} else if (r == WAIT_OBJECT_0 + handles.size ()) {
			MSG msg;
			while (PeekMessage (&msg, nullptr, 0, 0, PM_REMOVE)) {
				if (msg.message == WM_QUIT)
					return msg.wParam;

				TranslateMessage (&msg);
				DispatchMessage (&msg);
			}
		} else if (r >= WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + handles.size ()) {
			HANDLE h = handles[r - WAIT_OBJECT_0];
			if (h == wd.mpt.get ()) {
				if (wd.master_refreshing) {
					std::wostringstream ss;
					ss << L"Unexpected exit (";
					DWORD code;
					if (GetExitCodeThread (wd.mpt.get (), &code))
						ss << code << ')';
					else
						ss << wstrerror (GetLastError ()) << L" while getting exit code)";
					wd.on_master_error (ss.str ());
				}
				wd.mpt.reset (nullptr);
			}
		} else {
			std::wostringstream ss;
			ss << L"MsgWaitForMultipleObjects returned an unexpected value: " << r;
			MessageBox (hWnd, ss.str ().c_str (), L"Qarma", 0);
		}
	}
}
Example #5
0
__stdcall unsigned int master_proto (void* _args) {
	master_proto_args args = *reinterpret_cast<master_proto_args*> (_args);

	PostMessage (args.hwnd, qm_master_begin, args.id, 0);

	std::unique_ptr<addrinfo, decltype(&freeaddrinfo)> lookup (nullptr, freeaddrinfo);
	{
		std::default_random_engine reng (std::chrono::system_clock::now ().time_since_epoch ().count ());
		std::uniform_int_distribution<> rdist (0, 19);
		std::ostringstream host;
		host << "arma2oapc.ms" << rdist (reng) << ".gamespy.com";

		addrinfo hints = addrinfo ();
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		addrinfo* tmp;
		int r = getaddrinfo (host.str ().c_str (), "28910", &hints, &tmp); // TODO load balance
		if (r) {
			SendMessage (args.hwnd, qm_master_error, args.id, reinterpret_cast<LPARAM> (wstrerror (WSAGetLastError ()).c_str ()));
			return 0;
		}
		lookup.reset (tmp);
	}

	qsocket socket {lookup->ai_family, lookup->ai_socktype, lookup->ai_protocol};
	if (socket == INVALID_SOCKET) {
		SendMessage (args.hwnd, qm_master_error, args.id, reinterpret_cast<LPARAM> (wstrerror (WSAGetLastError ()).c_str ()));
		return 0;
	}

	int r = connect (socket, lookup->ai_addr, lookup->ai_addrlen);
	if (r == SOCKET_ERROR) {
		SendMessage (args.hwnd, qm_master_error, args.id, reinterpret_cast<LPARAM> (wstrerror (WSAGetLastError ()).c_str ()));
		return 0;
	}

	// transmit request
	std::array<unsigned char, 9> master_validate;
	enctypex_decoder_rand_validate (&master_validate[0]);
	{
		std::ostringstream packet;
		packet << '\0'
			   << '\1'
			   << '\3'
			   << '\0' // 32-bit
			   << '\0'
			   << '\0'
			   << '\0'
			   << "arma2oapc" << '\0'
			   << "gslive" << '\0';
		std::copy (master_validate.begin (), master_validate.end () - 1, std::ostreambuf_iterator<char> (packet)); // note: don't copy the final '\0' byte of master_validate
		packet << "" << '\0' // filter (note, not preceeded by a '\0' separator either
			   << REQUEST << '\0'
			   << '\0'
			   << '\0'
			   << '\0'
			   << '\1'; // 1 = requested information
		std::vector<char> buf (2 + packet.str ().size ());
		WSAHtons (socket, buf.size (), reinterpret_cast<u_short*> (&buf[0]));
		const std::string s = packet.str ();
		std::copy (s.begin (), s.end (), 2 + buf.begin ());

		int r = send (socket, &buf[0], buf.size (), 0);
		if (r == SOCKET_ERROR) {
			SendMessage (args.hwnd, qm_master_error, args.id, reinterpret_cast<LPARAM> (wstrerror (WSAGetLastError ()).c_str ()));
			return 0;
		} else if (r != static_cast<int> (buf.size ())) {
			PostMessage (args.hwnd, qm_master_error, args.id, reinterpret_cast<LPARAM> (L"short send"));
			return 0;
		}
	}
	shutdown (socket, SD_SEND); // XXX error check

	// read response
	enctypex_data_t enctypex_data;
	enctypex_data.start = 0;
	std::vector<unsigned char> data;
	data.reserve (16384);
	while (true) {
		std::array<char, 8192> buf;
		int r = recv (socket, &buf[0], buf.size (), 0);
		if (r == SOCKET_ERROR) {
			SendMessage (args.hwnd, qm_master_error, args.id, reinterpret_cast<LPARAM> (wstrerror (WSAGetLastError ()).c_str ()));
			return 0;
		} else if (r == 0) {
			PostMessage (args.hwnd, qm_master_error, args.id, reinterpret_cast<LPARAM> (L"short recv"));
			return 0;
		}
		std::copy (buf.begin (), buf.begin () + r, std::back_inserter (data));
		PostMessage (args.hwnd, qm_master_progress, args.id, data.size ());

		int len = data.size ();
		unsigned char* endp = enctypex_decoder (reinterpret_cast<unsigned char*> (const_cast<char*> ("Xn221z")), &master_validate[0], &data[0], &len, &enctypex_data);
		assert (endp);
		if (endp && enctypex_decoder_convert_to_ipport (endp, data.size () - (reinterpret_cast<unsigned char*> (endp) - &data[0]), nullptr, nullptr, 0, 0)) {
			break;
		}
	}
	shutdown (socket, SD_RECEIVE); // XXX handle errors

	static_assert (sizeof (server_endpoint) == 6, "server_endpoint is a weird size");
	{
		std::vector<server_endpoint> decoded_data (data.size () / 5); // XXX size seems like a bit of a guess!
		int len = enctypex_decoder_convert_to_ipport (&data[0] + enctypex_data.start, data.size () - enctypex_data.start, reinterpret_cast<unsigned char*> (decoded_data.data ()), nullptr, 0, 0);
		assert (len >= 0); // XXX handle (see gsmyfunc.h line 715)
		for (auto ep: decoded_data)
			SendMessage (args.hwnd, qm_master_found, args.id, reinterpret_cast<LPARAM> (&ep));
	}

	PostMessage (args.hwnd, qm_master_complete, args.id, 0);
	return 0;
}