Skip to content

Commit

Permalink
refactor module
Browse files Browse the repository at this point in the history
use appropriate naming for function, make _getsockname more generic and
doc more useful
  • Loading branch information
benoitc committed Nov 25, 2019
1 parent 3ae3d1c commit 444b2d8
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
8 changes: 8 additions & 0 deletions NOTICE
Expand Up @@ -122,3 +122,11 @@ util/unlink.py
--------------

backport frop python3 Lib/test/support.py


gunicorn.socketfromfd
---------------------

Under Apache License 2

Copyright (C) 2016 Christian Heimes
39 changes: 28 additions & 11 deletions gunicorn/socketfromfd.py
@@ -1,9 +1,20 @@
# Copyright (C) 2016 Christian Heimes
"""socketfromfd -- socket.fromd() with auto-discovery
# -*- coding: utf-8 -
#
# This file is part of gunicorn
# See the NOTICE for more information.

ATTENTION: Do not remove this backport till the minimum required version is
Python 3.7. See https://bugs.python.org/issue28134 for details.
# Copyright (C) 2016 Christian Heimes under Apache License 2

# source code based on https://github.com/tiran/socketfromfd/blob/master/socketfromfd.py
# and https://github.com/python/cpython/blob/master/Modules/socketmodule.c

"""socketfromfd -- create a socket from its file descriptor
This module detect the socket properties.
note: Before python 3.7 auto detecting the socket was not working.
See https://bugs.python.org/issue28134 for details.
"""

from __future__ import print_function

import ctypes
Expand Down Expand Up @@ -43,7 +54,7 @@ def _errcheck_errno(result, func, arguments):

if platform.system() == 'SunOS':
_libc_getsockopt = libc._so_getsockopt
_libc_getsockname = libc._so_getsockname
_lib_getsockname = libc._so_getsockname
else:
_libc_getsockopt = libc.getsockopt
_libc_getsockname = libc.getsockname
Expand All @@ -65,13 +76,17 @@ class SockAddr(ctypes.Structure):
('sa_family', ctypes.c_uint8),
('sa_data', ctypes.c_char * 14)
]


_libc_getsockname.argtypes = [
ctypes.c_int,
ctypes.POINTER(SockAddr),
ctypes.POINTER(ctypes.c_int)
]
_libc_getsockname.restype = ctypes.c_int # 0: ok, -1: err
_libc_getsockname.errcheck = _errcheck_errno

def _raw_getsockopt(fd, level, optname):
def _getsockopt(fd, level, optname):
"""Make raw getsockopt() call for int32 optval
:param fd: socket fd
Expand All @@ -85,11 +100,11 @@ def _raw_getsockopt(fd, level, optname):
ctypes.byref(optval), ctypes.byref(optlen))
return optval.value

def _raw_getsockname(fd):
def _getsockname(fd):
sockaddr = SockAddr()
sockaddrlen = ctypes.c_int(ctypes.sizeof(sockaddr))
_libc_getsockname(fd, sockaddr, sockaddrlen)
return sockaddr.sa_family
return sockaddr

def fromfd(fd, keep_fd=True):
"""Create a socket from a file descriptor
Expand All @@ -108,13 +123,15 @@ def fromfd(fd, keep_fd=True):
:return: socket.socket instance
:raises OSError: for invalid socket fd
"""
family = _raw_getsockname(fd)
sockaddr = _getsockname(fd)
family = sockaddr.sa_family
if hasattr(socket, 'SO_TYPE'):
typ = _raw_getsockopt(fd, socket.SOL_SOCKET, getattr(socket, 'SO_TYPE'))
typ = _getsockopt(fd, socket.SOL_SOCKET, getattr(socket, 'SO_TYPE'))
else:
typ = socket.SOCK_STREAM

if hasattr(socket, 'SO_PROTOCOL'):
proto = _raw_getsockopt(fd, socket.SOL_SOCKET, getattr(socket, 'SO_PROTOCOL'))
proto = _getsockopt(fd, socket.SOL_SOCKET, getattr(socket, 'SO_PROTOCOL'))
else:
proto = 0
if keep_fd:
Expand Down

0 comments on commit 444b2d8

Please sign in to comment.