acceptor.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. use log::*;
  2. use smol::{Async, Executor};
  3. use std::net::{SocketAddr, TcpListener};
  4. use std::sync::Arc;
  5. use crate::net::error::{NetError, NetResult};
  6. use crate::net::{Channel, ChannelPtr};
  7. use crate::system::{StoppableTask, StoppableTaskPtr, Subscriber, SubscriberPtr, Subscription};
  8. /// Atomic pointer to Acceptor class.
  9. pub type AcceptorPtr = Arc<Acceptor>;
  10. /// Handles the acceptance of inbound socket connections. Used to start listening on a local
  11. /// socket address, to accept incoming connections and to handle network errors.
  12. pub struct Acceptor {
  13. channel_subscriber: SubscriberPtr<NetResult<ChannelPtr>>,
  14. task: StoppableTaskPtr,
  15. }
  16. impl Acceptor {
  17. /// Create new Acceptor object.
  18. pub fn new() -> Arc<Self> {
  19. Arc::new(Self {
  20. channel_subscriber: Subscriber::new(),
  21. task: StoppableTask::new(),
  22. })
  23. }
  24. /// Start accepting inbound socket connections.
  25. pub fn start(
  26. self: Arc<Self>,
  27. accept_addr: SocketAddr,
  28. executor: Arc<Executor<'_>>,
  29. ) -> NetResult<()> {
  30. let listener = Self::setup(accept_addr)?;
  31. // Start detached task and return instantly
  32. self.accept(listener, executor);
  33. Ok(())
  34. }
  35. /// Stop accepting inbound socket connections.
  36. pub async fn stop(&self) {
  37. // Send stop signal
  38. self.task.stop().await;
  39. }
  40. /// Start receiving network messages.
  41. pub async fn subscribe(self: Arc<Self>) -> Subscription<NetResult<ChannelPtr>> {
  42. self.channel_subscriber.clone().subscribe().await
  43. }
  44. /// Start listening on a local socket address.
  45. fn setup(accept_addr: SocketAddr) -> NetResult<Async<TcpListener>> {
  46. let listener = match Async::<TcpListener>::bind(accept_addr) {
  47. Ok(listener) => listener,
  48. Err(err) => {
  49. error!("Bind listener failed: {}", err);
  50. return Err(NetError::OperationFailed);
  51. }
  52. };
  53. let local_addr = match listener.get_ref().local_addr() {
  54. Ok(addr) => addr,
  55. Err(err) => {
  56. error!("Failed to get local address: {}", err);
  57. return Err(NetError::OperationFailed);
  58. }
  59. };
  60. info!("Listening on {}", local_addr);
  61. Ok(listener)
  62. }
  63. /// Run the accept loop in a new thread and error if a connection problem occurs.
  64. fn accept(self: Arc<Self>, listener: Async<TcpListener>, executor: Arc<Executor<'_>>) {
  65. self.task.clone().start(
  66. self.clone().run_accept_loop(listener),
  67. |result| self.handle_stop(result),
  68. NetError::ServiceStopped,
  69. executor,
  70. );
  71. }
  72. /// Run the accept loop.
  73. async fn run_accept_loop(self: Arc<Self>, listener: Async<TcpListener>) -> NetResult<()> {
  74. loop {
  75. let channel = self.tick_accept(&listener).await?;
  76. self.channel_subscriber.notify(Ok(channel)).await;
  77. }
  78. }
  79. /// Handles network errors. Panics if error passes silently, otherwise broadcasts the error.
  80. async fn handle_stop(self: Arc<Self>, result: NetResult<()>) {
  81. match result {
  82. Ok(()) => panic!("Acceptor task should never complete without error status"),
  83. Err(err) => {
  84. // Send this error to all channel subscribers
  85. let result = Err(err);
  86. self.channel_subscriber.notify(result).await;
  87. }
  88. }
  89. }
  90. /// Single attempt to accept an incoming connection. Stops after one attempt.
  91. async fn tick_accept(&self, listener: &Async<TcpListener>) -> NetResult<ChannelPtr> {
  92. let (stream, peer_addr) = match listener.accept().await {
  93. Ok((s, a)) => (s, a),
  94. Err(err) => {
  95. error!("Error listening for connections: {}", err);
  96. return Err(NetError::ServiceStopped);
  97. }
  98. };
  99. info!("Accepted client: {}", peer_addr);
  100. let channel = Channel::new(stream, peer_addr).await;
  101. Ok(channel)
  102. }
  103. }