two-way file system sync
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

mod.rs 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. //! Module which implements a low-level packet protocol over websockets.
  2. //!
  3. //! The low-level protocol needs to implement two basic pieces of functionality: It needs to be
  4. //! able to implement remote procedure calls from the client to the server, and it needs to
  5. //! provide a method for the server to send asynchronous events. A protocol for both cases is
  6. //! outlined below, where each packet is sent as one WebSocket message.
  7. //!
  8. //! Remote procedure call:
  9. //! - The client allocates an ID from the range between 0..2^31-1 that is not currently in use
  10. //! for another RPC in progress.
  11. //! - The client prepares a packet with this ID and the appropriate payload and sends the packet to
  12. //! the server.
  13. //! - The server receives the packet, processes the request and sends a packet back with the
  14. //! identical ID.
  15. //! - In case of an error, the payload has the type "Error" which in turn contains the error
  16. //! type.
  17. //! - Unpon reception of the response, the client is free to reuse the ID for further RPCs.
  18. //! Note that this protocol does not allow the client to cancel an RPC that is currently in
  19. //! progress - implementing such functionality is difficult, error-prone, and most likely not
  20. //! worth the effort.
  21. //!
  22. //! Server-side event:
  23. //! - The server creates a packet with the ID 2^31 and the event content and sends it to the
  24. //! client.
  25. //! Note that the client does not have any method to acknowledge event reception. As events are
  26. //! asynchronous compared to RPCs on the same connection, the event type needs to be designed in
  27. //! a way that no such temporal information is necessary to process the events.
  28. //! TODO: Example to demonstrate the problem.
  29. pub mod client;
  30. pub mod idalloc;
  31. pub mod server;
  32. pub mod websocket;
  33. use serde::{Deserialize, Serialize};
  34. pub const SERVER_EVENT_ID: u32 = u32::max_value();
  35. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
  36. pub struct Packet<Payload> {
  37. pub id: u32,
  38. pub payload: Payload,
  39. }
  40. #[cfg(test)]
  41. pub mod test_utils {
  42. use futures::prelude::*;
  43. use futures::sink::Sink;
  44. use futures::stream::Stream;
  45. use futures::task::Context;
  46. use futures::task::Poll;
  47. use std::pin::Pin;
  48. use std::time::Duration;
  49. use tokio::sync::mpsc;
  50. pub struct Pipe {
  51. sender: Pin<Box<mpsc::UnboundedSender<Result<Vec<u8>, PipeError>>>>,
  52. receiver: Pin<Box<mpsc::UnboundedReceiver<Result<Vec<u8>, PipeError>>>>,
  53. }
  54. impl Pipe {
  55. pub fn new() -> (Self, Self) {
  56. let (send1, recv1) = mpsc::unbounded_channel();
  57. let (send2, recv2) = mpsc::unbounded_channel();
  58. (
  59. Self {
  60. sender: Box::pin(send1),
  61. receiver: Box::pin(recv2),
  62. },
  63. Self {
  64. sender: Box::pin(send2),
  65. receiver: Box::pin(recv1),
  66. },
  67. )
  68. }
  69. pub fn inject_error(&mut self) {
  70. self.sender.send(Err(PipeError::Injected)).unwrap();
  71. }
  72. }
  73. impl Sink<Vec<u8>> for Pipe {
  74. type Error = PipeError;
  75. fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Result<(), Self::Error>> {
  76. Poll::Ready(Ok(()))
  77. }
  78. fn start_send(self: Pin<&mut Self>, item: Vec<u8>) -> Result<(), Self::Error> {
  79. self.sender.send(Ok(item)).map_err(|_| PipeError::Closed)
  80. }
  81. fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Result<(), Self::Error>> {
  82. Poll::Ready(Ok(()))
  83. }
  84. fn poll_close(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Result<(), Self::Error>> {
  85. Poll::Ready(Ok(()))
  86. }
  87. }
  88. impl Stream for Pipe {
  89. type Item = Result<Vec<u8>, PipeError>;
  90. fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
  91. // Safe, as we will not move self_.
  92. let self_ = unsafe { self.get_unchecked_mut() };
  93. Pin::as_mut(&mut self_.receiver).poll_next(cx)
  94. }
  95. }
  96. #[derive(Debug, PartialEq)]
  97. pub enum PipeError {
  98. Closed,
  99. Injected,
  100. }
  101. pub async fn panic_after<T>(d: Duration, task: T) -> T::Output
  102. where
  103. T: Future + Send + 'static,
  104. T::Output: Send + 'static,
  105. {
  106. let task = tokio::spawn(task);
  107. match tokio::time::timeout(d, task).await {
  108. Err(_) => panic!("function timed out ({:?})", d),
  109. Ok(x) => x.unwrap(),
  110. }
  111. }
  112. }