Skip to main content

common/networking/
messages.rs

1use std::fmt;
2use std::fmt::Formatter;
3use serde::{Deserialize, Serialize};
4use crate::logging::LogLevel;
5use crate::cli_actions::{CliAction, CliActionResponse};
6use crate::networking::subscription_objects::{SubscribeTopic, UpdateMode, TopicPayload};
7
8/// Unique identifier for an active client session.
9pub type SessionID = u64;
10
11/// Initial payload sent by a client upon connecting to verify compatibility.
12#[derive(Serialize, Deserialize, Debug)]
13pub struct HandshakeRequest {
14    /// Must always be exactly "REKTAL" to identify the protocol.
15    pub magic_string: String,
16    /// A hash verifying the client and server share the exact same network message definitions.
17    pub protocol_hash: String,
18    /// The human-readable version string of the client software.
19    pub client_version: String,
20}
21
22/// The kernel's response to a client's handshake request.
23#[derive(Serialize, Deserialize, Debug)]
24pub enum HandshakeResponse {
25    /// Handshake successful; protocol and versions match.
26    Ok,
27    /// Handshake failed due to a protocol hash mismatch.
28    Mismatch { server_version: String },
29}
30
31/// Represents all valid messages dispatched from a client to the kernel over an active TCP connection.
32#[derive(Serialize, Deserialize, Debug)]
33pub enum TcpClientMessage {
34    /// Request to authenticate a new session.
35    Login {
36        password: String,
37        user_name: String,
38        user_role: UserRole,
39    },
40
41    /// Request to safely terminate the current session.
42    Logout,
43
44    /// Request to resume a previous session using an existing token.
45    Relogin {
46        user_id: SessionID,
47        clear_subscriptions: bool,
48    },
49
50    /// Request to listen for state changes on a specific topic.
51    Subscribe {
52        topic: SubscribeTopic,
53        update_mode: UpdateMode
54    },
55
56    /// Request to stop receiving updates for a specific topic.
57    Unsubscribe {
58        topic: SubscribeTopic,
59    },
60
61    /// Submits a raw CLI string for the server to parse and execute.
62    ExecuteCommand {
63        command: String,
64        response_id: u32
65    },
66
67    /// Submits a pre-parsed, structured CLI action directly.
68    ExecuteImplicitCommand {
69        command: CliAction,
70        response_id: u32
71    },
72
73    /// Requests exclusive editing rights for a specific engine resource.
74    RequestEdit(EditableResource),
75
76    /// Submits modifications for an exclusively locked resource.
77    SubmitEdit {
78        resource: EditableResource,
79        new_data: Vec<u8>
80    },
81
82    /// Drops the Lock on an exclusively locked resource, giving other Clients the chance to lock it.
83    DropEditLock(EditableResource),
84}
85
86/// Represents all valid messages dispatched from the kernel back to a connected client.
87#[derive(Serialize, Deserialize, Debug, Clone)]
88pub enum TcpServerMessage {
89    /// Emitted when a client attempts an action before authenticating.
90    Unauthenticated,
91
92    /// Indicates a successful login, providing the session token (for reconnecting later).
93    LoginOk {token: SessionID},
94    /// Indicates a failed login attempt with the given reason.
95    LoginFailed {reason: String},
96
97    /// Indicates a successful session resumption.
98    ReloginOk {token: SessionID},
99    /// Indicates a failed session resumption.
100    ReloginFailed {reason: String},
101
102    /// Confirms the session has been terminated.
103    LogoutOk,
104
105    /// Informs the client that the server forcibly closed the connection.
106    Kicked {reason: String},
107
108    /// Contains the text and log level output of a standard string command execution.
109    CommandOutput {
110        answer: (LogLevel, String),
111        response_id: u32
112    },
113    /// Contains the structured response of an implicit (pre-parsed) command execution.
114    ImplicitCommandOutput {
115        answer: CliActionResponse,
116        response_id: u32
117    },
118
119    /// Broadcasts new state data for a subscribed topic.
120    TopicUpdate {
121        data: TopicPayload,
122    },
123
124    /// Grants the client exclusive edit access to a resource, providing its current state.
125    EditGranted {
126        resource: EditableResource,
127        current_data: Vec<u8>
128    },
129    /// Denies an edit request because the resource is already locked or unavailable.
130    EditDenied {
131        resource: EditableResource,
132        reason: String
133    },
134    /// Acknowledges, that the Resource-Lock has been dropped, and can be picked up by other clients
135    DropEditAck(EditableResource),
136
137    /// Notifies all clients that the server is gracefully shutting down.
138    ShutdownAnnouncement,
139}
140
141
142
143//Dummy Enum until I implement it right
144/// Identifies a specific engine resource that can be locked for exclusive editing. Has currently no functionality, will
145/// be implemented later.
146#[derive(Serialize, Deserialize, Debug, Clone)]
147pub enum EditableResource {
148    Cuelist,
149}
150
151//This is only Temporarily here, will be moved to a different location once this location is programmed
152//Also, Interface may not belong here, that's why ist commented out, since it should be handled differently than the GUIs
153/// Defines the permission level and operational scope of a connected user.
154#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq)]
155pub enum UserRole {
156    /// Full access to edit the show and trigger outputs.
157    Programmer,
158    /// Access to edit the show without affecting live outputs (blind programming).
159    BlindProgrammer,
160    /// Access to trigger playbacks and run the show, but restricted from editing structural data.
161    Showrunner,
162//    Interface
163}
164
165impl fmt::Display for UserRole {
166    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
167        let text = match self {
168            UserRole::Programmer => "programmer",
169            UserRole::BlindProgrammer => "blind programmer",
170            UserRole::Showrunner => "showrunner",
171        };
172
173        write!(f, "{text}")
174    }
175}
176
177/// Retrieves the compile-time protocol hash to verify network message compatibility.
178pub fn get_protocol_version() -> String {
179    env!("PROTOCOL_HASH").to_string()
180}