blob: a59e6f750ca6d7696f795cae5fb0453226ce72eb [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 */
Martin v. Löwis272cb402002-03-01 08:31:07 +000012#if _MSC_VER >= 1300
13# include <winsock2.h>
14# include <ws2tcpip.h>
15# define HAVE_ADDRINFO
16# define HAVE_SOCKADDR_STORAGE
17# define HAVE_GETADDRINFO
18# define HAVE_GETNAMEINFO
19# define ENABLE_IPV6
20#else
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000021# include <winsock.h>
22#endif
Martin v. Löwis272cb402002-03-01 08:31:07 +000023#endif
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000024
25#ifdef HAVE_SYS_UN_H
26# include <sys/un.h>
27#else
28# undef AF_UNIX
29#endif
30
31#ifdef HAVE_NETPACKET_PACKET_H
32# include <sys/ioctl.h>
33# include <net/if.h>
34# include <netpacket/packet.h>
35#endif
36
37#ifndef Py__SOCKET_H
38#define Py__SOCKET_H
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43/* Python module and C API name */
44#define PySocket_MODULE_NAME "_socket"
45#define PySocket_CAPI_NAME "CAPI"
46
47/* Abstract the socket file descriptor type */
48#ifdef MS_WINDOWS
49typedef SOCKET SOCKET_T;
50# ifdef MS_WIN64
51# define SIZEOF_SOCKET_T 8
52# else
53# define SIZEOF_SOCKET_T 4
54# endif
55#else
56typedef int SOCKET_T;
57# define SIZEOF_SOCKET_T SIZEOF_INT
58#endif
59
60/* The object holding a socket. It holds some extra information,
61 like the address family, which is used to decode socket address
62 arguments properly. */
63
64typedef struct {
65 PyObject_HEAD
66 SOCKET_T sock_fd; /* Socket file descriptor */
67 int sock_family; /* Address family, e.g., AF_INET */
68 int sock_type; /* Socket type, e.g., SOCK_STREAM */
69 int sock_proto; /* Protocol type, usually 0 */
70 union sock_addr {
71 struct sockaddr_in in;
72#ifdef AF_UNIX
73 struct sockaddr_un un;
74#endif
75#ifdef ENABLE_IPV6
76 struct sockaddr_in6 in6;
77 struct sockaddr_storage storage;
78#endif
79#ifdef HAVE_NETPACKET_PACKET_H
80 struct sockaddr_ll ll;
81#endif
82 } sock_addr;
Tim Peters6f5505a2002-02-17 03:58:51 +000083 PyObject *(*errorhandler)(void); /* Error handler; checks
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000084 errno, returns NULL and
85 sets a Python exception */
86} PySocketSockObject;
87
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000088/* --- C API ----------------------------------------------------*/
89
Marc-André Lemburg666e70d2002-02-25 14:45:40 +000090/* Short explanation of what this C API export mechanism does
91 and how it works:
92
93 The _ssl module needs access to the type object defined in
94 the _socket module. Since cross-DLL linking introduces a lot of
95 problems on many platforms, the "trick" is to wrap the
96 C API of a module in a struct which then gets exported to
97 other modules via a PyCObject.
98
99 The code in socketmodule.c defines this struct (which currently
100 only contains the type object reference, but could very
101 well also include other C APIs needed by other modules)
102 and exports it as PyCObject via the module dictionary
103 under the name "CAPI".
104
105 Other modules can now include the socketmodule.h file
106 which defines the needed C APIs to import and set up
107 a static copy of this struct in the importing module.
108
109 After initialization, the importing module can then
110 access the C APIs from the _socket module by simply
111 referring to the static struct, e.g.
112
113 Load _socket module and its C API; this sets up the global
114 PySocketModule:
115
116 if (PySocketModule_ImportModuleAndAPI())
117 return;
118
119
120 Now use the C API as if it were defined in the using
121 module:
122
123 if (!PyArg_ParseTuple(args, "O!|zz:ssl",
124
125 PySocketModule.Sock_Type,
126
127 (PyObject*)&Sock,
128 &key_file, &cert_file))
129 return NULL;
130
131 Support could easily be extended to export more C APIs/symbols
132 this way. Currently, only the type object is exported,
133 other candidates would be socket constructors and socket
134 access functions.
135
136*/
137
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000138/* C API for usage by other Python modules */
139typedef struct {
Tim Peters6f5505a2002-02-17 03:58:51 +0000140 PyTypeObject *Sock_Type;
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000141} PySocketModule_APIObject;
Tim Peters6f5505a2002-02-17 03:58:51 +0000142
143/* XXX The net effect of the following appears to be to define a function
144 XXX named PySocketModule_APIObject in _ssl.c. It's unclear why it isn't
Marc-André Lemburg666e70d2002-02-25 14:45:40 +0000145 XXX defined there directly.
146
147 >>> It's defined here because other modules might also want to use
148 >>> the C API.
149
150*/
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000151#ifndef PySocket_BUILDING_SOCKET
152
153/* --- C API ----------------------------------------------------*/
154
155/* Interfacestructure to C API for other modules.
156 Call PySocket_ImportModuleAPI() to initialize this
157 structure. After that usage is simple:
158
159 if (!PyArg_ParseTuple(args, "O!|zz:ssl",
160 &PySocketModule.Sock_Type, (PyObject*)&Sock,
161 &key_file, &cert_file))
162 return NULL;
163 ...
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000164*/
165
Tim Peters6f5505a2002-02-17 03:58:51 +0000166static
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000167PySocketModule_APIObject PySocketModule;
168
169/* You *must* call this before using any of the functions in
170 PySocketModule and check its outcome; otherwise all accesses will
171 result in a segfault. Returns 0 on success. */
172
173#ifndef DPRINTF
174# define DPRINTF if (0) printf
175#endif
176
177static
178int PySocketModule_ImportModuleAndAPI(void)
179{
Tim Peters6f5505a2002-02-17 03:58:51 +0000180 PyObject *mod = 0, *v = 0;
181 char *apimodule = PySocket_MODULE_NAME;
182 char *apiname = PySocket_CAPI_NAME;
183 void *api;
184
185 DPRINTF("Importing the %s C API...\n", apimodule);
186 mod = PyImport_ImportModule(apimodule);
187 if (mod == NULL)
188 goto onError;
189 DPRINTF(" %s package found\n", apimodule);
190 v = PyObject_GetAttrString(mod, apiname);
191 if (v == NULL)
192 goto onError;
193 Py_DECREF(mod);
194 DPRINTF(" API object %s found\n", apiname);
195 api = PyCObject_AsVoidPtr(v);
196 if (api == NULL)
197 goto onError;
198 Py_DECREF(v);
199 memcpy(&PySocketModule, api, sizeof(PySocketModule));
200 DPRINTF(" API object loaded and initialized.\n");
201 return 0;
202
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000203 onError:
Tim Peters6f5505a2002-02-17 03:58:51 +0000204 DPRINTF(" not found.\n");
205 Py_XDECREF(mod);
206 Py_XDECREF(v);
207 return -1;
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000208}
209
Tim Peters6f5505a2002-02-17 03:58:51 +0000210#endif /* !PySocket_BUILDING_SOCKET */
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000211
212#ifdef __cplusplus
213}
214#endif
215#endif /* !Py__SOCKET_H */