1use hashbrown::HashMap;
50
51#[cfg(not(feature = "std"))]
52use alloc::{string::{String, ToString}, format};
53
54use serde::{Deserialize, Serialize, de::Error};
55use serde_json::Value;
56
57use crate::io::{TcpStreamImpl, TlsStreamImpl};
58
59pub mod battery;
60pub mod clipboard;
61pub mod connectivity_report;
62pub mod contacts;
63pub mod digitizer;
64pub mod identity;
65pub mod lock;
66pub mod mousepad;
67pub mod mpris;
68pub mod notification;
69pub mod pair;
70pub mod ping;
71pub mod presenter;
72pub mod runcommand;
73pub mod sftp;
74pub mod share;
75pub mod sms;
76pub mod system_volume;
77pub mod telephony;
78
79pub(super) fn deserialize_number_or_string<'de, D: serde::Deserializer<'de>>(
85 de: D,
86) -> Result<u64, D::Error> {
87 match Value::deserialize(de)? {
88 Value::Number(n) => n
89 .as_u64()
90 .ok_or_else(|| Error::custom("JSON number cannot be converted to u64")),
91 Value::String(s) => s
92 .parse::<u64>()
93 .map_err(|e| Error::custom(format!("String cannot be parsed as u64: {e}"))),
94 _ => Err(Error::custom("unknown type, expected number or string")),
95 }
96}
97
98pub(super) fn deserialize_number_or_string_in_option<'de, D: serde::Deserializer<'de>>(
104 de: D,
105) -> Result<Option<u64>, D::Error> {
106 match Value::deserialize(de)? {
107 Value::Number(n) => {
108 Ok(Some(n.as_u64().ok_or_else(|| {
109 Error::custom("JSON number cannot be converted to u64")
110 })?))
111 }
112 Value::String(s) => {
113 Ok(Some(s.parse::<u64>().map_err(|e| {
114 Error::custom(format!("String cannot be parsed as u64: {e}"))
115 })?))
116 }
117 _ => Err(Error::custom("unknown type, expected number or string")),
118 }
119}
120
121#[derive(Serialize, Deserialize, Debug, Clone)]
123#[serde(tag = "type", content = "body")]
124pub enum NetworkPacketBody {
125 #[serde(rename = "kdeconnect.identity")]
127 Identity(identity::IdentityPacket),
128
129 #[serde(rename = "kdeconnect.pair")]
131 Pair(pair::PairPacket),
132
133 #[serde(rename = "kdeconnect.battery")]
135 Battery(battery::BatteryPacket),
136
137 #[serde(rename = "kdeconnect.clipboard")]
139 Clipboard(clipboard::ClipboardPacket),
140
141 #[serde(rename = "kdeconnect.clipboard.connect")]
143 ClipboardConnect(clipboard::ClipboardConnectPacket),
144
145 #[serde(rename = "kdeconnect.connectivity_report")]
147 ConnectivityReport(connectivity_report::ConnectivityReportPacket),
148
149 #[serde(rename = "kdeconnect.contacts.request_all_uids_timestamps")]
151 ContactsRequestAllUidsTimestamps(()),
152
153 #[serde(rename = "kdeconnect.contacts.request_vcards_by_uid")]
155 ContactsRequestVcardByUid(contacts::ContactsRequestVcardsByUid),
156
157 #[serde(rename = "kdeconnect.contacts.response_uids_timestamps")]
159 ContactsResponseUidsTimestamps(contacts::ContactsResponseUidsTimestamp),
160
161 #[serde(rename = "kdeconnect.contacts.response_vcards")]
163 ContactsResponseVcards(contacts::ContactsResponseVcards),
164
165 #[serde(rename = "kdeconnect.digitizer.session")]
174 DigitizerSession(digitizer::DigitizerSessionPacket),
175
176 #[serde(rename = "kdeconnect.digitizer")]
181 Digitizer(digitizer::DigitizerPacket),
182
183 #[serde(rename = "kdeconnect.findmyphone.request")]
186 FindmyphoneRequest(()),
187
188 #[serde(rename = "kdeconnect.lock")]
190 Lock(lock::LockPacket),
191
192 #[serde(rename = "kdeconnect.lock.request")]
194 LockRequest(lock::LockRequestPacket),
195
196 #[serde(rename = "kdeconnect.mousepad.echo")]
198 MousepadEcho(mousepad::MousepadEchoPacket),
199
200 #[serde(rename = "kdeconnect.mousepad.keyboardstate")]
202 MousepadKeyboardState(mousepad::MousepadKeyboardStatePacket),
203
204 #[serde(rename = "kdeconnect.mousepad.request")]
206 MousepadRequest(mousepad::MousepadRequestPacket),
207
208 #[serde(rename = "kdeconnect.mpris")]
213 Mpris(mpris::MprisPacket),
214
215 #[serde(rename = "kdeconnect.mpris.request")]
218 MprisRequest(mpris::MprisRequestPacket),
219
220 #[serde(rename = "kdeconnect.notification")]
222 Notification(notification::NotificationPacket),
223
224 #[serde(rename = "kdeconnect.notification.action")]
226 NotificationAction(notification::NotificationActionPacket),
227
228 #[serde(rename = "kdeconnect.notification.reply")]
230 NotificationReply(notification::NotificationReplyPacket),
231
232 #[serde(rename = "kdeconnect.notification.request")]
234 NotificationRequest(notification::NotificationRequestPacket),
235
236 #[serde(rename = "kdeconnect.ping")]
238 Ping(ping::PingPacket),
239
240 #[serde(rename = "kdeconnect.presenter")]
242 Presenter(presenter::PresenterPacket),
243
244 #[serde(rename = "kdeconnect.runcommand")]
246 RunCommand(runcommand::RunCommandPacket),
247
248 #[serde(rename = "kdeconnect.runcommand.request")]
250 RunCommandRequest(runcommand::RunCommandRequestPacket),
251
252 #[serde(rename = "kdeconnect.sftp")]
254 Sftp(sftp::SftpPacket),
255
256 #[serde(rename = "kdeconnect.sftp.request")]
258 SftpRequest(sftp::SftpRequestPacket),
259
260 #[serde(rename = "kdeconnect.share.request")]
262 ShareRequest(share::ShareRequestPacket),
263
264 #[serde(rename = "kdeconnect.share.request.update")]
268 ShareRequestUpdate(share::ShareRequestUpdatePacket),
269
270 #[serde(rename = "kdeconnect.sms.attachment_file")]
272 SmsAttachmentFile(sms::SmsAttachmentFilePacket),
273
274 #[serde(rename = "kdeconnect.sms.messages")]
276 SmsMessages(sms::SmsMessagesPacket),
277
278 #[serde(rename = "kdeconnect.sms.request")]
280 SmsRequest(sms::SmsRequestPacket),
281
282 #[serde(rename = "kdeconnect.sms.request_attachment")]
284 SmsRequestAttachment(sms::SmsRequestAttachmentPacket),
285
286 #[serde(rename = "kdeconnect.sms.request_conversation")]
288 SmsRequestConversation(sms::SmsRequestConversationPacket),
289
290 #[serde(rename = "kdeconnect.sms.request_conversations")]
292 SmsRequestConversations(()),
293
294 #[serde(rename = "kdeconnect.systemvolume")]
296 SystemVolume(system_volume::SystemVolumePacket),
297
298 #[serde(rename = "kdeconnect.systemvolume.request")]
301 SystemVolumeRequest(system_volume::SystemVolumeRequestPacket),
302
303 #[serde(rename = "kdeconnect.telephony")]
305 Telephony(telephony::TelephonyPacket),
306
307 #[serde(rename = "kdeconnect.telephony.request_mute")]
309 TelephonyRequestMute(()),
310
311 #[serde(untagged)]
313 Other(Value),
314}
315
316impl NetworkPacketBody {
317 pub fn get_type(&self) -> NetworkPacketType {
319 match self {
320 NetworkPacketBody::Identity(_) => NetworkPacketType::Identity,
321 NetworkPacketBody::Pair(_) => NetworkPacketType::Pair,
322 NetworkPacketBody::Ping(_) => NetworkPacketType::Ping,
323 NetworkPacketBody::Battery(_) => NetworkPacketType::Battery,
324 NetworkPacketBody::Clipboard(_) => NetworkPacketType::Clipboard,
325 NetworkPacketBody::ClipboardConnect(_) => NetworkPacketType::ClipboardConnect,
326 NetworkPacketBody::ConnectivityReport(_) => NetworkPacketType::ConnectivityReport,
327 NetworkPacketBody::ContactsRequestAllUidsTimestamps(()) => {
328 NetworkPacketType::ContactsRequestAllUidsTimestamps
329 }
330 NetworkPacketBody::ContactsRequestVcardByUid(_) => {
331 NetworkPacketType::ContactsRequestVcardByUid
332 }
333 NetworkPacketBody::ContactsResponseUidsTimestamps(_) => {
334 NetworkPacketType::ContactsResponseUidsTimestamps
335 }
336 NetworkPacketBody::ContactsResponseVcards(_) => {
337 NetworkPacketType::ContactsResponseVcards
338 }
339 NetworkPacketBody::DigitizerSession(_) => NetworkPacketType::DigitizerSession,
340 NetworkPacketBody::Digitizer(_) => NetworkPacketType::Digitizer,
341 NetworkPacketBody::FindmyphoneRequest(()) => NetworkPacketType::FindmyphoneRequest,
342 NetworkPacketBody::Lock(_) => NetworkPacketType::Lock,
343 NetworkPacketBody::LockRequest(_) => NetworkPacketType::LockRequest,
344 NetworkPacketBody::MousepadEcho(_) => NetworkPacketType::MousepadEcho,
345 NetworkPacketBody::MousepadKeyboardState(_) => NetworkPacketType::MousepadKeyboardState,
346 NetworkPacketBody::MousepadRequest(_) => NetworkPacketType::MousepadRequest,
347 NetworkPacketBody::Mpris(_) => NetworkPacketType::Mpris,
348 NetworkPacketBody::MprisRequest(_) => NetworkPacketType::MprisRequest,
349 NetworkPacketBody::Notification(_) => NetworkPacketType::Notification,
350 NetworkPacketBody::NotificationAction(_) => NetworkPacketType::NotificationAction,
351 NetworkPacketBody::NotificationReply(_) => NetworkPacketType::NotificationReply,
352 NetworkPacketBody::NotificationRequest(_) => NetworkPacketType::NotificationRequest,
353 NetworkPacketBody::Presenter(_) => NetworkPacketType::Presenter,
354 NetworkPacketBody::RunCommand(_) => NetworkPacketType::RunCommand,
355 NetworkPacketBody::RunCommandRequest(_) => NetworkPacketType::RunCommandRequest,
356 NetworkPacketBody::Sftp(_) => NetworkPacketType::Sftp,
357 NetworkPacketBody::SftpRequest(_) => NetworkPacketType::SftpRequest,
358 NetworkPacketBody::ShareRequest(_) => NetworkPacketType::ShareRequest,
359 NetworkPacketBody::ShareRequestUpdate(_) => NetworkPacketType::ShareRequestUpdate,
360 NetworkPacketBody::SmsAttachmentFile(_) => NetworkPacketType::SmsAttachmentFile,
361 NetworkPacketBody::SmsMessages(_) => NetworkPacketType::SmsMessages,
362 NetworkPacketBody::SmsRequest(_) => NetworkPacketType::SmsRequest,
363 NetworkPacketBody::SmsRequestAttachment(_) => NetworkPacketType::SmsRequestAttachment,
364 NetworkPacketBody::SmsRequestConversation(_) => {
365 NetworkPacketType::SmsRequestConversation
366 }
367 NetworkPacketBody::SmsRequestConversations(()) => {
368 NetworkPacketType::SmsRequestConversations
369 }
370 NetworkPacketBody::SystemVolume(_) => NetworkPacketType::SystemVolume,
371 NetworkPacketBody::SystemVolumeRequest(_) => NetworkPacketType::SystemVolumeRequest,
372 NetworkPacketBody::Telephony(_) => NetworkPacketType::Telephony,
373 NetworkPacketBody::TelephonyRequestMute(()) => NetworkPacketType::TelephonyRequestMute,
374 NetworkPacketBody::Other(value) => NetworkPacketType::Other(
375 value
376 .get("type")
377 .unwrap_or(&Value::String("Unknown".into()))
378 .as_str()
379 .unwrap_or("Unknown")
380 .to_string(),
381 ),
382 }
383 }
384}
385
386#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
392pub enum NetworkPacketType {
393 #[serde(rename = "kdeconnect.identity")]
395 Identity,
396
397 #[serde(rename = "kdeconnect.pair")]
399 Pair,
400
401 #[serde(rename = "kdeconnect.battery")]
403 Battery,
404
405 #[serde(rename = "kdeconnect.clipboard")]
407 Clipboard,
408
409 #[serde(rename = "kdeconnect.clipboard.connect")]
411 ClipboardConnect,
412
413 #[serde(rename = "kdeconnect.connectivity_report")]
415 ConnectivityReport,
416
417 #[serde(rename = "kdeconnect.contacts.request_all_uids_timestamps")]
419 ContactsRequestAllUidsTimestamps,
420
421 #[serde(rename = "kdeconnect.contacts.request_vcards_by_uid")]
423 ContactsRequestVcardByUid,
424
425 #[serde(rename = "kdeconnect.contacts.response_uids_timestamps")]
427 ContactsResponseUidsTimestamps,
428
429 #[serde(rename = "kdeconnect.contacts.response_vcards")]
431 ContactsResponseVcards,
432
433 #[serde(rename = "kdeconnect.digitizer.session")]
442 DigitizerSession,
443
444 #[serde(rename = "kdeconnect.digitizer")]
449 Digitizer,
450
451 #[serde(rename = "kdeconnect.findmyphone.request")]
454 FindmyphoneRequest,
455
456 #[serde(rename = "kdeconnect.lock")]
458 Lock,
459
460 #[serde(rename = "kdeconnect.lock.request")]
462 LockRequest,
463
464 #[serde(rename = "kdeconnect.mousepad.echo")]
466 MousepadEcho,
467
468 #[serde(rename = "kdeconnect.mousepad.keyboardstate")]
470 MousepadKeyboardState,
471
472 #[serde(rename = "kdeconnect.mousepad.request")]
474 MousepadRequest,
475
476 #[serde(rename = "kdeconnect.mpris")]
481 Mpris,
482
483 #[serde(rename = "kdeconnect.mpris.request")]
486 MprisRequest,
487
488 #[serde(rename = "kdeconnect.notification")]
490 Notification,
491
492 #[serde(rename = "kdeconnect.notification.action")]
494 NotificationAction,
495
496 #[serde(rename = "kdeconnect.notification.reply")]
498 NotificationReply,
499
500 #[serde(rename = "kdeconnect.notification.request")]
502 NotificationRequest,
503
504 #[serde(rename = "kdeconnect.ping")]
506 Ping,
507
508 #[serde(rename = "kdeconnect.presenter")]
510 Presenter,
511
512 #[serde(rename = "kdeconnect.runcommand")]
514 RunCommand,
515
516 #[serde(rename = "kdeconnect.runcommand.request")]
518 RunCommandRequest,
519
520 #[serde(rename = "kdeconnect.sftp")]
522 Sftp,
523
524 #[serde(rename = "kdeconnect.sftp.request")]
526 SftpRequest,
527
528 #[serde(rename = "kdeconnect.share.request")]
530 ShareRequest,
531
532 #[serde(rename = "kdeconnect.share.request.update")]
536 ShareRequestUpdate,
537
538 #[serde(rename = "kdeconnect.sms.attachment_file")]
540 SmsAttachmentFile,
541
542 #[serde(rename = "kdeconnect.sms.messages")]
544 SmsMessages,
545
546 #[serde(rename = "kdeconnect.sms.request")]
548 SmsRequest,
549
550 #[serde(rename = "kdeconnect.sms.request_attachment")]
552 SmsRequestAttachment,
553
554 #[serde(rename = "kdeconnect.sms.request_conversation")]
556 SmsRequestConversation,
557
558 #[serde(rename = "kdeconnect.sms.request_conversations")]
560 SmsRequestConversations,
561
562 #[serde(rename = "kdeconnect.systemvolume")]
564 SystemVolume,
565
566 #[serde(rename = "kdeconnect.systemvolume.request")]
569 SystemVolumeRequest,
570
571 #[serde(rename = "kdeconnect.telephony")]
573 Telephony,
574
575 #[serde(rename = "kdeconnect.telephony.request_mute")]
577 TelephonyRequestMute,
578
579 #[serde(untagged)]
581 Other(String),
582}
583
584#[derive(Serialize, Deserialize, Debug, Clone)]
588pub struct NetworkPacket {
589 #[serde(deserialize_with = "deserialize_number_or_string")]
590 id: u64,
591
592 #[serde(flatten)]
594 pub body: NetworkPacketBody,
595
596 #[serde(skip_serializing_if = "Option::is_none")]
598 #[serde(default)]
599 pub range: Option<i64>,
600
601 #[serde(skip_serializing_if = "Option::is_none")]
603 #[serde(default)]
604 pub payload_transfer_info: Option<HashMap<String, Value>>,
605}
606
607impl NetworkPacket {
608 pub fn new(body: NetworkPacketBody) -> Self {
612 Self {
613 id: 0,
615 body,
616 range: None,
617 payload_transfer_info: None,
618 }
619 }
620
621 pub(crate) fn try_read_from(buf: &[u8]) -> Result<Self, serde_json::Error> {
622 serde_json::from_slice::<NetworkPacket>(buf)
623 }
624
625 pub(crate) async fn write_to_socket_unencrypted<T: TcpStreamImpl + Unpin>(self, socket: &mut T) {
626 let mut serialized_packet = serde_json::to_string(&self).unwrap();
627 serialized_packet.push('\n');
628
629 socket
630 .write_all(serialized_packet.as_bytes())
631 .await
632 .unwrap();
633 }
634
635 pub(crate) async fn write_to_socket<T: TlsStreamImpl + Unpin>(self, socket: &mut T) {
636 let mut serialized_packet = serde_json::to_string(&self).unwrap();
637 serialized_packet.push('\n');
638
639 socket
640 .write_all(serialized_packet.as_bytes())
641 .await
642 .unwrap();
643 }
644}