Skip to content

Commit

Permalink
docs: document remaining classes and types
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis committed Oct 6, 2024
1 parent 433ebc5 commit 260a389
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 42 deletions.
40 changes: 36 additions & 4 deletions src/dpp/dave/scope_exit.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,40 +30,72 @@

namespace dpp::dave {

/**
* @brief Calls a lambda when the class goes out of scope
*/
class [[nodiscard]] scope_exit final {
public:
template <typename Cleanup>
explicit scope_exit(Cleanup&& cleanup)
/**
* Create new scope_exit with a lambda
* @tparam Cleanup lambda type
* @param cleanup lambda
*/
template <typename Cleanup> explicit scope_exit(Cleanup&& cleanup)
: cleanup_{std::forward<Cleanup>(cleanup)}
{
}

scope_exit(scope_exit&& rhs)
: cleanup_{std::move(rhs.cleanup_)}
/**
* @brief Move constructor
* @param rhs other object
*/
scope_exit(scope_exit&& rhs) : cleanup_{std::move(rhs.cleanup_)}
{
rhs.cleanup_ = nullptr;
}

/**
* @brief Calls lambda
*/
~scope_exit()
{
if (cleanup_) {
cleanup_();
}
}

/**
* @brief move assignment
* @param rhs other object
* @return self
*/
scope_exit& operator=(scope_exit&& rhs)
{
cleanup_ = std::move(rhs.cleanup_);
rhs.cleanup_ = nullptr;
return *this;
}

/**
* @brief Clear the lambda so it isn't called
*/
void dismiss() { cleanup_ = nullptr; }

private:
/**
* @brief Deleted copy constructor
*/
scope_exit(scope_exit const&) = delete;

/**
* @brief Deleted assignment operator
* @return
*/
scope_exit& operator=(scope_exit const&) = delete;

/**
* @brief Lambda to call
*/
std::function<void()> cleanup_;
};

Expand Down
2 changes: 1 addition & 1 deletion src/dpp/dave/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

namespace dpp::dave::mls {

struct QueuedProposal {
struct queued_proposal {
::mlspp::ValidatedContent content;
::mlspp::bytes_ns::bytes ref;
};
Expand Down
196 changes: 159 additions & 37 deletions src/dpp/dave/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,74 +51,196 @@ namespace mlspp {

namespace dpp::dave::mls {

struct QueuedProposal;
struct queued_proposal;

class session {
/**
* @brief Represents an MLS DAVE session
*/
class session { // NOLINT
public:
/**
* @brief An MLS failure callback
*/
using mls_failure_callback = std::function<void(std::string const&, std::string const&)>;

session(key_pair_context_type context,
const std::string& authSessionId,
mls_failure_callback callback) noexcept;

/**
* @brief Constructor
* @param context key pair context (set to nullptr to use a transient key pair)
* @param authSessionId auth session id (set to empty string to use a transient key pair)
* @param callback callback for failure
*/
session(key_pair_context_type context, const std::string& authSessionId, mls_failure_callback callback) noexcept;

/**
* @brief Destructor
*/
~session() noexcept;

void init(protocol_version version,
uint64_t groupId,
std::string const& selfUserId,
std::shared_ptr<::mlspp::SignaturePrivateKey>& transientKey) noexcept;
/**
* @brief Initalise session
* @note This is not done in the constructor, as we may need to do this again on upgrade or downgrade,
* whilst preserving other state set by the constructor.
*
* @param version protocol version
* @param groupId group id (channel id)
* @param selfUserId bot's user id
* @param transientKey transient private key
*/
void init(protocol_version version, uint64_t groupId, std::string const& selfUserId, std::shared_ptr<::mlspp::SignaturePrivateKey>& transientKey) noexcept;

/**
* @brief Reset the session to defaults
*/
void reset() noexcept;

/**
* @brief Set protocol version for session
* @param version protocol version
*/
void set_protocol_version(protocol_version version) noexcept;
[[nodiscard]] protocol_version get_protocol_version() const noexcept { return protocolVersion_; }

/**
* @brief Get protocol version for session
* @return protocol version
*/
[[nodiscard]] protocol_version get_protocol_version() const noexcept {
return protocolVersion_;
}

/**
* @brief Get last epoch authenticator, the discord privacy code for the vc
* @return privacy code
*/
[[nodiscard]] std::vector<uint8_t> get_last_epoch_authenticator() const noexcept;

/**
* @brief Set external sender from external sender opcode
* @param externalSenderPackage external sender package
*/
void set_external_sender(std::vector<uint8_t> const& externalSenderPackage) noexcept;

std::optional<std::vector<uint8_t>> process_proposals(
std::vector<uint8_t> proposals,
std::set<std::string> const& recognizedUserIDs) noexcept;

/**
* @brief Process proposals from proposals opcode
* @param proposals proposals blob from websocket
* @param recognizedUserIDs list of recognised user IDs
* @return optional vector to send in reply as commit welcome
*/
std::optional<std::vector<uint8_t>> process_proposals(std::vector<uint8_t> proposals, std::set<std::string> const& recognizedUserIDs) noexcept;

/**
* @brief Process commit message from discord websocket
* @param commit commit message from discord websocket
* @return roster list of people in the vc
*/
roster_variant process_commit(std::vector<uint8_t> commit) noexcept;

std::optional<roster_map> process_welcome(
std::vector<uint8_t> welcome,
std::set<std::string> const& recognizedUserIDs) noexcept;

/**
* @brief Process welcome blob
* @param welcome welcome blob from discord
* @param recognizedUserIDs Recognised user ID list
* @return roster list of people in the vc
*/
std::optional<roster_map> process_welcome(std::vector<uint8_t> welcome, std::set<std::string> const& recognizedUserIDs) noexcept;

/**
* @brief Get the bot user's key package for sending to websocket
* @return marshalled key package
*/
std::vector<uint8_t> get_marshalled_key_package() noexcept;

/**
* @brief Get key ratchet for a user (including the bot)
* @param userId User id to get ratchet for
* @return The user's key ratchet for use in an encryptor or decryptor
*/
[[nodiscard]] std::unique_ptr<key_ratchet_interface> get_key_ratchet(std::string const& userId) const noexcept;

/**
* @brief callback for completion of pairwise fingerprint
*/
using pairwise_fingerprint_callback = std::function<void(std::vector<uint8_t> const&)>;

void get_pairwise_fingerprint(uint16_t version,
std::string const& userId,
pairwise_fingerprint_callback callback) const noexcept;
/**
* @brief Get pairwise fingerprint (used to validate discord member in vc)
* @warning This uses SCRYPT and is extremely resource intensive. It will spawn a thread
* which will call your callback on completion.
* @param version Should always be 0x00
* @param userId User ID to get fingerprint for
* @param callback Callback for completion
*/
void get_pairwise_fingerprint(uint16_t version, std::string const& userId, pairwise_fingerprint_callback callback) const noexcept;

private:
void init_leaf_node(std::string const& selfUserId,
std::shared_ptr<::mlspp::SignaturePrivateKey>& transientKey) noexcept;
/**
* @brief Initialise leaf node
* @param selfUserId Bot user id
* @param transientKey Transient key
*/
void init_leaf_node(std::string const& selfUserId, std::shared_ptr<::mlspp::SignaturePrivateKey>& transientKey) noexcept;

/**
* @brief Reset join key
*/
void reset_join_key_package() noexcept;

/**
* @brief Create pending MLS group
*/
void create_pending_group() noexcept;

bool has_cryptographic_state_for_welcome() const noexcept;

bool is_recognized_user_id(const ::mlspp::Credential& cred,
std::set<std::string> const& recognizedUserIDs) const;
bool validate_proposal_message(::mlspp::AuthenticatedContent const& message,
::mlspp::State const& targetState,
std::set<std::string> const& recognizedUserIDs) const;
bool verify_welcome_state(::mlspp::State const& state,
std::set<std::string> const& recognizedUserIDs) const;

bool can_process_commit(const ::mlspp::MLSMessage& commit) noexcept;

/**
* @brief Is ready for welcome
* @return true if ready for welcome
*/
[[nodiscard]] bool has_cryptographic_state_for_welcome() const noexcept;

/**
* @brief Check if user ID is valid
* @param cred MLS credential
* @param recognizedUserIDs list of recognised user IDs
* @return
*/
[[nodiscard]] bool is_recognized_user_id(const ::mlspp::Credential& cred, std::set<std::string> const& recognizedUserIDs) const;

/**
* @brief Validate proposals message
* @param message authenticated content message
* @param targetState new state
* @param recognizedUserIDs recognised list of user IDs
* @return true if validated
*/
[[nodiscard]] bool validate_proposal_message(::mlspp::AuthenticatedContent const& message, ::mlspp::State const& targetState, std::set<std::string> const& recognizedUserIDs) const;

/**
* @brief Verify that welcome state is valid
* @param state current state
* @param recognizedUserIDs list of recognised user IDs
* @return
*/
[[nodiscard]] bool verify_welcome_state(::mlspp::State const& state, std::set<std::string> const& recognizedUserIDs) const;

/**
* @brief Check if can process a commit now
* @param commit Commit message
* @return true if can process
*/
[[nodiscard]] bool can_process_commit(const ::mlspp::MLSMessage& commit) noexcept;

/**
* @brief Replace state with a new one
* @param state new state
* @return new roster list of users in VC
*/
roster_map replace_state(std::unique_ptr<::mlspp::State>&& state);

/**
* @brief Clear pending MLS state
*/
void clear_pending_state();

/**
* @brief Constant media key label
*/
inline static const std::string USER_MEDIA_KEY_BASE_LABEL = "Discord Secure Frames v0";

protocol_version protocolVersion_;
Expand All @@ -145,7 +267,7 @@ class session {
roster_map roster_;

std::unique_ptr<::mlspp::State> stateWithProposals_;
std::list<QueuedProposal> proposalQueue_;
std::list<queued_proposal> proposalQueue_;

mls_failure_callback onMLSFailureCallback_{};
};
Expand Down
13 changes: 13 additions & 0 deletions src/dpp/dave/user_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,20 @@

namespace dpp::dave::mls {

/**
* @brief Create user credentials
* @param userId user id
* @param version protocol version
* @return
*/
::mlspp::Credential create_user_credential(const std::string& userId, protocol_version version);

/**
* @brief Convert user credentials to string
* @param cred user credentials
* @param version protocol version
* @return user credentials as string
*/
std::string user_credential_to_string(const ::mlspp::Credential& cred, protocol_version version);

} // namespace dpp::dave::mls
Expand Down
11 changes: 11 additions & 0 deletions src/dpp/dave/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,18 @@

namespace dpp::dave::mls {

/**
* @brief Convert uint64_t to bytes
* @param value 64 bit value
* @return bytes
*/
::mlspp::bytes_ns::bytes big_endian_bytes_from(uint64_t value) noexcept;

/**
* @brief Convert uint64_t to bytes
* @param value bytes
* @return 64 bit value
*/
uint64_t from_big_endian_bytes(const ::mlspp::bytes_ns::bytes& value) noexcept;

} // namespace dpp::dave::mls
Expand Down
11 changes: 11 additions & 0 deletions src/dpp/dave/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,20 @@

namespace dpp::dave {

/**
* @brief Protocol Version ID
*/
using protocol_version = uint16_t;

/**
* @brief Signature version ID
*/
using signature_version = uint8_t;

/**
* @brief Get maximum supported protocol version
* @return maximum protocol version
*/
protocol_version max_protocol_version();

} // namespace dpp::dave
Expand Down

0 comments on commit 260a389

Please sign in to comment.