terminal-chat

Форк
0
/
data_manager.rs 
143 строки · 4.1 Кб
1
use std::sync::Arc;
2
use std::sync::mpsc::Receiver;
3
use std::thread;
4
use std::time::Duration;
5
use std::str::FromStr;
6
use anyhow::Result;
7
use parking_lot::Mutex;
8
use uuid::Uuid;
9

10
use crate::messages_pool::{PoolMessage, MessagesPool};
11
use crate::state::UserData;
12
use crate::types::{
13
  AuthStatus, 
14
  SignalData, 
15
  SignalHeader, 
16
  AuthConnectionError,
17
  IncomingMessageError,
18
  SignalType
19
};
20

21
use super::manager::Manager;
22
use super::stream_manager::StreamManager;
23

24
pub trait DataManager {
25
  fn deny_auth(&mut self) -> Result<()>;
26
  fn auth(&mut self, signal: String) -> Result<()>;
27
  fn remove_user(&mut self, username: String) -> Result<()>;
28
  fn process_messages_pool(&mut self, receiver: Receiver<()>) -> Result<()>;
29
  fn process_incoming_message(messages_pool: Arc<Mutex<MessagesPool>>, signal: String) -> Result<()>;
30
}
31

32
impl DataManager for Manager {
33
  fn deny_auth(&mut self) -> Result<()> {
34
    let response = SignalData::new(
35
      vec![SignalHeader::AuthStatus(AuthStatus::DENIED)],
36
      None
37
    );
38

39
    self.send_data(&response.to_string())?;
40
    Ok(())
41
  }
42

43
  fn auth(&mut self, signal: String) -> Result<()> {
44
    let data = SignalData::from_str(&signal)?;
45

46
    match data.signal_type.unwrap() {
47
        SignalType::Connection => {
48
          if let None = data.username {
49
            return Err(AuthConnectionError.into());
50
          }
51
          let mut state = self.state.get();
52
          if state.users.contains_key(&data.username.clone().unwrap()) {
53
            return Err(AuthConnectionError.into())
54
          }
55
          state.users.insert(data.username.clone().unwrap().to_owned(), UserData {
56
            address: self.stream.peer_addr()?.to_string(),
57
          });
58
          self.messages_pool.lock().push(PoolMessage {
59
            id: Uuid::new_v4().to_string(),
60
            username: String::new(),
61
            message: format!("{} joined the chat!", data.username.clone().unwrap()),
62
            from_server: true
63
          });
64
        }
65
        _ => return Err(AuthConnectionError.into()),
66
    }
67

68
    self.connected_user_username = Some(data.username.unwrap());
69

70
    let response = SignalData::new(
71
      vec![SignalHeader::AuthStatus(AuthStatus::ACCEPTED)],
72
      None
73
    );
74

75
    self.send_data(&response.to_string())?;
76
    Ok(())
77
  }
78

79
  fn remove_user(&mut self, username: String) -> Result<()> {
80
    let mut state = self.state.get();
81

82
    if state.users.contains_key(&username) {
83
      state.users.remove(&username);
84
      self.messages_pool.lock().push(PoolMessage {
85
        id: Uuid::new_v4().to_string(),
86
        username: String::new(),
87
        message: format!("{username} left the chat!"),
88
        from_server: true
89
      });
90
    }
91
    Ok(())
92
  }
93

94
  fn process_messages_pool(&mut self, receiver: Receiver<()>) -> Result<()> {
95
    loop {
96
      if let Ok(()) = receiver.try_recv() {
97
        break;
98
      };
99

100
      let lock_ref = self.messages_pool.clone();
101
      let pool_lock = lock_ref.lock();
102

103
      let messages = pool_lock.has_new(&self.last_read_message_id);
104
      if let Some(v) = messages {
105
        if let Some(last) = v.1 {
106
          self.last_read_message_id = last;
107
        }
108
        for message in v.0 {
109
          let mut syg_vec = vec![
110
            SignalHeader::SignalType(SignalType::NewMessage),
111
            SignalHeader::Username(message.username.clone()),
112
            SignalHeader::WithMessage
113
          ];
114
          if message.from_server {
115
            syg_vec.push(SignalHeader::ServerMessage);
116
          }
117
          let response = SignalData::new(syg_vec, Some(&message.message));
118
          self.send_data(&response.to_string())?;
119
        }
120
      }
121
      thread::sleep(Duration::from_millis(10));
122
    }
123

124
    Ok(())
125
  }
126

127
  fn process_incoming_message(messages_pool: Arc<Mutex<MessagesPool>>, signal: String) -> Result<()> {
128
    let data = SignalData::from_str(&signal)?;
129
  
130
    if !data.with_message || data.username.is_none() {
131
      return Err(IncomingMessageError.into())
132
    }
133
  
134
    messages_pool.lock().push(PoolMessage {
135
      id: Uuid::new_v4().to_string(),
136
      username: data.username.clone().unwrap(),
137
      message: data.message.clone().unwrap().trim().to_owned(),
138
      from_server: false
139
    });
140
  
141
    Ok(())
142
  }
143
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.