2828
2929use tokio:: net:: { TcpListener , TcpStream } ;
3030use tokio:: sync:: { mpsc, Mutex } ;
31- use tokio_stream:: { Stream , StreamExt } ;
32- use tokio_util:: codec:: { Framed , LinesCodec , LinesCodecError } ;
31+ use tokio_stream:: StreamExt ;
32+ use tokio_util:: codec:: { Framed , LinesCodec } ;
3333
3434use futures:: SinkExt ;
3535use std:: collections:: HashMap ;
3636use std:: env;
3737use std:: error:: Error ;
3838use std:: io;
3939use std:: net:: SocketAddr ;
40- use std:: pin:: Pin ;
4140use std:: sync:: Arc ;
42- use std:: task:: { Context , Poll } ;
4341
4442#[ tokio:: main]
4543async fn main ( ) -> Result < ( ) , Box < dyn Error > > {
@@ -101,6 +99,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
10199/// Shorthand for the transmit half of the message channel.
102100type Tx = mpsc:: UnboundedSender < String > ;
103101
102+ /// Shorthand for the receive half of the message channel.
103+ type Rx = mpsc:: UnboundedReceiver < String > ;
104+
104105/// Data that is shared between all peers in the chat server.
105106///
106107/// This is the set of `Tx` handles for all connected clients. Whenever a
@@ -124,7 +125,7 @@ struct Peer {
124125 ///
125126 /// This is used to receive messages from peers. When a message is received
126127 /// off of this `Rx`, it will be written to the socket.
127- rx : Pin < Box < dyn Stream < Item = String > + Send > > ,
128+ rx : Rx ,
128129}
129130
130131impl Shared {
@@ -156,58 +157,15 @@ impl Peer {
156157 let addr = lines. get_ref ( ) . peer_addr ( ) ?;
157158
158159 // Create a channel for this peer
159- let ( tx, mut rx) = mpsc:: unbounded_channel ( ) ;
160+ let ( tx, rx) = mpsc:: unbounded_channel ( ) ;
160161
161162 // Add an entry for this `Peer` in the shared state map.
162163 state. lock ( ) . await . peers . insert ( addr, tx) ;
163164
164- let rx = Box :: pin ( async_stream:: stream! {
165- while let Some ( item) = rx. recv( ) . await {
166- yield item;
167- }
168- } ) ;
169-
170165 Ok ( Peer { lines, rx } )
171166 }
172167}
173168
174- #[ derive( Debug ) ]
175- enum Message {
176- /// A message that should be broadcasted to others.
177- Broadcast ( String ) ,
178-
179- /// A message that should be received by a client
180- Received ( String ) ,
181- }
182-
183- // Peer implements `Stream` in a way that polls both the `Rx`, and `Framed` types.
184- // A message is produced whenever an event is ready until the `Framed` stream returns `None`.
185- impl Stream for Peer {
186- type Item = Result < Message , LinesCodecError > ;
187-
188- fn poll_next ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Option < Self :: Item > > {
189- // First poll the `UnboundedReceiver`.
190-
191- if let Poll :: Ready ( Some ( v) ) = Pin :: new ( & mut self . rx ) . poll_next ( cx) {
192- return Poll :: Ready ( Some ( Ok ( Message :: Received ( v) ) ) ) ;
193- }
194-
195- // Secondly poll the `Framed` stream.
196- let result: Option < _ > = futures:: ready!( Pin :: new( & mut self . lines) . poll_next( cx) ) ;
197-
198- Poll :: Ready ( match result {
199- // We've received a message we should broadcast to others.
200- Some ( Ok ( message) ) => Some ( Ok ( Message :: Broadcast ( message) ) ) ,
201-
202- // An error occurred.
203- Some ( Err ( e) ) => Some ( Err ( e) ) ,
204-
205- // The stream has been exhausted.
206- None => None ,
207- } )
208- }
209- }
210-
211169/// Process an individual chat client
212170async fn process (
213171 state : Arc < Mutex < Shared > > ,
@@ -241,28 +199,32 @@ async fn process(
241199 }
242200
243201 // Process incoming messages until our stream is exhausted by a disconnect.
244- while let Some ( result) = peer. next ( ) . await {
245- match result {
246- // A message was received from the current user, we should
247- // broadcast this message to the other users.
248- Ok ( Message :: Broadcast ( msg) ) => {
249- let mut state = state. lock ( ) . await ;
250- let msg = format ! ( "{}: {}" , username, msg) ;
251-
252- state. broadcast ( addr, & msg) . await ;
253- }
254- // A message was received from a peer. Send it to the
255- // current user.
256- Ok ( Message :: Received ( msg) ) => {
202+ loop {
203+ tokio:: select! {
204+ // A message was received from a peer. Send it to the current user.
205+ Some ( msg) = peer. rx. recv( ) => {
257206 peer. lines. send( & msg) . await ?;
258207 }
259- Err ( e) => {
260- tracing:: error!(
261- "an error occurred while processing messages for {}; error = {:?}" ,
262- username,
263- e
264- ) ;
265- }
208+ result = peer. lines. next( ) => match result {
209+ // A message was received from the current user, we should
210+ // broadcast this message to the other users.
211+ Some ( Ok ( msg) ) => {
212+ let mut state = state. lock( ) . await ;
213+ let msg = format!( "{}: {}" , username, msg) ;
214+
215+ state. broadcast( addr, & msg) . await ;
216+ }
217+ // An error occurred.
218+ Some ( Err ( e) ) => {
219+ tracing:: error!(
220+ "an error occurred while processing messages for {}; error = {:?}" ,
221+ username,
222+ e
223+ ) ;
224+ }
225+ // The stream has been exhausted.
226+ None => break ,
227+ } ,
266228 }
267229 }
268230
0 commit comments