Skip to content

Commit e19bf58

Browse files
committed
Implement basic socket.gethostbyname_ex
1 parent 28d3431 commit e19bf58

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SocketModuleBuiltins.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import static com.oracle.graal.python.runtime.PosixConstants.AF_INET;
5555
import static com.oracle.graal.python.runtime.PosixConstants.AF_INET6;
5656
import static com.oracle.graal.python.runtime.PosixConstants.AF_UNSPEC;
57+
import static com.oracle.graal.python.runtime.PosixConstants.AI_CANONNAME;
5758
import static com.oracle.graal.python.runtime.PosixConstants.AI_NUMERICHOST;
5859
import static com.oracle.graal.python.runtime.PosixConstants.INADDR_ANY;
5960
import static com.oracle.graal.python.runtime.PosixConstants.NI_DGRAM;
@@ -80,6 +81,7 @@
8081
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
8182
import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum;
8283
import com.oracle.graal.python.builtins.objects.function.PKeyword;
84+
import com.oracle.graal.python.builtins.objects.list.PList;
8385
import com.oracle.graal.python.builtins.objects.module.PythonModule;
8486
import com.oracle.graal.python.builtins.objects.socket.SocketNodes;
8587
import com.oracle.graal.python.builtins.objects.socket.SocketNodes.IdnaFromStringOrBytesConverterNode;
@@ -370,6 +372,55 @@ protected static IdnaFromStringOrBytesConverterNode createIdnaConverter() {
370372
}
371373
}
372374

375+
@Builtin(name = "gethostbyname_ex", minNumOfPositionalArgs = 1)
376+
@GenerateNodeFactory
377+
public abstract static class GetHostByNameExNode extends PythonUnaryBuiltinNode {
378+
@Specialization
379+
Object get(VirtualFrame frame, Object nameObj,
380+
@CachedLibrary("getPosixSupport()") PosixSupportLibrary posixLib,
381+
@CachedLibrary(limit = "1") UniversalSockAddrLibrary addrLib,
382+
@CachedLibrary(limit = "1") AddrInfoCursorLibrary addrInfoCursorLib,
383+
@Bind("this") Node inliningTarget,
384+
@Cached("createIdnaConverter()") IdnaFromStringOrBytesConverterNode idnaConverter,
385+
@Cached SysModuleBuiltins.AuditNode auditNode,
386+
@Cached PConstructAndRaiseNode.Lazy constructAndRaiseNode,
387+
@Cached PythonObjectFactory factory) {
388+
byte[] name = idnaConverter.execute(frame, nameObj);
389+
// The event name is really without the _ex, it's not a copy-paste error
390+
auditNode.audit(inliningTarget, "socket.gethostbyname", factory.createTuple(new Object[]{nameObj}));
391+
/*
392+
* TODO this uses getaddrinfo to emulate the legacy gethostbyname. It doesn't support
393+
* aliases and multiple addresses. We might want to use the legacy gethostbyname_r API
394+
* in the future
395+
*/
396+
try {
397+
AddrInfoCursor cursor = posixLib.getaddrinfo(getPosixSupport(), posixLib.createPathFromBytes(getPosixSupport(), name),
398+
null, AF_INET.value, 0, 0, AI_CANONNAME.value);
399+
try {
400+
TruffleString canonName = posixLib.getPathAsString(getPosixSupport(), addrInfoCursorLib.getCanonName(cursor));
401+
Inet4SockAddr inet4SockAddr = addrLib.asInet4SockAddr(addrInfoCursorLib.getSockAddr(cursor));
402+
TruffleString addr = posixLib.getPathAsString(getPosixSupport(), posixLib.inet_ntop(getPosixSupport(), AF_INET.value, inet4SockAddr.getAddressAsBytes()));
403+
// getaddrinfo doesn't support aliases
404+
PList aliases = factory.createList();
405+
// we support just one address for now
406+
PList addrs = factory.createList(new Object[]{addr});
407+
return factory.createTuple(new Object[]{canonName, aliases, addrs});
408+
} finally {
409+
addrInfoCursorLib.release(cursor);
410+
}
411+
} catch (GetAddrInfoException e) {
412+
throw constructAndRaiseNode.get(inliningTarget).executeWithArgsOnly(frame, SocketHError, new Object[]{e.getMessageAsTruffleString()});
413+
} catch (PosixException e) {
414+
throw constructAndRaiseNode.get(inliningTarget).raiseOSErrorFromPosixException(frame, e);
415+
}
416+
}
417+
418+
@NeverDefault
419+
protected static IdnaFromStringOrBytesConverterNode createIdnaConverter() {
420+
return IdnaFromStringOrBytesConverterNode.create("gethostbyname_ex", 1);
421+
}
422+
}
423+
373424
@Builtin(name = "getservbyname", minNumOfPositionalArgs = 1, numOfPositionalOnlyArgs = 2, parameterNames = {"servicename", "protocolname"})
374425
@ArgumentClinic(name = "servicename", conversion = ArgumentClinic.ClinicConversion.TString)
375426
@ArgumentClinic(name = "protocolname", conversion = ArgumentClinic.ClinicConversion.TString, defaultValue = "PNone.NO_VALUE")

0 commit comments

Comments
 (0)