Home | History | Annotate | Download | only in Modules
      1 /* Socket module header file */
      2 
      3 /* Includes needed for the sockaddr_* symbols below */
      4 #ifndef MS_WINDOWS
      5 #ifdef __VMS
      6 #   include <socket.h>
      7 # else
      8 #   include <sys/socket.h>
      9 # endif
     10 # include <netinet/in.h>
     11 # if !(defined(UEFI_C_SOURCE) || defined(__BEOS__) || defined(__CYGWIN__) || (defined(PYOS_OS2) && defined(PYCC_VACPP)))
     12 #  include <netinet/tcp.h>
     13 # endif
     14 
     15 #else /* MS_WINDOWS */
     16 # include <winsock2.h>
     17 # include <ws2tcpip.h>
     18 /* VC6 is shipped with old platform headers, and does not have MSTcpIP.h
     19  * Separate SDKs have all the functions we want, but older ones don't have
     20  * any version information.
     21  * I use SIO_GET_MULTICAST_FILTER to detect a decent SDK.
     22  */
     23 # ifdef SIO_GET_MULTICAST_FILTER
     24 #  include <MSTcpIP.h> /* for SIO_RCVALL */
     25 #  define HAVE_ADDRINFO
     26 #  define HAVE_SOCKADDR_STORAGE
     27 #  define HAVE_GETADDRINFO
     28 #  define HAVE_GETNAMEINFO
     29 #  define ENABLE_IPV6
     30 # else
     31 typedef int socklen_t;
     32 # endif /* IPPROTO_IPV6 */
     33 #endif /* MS_WINDOWS */
     34 
     35 #ifdef HAVE_SYS_UN_H
     36 # include <sys/un.h>
     37 #else
     38 # undef AF_UNIX
     39 #endif
     40 
     41 #ifdef HAVE_LINUX_NETLINK_H
     42 # ifdef HAVE_ASM_TYPES_H
     43 #  include <asm/types.h>
     44 # endif
     45 # include <linux/netlink.h>
     46 #else
     47 #  undef AF_NETLINK
     48 #endif
     49 
     50 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     51 #include <bluetooth/bluetooth.h>
     52 #include <bluetooth/rfcomm.h>
     53 #include <bluetooth/l2cap.h>
     54 #include <bluetooth/sco.h>
     55 #include <bluetooth/hci.h>
     56 #endif
     57 
     58 #ifdef HAVE_BLUETOOTH_H
     59 #include <bluetooth.h>
     60 #endif
     61 
     62 #ifdef HAVE_NETPACKET_PACKET_H
     63 # include <sys/ioctl.h>
     64 # include <net/if.h>
     65 # include <netpacket/packet.h>
     66 #endif
     67 
     68 #ifdef HAVE_LINUX_TIPC_H
     69 # include <linux/tipc.h>
     70 #endif
     71 
     72 #ifndef Py__SOCKET_H
     73 #define Py__SOCKET_H
     74 #ifdef __cplusplus
     75 extern "C" {
     76 #endif
     77 
     78 /* Python module and C API name */
     79 #define PySocket_MODULE_NAME    "_socket"
     80 #define PySocket_CAPI_NAME      "CAPI"
     81 #define PySocket_CAPSULE_NAME  (PySocket_MODULE_NAME "." PySocket_CAPI_NAME)
     82 
     83 /* Abstract the socket file descriptor type */
     84 #ifdef MS_WINDOWS
     85 typedef SOCKET SOCKET_T;
     86 #       ifdef MS_WIN64
     87 #               define SIZEOF_SOCKET_T 8
     88 #       else
     89 #               define SIZEOF_SOCKET_T 4
     90 #       endif
     91 #else
     92 typedef int SOCKET_T;
     93 #       define SIZEOF_SOCKET_T SIZEOF_INT
     94 #endif
     95 
     96 /* Socket address */
     97 typedef union sock_addr {
     98     struct sockaddr_in in;
     99 #ifdef AF_UNIX
    100     struct sockaddr_un un;
    101 #endif
    102 #ifdef AF_NETLINK
    103     struct sockaddr_nl nl;
    104 #endif
    105 #ifdef ENABLE_IPV6
    106     struct sockaddr_in6 in6;
    107     struct sockaddr_storage storage;
    108 #endif
    109 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
    110     struct sockaddr_l2 bt_l2;
    111     struct sockaddr_rc bt_rc;
    112     struct sockaddr_sco bt_sco;
    113     struct sockaddr_hci bt_hci;
    114 #endif
    115 #ifdef HAVE_NETPACKET_PACKET_H
    116     struct sockaddr_ll ll;
    117 #endif
    118 } sock_addr_t;
    119 
    120 /* The object holding a socket.  It holds some extra information,
    121    like the address family, which is used to decode socket address
    122    arguments properly. */
    123 
    124 typedef struct {
    125     PyObject_HEAD
    126     SOCKET_T sock_fd;           /* Socket file descriptor */
    127     int sock_family;            /* Address family, e.g., AF_INET */
    128     int sock_type;              /* Socket type, e.g., SOCK_STREAM */
    129     int sock_proto;             /* Protocol type, usually 0 */
    130     PyObject *(*errorhandler)(void); /* Error handler; checks
    131                                         errno, returns NULL and
    132                                         sets a Python exception */
    133     double sock_timeout;                 /* Operation timeout in seconds;
    134                                         0.0 means non-blocking */
    135 } PySocketSockObject;
    136 
    137 /* --- C API ----------------------------------------------------*/
    138 
    139 /* Short explanation of what this C API export mechanism does
    140    and how it works:
    141 
    142     The _ssl module needs access to the type object defined in
    143     the _socket module. Since cross-DLL linking introduces a lot of
    144     problems on many platforms, the "trick" is to wrap the
    145     C API of a module in a struct which then gets exported to
    146     other modules via a PyCapsule.
    147 
    148     The code in socketmodule.c defines this struct (which currently
    149     only contains the type object reference, but could very
    150     well also include other C APIs needed by other modules)
    151     and exports it as PyCapsule via the module dictionary
    152     under the name "CAPI".
    153 
    154     Other modules can now include the socketmodule.h file
    155     which defines the needed C APIs to import and set up
    156     a static copy of this struct in the importing module.
    157 
    158     After initialization, the importing module can then
    159     access the C APIs from the _socket module by simply
    160     referring to the static struct, e.g.
    161 
    162     Load _socket module and its C API; this sets up the global
    163     PySocketModule:
    164 
    165     if (PySocketModule_ImportModuleAndAPI())
    166         return;
    167 
    168 
    169     Now use the C API as if it were defined in the using
    170     module:
    171 
    172     if (!PyArg_ParseTuple(args, "O!|zz:ssl",
    173 
    174                           PySocketModule.Sock_Type,
    175 
    176                           (PyObject*)&Sock,
    177                           &key_file, &cert_file))
    178         return NULL;
    179 
    180     Support could easily be extended to export more C APIs/symbols
    181     this way. Currently, only the type object is exported,
    182     other candidates would be socket constructors and socket
    183     access functions.
    184 
    185 */
    186 
    187 /* C API for usage by other Python modules */
    188 typedef struct {
    189     PyTypeObject *Sock_Type;
    190     PyObject *error;
    191 } PySocketModule_APIObject;
    192 
    193 /* XXX The net effect of the following appears to be to define a function
    194    XXX named PySocketModule_APIObject in _ssl.c.  It's unclear why it isn't
    195    XXX defined there directly.
    196 
    197    >>> It's defined here because other modules might also want to use
    198    >>> the C API.
    199 
    200 */
    201 #ifndef PySocket_BUILDING_SOCKET
    202 
    203 /* --- C API ----------------------------------------------------*/
    204 
    205 /* Interfacestructure to C API for other modules.
    206    Call PySocketModule_ImportModuleAndAPI() to initialize this
    207    structure. After that usage is simple:
    208 
    209    if (!PyArg_ParseTuple(args, "O!|zz:ssl",
    210                          &PySocketModule.Sock_Type, (PyObject*)&Sock,
    211                          &key_file, &cert_file))
    212      return NULL;
    213    ...
    214 */
    215 
    216 static
    217 PySocketModule_APIObject PySocketModule;
    218 
    219 /* You *must* call this before using any of the functions in
    220    PySocketModule and check its outcome; otherwise all accesses will
    221    result in a segfault. Returns 0 on success. */
    222 
    223 #ifndef DPRINTF
    224 # define DPRINTF if (0) printf
    225 #endif
    226 
    227 static
    228 int PySocketModule_ImportModuleAndAPI(void)
    229 {
    230     void *api;
    231 
    232   DPRINTF(" Loading capsule %s\n", PySocket_CAPSULE_NAME);
    233   api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1);
    234     if (api == NULL)
    235         goto onError;
    236     memcpy(&PySocketModule, api, sizeof(PySocketModule));
    237     DPRINTF(" API object loaded and initialized.\n");
    238     return 0;
    239 
    240  onError:
    241     DPRINTF(" not found.\n");
    242     return -1;
    243 }
    244 
    245 #endif /* !PySocket_BUILDING_SOCKET */
    246 
    247 #ifdef __cplusplus
    248 }
    249 #endif
    250 #endif /* !Py__SOCKET_H */
    251