123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- /* Socket module header file */
- /* Includes needed for the sockaddr_* symbols below */
- #ifndef MS_WINDOWS
- #ifdef __VMS
- # include <socket.h>
- # else
- # include <sys/socket.h>
- # endif
- # include <netinet/in.h>
- # include <netinet/tcp.h>
- #else /* MS_WINDOWS */
- # include <winsock2.h>
- /*
- * If Windows has bluetooth support, include bluetooth constants.
- */
- #ifdef AF_BTH
- # include <ws2bth.h>
- # include <pshpack1.h>
- /*
- * The current implementation assumes the bdaddr in the sockaddr structs
- * will be a bdaddr_t. We treat this as an opaque type: on *nix systems, it
- * will be a struct with a single member (an array of six bytes). On windows,
- * we typedef this to ULONGLONG to match the Windows definition.
- */
- typedef ULONGLONG bdaddr_t;
- /*
- * Redefine SOCKADDR_BTH to provide names compatible with _BT_RC_MEMB() macros.
- */
- struct SOCKADDR_BTH_REDEF {
- union {
- USHORT addressFamily;
- USHORT family;
- };
- union {
- ULONGLONG btAddr;
- bdaddr_t bdaddr;
- };
- GUID serviceClassId;
- union {
- ULONG port;
- ULONG channel;
- };
- };
- # include <poppack.h>
- #endif
- /* Windows 'supports' CMSG_LEN, but does not follow the POSIX standard
- * interface at all, so there is no point including the code that
- * attempts to use it.
- */
- # ifdef PySocket_BUILDING_SOCKET
- # undef CMSG_LEN
- # endif
- # include <ws2tcpip.h>
- /* VC6 is shipped with old platform headers, and does not have MSTcpIP.h
- * Separate SDKs have all the functions we want, but older ones don't have
- * any version information.
- * I use SIO_GET_MULTICAST_FILTER to detect a decent SDK.
- */
- # ifdef SIO_GET_MULTICAST_FILTER
- # include <mstcpip.h> /* for SIO_RCVALL */
- # define HAVE_ADDRINFO
- # define HAVE_SOCKADDR_STORAGE
- # define HAVE_GETADDRINFO
- # define HAVE_GETNAMEINFO
- # define ENABLE_IPV6
- # else
- typedef int socklen_t;
- # endif /* IPPROTO_IPV6 */
- /* Remove ifdef once Py_WINVER >= 0x0604
- * socket.h only defines AF_HYPERV if _WIN32_WINNT is at that level or higher
- * so for now it's just manually defined.
- */
- # ifndef AF_HYPERV
- # define AF_HYPERV 34
- # endif
- # include <hvsocket.h>
- #endif /* MS_WINDOWS */
- #ifdef HAVE_SYS_UN_H
- # include <sys/un.h>
- #else
- # undef AF_UNIX
- #endif
- #ifdef HAVE_LINUX_NETLINK_H
- # ifdef HAVE_ASM_TYPES_H
- # include <asm/types.h>
- # endif
- # include <linux/netlink.h>
- #else
- # undef AF_NETLINK
- #endif
- #ifdef HAVE_LINUX_QRTR_H
- # ifdef HAVE_ASM_TYPES_H
- # include <asm/types.h>
- # endif
- # include <linux/qrtr.h>
- #else
- # undef AF_QIPCRTR
- #endif
- #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
- #error #include <bluetooth/bluetooth.h>
- #error #include <bluetooth/rfcomm.h>
- #error #include <bluetooth/l2cap.h>
- #error #include <bluetooth/sco.h>
- #error #include <bluetooth/hci.h>
- #endif
- #ifdef HAVE_BLUETOOTH_H
- #error #include <bluetooth.h>
- #endif
- #ifdef HAVE_NET_IF_H
- # include <net/if.h>
- #endif
- #ifdef HAVE_NETPACKET_PACKET_H
- # include <sys/ioctl.h>
- # include <netpacket/packet.h>
- #endif
- #ifdef HAVE_LINUX_TIPC_H
- # include <linux/tipc.h>
- #endif
- #ifdef HAVE_LINUX_CAN_H
- # include <linux/can.h>
- #elif defined(HAVE_NETCAN_CAN_H)
- # error #include <netcan/can.h>
- #else
- # undef AF_CAN
- # undef PF_CAN
- #endif
- #ifdef HAVE_LINUX_CAN_RAW_H
- #include <linux/can/raw.h>
- #endif
- #ifdef HAVE_LINUX_CAN_BCM_H
- #include <linux/can/bcm.h>
- #endif
- #ifdef HAVE_LINUX_CAN_J1939_H
- #include <linux/can/j1939.h>
- #endif
- #ifdef HAVE_SYS_SYS_DOMAIN_H
- #include <sys/sys_domain.h>
- #endif
- #ifdef HAVE_SYS_KERN_CONTROL_H
- #include <sys/kern_control.h>
- #endif
- #ifdef HAVE_LINUX_VM_SOCKETS_H
- # include <linux/vm_sockets.h>
- #else
- # undef AF_VSOCK
- #endif
- #ifdef HAVE_SOCKADDR_ALG
- # include <linux/if_alg.h>
- # ifndef AF_ALG
- # define AF_ALG 38
- # endif
- # ifndef SOL_ALG
- # define SOL_ALG 279
- # endif
- /* Linux 3.19 */
- # ifndef ALG_SET_AEAD_ASSOCLEN
- # define ALG_SET_AEAD_ASSOCLEN 4
- # endif
- # ifndef ALG_SET_AEAD_AUTHSIZE
- # define ALG_SET_AEAD_AUTHSIZE 5
- # endif
- /* Linux 4.8 */
- # ifndef ALG_SET_PUBKEY
- # define ALG_SET_PUBKEY 6
- # endif
- # ifndef ALG_OP_SIGN
- # define ALG_OP_SIGN 2
- # endif
- # ifndef ALG_OP_VERIFY
- # define ALG_OP_VERIFY 3
- # endif
- #endif /* HAVE_SOCKADDR_ALG */
- #ifdef __EMSCRIPTEN__
- // wasm32-emscripten sockets only support subset of IPv4 and IPv6.
- // SCTP protocol crashes runtime.
- #ifdef IPPROTO_SCTP
- # undef IPPROTO_SCTP
- #endif
- // setsockopt() fails with ENOPROTOOPT, getsockopt only supports SO_ERROR.
- // undef SO_REUSEADDR and SO_REUSEPORT so they cannot be used.
- #ifdef SO_REUSEADDR
- # undef SO_REUSEADDR
- #endif
- #ifdef SO_REUSEPORT
- # undef SO_REUSEPORT
- #endif
- #endif // __EMSCRIPTEN__
- #ifndef Py__SOCKET_H
- #define Py__SOCKET_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* Python module and C API name */
- #define PySocket_MODULE_NAME "_socket"
- #define PySocket_CAPI_NAME "CAPI"
- #define PySocket_CAPSULE_NAME PySocket_MODULE_NAME "." PySocket_CAPI_NAME
- /* Abstract the socket file descriptor type */
- #ifdef MS_WINDOWS
- typedef SOCKET SOCKET_T;
- # ifdef MS_WIN64
- # define SIZEOF_SOCKET_T 8
- # else
- # define SIZEOF_SOCKET_T 4
- # endif
- #else
- typedef int SOCKET_T;
- # define SIZEOF_SOCKET_T SIZEOF_INT
- #endif
- #if SIZEOF_SOCKET_T <= SIZEOF_LONG
- #define PyLong_FromSocket_t(fd) PyLong_FromLong((SOCKET_T)(fd))
- #define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLong(fd)
- #else
- #define PyLong_FromSocket_t(fd) PyLong_FromLongLong((SOCKET_T)(fd))
- #define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLongLong(fd)
- #endif
- // AF_HYPERV is only supported on Windows
- #if defined(AF_HYPERV) && defined(MS_WINDOWS)
- # define HAVE_AF_HYPERV
- #endif
- /* Socket address */
- typedef union sock_addr {
- struct sockaddr_in in;
- struct sockaddr sa;
- #ifdef AF_UNIX
- struct sockaddr_un un;
- #endif
- #ifdef AF_NETLINK
- struct sockaddr_nl nl;
- #endif
- #ifdef ENABLE_IPV6
- struct sockaddr_in6 in6;
- struct sockaddr_storage storage;
- #endif
- #if defined(HAVE_BLUETOOTH_H) && defined(__FreeBSD__)
- struct sockaddr_l2cap bt_l2;
- struct sockaddr_rfcomm bt_rc;
- struct sockaddr_sco bt_sco;
- struct sockaddr_hci bt_hci;
- #elif defined(HAVE_BLUETOOTH_BLUETOOTH_H)
- struct sockaddr_l2 bt_l2;
- struct sockaddr_rc bt_rc;
- struct sockaddr_sco bt_sco;
- struct sockaddr_hci bt_hci;
- #elif defined(MS_WINDOWS)
- struct SOCKADDR_BTH_REDEF bt_rc;
- #endif
- #ifdef HAVE_NETPACKET_PACKET_H
- struct sockaddr_ll ll;
- #endif
- #if defined(HAVE_LINUX_CAN_H) || defined(HAVE_NETCAN_CAN_H)
- struct sockaddr_can can;
- #endif
- #ifdef HAVE_SYS_KERN_CONTROL_H
- struct sockaddr_ctl ctl;
- #endif
- #ifdef HAVE_SOCKADDR_ALG
- struct sockaddr_alg alg;
- #endif
- #ifdef AF_QIPCRTR
- struct sockaddr_qrtr sq;
- #endif
- #ifdef AF_VSOCK
- struct sockaddr_vm vm;
- #endif
- #ifdef HAVE_LINUX_TIPC_H
- struct sockaddr_tipc tipc;
- #endif
- #ifdef HAVE_AF_HYPERV
- SOCKADDR_HV hv;
- #endif
- } sock_addr_t;
- /* The object holding a socket. It holds some extra information,
- like the address family, which is used to decode socket address
- arguments properly. */
- typedef struct {
- PyObject_HEAD
- SOCKET_T sock_fd; /* Socket file descriptor */
- int sock_family; /* Address family, e.g., AF_INET */
- int sock_type; /* Socket type, e.g., SOCK_STREAM */
- int sock_proto; /* Protocol type, usually 0 */
- PyObject *(*errorhandler)(void); /* Error handler; checks
- errno, returns NULL and
- sets a Python exception */
- _PyTime_t sock_timeout; /* Operation timeout in seconds;
- 0.0 means non-blocking */
- struct _socket_state *state;
- } PySocketSockObject;
- /* --- C API ----------------------------------------------------*/
- /* Short explanation of what this C API export mechanism does
- and how it works:
- The _ssl module needs access to the type object defined in
- the _socket module. Since cross-DLL linking introduces a lot of
- problems on many platforms, the "trick" is to wrap the
- C API of a module in a struct which then gets exported to
- other modules via a PyCapsule.
- The code in socketmodule.c defines this struct (which currently
- only contains the type object reference, but could very
- well also include other C APIs needed by other modules)
- and exports it as PyCapsule via the module dictionary
- under the name "CAPI".
- Other modules can now include the socketmodule.h file
- which defines the needed C APIs to import and set up
- a static copy of this struct in the importing module.
- After initialization, the importing module can then
- access the C APIs from the _socket module by simply
- referring to the static struct, e.g.
- Load _socket module and its C API; this sets up the global
- PySocketModule:
- if (PySocketModule_ImportModuleAndAPI())
- return;
- Now use the C API as if it were defined in the using
- module:
- if (!PyArg_ParseTuple(args, "O!|zz:ssl",
- PySocketModule.Sock_Type,
- (PyObject*)&Sock,
- &key_file, &cert_file))
- return NULL;
- Support could easily be extended to export more C APIs/symbols
- this way. Currently, only the type object is exported,
- other candidates would be socket constructors and socket
- access functions.
- */
- /* C API for usage by other Python modules.
- * Always add new things to the end for binary compatibility. */
- typedef struct {
- PyTypeObject *Sock_Type;
- PyObject *error;
- PyObject *timeout_error;
- } PySocketModule_APIObject;
- #define PySocketModule_ImportModuleAndAPI() PyCapsule_Import(PySocket_CAPSULE_NAME, 1)
- #ifdef __cplusplus
- }
- #endif
- #endif /* !Py__SOCKET_H */
|