private void doPropagateOutbound(@Nonnull Packet stanza, @Nonnull MUCOccupant sender, @Nonnull CompletableFuture<?> result )
    {
        Log.debug("(room: '{}'): Propagating a stanza (type '{}') from user '{}' (as '{}') to the joined FMUC node {}.", room.getJID(), stanza.getClass().getSimpleName(), sender.getUserAddress(), sender.getOccupantJID(), outboundJoin.getPeer() );

        final Packet enriched = enrichWithFMUCElement( stanza, sender );
        enriched.setFrom( new JID(room.getName(), room.getMUCService().getServiceDomain(), sender.getNickname() ) );
        enriched.setTo( new JID(outboundJoin.getPeer().getNode(), outboundJoin.getPeer().getDomain(), sender.getNickname() ) );

        // When we're in a master-slave mode with the remote FMUC node that we're joining to, we must wait for it
        // to echo back the presence data, before we can distribute it in the local room.
        final boolean mustBlock = outboundJoin.getMode() == FMUCMode.MasterSlave;
        if ( !mustBlock ) {
            Log.trace("(room: '{}'): No need to wait for an echo back from joined FMUC node {} of the propagation of stanza sent by user '{}' (as '{}').", room.getJID(), outboundJoin.getPeer(), sender.getUserAddress(), sender.getOccupantJID() );
            result.complete( null );
        } else {
            Log.debug("(room: '{}'): An echo back from joined FMUC node {} of the propagation of stanza snet by user '{}' (as '{}') needs to be received before the join event can be propagated locally.", room.getJID(), outboundJoin.getPeer(), sender.getUserAddress(), sender.getOccupantJID() );

            // register callback to complete this future when echo is received back.
            outboundJoin.registerEchoCallback( enriched, result );
        }

        // Send the outbound stanza.
        XMPPServer.getInstance().getPacketRouter().route( enriched );
    }
Sends a stanza to the joined FMUC node, when the local node has established such an outbound join.

Note that when a master-slave mode is active, we need to wait for an echo back, before the message can be
broadcasted locally. This method will return a CompletableFuture object that is completed as soon as processing
can continue. This doesn't necessarily mean that processing/propagating has been completed (eg: when the FMUC
is configured to use master-master mode, a completed Future instance will be returned.

@param stanza The stanza to be sent.
@param sender Representation of the sender of the stanza.
@return A future object that completes when the stanza can be propagated locally.
xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/FMUCHandler.java