qgrpcstream: add a messageWritten signal to pace streaming writes


The Http2Handler queues outgoing messages without a size limit. An
application that writes faster than the network transmits, or a peer
that withholds HTTP/2 flow-control credit, grows that queue without
bound and exhausts client memory (availability / DoS).

Emit a signal once per message after QHttp2Stream has fully written it
to the connection, which happens only within the send window the server
granted. Writing the next message in response to the signal therefore
bounds an application to one queued message, the same write-then-wait
discipline as seen in grpc-c++, e.g. ClientWriteReactor::OnWriteDone.

The emission is deferred by one event-loop turn because uploadFinished
fires synchronously from within writeMessage() when the window is open,
and a synchronous emission would re-enter the user's slot. The deferred
lambda re-checks the handler state so the signal never follows
finished().

The client guide's client-streaming example is rewritten to pace with
the signal, and bench_qtgrpcclient gains a --paced mode so the pacing
can be measured against burst writes.

QGrpcOperationContext::messageWritten is the channel-side counterpart;
custom channels must emit it for the stream signals to work.

[ChangeLog][QGrpcClientStream] Added the messageWritten() signal
to QGrpcClientStream and QGrpcBidiStream. It is emitted once per
outgoing message after the channel has handed the message to the
transport, and respects HTTP/2 flow control. Write the next message in
response to it to bound the outgoing queue.

Fixes: QTBUG-147934
Change-Id: Id6f3a6e8271832a8778c901180c4a26558d589a4
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
commitd2876ae9d8a1dd98159bedc710b4096841a13ca8
parent3a67dac037f6cc16d6e4c059a188c1a6607b8f8e
authorDennis Oberst <dennis.oberst@qt.io>
committerDennis Oberst <dennis.oberst@qt.io>
commit timeMon, 17 Aug 2026 13:13:56 +0000