-
-
Notifications
You must be signed in to change notification settings - Fork 30.8k
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
bpo-28134: Auto-detect socket values from file descriptor #1349
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4204,7 +4204,7 @@ def get_high_socket_fd(self): | |
|
||
def close(self, fd): | ||
if WIN32: | ||
socket.socket(fileno=fd).close() | ||
socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=fd).close() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use keyword arguments for all of these. |
||
else: | ||
os.close(fd) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Sockets now auto-detect family, type and protocol from file descriptor by | ||
default. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,7 +102,8 @@ Local naming conventions: | |
|
||
/* Socket object documentation */ | ||
PyDoc_STRVAR(sock_doc, | ||
"socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) -> socket object\n\ | ||
"socket(family=AF_INET, type=SOCK_STREAM, proto=0) -> socket object\n\ | ||
socket(family=-1, type=-1, proto=-1, fileno=None) -> socket object\n\ | ||
\n\ | ||
Open a socket of the given type. The family argument specifies the\n\ | ||
address family; it defaults to AF_INET. The type argument specifies\n\ | ||
|
@@ -111,6 +112,9 @@ or datagram (SOCK_DGRAM) socket. The protocol argument defaults to 0,\n\ | |
specifying the default protocol. Keyword arguments are accepted.\n\ | ||
The socket is created as non-inheritable.\n\ | ||
\n\ | ||
When a fileno is passed in, family, type and proto are auto-detected,\n\ | ||
unless they are explicitly set.\n\ | ||
\n\ | ||
A socket object represents one endpoint of a network connection.\n\ | ||
\n\ | ||
Methods of socket objects (keyword arguments not allowed):\n\ | ||
|
@@ -4745,7 +4749,7 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) | |
PySocketSockObject *s = (PySocketSockObject *)self; | ||
PyObject *fdobj = NULL; | ||
SOCKET_T fd = INVALID_SOCKET; | ||
int family = AF_INET, type = SOCK_STREAM, proto = 0; | ||
int family = -1, type = -1, proto = -1; | ||
static char *keywords[] = {"family", "type", "proto", "fileno", 0}; | ||
#ifndef MS_WINDOWS | ||
#ifdef SOCK_CLOEXEC | ||
|
@@ -4795,9 +4799,72 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) | |
"can't use invalid socket value"); | ||
return -1; | ||
} | ||
|
||
if (family == -1) { | ||
sock_addr_t addrbuf; | ||
socklen_t addrlen = sizeof(sock_addr_t); | ||
|
||
memset(&addrbuf, 0, addrlen); | ||
if (getsockname(fd, SAS2SA(&addrbuf), &addrlen) == 0) { | ||
family = SAS2SA(&addrbuf)->sa_family; | ||
} else { | ||
#ifdef MS_WINDOWS | ||
PyErr_SetFromWindowsErrWithFilename(0, "family"); | ||
#else | ||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, "family"); | ||
#endif | ||
return -1; | ||
} | ||
} | ||
#ifdef SO_TYPE | ||
if (type == -1) { | ||
int tmp; | ||
socklen_t slen = sizeof(tmp); | ||
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &tmp, &slen) == 0) { | ||
type = tmp; | ||
} else { | ||
#ifdef MS_WINDOWS | ||
PyErr_SetFromWindowsErrWithFilename(0, "type"); | ||
#else | ||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, "type"); | ||
#endif | ||
return -1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any idea if SO_TYPE or SO_PROTOCOL are ever actually undefined on any platforms? If so, it'd be nice if we could make the exception raised as a result of this contain error message text indicating that the type and protocol must be supplied on the given platform. |
||
} | ||
} | ||
#else | ||
type = SOCK_STREAM; | ||
#endif | ||
#ifdef SO_PROTOCOL | ||
if (proto == -1) { | ||
int tmp; | ||
socklen_t slen = sizeof(tmp); | ||
if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &tmp, &slen) == 0) { | ||
proto = tmp; | ||
} else { | ||
#ifdef MS_WINDOWS | ||
PyErr_SetFromWindowsErrWithFilename(0, "protocol"); | ||
#else | ||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, "protocol"); | ||
#endif | ||
return -1; | ||
} | ||
} | ||
#else | ||
proto = 0; | ||
#endif | ||
} | ||
} | ||
else { | ||
/* No fd, default to AF_INET and SOCK_STREAM */ | ||
if (family == -1) { | ||
family = AF_INET; | ||
} | ||
if (type == -1) { | ||
type = SOCK_STREAM; | ||
} | ||
if (proto == -1) { | ||
proto = 0; | ||
} | ||
#ifdef MS_WINDOWS | ||
/* Windows implementation */ | ||
#ifndef WSA_FLAG_NO_HANDLE_INHERIT | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block is not necessary but makes the code easier to understand for non-C coders
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you propose to remove it? If not, I suggest None for default values rather than −1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed, while -1 falling through to socketmodule.c would trigger its default behavior, writing this here in Python would be nicer using the =None idiom.