2001-03-27 00:44:59 +00:00
|
|
|
/*
|
2005-04-29 00:24:12 +00:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
2005-04-29 00:24:12 +00:00
|
|
|
* SPDX-License-Identifier: MPL-2.0 AND ISC
|
2007-06-18 23:47:57 +00:00
|
|
|
*
|
2001-03-27 00:44:59 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2007-06-18 23:47:57 +00:00
|
|
|
*
|
2001-03-27 00:44:59 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
2018-02-23 09:53:12 +01:00
|
|
|
*/
|
2021-06-03 08:37:05 +02:00
|
|
|
|
2018-02-23 09:53:12 +01:00
|
|
|
/*
|
2001-03-27 00:44:59 +00:00
|
|
|
* Copyright (C) 2001 Nominum, Inc.
|
|
|
|
*
|
2007-08-28 07:20:43 +00:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
2001-03-27 00:44:59 +00:00
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
|
|
|
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2001-03-27 00:44:59 +00:00
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
|
|
|
|
2001-03-27 00:44:59 +00:00
|
|
|
#include <isc/mem.h>
|
2020-04-16 13:06:42 -07:00
|
|
|
#include <isc/netmgr.h>
|
2001-03-27 00:44:59 +00:00
|
|
|
#include <isc/result.h>
|
2020-04-16 13:06:42 -07:00
|
|
|
#include <isc/string.h>
|
2001-03-27 00:44:59 +00:00
|
|
|
#include <isc/util.h>
|
|
|
|
|
|
|
|
#include <isccc/ccmsg.h>
|
|
|
|
|
2001-06-04 19:33:39 +00:00
|
|
|
#define CCMSG_MAGIC ISC_MAGIC('C', 'C', 'm', 's')
|
2001-03-27 00:44:59 +00:00
|
|
|
#define VALID_CCMSG(foo) ISC_MAGIC_VALID(foo, CCMSG_MAGIC)
|
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
/*
|
|
|
|
* Try parsing a message from the internal read_buffer and set state
|
|
|
|
* accordingly. Returns true if a message was successfully parsed, false if not.
|
|
|
|
* If no message could be parsed the ccmsg struct remains untouched.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
|
|
|
try_parse_message(isccc_ccmsg_t *ccmsg) {
|
|
|
|
REQUIRE(ccmsg != NULL);
|
|
|
|
|
|
|
|
uint32_t len = 0;
|
|
|
|
if (isc_buffer_peekuint32(ccmsg->buffer, &len) != ISC_R_SUCCESS) {
|
|
|
|
return ISC_R_NOMORE;
|
|
|
|
}
|
|
|
|
if (len == 0) {
|
|
|
|
return ISC_R_UNEXPECTEDEND;
|
|
|
|
}
|
|
|
|
if (len > ccmsg->maxsize) {
|
|
|
|
return ISC_R_RANGE;
|
|
|
|
}
|
|
|
|
if (isc_buffer_remaininglength(ccmsg->buffer) < sizeof(uint32_t) + len)
|
|
|
|
{
|
|
|
|
return ISC_R_NOMORE;
|
|
|
|
}
|
|
|
|
/* Skip the size we just peeked */
|
|
|
|
isc_buffer_forward(ccmsg->buffer, sizeof(uint32_t));
|
|
|
|
ccmsg->size = len;
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2001-03-27 00:44:59 +00:00
|
|
|
static void
|
2020-07-01 19:07:04 +02:00
|
|
|
recv_data(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|
|
|
void *arg) {
|
2020-04-16 13:06:42 -07:00
|
|
|
isccc_ccmsg_t *ccmsg = arg;
|
2001-03-27 00:44:59 +00:00
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
2020-05-14 14:03:37 -07:00
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
REQUIRE(handle == ccmsg->handle);
|
|
|
|
if (eresult != ISC_R_SUCCESS) {
|
2020-04-16 13:06:42 -07:00
|
|
|
goto done;
|
|
|
|
}
|
2001-03-27 00:44:59 +00:00
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
REQUIRE(region != NULL);
|
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
/* Copy the received data to our reassembly buffer */
|
|
|
|
eresult = isc_buffer_copyregion(ccmsg->buffer, region);
|
|
|
|
if (eresult != ISC_R_SUCCESS) {
|
|
|
|
goto done;
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|
2023-11-09 10:26:43 +01:00
|
|
|
isc_region_consume(region, region->length);
|
2001-03-27 00:44:59 +00:00
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
/* Try to parse a single message of the buffer */
|
|
|
|
eresult = try_parse_message(ccmsg);
|
|
|
|
/* No results from parsing, we need more data */
|
|
|
|
if (eresult == ISC_R_NOMORE) {
|
2020-04-16 13:06:42 -07:00
|
|
|
return;
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
done:
|
2022-08-29 10:55:10 +02:00
|
|
|
isc_nm_read_stop(handle);
|
2024-02-08 12:31:09 +01:00
|
|
|
ccmsg->recv_cb(handle, eresult, ccmsg->recv_cbarg);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
|
|
|
|
return;
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-16 13:06:42 -07:00
|
|
|
isccc_ccmsg_init(isc_mem_t *mctx, isc_nmhandle_t *handle,
|
|
|
|
isccc_ccmsg_t *ccmsg) {
|
2001-03-27 00:44:59 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
2020-04-16 13:06:42 -07:00
|
|
|
REQUIRE(handle != NULL);
|
2001-03-27 00:44:59 +00:00
|
|
|
REQUIRE(ccmsg != NULL);
|
|
|
|
|
2019-12-15 16:45:17 -08:00
|
|
|
*ccmsg = (isccc_ccmsg_t){
|
|
|
|
.magic = CCMSG_MAGIC,
|
|
|
|
.maxsize = 0xffffffffU, /* Largest message possible. */
|
|
|
|
.mctx = mctx,
|
|
|
|
};
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
/* Preallocate the buffer to maximum single TCP read */
|
|
|
|
isc_buffer_allocate(ccmsg->mctx, &ccmsg->buffer,
|
|
|
|
UINT16_MAX + sizeof(uint16_t));
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
isc_nmhandle_attach(handle, &ccmsg->handle);
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) {
|
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
|
|
|
|
|
|
|
ccmsg->maxsize = maxsize;
|
|
|
|
}
|
|
|
|
|
2020-10-21 12:52:09 +02:00
|
|
|
void
|
2020-04-16 13:06:42 -07:00
|
|
|
isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_nm_cb_t cb, void *cbarg) {
|
2001-03-27 00:44:59 +00:00
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
2020-04-16 13:06:42 -07:00
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
if (ccmsg->size != 0) {
|
|
|
|
/* Remove the previously read message from the buffer */
|
|
|
|
isc_buffer_forward(ccmsg->buffer, ccmsg->size);
|
|
|
|
ccmsg->size = 0;
|
|
|
|
isc_buffer_trycompact(ccmsg->buffer);
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
ccmsg->recv_cb = cb;
|
|
|
|
ccmsg->recv_cbarg = cbarg;
|
2001-03-27 00:44:59 +00:00
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
/* If we have previous data still in the buffer, try to parse it */
|
|
|
|
isc_result_t result = try_parse_message(ccmsg);
|
|
|
|
if (result == ISC_R_NOMORE) {
|
|
|
|
/* We need to read more data */
|
|
|
|
isc_nm_read(ccmsg->handle, recv_data, ccmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ccmsg->recv_cb(ccmsg->handle, result, ccmsg->recv_cbarg);
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
static void
|
|
|
|
ccmsg_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
|
|
|
isccc_ccmsg_t *ccmsg = arg;
|
|
|
|
|
2001-03-27 00:44:59 +00:00
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
2024-02-08 12:31:09 +01:00
|
|
|
REQUIRE(ccmsg->send_cb != NULL);
|
2001-03-27 00:44:59 +00:00
|
|
|
|
2024-02-08 12:31:09 +01:00
|
|
|
isc_nm_cb_t send_cb = ccmsg->send_cb;
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
ccmsg->send_cb = NULL;
|
|
|
|
|
2024-02-08 12:31:09 +01:00
|
|
|
send_cb(handle, eresult, ccmsg->send_cbarg);
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
isc_nmhandle_detach(&handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isccc_ccmsg_sendmessage(isccc_ccmsg_t *ccmsg, isc_region_t *region,
|
|
|
|
isc_nm_cb_t cb, void *cbarg) {
|
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
|
|
|
REQUIRE(ccmsg->send_cb == NULL);
|
|
|
|
|
|
|
|
ccmsg->send_cb = cb;
|
|
|
|
ccmsg->send_cbarg = cbarg;
|
|
|
|
|
|
|
|
isc_nmhandle_ref(ccmsg->handle);
|
|
|
|
isc_nm_send(ccmsg->handle, region, ccmsg_senddone, ccmsg);
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|
|
|
|
|
Defer control channel message invalidation
The conn_shutdown() function is called whenever a control channel
connection is supposed to be closed, e.g. after a response to the client
is sent or when named is being shut down. That function calls
isccc_ccmsg_invalidate(), which resets the magic number in the structure
holding the messages exchanged over a given control channel connection
(isccc_ccmsg_t). The expectation here is that all operations related to
the given control channel connection will have been completed by the
time the connection needs to be shut down.
However, if named shutdown is initiated while a control channel message
is still in flight, some netmgr callbacks might still be pending when
conn_shutdown() is called and isccc_ccmsg_t invalidated. This causes
the REQUIRE assertion checking the magic number in ccmsg_senddone() to
fail when the latter function is eventually called, resulting in a
crash.
Fix by splitting up isccc_ccmsg_invalidate() into two separate
functions:
- isccc_ccmsg_disconnect(), which initiates TCP connection shutdown,
- isccc_ccmsg_invalidate(), which cleans up magic number and buffer,
and then:
- replacing all existing uses of isccc_ccmsg_invalidate() with calls
to isccc_ccmsg_disconnect(),
- only calling isccc_ccmsg_invalidate() when all netmgr callbacks are
guaranteed to have been run.
Adjust function comments accordingly.
2024-01-10 14:35:36 +11:00
|
|
|
void
|
|
|
|
isccc_ccmsg_disconnect(isccc_ccmsg_t *ccmsg) {
|
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
|
|
|
|
|
|
|
if (ccmsg->handle != NULL) {
|
2024-02-08 12:31:09 +01:00
|
|
|
isc_nm_read_stop(ccmsg->handle);
|
Defer control channel message invalidation
The conn_shutdown() function is called whenever a control channel
connection is supposed to be closed, e.g. after a response to the client
is sent or when named is being shut down. That function calls
isccc_ccmsg_invalidate(), which resets the magic number in the structure
holding the messages exchanged over a given control channel connection
(isccc_ccmsg_t). The expectation here is that all operations related to
the given control channel connection will have been completed by the
time the connection needs to be shut down.
However, if named shutdown is initiated while a control channel message
is still in flight, some netmgr callbacks might still be pending when
conn_shutdown() is called and isccc_ccmsg_t invalidated. This causes
the REQUIRE assertion checking the magic number in ccmsg_senddone() to
fail when the latter function is eventually called, resulting in a
crash.
Fix by splitting up isccc_ccmsg_invalidate() into two separate
functions:
- isccc_ccmsg_disconnect(), which initiates TCP connection shutdown,
- isccc_ccmsg_invalidate(), which cleans up magic number and buffer,
and then:
- replacing all existing uses of isccc_ccmsg_invalidate() with calls
to isccc_ccmsg_disconnect(),
- only calling isccc_ccmsg_invalidate() when all netmgr callbacks are
guaranteed to have been run.
Adjust function comments accordingly.
2024-01-10 14:35:36 +11:00
|
|
|
isc_nmhandle_close(ccmsg->handle);
|
|
|
|
isc_nmhandle_detach(&ccmsg->handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-27 00:44:59 +00:00
|
|
|
void
|
|
|
|
isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
|
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
2023-11-09 10:26:43 +01:00
|
|
|
REQUIRE(ccmsg->handle == NULL);
|
2001-03-27 00:44:59 +00:00
|
|
|
|
|
|
|
ccmsg->magic = 0;
|
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
isc_buffer_free(&ccmsg->buffer);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isccc_ccmsg_toregion(isccc_ccmsg_t *ccmsg, isccc_region_t *ccregion) {
|
|
|
|
REQUIRE(VALID_CCMSG(ccmsg));
|
2023-11-09 10:26:43 +01:00
|
|
|
REQUIRE(ccmsg->buffer);
|
|
|
|
REQUIRE(isc_buffer_remaininglength(ccmsg->buffer) >= ccmsg->size);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
|
2023-11-09 10:26:43 +01:00
|
|
|
ccregion->rstart = isc_buffer_current(ccmsg->buffer);
|
|
|
|
ccregion->rend = ccregion->rstart + ccmsg->size;
|
2001-03-27 00:44:59 +00:00
|
|
|
}
|