pub fn from_stream_with_identity(
        context: &Context,
        stream: S,
        stream_ty: StreamType,
        method: CipherKind,
        key: &[u8],
        identity_keys: &[Bytes],
        user_manager: Option<Arc<ServerUserManager>>,
    ) -> Self {
        let category = method.category();

        if category == CipherCategory::None {
            // Fast-path for none cipher
            return Self::new_none(stream, method);
        }

        let prev_len = match category {
            #[cfg(feature = "stream-cipher")]
            CipherCategory::Stream => method.iv_len(),
            #[cfg(feature = "aead-cipher")]
            CipherCategory::Aead => method.salt_len(),
            CipherCategory::None => 0,
            #[cfg(feature = "aead-cipher-2022")]
            CipherCategory::Aead2022 => method.salt_len(),
        };

        let iv = match category {
            #[cfg(feature = "stream-cipher")]
            CipherCategory::Stream => {
                let mut local_iv = vec![0u8; prev_len];
                context.generate_nonce(method, &mut local_iv, true);
                trace!("generated Stream cipher IV {:?}", ByteStr::new(&local_iv));
                local_iv
            }
            #[cfg(feature = "aead-cipher")]
            CipherCategory::Aead => {
                let mut local_salt = vec![0u8; prev_len];
                context.generate_nonce(method, &mut local_salt, true);
                trace!("generated AEAD cipher salt {:?}", ByteStr::new(&local_salt));
                local_salt
            }
            CipherCategory::None => {
                debug_assert_eq!(prev_len, 0);
                let _ = context;
                Vec::new()
            }
            #[cfg(feature = "aead-cipher-2022")]
            CipherCategory::Aead2022 => {
                // AEAD-2022 has a request-salt in respond header, so the generated salt doesn't need to be remembered.

                let mut local_salt = vec![0u8; prev_len];
                context.generate_nonce(method, &mut local_salt, false);
                trace!("generated AEAD cipher salt {:?}", ByteStr::new(&local_salt));
                local_salt
            }
        };

        Self {
            stream,
            dec: DecryptedReader::with_user_manager(stream_ty, method, key, user_manager),
            enc: EncryptedWriter::with_identity(stream_ty, method, key, &iv, identity_keys),
            method,
            has_handshaked: false,
        }
    }
Create a new CryptoStream with the underlying stream connection
crates/shadowsocks/src/relay/tcprelay/crypto_io.rs