Skip to content

Commit 56ff222

Browse files
committed
tests: cover the channel close callback
wolfSSH_CTX_SetChannelCloseCb() had no caller in tests/, examples/ or apps/, so nothing held DoChannelClose() to running the hook before it retires the channel. - assert the callback runs with the closing channel's id and the ctx set on the session - assert the channel is still on the list inside the callback and gone by the time the caller is told - a rejecting callback changes nothing: the return is discarded and the close completes
1 parent fc0b7fa commit 56ff222

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

tests/regress.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3157,6 +3157,104 @@ static void TestChannelOpenFailCallbackRejects(void)
31573157
FreeChannelOpenHarness(&harness);
31583158
}
31593159

3160+
/* What the close callback saw, including whether the channel was still on
3161+
* the list when it ran. */
3162+
static int closeCbCalls;
3163+
static word32 closeCbChannel;
3164+
static void* closeCbCtx;
3165+
static word32 closeCbListSz;
3166+
static int closeCbReturn;
3167+
3168+
static int RecordingChannelCloseCb(WOLFSSH_CHANNEL* channel, void* ctx)
3169+
{
3170+
AssertNotNull(channel);
3171+
AssertNotNull(channel->ssh);
3172+
closeCbCalls++;
3173+
closeCbChannel = channel->channel;
3174+
closeCbCtx = ctx;
3175+
closeCbListSz = channel->ssh->channelListSz;
3176+
3177+
return closeCbReturn;
3178+
}
3179+
3180+
/* Drives a peer close of a confirmed channel through the recording callback,
3181+
* set to return cbReturn, and returns what DoReceive() reported. */
3182+
static int CloseThroughRecordingCb(ChannelOpenHarness* harness, void* cbCtx,
3183+
int cbReturn, word32* selfChannelId)
3184+
{
3185+
WOLFSSH_CHANNEL* channel;
3186+
byte in[64];
3187+
word32 inSz;
3188+
int ret;
3189+
3190+
closeCbCalls = 0;
3191+
closeCbChannel = REGRESS_NO_CHANNEL;
3192+
closeCbCtx = NULL;
3193+
closeCbListSz = 0;
3194+
closeCbReturn = cbReturn;
3195+
3196+
InitChannelOpenHarness(harness, NULL, 0);
3197+
AssertIntEQ(wolfSSH_CTX_SetChannelCloseCb(harness->ctx,
3198+
RecordingChannelCloseCb), WS_SUCCESS);
3199+
AssertIntEQ(wolfSSH_SetChannelCloseCtx(harness->ssh, cbCtx), WS_SUCCESS);
3200+
3201+
channel = SeedUnconfirmedChannel(harness);
3202+
*selfChannelId = channel->channel;
3203+
AssertIntEQ(ChannelUpdatePeer(channel, 5, 1024, 1024), WS_SUCCESS);
3204+
channel->openConfirmed = 1;
3205+
3206+
inSz = BuildChannelClosePacket(*selfChannelId, in, sizeof(in));
3207+
RepointHarnessInput(harness, in, inSz);
3208+
3209+
ret = DoReceive(harness->ssh);
3210+
AssertIntEQ(harness->io.inOff, harness->io.inSz);
3211+
3212+
return ret;
3213+
}
3214+
3215+
/* The close callback is an application's only notice that a peer closed a
3216+
* channel, and it has to run while the channel is still findable:
3217+
* DoChannelClose() retires it a few lines later, and after that there is
3218+
* nothing left to name. */
3219+
static void TestChannelCloseCallbackRuns(void)
3220+
{
3221+
ChannelOpenHarness harness;
3222+
word32 selfChannelId;
3223+
int cbCtx = 0;
3224+
int ret;
3225+
3226+
ret = CloseThroughRecordingCb(&harness, &cbCtx, WS_SUCCESS,
3227+
&selfChannelId);
3228+
AssertIntEQ(ret, WS_CHANNEL_CLOSED);
3229+
AssertIntEQ(closeCbCalls, 1);
3230+
AssertIntEQ(closeCbChannel, selfChannelId);
3231+
AssertTrue(closeCbCtx == &cbCtx);
3232+
AssertIntEQ(closeCbListSz, 1);
3233+
3234+
/* And the channel is gone by the time the caller is told. */
3235+
AssertIntEQ(harness.ssh->channelListSz, 0);
3236+
3237+
FreeChannelOpenHarness(&harness);
3238+
}
3239+
3240+
/* The close callback's return is discarded: the peer has closed whatever
3241+
* the application thinks, so the close completes either way. */
3242+
static void TestChannelCloseCallbackReturnIgnored(void)
3243+
{
3244+
ChannelOpenHarness harness;
3245+
word32 selfChannelId;
3246+
int cbCtx = 0;
3247+
int ret;
3248+
3249+
ret = CloseThroughRecordingCb(&harness, &cbCtx, WS_BAD_ARGUMENT,
3250+
&selfChannelId);
3251+
AssertIntEQ(ret, WS_CHANNEL_CLOSED);
3252+
AssertIntEQ(closeCbCalls, 1);
3253+
AssertIntEQ(harness.ssh->channelListSz, 0);
3254+
3255+
FreeChannelOpenHarness(&harness);
3256+
}
3257+
31603258
/* A username change after the first userauth request must end the session. */
31613259
static void TestUsernameChangeDisconnects(void)
31623260
{
@@ -12355,6 +12453,8 @@ int main(int argc, char** argv)
1235512453
TestChannelOpenFailCallbackRuns();
1235612454
TestChannelOpenConfCallbackRejects();
1235712455
TestChannelOpenFailCallbackRejects();
12456+
TestChannelCloseCallbackRuns();
12457+
TestChannelCloseCallbackReturnIgnored();
1235812458
TestSecondSessionChannelRejected();
1235912459
TestUsernameChangeDisconnects();
1236012460
TestSameUserRetryAllowed();

0 commit comments

Comments
 (0)