Skip to content

Commit 5f9752f

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 9a90a87 commit 5f9752f

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
@@ -3252,6 +3252,104 @@ static void TestChannelOpenFailCallbackRejects(void)
32523252
FreeChannelOpenHarness(&harness);
32533253
}
32543254

3255+
/* What the close callback saw, including whether the channel was still on
3256+
* the list when it ran. */
3257+
static int closeCbCalls;
3258+
static word32 closeCbChannel;
3259+
static void* closeCbCtx;
3260+
static word32 closeCbListSz;
3261+
static int closeCbReturn;
3262+
3263+
static int RecordingChannelCloseCb(WOLFSSH_CHANNEL* channel, void* ctx)
3264+
{
3265+
AssertNotNull(channel);
3266+
AssertNotNull(channel->ssh);
3267+
closeCbCalls++;
3268+
closeCbChannel = channel->channel;
3269+
closeCbCtx = ctx;
3270+
closeCbListSz = channel->ssh->channelListSz;
3271+
3272+
return closeCbReturn;
3273+
}
3274+
3275+
/* Drives a peer close of a confirmed channel through the recording callback,
3276+
* set to return cbReturn, and returns what DoReceive() reported. */
3277+
static int CloseThroughRecordingCb(ChannelOpenHarness* harness, void* cbCtx,
3278+
int cbReturn, word32* selfChannelId)
3279+
{
3280+
WOLFSSH_CHANNEL* channel;
3281+
byte in[64];
3282+
word32 inSz;
3283+
int ret;
3284+
3285+
closeCbCalls = 0;
3286+
closeCbChannel = REGRESS_NO_CHANNEL;
3287+
closeCbCtx = NULL;
3288+
closeCbListSz = 0;
3289+
closeCbReturn = cbReturn;
3290+
3291+
InitChannelOpenHarness(harness, NULL, 0);
3292+
AssertIntEQ(wolfSSH_CTX_SetChannelCloseCb(harness->ctx,
3293+
RecordingChannelCloseCb), WS_SUCCESS);
3294+
AssertIntEQ(wolfSSH_SetChannelCloseCtx(harness->ssh, cbCtx), WS_SUCCESS);
3295+
3296+
channel = SeedUnconfirmedChannel(harness);
3297+
*selfChannelId = channel->channel;
3298+
AssertIntEQ(ChannelUpdatePeer(channel, 5, 1024, 1024), WS_SUCCESS);
3299+
channel->openConfirmed = 1;
3300+
3301+
inSz = BuildChannelClosePacket(*selfChannelId, in, sizeof(in));
3302+
RepointHarnessInput(harness, in, inSz);
3303+
3304+
ret = DoReceive(harness->ssh);
3305+
AssertIntEQ(harness->io.inOff, harness->io.inSz);
3306+
3307+
return ret;
3308+
}
3309+
3310+
/* The close callback is an application's only notice that a peer closed a
3311+
* channel, and it has to run while the channel is still findable:
3312+
* DoChannelClose() retires it a few lines later, and after that there is
3313+
* nothing left to name. */
3314+
static void TestChannelCloseCallbackRuns(void)
3315+
{
3316+
ChannelOpenHarness harness;
3317+
word32 selfChannelId;
3318+
int cbCtx = 0;
3319+
int ret;
3320+
3321+
ret = CloseThroughRecordingCb(&harness, &cbCtx, WS_SUCCESS,
3322+
&selfChannelId);
3323+
AssertIntEQ(ret, WS_CHANNEL_CLOSED);
3324+
AssertIntEQ(closeCbCalls, 1);
3325+
AssertIntEQ(closeCbChannel, selfChannelId);
3326+
AssertTrue(closeCbCtx == &cbCtx);
3327+
AssertIntEQ(closeCbListSz, 1);
3328+
3329+
/* And the channel is gone by the time the caller is told. */
3330+
AssertIntEQ(harness.ssh->channelListSz, 0);
3331+
3332+
FreeChannelOpenHarness(&harness);
3333+
}
3334+
3335+
/* The close callback's return is discarded: the peer has closed whatever
3336+
* the application thinks, so the close completes either way. */
3337+
static void TestChannelCloseCallbackReturnIgnored(void)
3338+
{
3339+
ChannelOpenHarness harness;
3340+
word32 selfChannelId;
3341+
int cbCtx = 0;
3342+
int ret;
3343+
3344+
ret = CloseThroughRecordingCb(&harness, &cbCtx, WS_BAD_ARGUMENT,
3345+
&selfChannelId);
3346+
AssertIntEQ(ret, WS_CHANNEL_CLOSED);
3347+
AssertIntEQ(closeCbCalls, 1);
3348+
AssertIntEQ(harness.ssh->channelListSz, 0);
3349+
3350+
FreeChannelOpenHarness(&harness);
3351+
}
3352+
32553353
/* A username change after the first userauth request must end the session. */
32563354
static void TestUsernameChangeDisconnects(void)
32573355
{
@@ -12454,6 +12552,8 @@ int main(int argc, char** argv)
1245412552
TestChannelOpenFailCallbackRuns();
1245512553
TestChannelOpenConfCallbackRejects();
1245612554
TestChannelOpenFailCallbackRejects();
12555+
TestChannelCloseCallbackRuns();
12556+
TestChannelCloseCallbackReturnIgnored();
1245712557
TestSecondSessionChannelRejected();
1245812558
TestUsernameChangeDisconnects();
1245912559
TestSameUserRetryAllowed();

0 commit comments

Comments
 (0)