浏览代码

Some more RPC client code.

父节点
当前提交
01ef3641aa
共有 2 个文件被更改,包括 175 次插入52 次删除
  1. 167
    52
      src/network/client.rs
  2. 8
    0
      src/network/websocket.rs

+ 167
- 52
src/network/client.rs 查看文件

1
-use futures::Future;
2
-//use futures::task::{Context, Poll};
3
-//use core::pin::Pin;
1
+use std::time::Duration;
2
+
3
+use async_tungstenite::{tokio::connect_async, tungstenite::Message, WebSocketStream};
4
+use core::pin::Pin;
5
+use futures::future::{self, Either, Future};
6
+use futures::task::{Context, Poll};
4
 use tokio::stream::Stream;
7
 use tokio::stream::Stream;
5
-//use async_tungstenite::{tokio::connect_async, tungstenite::Message, WebSocketStream};
6
-//use url::Url;
8
+use tokio::stream::StreamExt;
9
+use tokio::sync::{mpsc, oneshot};
10
+use tokio::time::{delay_for, Delay};
11
+use url::Url;
7
 
12
 
8
 use super::packet::IncomingPacket;
13
 use super::packet::IncomingPacket;
9
 
14
 
10
-use std::time::Duration;
11
-
12
-pub trait RPCInterface {
13
-    type PacketType;
14
-    type NetworkError;
15
-    type Call: RPC<Output = Result<IncomingPacket<Self::PacketType>, Self::NetworkError>>;
16
-
17
-    fn call(call: &Self::PacketType) -> Self::Call;
15
+pub fn create<StreamType, ErrorType, PacketType>(
16
+    stream: StreamType,
17
+) -> (
18
+    RPCInterface<StreamType, PacketType>,
19
+    ServerEventStream<PacketType>,
20
+)
21
+where
22
+    StreamType: Stream<Item = Result<Vec<u8>, ErrorType>> + Unpin + Send + 'static,
23
+{
24
+    let (cmd_send, cmd_receive) = mpsc::channel(1);
25
+    tokio::spawn(async move {
26
+        // TODO: Remove type annotations.
27
+        client_connection_task::<StreamType, ErrorType, PacketType>(stream, cmd_receive).await;
28
+    });
29
+    // TODO
30
+    panic!("Not yet implemented.");
18
 }
31
 }
19
 
32
 
20
-pub trait RPC: Future {
21
-    fn with_timeout(self, timeout: Duration) -> Self;
33
+enum ClientTaskCommand {
34
+    Close,
35
+    SendPackets,
22
 }
36
 }
23
 
37
 
24
-pub trait ServerEventStream<PacketType>: Stream<Item = PacketType> {}
25
-
26
-/*pub struct WSRPCInterface<PacketType, Stream> {
38
+struct OutgoingCallMap {
27
     // TODO
39
     // TODO
28
-    _unused: PacketType,
29
-    stream: WebSocketStream<Stream>,
30
 }
40
 }
31
 
41
 
32
-impl<P, S> WSRPCInterface<P, S> {
33
-    fn create<P2, S2>(_ws_stream: WebSocketStream<S2>) -> (Self, WSServerEventStream<P2>) {
42
+async fn client_connection_task<StreamType, ErrorType, PacketType>(
43
+    mut stream: StreamType,
44
+    mut cmd_receive: mpsc::Receiver<ClientTaskCommand>,
45
+) where
46
+    StreamType: Stream<Item = Result<Vec<u8>, ErrorType>> + Unpin,
47
+{
48
+    let mut connection_closed = false;
49
+    loop {
50
+        match future::select(Box::pin(stream.next()), Box::pin(cmd_receive.recv())).await {
51
+            Either::Left((packet, _cmd_future)) => {
52
+                match packet {
53
+                    Some(data) => {
54
+                        // TODO
55
+                    }
56
+                    None => {
57
+                        // Stream closed. We still need to return errors for any
58
+                        // packet sent by the client, so do not exit the loop
59
+                        // immediately but rather return an error for any
60
+                        // incoming packet.
61
+                        connection_closed = true;
62
+                        break;
63
+                    }
64
+                }
65
+            }
66
+            Either::Right((cmd, _stream_future)) => {
67
+                match cmd {
68
+                    Some(ClientTaskCommand::Close) => {
69
+                        // The RPC interface for this connection was dropped, so
70
+                        // we just exit the loop and close the connection.
71
+
72
+                        // We need to return errors for all pending packets
73
+                        // first, though.
74
+                        // TODO
75
+                        break;
76
+                    }
77
+                    Some(ClientTaskCommand::SendPackets) => {
78
+                        // TODO
79
+                    }
80
+                    None => {
81
+                        // This should never happen.
82
+                        break;
83
+                    }
84
+                }
85
+            }
86
+        };
87
+    }
88
+
89
+    if connection_closed {
90
+        // The stream was closed, but the command channel was not. We still need
91
+        // to return errors for any packet sent by the client, so do not exit
92
+        // the loop immediately but rather return an error for any incoming
93
+        // packet.
94
+        client_connection_closed(cmd_receive).await;
95
+    } else {
96
+        // The command channel was closed, but the stream was not. Gracefully
97
+        // close the stream.
34
         // TODO
98
         // TODO
35
-        panic!("Not yet implemented.");
36
     }
99
     }
37
 }
100
 }
38
 
101
 
39
-impl<P, S> RPCInterface for WSRPCInterface<P, S> {
40
-    type PacketType = P;
41
-    type NetworkError = String; // TODO
102
+async fn client_connection_closed(mut cmd_receive: mpsc::Receiver<ClientTaskCommand>) {
103
+    loop {
104
+        match cmd_receive.recv().await {
105
+            Some(ClientTaskCommand::Close) => {
106
+                // The connection was already closed.
107
+                break;
108
+            }
109
+            Some(ClientTaskCommand::SendPackets) => {
110
+                // The connection was closed, so return an error for any
111
+                // packet sent.
112
+                // TODO
113
+            }
114
+            None => {
115
+                // This should never happen.
116
+                break;
117
+            }
118
+        }
119
+    }
120
+}
42
 
121
 
43
-    type Call = WSRPC<Self::PacketType>;
122
+pub struct RPCInterface<StreamType, PacketType> {
123
+    stream: StreamType,
124
+    _packet: Option<PacketType>, // TODO: Remove.
125
+}
44
 
126
 
45
-    fn call(call: &Self::PacketType) -> Self::Call {
127
+impl<StreamType, PacketType> RPCInterface<StreamType, PacketType> {
128
+    fn call(_call: &PacketType) -> RPC<StreamType, PacketType> {
46
         // TODO
129
         // TODO
47
         panic!("Not yet implemented.");
130
         panic!("Not yet implemented.");
48
     }
131
     }
49
 }
132
 }
50
 
133
 
51
-pub struct WSRPC<PacketType> {
52
-    // TODO
53
-    _unused: PacketType,
134
+pub struct RPC<PacketType, ErrorType> {
135
+    result: Pin<Box<oneshot::Receiver<Result<IncomingPacket<PacketType>, ErrorType>>>>,
136
+    timeout: Option<Pin<Box<Delay>>>,
54
 }
137
 }
55
-
56
-impl<P> Future for WSRPC<P> {
57
-    type Output = Result<IncomingPacket<P>, String>;
58
-
59
-    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
60
-        // TODO
61
-        panic!("Not yet implemented.");
138
+impl<PacketType, ErrorType> RPC<PacketType, ErrorType> {
139
+    pub fn with_timeout(mut self, timeout: Duration) -> Self {
140
+        self.timeout = Some(Box::pin(delay_for(timeout)));
141
+        self
62
     }
142
     }
63
 }
143
 }
64
 
144
 
65
-impl<P> RPC for WSRPC<P> {
66
-    fn with_timeout(self, timeout: Duration) -> Self {
67
-        // TODO
68
-        panic!("Not yet implemented.");
145
+impl<PacketType, ErrorType> Future for RPC<PacketType, ErrorType> {
146
+    type Output = Result<IncomingPacket<PacketType>, RPCError<ErrorType>>;
147
+
148
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
149
+        // Safe, as we will not move self_.
150
+        let self_ = unsafe { self.get_unchecked_mut() };
151
+
152
+        // Try receiving from the receiver.
153
+        match Pin::as_mut(&mut self_.result).poll(cx) {
154
+            Poll::Ready(Ok(result)) => return Poll::Ready(result.map_err(|x| RPCError::Stream(x))),
155
+            Poll::Ready(Err(_)) => {
156
+                // The channel was closed.
157
+                return Poll::Ready(Err(RPCError::Closed));
158
+            }
159
+            Poll::Pending => (),
160
+        }
161
+
162
+        // Nothing received, check the timeout instead.
163
+        if self_.timeout.is_some() {
164
+            match Pin::as_mut(&mut self_.timeout.as_mut().unwrap()).poll(cx) {
165
+                Poll::Ready(()) => return Poll::Ready(Err(RPCError::Timeout)),
166
+                Poll::Pending => (),
167
+            }
168
+        }
169
+
170
+        Poll::Pending
69
     }
171
     }
70
 }
172
 }
71
 
173
 
72
-struct WSServerEventStream<PacketType> {
73
-    _unused: PacketType,
174
+// TODO: Do we even need this type?
175
+pub struct ServerEventStream<PacketType> {
176
+    packets: Pin<Box<mpsc::Receiver<IncomingPacket<PacketType>>>>,
74
 }
177
 }
75
 
178
 
76
-impl<P> Stream for WSServerEventStream<P> {
77
-    type Item = P;
179
+impl<PacketType> Stream for ServerEventStream<PacketType> {
180
+    type Item = IncomingPacket<PacketType>;
78
 
181
 
79
     fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
182
     fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
80
-        // TODO
81
-        panic!("Not yet implemented.");
183
+        // Safe, as we will not move self_.
184
+        let self_ = unsafe { self.get_unchecked_mut() };
185
+
186
+        Pin::as_mut(&mut self_.packets).poll_next(cx)
82
     }
187
     }
83
-}*/
188
+}
189
+
190
+pub enum RPCError<StreamError> {
191
+    Closed,
192
+    Timeout,
193
+    Stream(StreamError)
194
+}
195
+
196
+pub async fn low_level_integration_test_client(address: String) {
197
+    use super::websocket::WebSocketConnection;
84
 
198
 
85
-pub async fn low_level_integration_test_client(_address: String) {
86
-    //let url = Url::parse(&address).unwrap();
87
-    //let (mut ws_stream, _) = connect_async(url).await.unwrap();
199
+    let url = Url::parse(&address).unwrap();
200
+    let (mut ws_stream, _) = connect_async(url).await.unwrap();
201
+    let mut conn = WebSocketConnection::new(ws_stream);
202
+    let (rpc_interface, server_events) = create::<_, _, u32>(conn);
88
     // TODO
203
     // TODO
89
     panic!("Not yet implemented.");
204
     panic!("Not yet implemented.");
90
 }
205
 }

+ 8
- 0
src/network/websocket.rs 查看文件

11
     stream: Pin<Box<WebSocketStream<S>>>,
11
     stream: Pin<Box<WebSocketStream<S>>>,
12
 }
12
 }
13
 
13
 
14
+impl<S> WebSocketConnection<S> {
15
+    pub fn new(s: WebSocketStream<S>) -> Self {
16
+        Self {
17
+            stream: Box::pin(s),
18
+        }
19
+    }
20
+}
21
+
14
 impl<S> Sink<Vec<u8>> for WebSocketConnection<S>
22
 impl<S> Sink<Vec<u8>> for WebSocketConnection<S>
15
 where
23
 where
16
     S: AsyncRead + AsyncWrite + Unpin,
24
     S: AsyncRead + AsyncWrite + Unpin,

正在加载...
取消
保存