Add ngtcp2_max_remote_stream_id callback
diff --git a/examples/client.cc b/examples/client.cc
index 1fc3732..6b55190 100644
--- a/examples/client.cc
+++ b/examples/client.cc
@@ -931,6 +931,8 @@
path_validation,
::select_preferred_address,
nullptr, // stream_reset
+ nullptr, // max_remote_stream_id_bidi,
+ nullptr, // max_remote_stream_id_uni,
};
auto dis = std::uniform_int_distribution<uint8_t>(
diff --git a/examples/server.cc b/examples/server.cc
index d73ccd8..b3998f0 100644
--- a/examples/server.cc
+++ b/examples/server.cc
@@ -1066,6 +1066,8 @@
path_validation,
nullptr, // select_preferred_addr
nullptr, // stream_reset
+ nullptr, // max_remote_stream_id_bidi,
+ nullptr, // max_remote_stream_id_uni,
};
ngtcp2_settings settings;
diff --git a/lib/includes/ngtcp2/ngtcp2.h b/lib/includes/ngtcp2/ngtcp2.h
index 06a94f5..c364577 100644
--- a/lib/includes/ngtcp2/ngtcp2.h
+++ b/lib/includes/ngtcp2/ngtcp2.h
@@ -1451,6 +1451,22 @@
const ngtcp2_preferred_addr *paddr,
void *user_data);
+/**
+ * @functypedef
+ *
+ * :type:`ngtcp2_max_remote_stream_id` is a callback function which is
+ * invoked when the maximum stream ID which remote endpoint can open
+ * is extended. |max_stream_id| is the maximum stream ID which remote
+ * endpoint can initiate.
+ *
+ * The callback function must return 0 if it succeeds. Returning
+ * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
+ * immediately.
+ */
+typedef int (*ngtcp2_max_remote_stream_id)(ngtcp2_conn *conn,
+ int64_t max_stream_id,
+ void *user_data);
+
typedef struct {
ngtcp2_client_initial client_initial;
ngtcp2_recv_client_initial recv_client_initial;
@@ -1503,6 +1519,8 @@
ngtcp2_path_validation path_validation;
ngtcp2_select_preferred_addr select_preferred_addr;
ngtcp2_stream_reset stream_reset;
+ ngtcp2_max_remote_stream_id max_remote_stream_id_bidi;
+ ngtcp2_max_remote_stream_id max_remote_stream_id_uni;
} ngtcp2_conn_callbacks;
/*
diff --git a/lib/ngtcp2_conn.c b/lib/ngtcp2_conn.c
index f7f5a4a..2b348d1 100644
--- a/lib/ngtcp2_conn.c
+++ b/lib/ngtcp2_conn.c
@@ -266,6 +266,40 @@
return 0;
}
+static int conn_call_max_remote_stream_id_bidi(ngtcp2_conn *conn,
+ int64_t max_stream_id) {
+ int rv;
+
+ if (!conn->callbacks.max_remote_stream_id_bidi) {
+ return 0;
+ }
+
+ rv = conn->callbacks.max_remote_stream_id_bidi(conn, max_stream_id,
+ conn->user_data);
+ if (rv != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int conn_call_max_remote_stream_id_uni(ngtcp2_conn *conn,
+ int64_t max_stream_id) {
+ int rv;
+
+ if (!conn->callbacks.max_remote_stream_id_uni) {
+ return 0;
+ }
+
+ rv = conn->callbacks.max_remote_stream_id_uni(conn, max_stream_id,
+ conn->user_data);
+ if (rv != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
/*
* bw_reset resets |bw| to the initial state.
*/
@@ -2229,6 +2263,13 @@
if (rv != NGTCP2_ERR_NOBUF && *pfrc == NULL &&
conn->remote.bidi.unsent_max_stream_id >
conn->remote.bidi.max_stream_id) {
+ rv = conn_call_max_remote_stream_id_bidi(
+ conn, conn->remote.bidi.unsent_max_stream_id);
+ if (rv != 0) {
+ assert(ngtcp2_err_is_fatal(rv));
+ return rv;
+ }
+
rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
@@ -2254,6 +2295,13 @@
if (rv != NGTCP2_ERR_NOBUF && *pfrc == NULL) {
if (conn->remote.uni.unsent_max_stream_id >
conn->remote.uni.max_stream_id) {
+ rv = conn_call_max_remote_stream_id_uni(
+ conn, conn->remote.uni.unsent_max_stream_id);
+ if (rv != 0) {
+ assert(ngtcp2_err_is_fatal(rv));
+ return rv;
+ }
+
rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));