2
* A type which wraps a socket
6
* Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
9
#include "multiprocessing.h"
12
# define WRITE(h, buffer, length) send((SOCKET)h, buffer, length, 0)
13
# define READ(h, buffer, length) recv((SOCKET)h, buffer, length, 0)
14
# define CLOSE(h) closesocket((SOCKET)h)
16
# define WRITE(h, buffer, length) write(h, buffer, length)
17
# define READ(h, buffer, length) read(h, buffer, length)
18
# define CLOSE(h) close(h)
22
* Send string to file descriptor
26
_conn_sendall(HANDLE h, char *string, size_t length)
32
res = WRITE(h, p, length);
34
return MP_SOCKET_ERROR;
43
* Receive string of exact length from file descriptor
47
_conn_recvall(HANDLE h, char *buffer, size_t length)
49
size_t remaining = length;
53
while (remaining > 0) {
54
temp = READ(h, p, remaining);
57
return remaining == length ?
58
MP_END_OF_FILE : MP_EARLY_END_OF_FILE;
70
* Send a string prepended by the string length in network byte order
74
conn_send_string(ConnectionObject *conn, char *string, size_t length)
77
/* The "header" of the message is a 32 bit unsigned number (in
78
network order) which specifies the length of the "body". If
79
the message is shorter than about 16kb then it is quicker to
80
combine the "header" and the "body" of the message and send
82
if (length < (16*1024)) {
85
message = PyMem_Malloc(length+4);
87
return MP_MEMORY_ERROR;
89
*(UINT32*)message = htonl((UINT32)length);
90
memcpy(message+4, string, length);
91
Py_BEGIN_ALLOW_THREADS
92
res = _conn_sendall(conn->handle, message, length+4);
98
if (length > MAX_MESSAGE_LENGTH)
99
return MP_BAD_MESSAGE_LENGTH;
101
lenbuff = htonl((UINT32)length);
102
Py_BEGIN_ALLOW_THREADS
103
res = _conn_sendall(conn->handle, (char*)&lenbuff, 4) ||
104
_conn_sendall(conn->handle, string, length);
111
* Attempts to read into buffer, or failing that into *newbuffer
113
* Returns number of bytes read.
117
conn_recv_string(ConnectionObject *conn, char *buffer,
118
size_t buflength, char **newbuffer, size_t maxlength)
125
Py_BEGIN_ALLOW_THREADS
126
res = _conn_recvall(conn->handle, (char*)&ulength, 4);
131
ulength = ntohl(ulength);
132
if (ulength > maxlength)
133
return MP_BAD_MESSAGE_LENGTH;
135
if (ulength <= buflength) {
136
Py_BEGIN_ALLOW_THREADS
137
res = _conn_recvall(conn->handle, buffer, (size_t)ulength);
139
return res < 0 ? res : ulength;
141
*newbuffer = PyMem_Malloc((size_t)ulength);
142
if (*newbuffer == NULL)
143
return MP_MEMORY_ERROR;
144
Py_BEGIN_ALLOW_THREADS
145
res = _conn_recvall(conn->handle, *newbuffer, (size_t)ulength);
147
return res < 0 ? (Py_ssize_t)res : (Py_ssize_t)ulength;
152
* Check whether any data is available for reading -- neg timeout blocks
156
conn_poll(ConnectionObject *conn, double timeout, PyThreadState *_save)
162
* Verify the handle, issue 3321. Not required for windows.
165
if (((int)conn->handle) < 0 || ((int)conn->handle) >= FD_SETSIZE) {
167
PyErr_SetString(PyExc_IOError, "handle out of range in select()");
169
return MP_EXCEPTION_HAS_BEEN_SET;
174
FD_SET((SOCKET)conn->handle, &rfds);
177
res = select((int)conn->handle+1, &rfds, NULL, NULL, NULL);
180
tv.tv_sec = (long)timeout;
181
tv.tv_usec = (long)((timeout - tv.tv_sec) * 1e6 + 0.5);
182
res = select((int)conn->handle+1, &rfds, NULL, NULL, &tv);
186
return MP_SOCKET_ERROR;
187
} else if (FD_ISSET(conn->handle, &rfds)) {
196
* "connection.h" defines the Connection type using defs above
199
#define CONNECTION_NAME "Connection"
200
#define CONNECTION_TYPE ConnectionType
202
#include "connection.h"