@@ -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. */
32563354static 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