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"