Add zts_py_sendall() method
This commit is contained in:
@@ -174,6 +174,71 @@ int zts_py_send(int fd, PyObject* buf, int flags)
|
|||||||
return bytes_sent;
|
return bytes_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zts_py_sendall(int fd, PyObject* bytes, int flags)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
Py_buffer pbuf = *(Py_buffer*) bytes;
|
||||||
|
char *buf = (char *) pbuf.buf;
|
||||||
|
int bytes_left = pbuf.len;
|
||||||
|
|
||||||
|
int has_timeout;
|
||||||
|
int deadline_initialized = 0;
|
||||||
|
|
||||||
|
_PyTime_t timeout;
|
||||||
|
_PyTime_t interval;
|
||||||
|
_PyTime_t deadline;
|
||||||
|
|
||||||
|
res = zts_get_send_timeout(fd);
|
||||||
|
if (res < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
timeout = (_PyTime_t) 1000 * 1000 * (int64_t) res; // Convert ms to ns
|
||||||
|
interval = timeout;
|
||||||
|
has_timeout = (interval > 0);
|
||||||
|
|
||||||
|
/* Call zts_bsd_send() until no more bytes left to send in the buffer.
|
||||||
|
Keep track of remaining time until timeout and exit with ZTS_ETIMEDOUT if timeout exceeded.
|
||||||
|
Check signals between calls to send() to prevent undue blocking.*/
|
||||||
|
do {
|
||||||
|
if (has_timeout) {
|
||||||
|
if (deadline_initialized) {
|
||||||
|
interval = deadline - _PyTime_GetMonotonicClock();
|
||||||
|
} else {
|
||||||
|
deadline_initialized = 1;
|
||||||
|
deadline = _PyTime_GetMonotonicClock() + timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interval <= 0) {
|
||||||
|
zts_errno = ZTS_ETIMEDOUT;
|
||||||
|
res = ZTS_ERR_SOCKET;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
res = zts_bsd_send(fd, buf, bytes_left, flags);
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
|
if (res < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
int bytes_sent = res;
|
||||||
|
assert(bytes_sent > 0);
|
||||||
|
buf += bytes_sent; // Advance pointer
|
||||||
|
bytes_left -= bytes_sent;
|
||||||
|
|
||||||
|
if (PyErr_CheckSignals()) // Handle interrupts, etc.
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
} while (bytes_left > 0);
|
||||||
|
|
||||||
|
res = 0; // Success
|
||||||
|
|
||||||
|
done:
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int zts_py_close(int fd)
|
int zts_py_close(int fd)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ PyObject* zts_py_recv(int fd, int len, int flags);
|
|||||||
|
|
||||||
int zts_py_send(int fd, PyObject* buf, int flags);
|
int zts_py_send(int fd, PyObject* buf, int flags);
|
||||||
|
|
||||||
|
int zts_py_sendall(int fd, PyObject* bytes, int flags);
|
||||||
|
|
||||||
int zts_py_close(int fd);
|
int zts_py_close(int fd);
|
||||||
|
|
||||||
PyObject* zts_py_addr_get_str(uint64_t net_id, int family);
|
PyObject* zts_py_addr_get_str(uint64_t net_id, int family);
|
||||||
|
|||||||
@@ -382,9 +382,23 @@ class socket:
|
|||||||
handle_error(err)
|
handle_error(err)
|
||||||
return err
|
return err
|
||||||
|
|
||||||
def sendall(self, n_bytes, flags):
|
def sendall(self, bytes, flags=0):
|
||||||
"""libzt does not support this (yet)"""
|
"""sendall(data[, flags])
|
||||||
raise NotImplementedError("libzt does not support this (yet?)")
|
|
||||||
|
| Write data to the socket. Sends data until all data is sent, then returns None. Optional flags may be:
|
||||||
|
| - ZTS_MSG_PEEK - Peeks at an incoming message.
|
||||||
|
| - ZTS_MSG_DONTWAIT - Nonblocking I/O for this operation only.
|
||||||
|
| - ZTS_MSG_MORE - Sender will send more.
|
||||||
|
|
||||||
|
:param bytes: Data to send
|
||||||
|
:type bytes: Union[bytes, bytearray]
|
||||||
|
:param flags: Optional flags
|
||||||
|
:type flags: int
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
err = libzt.zts_py_sendall(self._fd, bytes, flags)
|
||||||
|
if err < 0:
|
||||||
|
handle_error(err)
|
||||||
|
|
||||||
def sendto(self, n_bytes, flags, address):
|
def sendto(self, n_bytes, flags, address):
|
||||||
"""libzt does not support this (yet)"""
|
"""libzt does not support this (yet)"""
|
||||||
|
|||||||
Reference in New Issue
Block a user