websocket.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. use actors::ws::WebsocketActor;
  2. use actors::Actor;
  3. use warp::Filter;
  4. #[tokio::main]
  5. async fn main() {
  6. // GET /chat -> websocket upgrade
  7. let chat = warp::path("chat")
  8. // The `ws()` filter will prepare Websocket handshake...
  9. .and(warp::ws())
  10. .map(|ws: warp::ws::Ws| {
  11. // This will call our function if the handshake succeeds.
  12. ws.on_upgrade(move |socket| {
  13. let actor = WebsocketActor::new(socket);
  14. actor.start();
  15. futures::future::ready(())
  16. })
  17. });
  18. // GET / -> index html
  19. let index = warp::path::end().map(|| warp::reply::html(INDEX_HTML));
  20. let routes = index.or(chat);
  21. warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
  22. }
  23. /*
  24. async fn user_connected(ws: WebSocket, users: Users) {
  25. // Use a counter to assign a new unique ID for this user.
  26. let my_id = NEXT_USER_ID.fetch_add(1, Ordering::Relaxed);
  27. eprintln!("new chat user: {}", my_id);
  28. // Split the socket into a sender and receive of messages.
  29. let (mut user_ws_tx, mut user_ws_rx) = ws.split();
  30. // Use an unbounded channel to handle buffering and flushing of messages
  31. // to the websocket...
  32. let (tx, rx) = mpsc::unbounded_channel();
  33. let mut rx = UnboundedReceiverStream::new(rx);
  34. tokio::task::spawn(async move {
  35. while let Some(message) = rx.next().await {
  36. user_ws_tx
  37. .send(message)
  38. .unwrap_or_else(|e| {
  39. eprintln!("websocket send error: {}", e);
  40. })
  41. .await;
  42. }
  43. });
  44. // Save the sender in our list of connected users.
  45. users.write().await.insert(my_id, tx);
  46. // Return a `Future` that is basically a state machine managing
  47. // this specific user's connection.
  48. // Every time the user sends a message, broadcast it to
  49. // all other users...
  50. while let Some(result) = user_ws_rx.next().await {
  51. let msg = match result {
  52. Ok(msg) => {
  53. println!("MESSAGE {msg:?}");
  54. msg
  55. }
  56. Err(e) => {
  57. eprintln!("websocket error(uid={}): {}", my_id, e);
  58. break;
  59. }
  60. };
  61. // Skip any non-Text messages...
  62. let msg = if let Ok(s) = msg.to_str() {
  63. s
  64. } else {
  65. return;
  66. };
  67. let new_msg = format!("<User#{}>: {}", my_id, msg);
  68. // New message from this user, send it to everyone else (except same uid)...
  69. for (&uid, tx) in users.read().await.iter() {
  70. if my_id != uid {
  71. if let Err(_disconnected) = tx.send(Message::text(new_msg.clone())) {
  72. // The tx is disconnected, our `user_disconnected` code
  73. // should be happening in another task, nothing more to
  74. // do here.
  75. }
  76. }
  77. }
  78. }
  79. // user_ws_rx stream will keep processing as long as the user stays
  80. // connected. Once they disconnect, then...
  81. user_disconnected(my_id, &users).await;
  82. }
  83. */
  84. static INDEX_HTML: &str = r#"<!DOCTYPE html>
  85. <html lang="en">
  86. <head>
  87. <title>Warp Chat</title>
  88. </head>
  89. <body>
  90. <h1>Warp chat</h1>
  91. <div id="chat">
  92. <p><em>Connecting...</em></p>
  93. </div>
  94. <input type="text" id="text" />
  95. <button type="button" id="send">Send</button>
  96. <script type="text/javascript">
  97. const chat = document.getElementById('chat');
  98. const text = document.getElementById('text');
  99. const uri = 'ws://' + location.host + '/chat';
  100. const ws = new WebSocket(uri);
  101. function message(data) {
  102. const line = document.createElement('p');
  103. line.innerText = data;
  104. chat.appendChild(line);
  105. }
  106. ws.onopen = function() {
  107. chat.innerHTML = '<p><em>Connected!</em></p>';
  108. };
  109. ws.onmessage = function(msg) {
  110. message(msg.data);
  111. };
  112. ws.onclose = function() {
  113. chat.getElementsByTagName('em')[0].innerText = 'Disconnected!';
  114. };
  115. send.onclick = function() {
  116. const msg = text.value;
  117. ws.send(msg);
  118. text.value = '';
  119. message('<You>: ' + msg);
  120. };
  121. </script>
  122. </body>
  123. </html>
  124. "#;