Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion src/core/IronPython.Modules/_socket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
Expand Down Expand Up @@ -1070,6 +1071,7 @@ public static PythonTuple gethostbyname_ex(CodeContext/*!*/ context, [NotNone] s
PythonList aliases;
PythonList ips = new PythonList();

host = EncodeHostName(host);
if (IPAddress.TryParse(host, out IPAddress? addr)) {
if (AddressFamily.InterNetwork == addr.AddressFamily) {
hostname = host;
Expand Down Expand Up @@ -1971,6 +1973,29 @@ private static string ConvertSpecialAddresses(string host) {
}
}

private static readonly IdnMapping _idnMapping = new IdnMapping();

/// <summary>
/// Convert an internationalized host name to its ASCII-compatible (punycode) form.
/// </summary>
/// <remarks>
/// CPython encodes host names with the "idna" codec before resolving them. .NET does the
/// equivalent only on Windows; on POSIX the name reaches getaddrinfo as raw UTF-8, which
/// the resolver usually fails to find. ASCII host names are returned unchanged.
/// </remarks>
private static string EncodeHostName(string host) {
foreach (char c in host) {
if (c > 0x7f) {
try {
return _idnMapping.GetAscii(host);
} catch (ArgumentException ex) {
throw PythonOps.UnicodeError("encoding with 'idna' codec failed (UnicodeError: {0})", ex.Message);
}
}
}
return host;
}

/// <summary>
/// Return the IP address associated with host, with optional address family checking.
/// host may be either a name or an IP address (in string form).
Expand All @@ -1992,7 +2017,7 @@ private static IPAddress HostToAddress(CodeContext/*!*/ context, string host, Ad
/// converted to an IP address (e.g. through a name lookup failure).
/// </summary>
private static IPAddress[] HostToAddresses(CodeContext/*!*/ context, string host, AddressFamily family) {
host = ConvertSpecialAddresses(host);
host = EncodeHostName(ConvertSpecialAddresses(host));
try {
bool numeric = true;
int dotCount = 0;
Expand Down
5 changes: 0 additions & 5 deletions tests/suite/stdlib/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ def load_tests(loader, standard_tests, pattern):
failing_tests += [
test.test_socket.NonBlockingTCPTests('testRecv'), # TODO: figure out
]
if is_linux:
failing_tests += [
test.test_socket.GeneralModuleTests('test_idna'), # TODO: figure out
]

skip_tests = [
test.test_socket.UnbufferedFileObjectClassTestCase('testWriteNonBlocking') # fails intermittently during CI
]
Expand Down
Loading