Skip to content

Commit 9cedb5a

Browse files
ejohnstownphilljj
authored andcommitted
Keep queued replies with the folded forward
A port-0 reply naming a port another registration stands for merges the two, since one bind gets one registration. The requests still queued against the entry that goes named that same bind, so FwdReplyRebind() hands them to the survivor. Left naming nothing, a cancel among them settles no forward and the merged one keeps matching opens. - FwdReplyRebind() repoints queued slots before the stale entry is unlinked and FwdReplyVoid() clears them - Test folds a port-0 reply onto a forward with a cancel already queued, and checks the cancel takes the survivor down
1 parent a88404c commit 9cedb5a

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

src/internal.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3986,6 +3986,21 @@ static void FwdReplyVoid(WOLFSSH* ssh, const WOLFSSH_FWD_REMOTE* entry)
39863986
}
39873987

39883988

3989+
/* Hand every queued slot naming one forward over to another. A slot names the
3990+
* bind it asked about, so when two registrations turn out to be the same bind,
3991+
* the surviving one is what those requests were about. */
3992+
static void FwdReplyRebind(WOLFSSH* ssh, const WOLFSSH_FWD_REMOTE* from,
3993+
WOLFSSH_FWD_REMOTE* to)
3994+
{
3995+
WOLFSSH_FWD_REPLY* reply;
3996+
3997+
for (reply = ssh->fwdReplyHead; reply != NULL; reply = reply->next) {
3998+
if (reply->entry == from)
3999+
reply->entry = to;
4000+
}
4001+
}
4002+
4003+
39894004
static void FwdRemoteUnlink(WOLFSSH* ssh, void* heap,
39904005
WOLFSSH_FWD_REMOTE* entry)
39914006
{
@@ -4149,6 +4164,11 @@ static void FwdRemoteSettle(WOLFSSH* ssh, WOLFSSH_FWD_REMOTE* entry,
41494164

41504165
WLOG(WS_LOG_INFO, "Remote forward reply named a port already "
41514166
"registered");
4167+
/* Requests still queued on the stale entry asked about this bind,
4168+
* so they answer for the entry that stands at it now. Unlinking
4169+
* without this leaves them naming nothing, and a cancel among
4170+
* them would settle no forward. */
4171+
FwdReplyRebind(ssh, dup, entry);
41524172
FwdRemoteUnlink(ssh, ssh->ctx->heap, dup);
41534173
}
41544174
}

tests/regress.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5409,6 +5409,47 @@ static void TestForwardedTcpipPortZeroReplyFoldsDuplicate(void)
54095409
FreeChannelOpenHarness(&harness);
54105410
}
54115411

5412+
/* A cancel queued against the entry the fold drops still names that bind, so
5413+
* the surviving registration is what it answers for. */
5414+
static void TestForwardedTcpipPortZeroFoldSettlesQueuedCancel(void)
5415+
{
5416+
ChannelOpenHarness harness;
5417+
byte reply[64];
5418+
word32 replySz;
5419+
5420+
InitFwdRemoteHarness(&harness);
5421+
5422+
AssertIntEQ(wolfSSH_FwdRemoteSetup(harness.ssh, "127.0.0.1", 8080, 1),
5423+
WS_SUCCESS);
5424+
AssertIntEQ(wolfSSH_FwdRemoteSetup(harness.ssh, "127.0.0.1", 0, 1),
5425+
WS_SUCCESS);
5426+
AssertIntEQ(wolfSSH_FwdRemoteCancel(harness.ssh, "127.0.0.1", 8080, 1),
5427+
WS_SUCCESS);
5428+
AssertIntEQ(FwdRemoteCount(harness.ssh), 2);
5429+
5430+
/* The peer refused the explicit setup, but the cancel still names that
5431+
* registration, so it stands for now. */
5432+
FeedRequestFailure(&harness);
5433+
AssertIntEQ(FwdRemoteCount(harness.ssh), 2);
5434+
5435+
/* The port-0 request got the port the refused one asked for. One bind,
5436+
* one registration. */
5437+
replySz = BuildRequestSuccessPortPacket(8080, reply, sizeof(reply));
5438+
AssertIntEQ(FeedOnePacket(&harness, reply, replySz), WS_SUCCESS);
5439+
AssertIntEQ(FwdRemoteCount(harness.ssh), 1);
5440+
5441+
/* The cancel went out after both setups, so it is the last word on the
5442+
* bind and matching stops on it alone. */
5443+
AssertForwardedOpenRefused(&harness, "127.0.0.1", 8080);
5444+
5445+
/* Confirming it takes the merged registration down with it. */
5446+
FeedRequestSuccess(&harness);
5447+
AssertIntEQ(FwdRemoteCount(harness.ssh), 0);
5448+
AssertForwardedOpenRefused(&harness, "127.0.0.1", 8080);
5449+
5450+
FreeChannelOpenHarness(&harness);
5451+
}
5452+
54125453
static void TestForwardedTcpipRepliesPairInSendOrder(void)
54135454
{
54145455
ChannelOpenHarness harness;
@@ -10843,6 +10884,7 @@ int main(int argc, char** argv)
1084310884
TestForwardedTcpipConfirmedCancelDropsEarlierSuccess();
1084410885
TestForwardedTcpipConfirmedCancelThenSetupBinds();
1084510886
TestForwardedTcpipPortZeroReplyFoldsDuplicate();
10887+
TestForwardedTcpipPortZeroFoldSettlesQueuedCancel();
1084610888
TestForwardedTcpipPostSendErrorStillRegisters();
1084710889
TestForwardedTcpipFailedSendRegistersNothing();
1084810890
TestForwardedTcpipReentrantSetupDuringSend();

0 commit comments

Comments
 (0)