1use std::collections::HashMap;
10use std::str::FromStr;
11
12use serde_derive::{Deserialize, Serialize};
13use strum_macros::{AsRefStr, Display, EnumString};
14use uuid::Uuid;
15
16use autopush_common::notification::Notification;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, AsRefStr, Display, EnumString)]
31#[strum(serialize_all = "snake_case")]
32pub enum MessageType {
33 Hello,
34 Register,
35 Unregister,
36 BroadcastSubscribe,
37 Ack,
38 Nack,
39 Ping,
40 Notification,
41 Broadcast,
42}
43
44impl MessageType {
45 pub fn expected_msg(&self) -> String {
47 format!(r#"Expected messageType="{}""#, self.as_ref())
48 }
49}
50
51#[derive(Debug, Eq, PartialEq, Serialize)]
52#[serde(untagged)]
53pub enum BroadcastValue {
54 Value(String),
55 Nested(HashMap<String, BroadcastValue>),
56}
57
58#[derive(Debug, Default)]
59pub enum ServerNotification {
61 CheckStorage,
62 Notification(Notification),
63 #[default]
64 Disconnect,
65}
66
67#[derive(Debug, Deserialize)]
68#[serde(tag = "messageType", rename_all = "snake_case")]
69pub enum ClientMessage {
70 Hello {
71 uaid: Option<String>,
72 #[serde(rename = "channelIDs", skip_serializing_if = "Option::is_none")]
73 _channel_ids: Option<Vec<Uuid>>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 broadcasts: Option<HashMap<String, String>>,
76 },
77
78 Register {
79 #[serde(rename = "channelID")]
80 channel_id: String,
81 key: Option<String>,
82 },
83
84 Unregister {
85 #[serde(rename = "channelID")]
86 channel_id: Uuid,
87 code: Option<u32>,
88 },
89
90 BroadcastSubscribe {
91 broadcasts: HashMap<String, String>,
92 },
93
94 Ack {
95 updates: Vec<ClientAck>,
96 },
97
98 Nack {
99 code: Option<i32>,
100 version: String,
101 },
102
103 Ping,
104}
105
106impl ClientMessage {
107 pub fn message_type(&self) -> MessageType {
109 match self {
110 ClientMessage::Hello { .. } => MessageType::Hello,
111 ClientMessage::Register { .. } => MessageType::Register,
112 ClientMessage::Unregister { .. } => MessageType::Unregister,
113 ClientMessage::BroadcastSubscribe { .. } => MessageType::BroadcastSubscribe,
114 ClientMessage::Ack { .. } => MessageType::Ack,
115 ClientMessage::Nack { .. } => MessageType::Nack,
116 ClientMessage::Ping => MessageType::Ping,
117 }
118 }
119}
120
121impl FromStr for ClientMessage {
122 type Err = serde_json::error::Error;
123
124 fn from_str(s: &str) -> Result<Self, Self::Err> {
125 serde_json::from_str::<HashMap<(), ()>>(s)
127 .map(|_| ClientMessage::Ping)
128 .or_else(|_| serde_json::from_str(s))
129 }
130}
131
132#[derive(Debug, Deserialize)]
136pub struct ClientAck {
137 #[serde(rename = "channelID")]
139 pub channel_id: Uuid,
140 pub version: String,
142 pub code: Option<u16>,
144}
145
146impl ClientAck {
147 #[cfg(feature = "reliable_report")]
148 pub fn reliability_state(&self) -> autopush_common::reliability::ReliabilityState {
149 match self.code.unwrap_or(100) {
150 101 => autopush_common::reliability::ReliabilityState::DecryptionError,
151 102 => autopush_common::reliability::ReliabilityState::NotDelivered,
152 _ => autopush_common::reliability::ReliabilityState::Delivered,
154 }
155 }
156}
157
158#[derive(Debug, Serialize)]
159#[serde(tag = "messageType", rename_all = "snake_case")]
160pub enum ServerMessage {
161 Hello {
162 uaid: String,
163 status: u32,
164 use_webpush: bool,
166 broadcasts: HashMap<String, BroadcastValue>,
167 },
168
169 Register {
170 #[serde(rename = "channelID")]
171 channel_id: Uuid,
172 status: u32,
173 #[serde(rename = "pushEndpoint")]
174 push_endpoint: String,
175 },
176
177 Unregister {
178 #[serde(rename = "channelID")]
179 channel_id: Uuid,
180 status: u32,
181 },
182
183 Broadcast {
184 broadcasts: HashMap<String, BroadcastValue>,
185 },
186
187 Notification(Notification),
188
189 Ping,
190}
191
192impl ServerMessage {
193 pub fn message_type(&self) -> MessageType {
195 match self {
196 ServerMessage::Hello { .. } => MessageType::Hello,
197 ServerMessage::Register { .. } => MessageType::Register,
198 ServerMessage::Unregister { .. } => MessageType::Unregister,
199 ServerMessage::Broadcast { .. } => MessageType::Broadcast,
200 ServerMessage::Notification(..) => MessageType::Notification,
201 ServerMessage::Ping => MessageType::Ping,
202 }
203 }
204
205 pub fn to_json(&self) -> Result<String, serde_json::error::Error> {
206 match self {
207 ServerMessage::Ping => Ok("{}".to_string()),
210 _ => serde_json::to_string(self),
211 }
212 }
213}