Skip to content

Commit af63e14

Browse files
committed
issue: 1792164 Support MSG_ERRQUEUE in sockinfo::rx()
rx() processing should allow return information from error queue and income data in single call. Depending on user application it means that rx() logic should return: 1. only income data 2. only error queue data 3. income and error queue data Error processing logic is done accordingly. Signed-off-by: Igor Ivanov <[email protected]>
1 parent 23f0f7f commit af63e14

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

src/vma/sock/sockinfo_tcp.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,7 +1910,7 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19101910
int total_rx = 0;
19111911
int poll_count = 0;
19121912
int bytes_to_tcp_recved;
1913-
size_t total_iov_sz = 1;
1913+
size_t total_iov_sz = 0;
19141914
int out_flags = 0;
19151915
int in_flags = *p_flags;
19161916
bool block_this_run = BLOCK_THIS_RUN(m_b_blocking, in_flags);
@@ -1932,6 +1932,18 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19321932
TAKE_T_RX_START;
19331933
#endif
19341934

1935+
/* In general, without any special flags, socket options, or ioctls being set,
1936+
* a recv call on a blocking TCP socket will return any number of bytes less than
1937+
* or equal to the size being requested. But unless the socket is closed remotely,
1938+
* interrupted by signal, or in an error state,
1939+
* it will block until at least 1 byte is available.
1940+
* With MSG_ERRQUEUE flag user application can request just information from
1941+
* error queue without any income data.
1942+
*/
1943+
if (p_iov && (sz_iov > 0)) {
1944+
total_iov_sz = 1;
1945+
}
1946+
19351947
if (unlikely((in_flags & MSG_WAITALL) && !(in_flags & MSG_PEEK))) {
19361948
total_iov_sz = 0;
19371949
for (int i = 0; i < sz_iov; i++) {
@@ -1942,13 +1954,22 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19421954
}
19431955

19441956
si_tcp_logfunc("rx: iov=%p niovs=%d", p_iov, sz_iov);
1945-
/* poll rx queue till we have something */
1957+
1958+
/* poll rx queue till we have something */
19461959
lock_tcp_con();
1960+
if (__msg) {
1961+
handle_cmsg(__msg, in_flags);
1962+
if (__msg->msg_controllen == 0) {
1963+
errno = EAGAIN;
1964+
unlock_tcp_con();
1965+
return -1;
1966+
}
1967+
}
19471968
return_reuse_buffers_postponed();
19481969
unlock_tcp_con();
19491970

19501971
while (m_rx_ready_byte_count < total_iov_sz) {
1951-
if (unlikely(g_b_exit ||!is_rtr() || (rx_wait_lockless(poll_count, block_this_run) < 0))) {
1972+
if (unlikely(g_b_exit || !is_rtr() || (rx_wait_lockless(poll_count, block_this_run) < 0))) {
19521973
return handle_rx_error(block_this_run);
19531974
}
19541975
}
@@ -1957,8 +1978,9 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19571978

19581979
si_tcp_logfunc("something in rx queues: %d %p", m_n_rx_pkt_ready_list_count, m_rx_pkt_ready_list.front());
19591980

1960-
total_rx = dequeue_packet(p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
1961-
if (__msg) handle_cmsg(__msg, in_flags);
1981+
if (total_iov_sz > 0) {
1982+
total_rx = dequeue_packet(p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
1983+
}
19621984

19631985
/*
19641986
* RCVBUFF Accounting: Going 'out' of the internal buffer: if some bytes are not tcp_recved yet - do that.

0 commit comments

Comments
 (0)