8000 gh-92658: Add Hyper-V socket support by jborean93 · Pull Request #92755 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-92658: Add Hyper-V socket support #92755

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

Merged
merged 7 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Fixes for review
  • Loading branch information
jborean93 committed May 19, 2022
commit f39731c3acb10e2655f07dd7c0ac431cb07cee4a
13 changes: 11 additions & 2 deletions Doc/library/socket.rst
Original file line number Diff line number Diff line change
Expand Up @@ -614,8 +614,17 @@ Constants

.. data:: AF_HYPERV
HV_PROTOCOL_RAW
HVSOCKET_*
HV_GUID_*
HVSOCKET_CONNECT_TIMEOUT
HVSOCKET_CONNECT_TIMEOUT_MAX
HVSOCKET_CONTAINER_PASSTHRU
HVSOCKET_CONNECTED_SUSPEND
HVSOCKET_ADDRESS_FLAG_PASSTHRU
HV_GUID_ZERO
HV_GUID_WILDCARD
HV_GUID_BROADCAST
HV_GUID_CHILDREN
HV_GUID_LOOPBACK
HV_GUID_LOOPBACK

Constants for Windows Hyper-V sockets for host/guest communications.

Expand Down
20 changes: 14 additions & 6 deletions Lib/test/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import signal
import math
import pickle
import re
import struct
import random
import shutil
Expand Down Expand Up @@ -2490,32 +2491,39 @@ def testHyperVConstants(self):
socket.HV_GUID_LOOPBACK

def testCreateHyperVSocketWithUnknownProtoFailure(self):
with self.assertRaises(OSError):
expected = "A protocol was specified in the socket function call " \
"that does not support the semantics of the socket type requested"
with self.assertRaisesRegex(OSError, expected):
socket.socket(socket.AF_HYPERV, socket.SOCK_STREAM)

def testCreateHyperVSocketAddrNotTupleFailure(self):
expected = "connect(): AF_HYPERV address must be tuple, not str"
with socket.socket(socket.AF_HYPERV, socket.SOCK_STREAM, socket.HV_PROTOCOL_RAW) as s:
with self.assertRaises(TypeError):
with self.assertRaisesRegex(TypeError, re.escape(expected)):
s.connect(socket.HV_GUID_ZERO)

def testCreateHyperVSocketAddrNotTupleOf2StrsFailure(self):
expected = "AF_HYPERV address must be a str tuple (vm_id, service_id)"
with socket.socket(socket.AF_HYPERV, socket.SOCK_STREAM, socket.HV_PROTOCOL_RAW) as s:
with self.assertRaises(TypeError):
with self.assertRaisesRegex(TypeError, re.escape(expected)):
s.connect((socket.HV_GUID_ZERO,))

def testCreateHyperVSocketAddrNotTupleOfStrsFailure(self):
expected = "AF_HYPERV address must be a str tuple (vm_id, service_id)"
with socket.socket(socket.AF_HYPERV, socket.SOCK_STREAM, socket.HV_PROTOCOL_RAW) as s:
with self.assertRaises(TypeError):
with self.assertRaisesRegex(TypeError, re.escape(expected)):
s.connect((1, 2))

def testCreateHyperVSocketAddrVmIdNotValidUUIDFailure(self):
expected = "connect(): AF_HYPERV address vm_id is not a valid UUID string"
with socket.socket(socket.AF_HYPERV, socket.SOCK_STREAM, socket.HV_PROTOCOL_RAW) as s:
with self.assertRaises(ValueError):
with self.assertRaisesRegex(ValueError, re.escape(expected)):
s.connect(("00", socket.HV_GUID_ZERO))

def testCreateHyperVSocketAddrServiceIdNotValidUUIDFailure(self):
expected = "connect(): AF_HYPERV address service_id is not a valid UUID string"
with socket.socket(socket.AF_HYPERV, socket.SOCK_STREAM, socket.HV_PROTOCOL_RAW) as s:
with self.assertRaises(ValueError):
with self.assertRaisesRegex(ValueError, re.escape(expected)):
s.connect((socket.HV_GUID_ZERO, "00"))


Expand Down
40 changes: 19 additions & 21 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1588,24 +1588,20 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
SOCKADDR_HV *a = (SOCKADDR_HV *) addr;

wchar_t *guidStr;
PyObject *vmId;
PyObject *serviceId;

if (UuidToStringW(&a->VmId, &guidStr) == RPC_S_OUT_OF_MEMORY) {
PyErr_SetString(PyExc_MemoryError,
"out of memory in makesockaddr");
return NULL;
return PyErr_NoMemory();
}
vmId = PyUnicode_FromWideChar(guidStr, -1);
RpcStringFreeW(&guidStr);
PyObject *vmId = PyUnicode_FromWideChar(guidStr, -1);
RPC_STATUS res = RpcStringFreeW(&guidStr);
assert(res == RPC_S_OK);
8000
if (UuidToStringW(&a->ServiceId, &guidStr) == RPC_S_OUT_OF_MEMORY) {
PyErr_SetString(PyExc_MemoryError,
"out of memory in makesockaddr");
return NULL;
Py_DECREF(vmId);
return PyErr_NoMemory();
}
serviceId = PyUnicode_FromWideChar(guidStr, -1);
RpcStringFreeW(&guidStr);
PyObject *serviceId = PyUnicode_FromWideChar(guidStr, -1);
res = RpcStringFreeW(&guidStr);
assert(res == RPC_S_OK);

return Py_BuildValue("NN", vmId, serviceId);
}
Expand Down Expand Up @@ -2415,7 +2411,6 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
{
PyObject *vm_id_obj = NULL;
PyObject *service_id_obj = NULL;
wchar_t *guid_str;

SOCKADDR_HV *addr = &addrbuf->hv;

Expand All @@ -2435,20 +2430,21 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
return 0;
}

guid_str = PyUnicode_AsWideCharString(vm_id_obj, NULL);
wchar_t *guid_str = PyUnicode_AsWideCharString(vm_id_obj, NULL);
if (guid_str == NULL) {
PyErr_Format(PyExc_ValueError,
"%s(): AF_HYPERV address vm_id is not a valid UUID string",
caller);
return 0;
}
if (UuidFromStringW(guid_str, &addr->VmId) != RPC_S_OK) {
RPC_STATUS rc = UuidFromStringW(guid_str, &addr->VmId);
PyMem_Free(guid_str);
if (rc != RPC_S_OK) {
PyErr_Format(PyExc_ValueError,
"%s(): AF_HYPERV address vm_id is not a valid UUID string",
caller);
return 0;
}
PyMem_Free(guid_str);

guid_str = PyUnicode_AsWideCharString(service_id_obj, NULL);
if (guid_str == NULL) {
Expand All @@ -2457,20 +2453,22 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
caller);
return 0;
}
if (UuidFromStringW(guid_str, &addr->ServiceId) != RPC_S_OK) {
rc = UuidFromStringW(guid_str, &addr->ServiceId);
PyMem_Free(guid_str);
if (rc != RPC_S_OK) {
PyErr_Format(PyExc_ValueError,
"%s(): AF_HYPERV address service_id is not a valid UUID string",
caller);
return 0;
}
PyMem_Free(guid_str);

*len_ret = sizeof(*addr);
return 1;
}
default:
PyErr_Format(PyExc_OSError,
"%s(): unsupported AF_HYPERV protocol", caller);
"%s(): unsupported AF_HYPERV protocol: %d",
caller, s->sock_proto);
return 0;
}
}
Expand Down Expand Up @@ -7478,7 +7476,7 @@ PyInit__socket(void)
PyModule_AddStringConstant(m, "HV_GUID_BROADCAST", "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF");
PyModule_AddStringConstant(m, "HV_GUID_CHILDREN", "90DB8B89-0D35-4F79-8CE9-49EA0AC8B7CD");
PyModule_AddStringConstant(m, "HV_GUID_LOOPBACK", "E0E16197-DD56-4A10-9195-5EE7A155A838");
PyModule_AddStringConstant(m, "HV_GUID_PARENT", "E0E16197-DD56-4A10-9195-5EE7A155A838");
PyModule_AddStringConstant(m, "HV_GUID_PARENT", "A42E7CDA-D03F-480C-9CC2-A4DE20ABB878");
#endif /* AF_HYPERV */

#ifdef USE_BLUETOOTH
Expand Down
0