Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve winsock deprecation #16

Open
Brett208 opened this issue Mar 6, 2019 · 2 comments
Open

Resolve winsock deprecation #16

Brett208 opened this issue Mar 6, 2019 · 2 comments

Comments

@Brett208
Copy link
Member

Brett208 commented Mar 6, 2019

Looks similar to deprecated functions in NetHelper/miniupnp we fixed earlier.

Warning C4996 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings NetFixClient \netfixclient\opunettransportlayer.cpp 916

Warning C4996 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings NetFixClient \netfixclient\opunettransportlayer.cpp 910

@DanRStevens
Copy link
Member

DanRStevens commented Mar 14, 2019

I was looking at this code. Both deprecated calls are in OPUNetTransportLayer::GetHostAddress. The method is used to convert a string form address to an address structure. It supports either numeric dotted IPv4 addresses (Ex: "192.168.1.2:47800"), or DNS names (Ex: "netfix.outpost2.net:47800") which causes a DNS lookup.

Both of these uses are supported by the new getaddrinfo method. Hence, both deprecated methods can be replaced by a single new method. Quite likely the function can be shortened.

I propose the following as a candidate replacement function:

sockaddr OPUNetTransportLayer::StringToAddress(const char* addressString) {
	// Skip any leading spaces
	while (addressString[0] == ' ' || addressString[0] == '\t')
		addressString++;

	// Break string into hostname and port components
	const char* portNumString = strchr(addressString, ':');
	// Advance past ":"
	portNumString += portNumString != nullptr ? 1 : 0;

	// Convert address to struct form
	addrinfo hints = {0, AF_INET, SOCK_DGRAM, IPPROTO_UDP };
	addrinfo* addressLinkedList;
	auto errorCode = getaddrinfo(addressString, portNumString, &hints, &addressLinkedList);
	if (errorCode) {
		throw std::runtime_error(gai_strerror(errorCode));
	}
	if (addressLinkedList->ai_addr == nullptr) {
		throw std::runtime_error("No candidate addresses");
	}
	// Simplification: Just return the first address in the list
	auto address = *addressLinkedList->ai_addr;
	freeaddrinfo(addressLinkedList);

	return address;
}

There are a couple of caveats though. One is the simplification used by this function, where it just returns the first found address. Another is that it copies the full struct to the output, whereas the old method passed in a struct, which then had specific fields initialized. Fields that were not set by the old method could be pre-initialized so they'd have known output values. This was used in one place to form a broadcast address used to search for games.

Additionally, the type of address was changed to the more generic sockaddr, rather than the IPv4 specific sockaddr_in. I believe we should use the more generic struct name whenever possible, though the specific name is used in quite a few places, so updates may be somewhat widespread.

I'd like to see if there are a few step-wise refactorings I can do, so this isn't just one big huge mess when it lands.


Edit: It seems sockaddr is the common fields at the beginning of both sockaddr_in (IPv4) and sockaddr_in6 (IPv6). That means the copy/return above won't quite work right, as it may slice what should be a larger struct.

DanRStevens pushed a commit that referenced this issue Mar 5, 2020
…rCallPoint

Move Variable declarations closer to point of call within functions where appropriate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants