diff --git a/ssh.c b/ssh.c index 719d9e61..c2951499 100644 --- a/ssh.c +++ b/ssh.c @@ -996,7 +996,8 @@ static size_t ssh_sendbuffer(Backend *be) backlog = ssh_stdin_backlog(ssh->cl); - /* FIXME: also include sizes of pqs */ + if (ssh->base_layer) + backlog += ssh_ppl_queued_data_size(ssh->base_layer); /* * If the SSH socket itself has backed up, add the total backup diff --git a/ssh1connection.c b/ssh1connection.c index c7396166..b3e200b3 100644 --- a/ssh1connection.c +++ b/ssh1connection.c @@ -43,6 +43,7 @@ static const struct PacketProtocolLayerVtable ssh1_connection_vtable = { ssh1_connection_want_user_input, ssh1_connection_got_user_input, ssh1_connection_reconfigure, + ssh_ppl_default_queued_data_size, NULL /* no layer names in SSH-1 */, }; diff --git a/ssh1login-server.c b/ssh1login-server.c index d4988516..3316a6c3 100644 --- a/ssh1login-server.c +++ b/ssh1login-server.c @@ -65,6 +65,7 @@ static const struct PacketProtocolLayerVtable ssh1_login_server_vtable = { ssh1_login_server_want_user_input, ssh1_login_server_got_user_input, ssh1_login_server_reconfigure, + ssh_ppl_default_queued_data_size, NULL /* no layer names in SSH-1 */, }; diff --git a/ssh1login.c b/ssh1login.c index c129b866..803e590e 100644 --- a/ssh1login.c +++ b/ssh1login.c @@ -80,6 +80,7 @@ static const struct PacketProtocolLayerVtable ssh1_login_vtable = { ssh1_login_want_user_input, ssh1_login_got_user_input, ssh1_login_reconfigure, + ssh_ppl_default_queued_data_size, NULL /* no layer names in SSH-1 */, }; diff --git a/ssh2connection.c b/ssh2connection.c index a8c20f2d..666d6db7 100644 --- a/ssh2connection.c +++ b/ssh2connection.c @@ -30,6 +30,7 @@ static const struct PacketProtocolLayerVtable ssh2_connection_vtable = { ssh2_connection_want_user_input, ssh2_connection_got_user_input, ssh2_connection_reconfigure, + ssh_ppl_default_queued_data_size, "ssh-connection", }; diff --git a/ssh2transport.c b/ssh2transport.c index 982cee8c..88f1f6d4 100644 --- a/ssh2transport.c +++ b/ssh2transport.c @@ -71,6 +71,7 @@ static void ssh2_transport_special_cmd(PacketProtocolLayer *ppl, static bool ssh2_transport_want_user_input(PacketProtocolLayer *ppl); static void ssh2_transport_got_user_input(PacketProtocolLayer *ppl); static void ssh2_transport_reconfigure(PacketProtocolLayer *ppl, Conf *conf); +static size_t ssh2_transport_queued_data_size(PacketProtocolLayer *ppl); static void ssh2_transport_set_max_data_size(struct ssh2_transport_state *s); static unsigned long sanitise_rekey_time(int rekey_time, unsigned long def); @@ -84,6 +85,7 @@ static const struct PacketProtocolLayerVtable ssh2_transport_vtable = { ssh2_transport_want_user_input, ssh2_transport_got_user_input, ssh2_transport_reconfigure, + ssh2_transport_queued_data_size, NULL, /* no protocol name for this layer */ }; @@ -2028,3 +2030,12 @@ static int ssh2_transport_confirm_weak_crypto_primitive( return seat_confirm_weak_crypto_primitive( s->ppl.seat, type, name, ssh2_transport_dialog_callback, s); } + +static size_t ssh2_transport_queued_data_size(PacketProtocolLayer *ppl) +{ + struct ssh2_transport_state *s = + container_of(ppl, struct ssh2_transport_state, ppl); + + return (ssh_ppl_default_queued_data_size(ppl) + + ssh_ppl_queued_data_size(s->higher_layer)); +} diff --git a/ssh2userauth-server.c b/ssh2userauth-server.c index 37753956..7e67e557 100644 --- a/ssh2userauth-server.c +++ b/ssh2userauth-server.c @@ -46,6 +46,7 @@ static const struct PacketProtocolLayerVtable ssh2_userauth_server_vtable = { NULL /* want_user_input */, NULL /* got_user_input */, NULL /* reconfigure */, + ssh_ppl_default_queued_data_size, "ssh-userauth", }; diff --git a/ssh2userauth.c b/ssh2userauth.c index 62c4b409..dace56f1 100644 --- a/ssh2userauth.c +++ b/ssh2userauth.c @@ -120,6 +120,7 @@ static const struct PacketProtocolLayerVtable ssh2_userauth_vtable = { ssh2_userauth_want_user_input, ssh2_userauth_got_user_input, ssh2_userauth_reconfigure, + ssh_ppl_default_queued_data_size, "ssh-userauth", }; diff --git a/sshcommon.c b/sshcommon.c index 0d56460f..c19880b5 100644 --- a/sshcommon.c +++ b/sshcommon.c @@ -835,6 +835,11 @@ void ssh_ppl_user_output_string_and_free(PacketProtocolLayer *ppl, char *text) sfree(text); } +size_t ssh_ppl_default_queued_data_size(PacketProtocolLayer *ppl) +{ + return ppl->out_pq->pqb.total_size; +} + /* ---------------------------------------------------------------------- * Common helper functions for clients and implementations of * BinaryPacketProtocol. diff --git a/sshppl.h b/sshppl.h index 4d55d380..cfd6d6be 100644 --- a/sshppl.h +++ b/sshppl.h @@ -19,6 +19,7 @@ struct PacketProtocolLayerVtable { bool (*want_user_input)(PacketProtocolLayer *ppl); void (*got_user_input)(PacketProtocolLayer *ppl); void (*reconfigure)(PacketProtocolLayer *ppl, Conf *conf); + size_t (*queued_data_size)(PacketProtocolLayer *ppl); /* Protocol-level name of this layer. */ const char *name; @@ -73,6 +74,8 @@ static inline void ssh_ppl_got_user_input(PacketProtocolLayer *ppl) { ppl->vt->got_user_input(ppl); } static inline void ssh_ppl_reconfigure(PacketProtocolLayer *ppl, Conf *conf) { ppl->vt->reconfigure(ppl, conf); } +static inline size_t ssh_ppl_queued_data_size(PacketProtocolLayer *ppl) +{ return ppl->vt->queued_data_size(ppl); } /* ssh_ppl_free is more than just a macro wrapper on the vtable; it * does centralised parts of the freeing too. */ @@ -90,6 +93,11 @@ void ssh_ppl_setup_queues(PacketProtocolLayer *ppl, * avoid dereferencing itself on return from this function! */ void ssh_ppl_replace(PacketProtocolLayer *old, PacketProtocolLayer *new); +/* Default implementation of queued_data_size, which just adds up the + * sizes of all the packets in pq_out. A layer can override this if it + * has other things to take into account as well. */ +size_t ssh_ppl_default_queued_data_size(PacketProtocolLayer *ppl); + PacketProtocolLayer *ssh1_login_new( Conf *conf, const char *host, int port, PacketProtocolLayer *successor_layer);