blob: d1503ba1b45dc034cd0c55f2ad6970c3ce95ac3a [file] [log] [blame]
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +00001/* Socket module header file */
2
3/* Includes needed for the sockaddr_* symbols below */
4#ifndef MS_WINDOWS
5# include <sys/socket.h>
6# include <netinet/in.h>
7# if !(defined(__BEOS__) || defined(__CYGWIN__) || (defined(PYOS_OS2) && defined(PYCC_VACPP)))
8# include <netinet/tcp.h>
9# endif
10
11#else /* MS_WINDOWS */
12# include <winsock.h>
13#endif
14
15#ifdef HAVE_SYS_UN_H
16# include <sys/un.h>
17#else
18# undef AF_UNIX
19#endif
20
21#ifdef HAVE_NETPACKET_PACKET_H
22# include <sys/ioctl.h>
23# include <net/if.h>
24# include <netpacket/packet.h>
25#endif
26
27#ifndef Py__SOCKET_H
28#define Py__SOCKET_H
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/* Python module and C API name */
34#define PySocket_MODULE_NAME "_socket"
35#define PySocket_CAPI_NAME "CAPI"
36
37/* Abstract the socket file descriptor type */
38#ifdef MS_WINDOWS
39typedef SOCKET SOCKET_T;
40# ifdef MS_WIN64
41# define SIZEOF_SOCKET_T 8
42# else
43# define SIZEOF_SOCKET_T 4
44# endif
45#else
46typedef int SOCKET_T;
47# define SIZEOF_SOCKET_T SIZEOF_INT
48#endif
49
50/* The object holding a socket. It holds some extra information,
51 like the address family, which is used to decode socket address
52 arguments properly. */
53
54typedef struct {
55 PyObject_HEAD
56 SOCKET_T sock_fd; /* Socket file descriptor */
57 int sock_family; /* Address family, e.g., AF_INET */
58 int sock_type; /* Socket type, e.g., SOCK_STREAM */
59 int sock_proto; /* Protocol type, usually 0 */
60 union sock_addr {
61 struct sockaddr_in in;
62#ifdef AF_UNIX
63 struct sockaddr_un un;
64#endif
65#ifdef ENABLE_IPV6
66 struct sockaddr_in6 in6;
67 struct sockaddr_storage storage;
68#endif
69#ifdef HAVE_NETPACKET_PACKET_H
70 struct sockaddr_ll ll;
71#endif
72 } sock_addr;
Tim Peters6f5505a2002-02-17 03:58:51 +000073 PyObject *(*errorhandler)(void); /* Error handler; checks
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000074 errno, returns NULL and
75 sets a Python exception */
76} PySocketSockObject;
77
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000078/* --- C API ----------------------------------------------------*/
79
Marc-André Lemburg666e70d2002-02-25 14:45:40 +000080/* Short explanation of what this C API export mechanism does
81 and how it works:
82
83 The _ssl module needs access to the type object defined in
84 the _socket module. Since cross-DLL linking introduces a lot of
85 problems on many platforms, the "trick" is to wrap the
86 C API of a module in a struct which then gets exported to
87 other modules via a PyCObject.
88
89 The code in socketmodule.c defines this struct (which currently
90 only contains the type object reference, but could very
91 well also include other C APIs needed by other modules)
92 and exports it as PyCObject via the module dictionary
93 under the name "CAPI".
94
95 Other modules can now include the socketmodule.h file
96 which defines the needed C APIs to import and set up
97 a static copy of this struct in the importing module.
98
99 After initialization, the importing module can then
100 access the C APIs from the _socket module by simply
101 referring to the static struct, e.g.
102
103 Load _socket module and its C API; this sets up the global
104 PySocketModule:
105
106 if (PySocketModule_ImportModuleAndAPI())
107 return;
108
109
110 Now use the C API as if it were defined in the using
111 module:
112
113 if (!PyArg_ParseTuple(args, "O!|zz:ssl",
114
115 PySocketModule.Sock_Type,
116
117 (PyObject*)&Sock,
118 &key_file, &cert_file))
119 return NULL;
120
121 Support could easily be extended to export more C APIs/symbols
122 this way. Currently, only the type object is exported,
123 other candidates would be socket constructors and socket
124 access functions.
125
126*/
127
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000128/* C API for usage by other Python modules */
129typedef struct {
Tim Peters6f5505a2002-02-17 03:58:51 +0000130 PyTypeObject *Sock_Type;
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000131} PySocketModule_APIObject;
Tim Peters6f5505a2002-02-17 03:58:51 +0000132
133/* XXX The net effect of the following appears to be to define a function
134 XXX named PySocketModule_APIObject in _ssl.c. It's unclear why it isn't
Marc-André Lemburg666e70d2002-02-25 14:45:40 +0000135 XXX defined there directly.
136
137 >>> It's defined here because other modules might also want to use
138 >>> the C API.
139
140*/
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000141#ifndef PySocket_BUILDING_SOCKET
142
143/* --- C API ----------------------------------------------------*/
144
145/* Interfacestructure to C API for other modules.
146 Call PySocket_ImportModuleAPI() to initialize this
147 structure. After that usage is simple:
148
149 if (!PyArg_ParseTuple(args, "O!|zz:ssl",
150 &PySocketModule.Sock_Type, (PyObject*)&Sock,
151 &key_file, &cert_file))
152 return NULL;
153 ...
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000154*/
155
Tim Peters6f5505a2002-02-17 03:58:51 +0000156static
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000157PySocketModule_APIObject PySocketModule;
158
159/* You *must* call this before using any of the functions in
160 PySocketModule and check its outcome; otherwise all accesses will
161 result in a segfault. Returns 0 on success. */
162
163#ifndef DPRINTF
164# define DPRINTF if (0) printf
165#endif
166
167static
168int PySocketModule_ImportModuleAndAPI(void)
169{
Tim Peters6f5505a2002-02-17 03:58:51 +0000170 PyObject *mod = 0, *v = 0;
171 char *apimodule = PySocket_MODULE_NAME;
172 char *apiname = PySocket_CAPI_NAME;
173 void *api;
174
175 DPRINTF("Importing the %s C API...\n", apimodule);
176 mod = PyImport_ImportModule(apimodule);
177 if (mod == NULL)
178 goto onError;
179 DPRINTF(" %s package found\n", apimodule);
180 v = PyObject_GetAttrString(mod, apiname);
181 if (v == NULL)
182 goto onError;
183 Py_DECREF(mod);
184 DPRINTF(" API object %s found\n", apiname);
185 api = PyCObject_AsVoidPtr(v);
186 if (api == NULL)
187 goto onError;
188 Py_DECREF(v);
189 memcpy(&PySocketModule, api, sizeof(PySocketModule));
190 DPRINTF(" API object loaded and initialized.\n");
191 return 0;
192
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000193 onError:
Tim Peters6f5505a2002-02-17 03:58:51 +0000194 DPRINTF(" not found.\n");
195 Py_XDECREF(mod);
196 Py_XDECREF(v);
197 return -1;
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000198}
199
Tim Peters6f5505a2002-02-17 03:58:51 +0000200#endif /* !PySocket_BUILDING_SOCKET */
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000201
202#ifdef __cplusplus
203}
204#endif
205#endif /* !Py__SOCKET_H */