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