PageRenderTime 117ms CodeModel.GetById 35ms app.highlight 36ms RepoModel.GetById 25ms app.codeStats 0ms

/Modules/socketmodule.h

http://unladen-swallow.googlecode.com/
C++ Header | 264 lines | 149 code | 28 blank | 87 comment | 11 complexity | 84b36326160876b69b525dbebe5108bc MD5 | raw file
  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
 82/* Abstract the socket file descriptor type */
 83#ifdef MS_WINDOWS
 84typedef SOCKET SOCKET_T;
 85#	ifdef MS_WIN64
 86#		define SIZEOF_SOCKET_T 8
 87#	else
 88#		define SIZEOF_SOCKET_T 4
 89#	endif
 90#else
 91typedef int SOCKET_T;
 92#	define SIZEOF_SOCKET_T SIZEOF_INT
 93#endif
 94
 95/* Socket address */
 96typedef union sock_addr {
 97	struct sockaddr_in in;
 98#ifdef AF_UNIX
 99	struct sockaddr_un un;
100#endif
101#ifdef AF_NETLINK
102	struct sockaddr_nl nl;
103#endif
104#ifdef ENABLE_IPV6
105	struct sockaddr_in6 in6;
106	struct sockaddr_storage storage;
107#endif
108#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
109	struct sockaddr_l2 bt_l2;
110	struct sockaddr_rc bt_rc;
111	struct sockaddr_sco bt_sco;
112	struct sockaddr_hci bt_hci;
113#endif
114#ifdef HAVE_NETPACKET_PACKET_H
115	struct sockaddr_ll ll;
116#endif
117} sock_addr_t;
118
119/* The object holding a socket.  It holds some extra information,
120   like the address family, which is used to decode socket address
121   arguments properly. */
122
123typedef struct {
124	PyObject_HEAD
125	SOCKET_T sock_fd;	/* Socket file descriptor */
126	int sock_family;	/* Address family, e.g., AF_INET */
127	int sock_type;		/* Socket type, e.g., SOCK_STREAM */
128	int sock_proto;		/* Protocol type, usually 0 */
129	PyObject *(*errorhandler)(void); /* Error handler; checks
130					    errno, returns NULL and
131					    sets a Python exception */
132	double sock_timeout;		 /* Operation timeout in seconds;
133					    0.0 means non-blocking */
134} PySocketSockObject;
135
136/* --- C API ----------------------------------------------------*/
137
138/* Short explanation of what this C API export mechanism does
139   and how it works:
140
141    The _ssl module needs access to the type object defined in 
142    the _socket module. Since cross-DLL linking introduces a lot of
143    problems on many platforms, the "trick" is to wrap the
144    C API of a module in a struct which then gets exported to
145    other modules via a PyCObject.
146
147    The code in socketmodule.c defines this struct (which currently
148    only contains the type object reference, but could very
149    well also include other C APIs needed by other modules)
150    and exports it as PyCObject via the module dictionary
151    under the name "CAPI".
152
153    Other modules can now include the socketmodule.h file
154    which defines the needed C APIs to import and set up
155    a static copy of this struct in the importing module.
156
157    After initialization, the importing module can then
158    access the C APIs from the _socket module by simply
159    referring to the static struct, e.g.
160
161    Load _socket module and its C API; this sets up the global
162    PySocketModule:
163    
164	if (PySocketModule_ImportModuleAndAPI())
165	    return;
166
167
168    Now use the C API as if it were defined in the using
169    module:
170
171        if (!PyArg_ParseTuple(args, "O!|zz:ssl",
172
173			      PySocketModule.Sock_Type,
174
175			      (PyObject*)&Sock,
176			      &key_file, &cert_file))
177	    return NULL;
178
179    Support could easily be extended to export more C APIs/symbols
180    this way. Currently, only the type object is exported, 
181    other candidates would be socket constructors and socket
182    access functions.
183
184*/
185
186/* C API for usage by other Python modules */
187typedef struct {
188	PyTypeObject *Sock_Type;
189        PyObject *error;
190} PySocketModule_APIObject;
191
192/* XXX The net effect of the following appears to be to define a function
193   XXX named PySocketModule_APIObject in _ssl.c.  It's unclear why it isn't
194   XXX defined there directly. 
195
196   >>> It's defined here because other modules might also want to use
197   >>> the C API.
198
199*/
200#ifndef PySocket_BUILDING_SOCKET
201
202/* --- C API ----------------------------------------------------*/
203
204/* Interfacestructure to C API for other modules.
205   Call PySocketModule_ImportModuleAndAPI() to initialize this
206   structure. After that usage is simple:
207
208   if (!PyArg_ParseTuple(args, "O!|zz:ssl",
209                         &PySocketModule.Sock_Type, (PyObject*)&Sock,
210	 		 &key_file, &cert_file))
211 	 return NULL;
212   ...
213*/
214
215static
216PySocketModule_APIObject PySocketModule;
217
218/* You *must* call this before using any of the functions in
219   PySocketModule and check its outcome; otherwise all accesses will
220   result in a segfault. Returns 0 on success. */
221
222#ifndef DPRINTF
223# define DPRINTF if (0) printf
224#endif
225
226static
227int PySocketModule_ImportModuleAndAPI(void)
228{
229	PyObject *mod = 0, *v = 0;
230	char *apimodule = PySocket_MODULE_NAME;
231	char *apiname = PySocket_CAPI_NAME;
232	void *api;
233
234	DPRINTF("Importing the %s C API...\n", apimodule);
235	mod = PyImport_ImportModuleNoBlock(apimodule);
236	if (mod == NULL)
237		goto onError;
238	DPRINTF(" %s package found\n", apimodule);
239	v = PyObject_GetAttrString(mod, apiname);
240	if (v == NULL)
241		goto onError;
242	Py_DECREF(mod);
243	DPRINTF(" API object %s found\n", apiname);
244	api = PyCObject_AsVoidPtr(v);
245	if (api == NULL)
246		goto onError;
247	Py_DECREF(v);
248	memcpy(&PySocketModule, api, sizeof(PySocketModule));
249	DPRINTF(" API object loaded and initialized.\n");
250	return 0;
251
252 onError:
253	DPRINTF(" not found.\n");
254	Py_XDECREF(mod);
255	Py_XDECREF(v);
256	return -1;
257}
258
259#endif /* !PySocket_BUILDING_SOCKET */
260
261#ifdef __cplusplus
262}
263#endif
264#endif /* !Py__SOCKET_H */