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(__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
31typedef 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
75extern "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
85typedef 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
92typedef int SOCKET_T;
93#       define SIZEOF_SOCKET_T SIZEOF_INT
94#endif
95
96/* Socket address */
97typedef 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
124typedef 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    PyObject *weakreflist;
136} PySocketSockObject;
137
138/* --- C API ----------------------------------------------------*/
139
140/* Short explanation of what this C API export mechanism does
141   and how it works:
142
143    The _ssl module needs access to the type object defined in
144    the _socket module. Since cross-DLL linking introduces a lot of
145    problems on many platforms, the "trick" is to wrap the
146    C API of a module in a struct which then gets exported to
147    other modules via a PyCapsule.
148
149    The code in socketmodule.c defines this struct (which currently
150    only contains the type object reference, but could very
151    well also include other C APIs needed by other modules)
152    and exports it as PyCapsule via the module dictionary
153    under the name "CAPI".
154
155    Other modules can now include the socketmodule.h file
156    which defines the needed C APIs to import and set up
157    a static copy of this struct in the importing module.
158
159    After initialization, the importing module can then
160    access the C APIs from the _socket module by simply
161    referring to the static struct, e.g.
162
163    Load _socket module and its C API; this sets up the global
164    PySocketModule:
165
166    if (PySocketModule_ImportModuleAndAPI())
167        return;
168
169
170    Now use the C API as if it were defined in the using
171    module:
172
173    if (!PyArg_ParseTuple(args, "O!|zz:ssl",
174
175                          PySocketModule.Sock_Type,
176
177                          (PyObject*)&Sock,
178                          &key_file, &cert_file))
179        return NULL;
180
181    Support could easily be extended to export more C APIs/symbols
182    this way. Currently, only the type object is exported,
183    other candidates would be socket constructors and socket
184    access functions.
185
186*/
187
188/* C API for usage by other Python modules */
189typedef struct {
190    PyTypeObject *Sock_Type;
191    PyObject *error;
192} PySocketModule_APIObject;
193
194/* XXX The net effect of the following appears to be to define a function
195   XXX named PySocketModule_APIObject in _ssl.c.  It's unclear why it isn't
196   XXX defined there directly.
197
198   >>> It's defined here because other modules might also want to use
199   >>> the C API.
200
201*/
202#ifndef PySocket_BUILDING_SOCKET
203
204/* --- C API ----------------------------------------------------*/
205
206/* Interfacestructure to C API for other modules.
207   Call PySocketModule_ImportModuleAndAPI() to initialize this
208   structure. After that usage is simple:
209
210   if (!PyArg_ParseTuple(args, "O!|zz:ssl",
211                         &PySocketModule.Sock_Type, (PyObject*)&Sock,
212                         &key_file, &cert_file))
213     return NULL;
214   ...
215*/
216
217static
218PySocketModule_APIObject PySocketModule;
219
220/* You *must* call this before using any of the functions in
221   PySocketModule and check its outcome; otherwise all accesses will
222   result in a segfault. Returns 0 on success. */
223
224#ifndef DPRINTF
225# define DPRINTF if (0) printf
226#endif
227
228static
229int PySocketModule_ImportModuleAndAPI(void)
230{
231    void *api;
232
233  DPRINTF(" Loading capsule %s\n", PySocket_CAPSULE_NAME);
234  api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1);
235    if (api == NULL)
236        goto onError;
237    memcpy(&PySocketModule, api, sizeof(PySocketModule));
238    DPRINTF(" API object loaded and initialized.\n");
239    return 0;
240
241 onError:
242    DPRINTF(" not found.\n");
243    return -1;
244}
245
246#endif /* !PySocket_BUILDING_SOCKET */
247
248#ifdef __cplusplus
249}
250#endif
251#endif /* !Py__SOCKET_H */
252