use crate::{
codes::{
Code, DISCONNECT as DISCONNECT_, REMOVE_CLIENT, REQUEST_CONNECTION, STATUS_OK,
UNKNOWN_STATUS,
},
connections::Connections,
dlcmd::{send_dlcmd, CONNECT, DISCONNECT, SEND},
encryption::EncryptionInfo,
id::*,
message::{string_to_contents, Message, ReceiveInfo, TransmitInfo},
};
use std::{
fs::File,
io::{BufRead, BufReader},
path::Path,
thread::sleep,
time::Duration,
};
#[allow(improper_ctypes_definitions)]
fn empty_encryption_function(_i: [i32; 6], s: String) -> String {
s
}
pub(crate) const EMPTY_ENCRYPTIONIFNO: EncryptionInfo = EncryptionInfo {
encode_function: empty_encryption_function,
decode_function: empty_encryption_function,
info: [0; 6],
};
#[derive(Copy, Clone)]
pub enum StreamType {
Client {
rid: LId,
rdid: DId,
port: u16,
},
Server {
port: u16,
},
}
impl StreamType {
pub fn is_client(self) -> bool {
return match self {
Self::Client { .. } => true,
Self::Server { .. } => false,
};
}
pub fn rid(self) -> LId {
return match self {
Self::Client {
rid,
rdid: _,
port: _,
} => rid,
Self::Server { .. } => local_user_id().unwrap_or(0),
};
}
pub fn rdid(self) -> DId {
return match self {
Self::Client {
rid: _,
rdid,
port: _,
} => rdid,
Self::Server { .. } => distributor_id().unwrap_or(0),
};
}
pub fn port(self) -> u16 {
return match self {
Self::Client {
rid: _,
rdid: _,
port,
} => port,
Self::Server { port } => port,
};
}
}
pub struct Stream {
pub stream_type: StreamType,
pub encryption: EncryptionInfo,
pub history: bool,
connections: Connections,
instance_id: InstanceID,
received_messages: Vec<Message>,
sent_messages: Vec<Message>,
running: bool,
}
impl Stream {
pub fn new(stream_type: StreamType, history: bool) -> Self {
return Stream {
stream_type,
encryption: EMPTY_ENCRYPTIONIFNO,
history,
connections: Connections::empty(),
instance_id: 0,
received_messages: vec![],
sent_messages: vec![],
running: false,
};
}
pub fn add_not_allowed_connections(&mut self, not_allowed_connections: Vec<ReceiveInfo>) {
if self.stream_type.is_client() {
return;
}
if self.connections.not_allowed.is_empty() {
self.connections.not_allowed = not_allowed_connections;
} else {
for i in 0..not_allowed_connections.len() {
self.connections
.not_allowed
.push(not_allowed_connections[i]);
}
}
}
pub fn check_add_connection(&mut self, message: Message) -> bool {
if self.stream_type.is_client() {
return false;
}
let ri = message.ti.into_ri(message.ri.instance_id, message.ri.port);
if self.connections.is_allowed(ri) {
return false;
}
if self.connections.current.get(&ri).is_some() {
return true;
} else {
self.connections.current.insert(
ri,
Stream::new(
StreamType::Client {
rid: ri.rid,
rdid: ri.rdid,
port: ri.port,
},
self.history,
),
);
self.connections
.current
.get_mut(&ri)
.unwrap()
.add_encryption_info(self.encryption);
self.connections.current.get_mut(&ri).unwrap().start();
return true;
}
}
pub fn remove_connection(&mut self, ri: ReceiveInfo) -> Code {
if self.stream_type.is_client() {
return UNKNOWN_STATUS;
}
let stream = self.connections.current.remove(&ri);
if stream.is_none() {
return UNKNOWN_STATUS;
} else {
stream.unwrap().write(String::new(), DISCONNECT_);
return STATUS_OK;
}
}
fn stream_file_exists(&self) -> bool {
Path::new(&format!(
"/tmp/darklight/connections/_dl_{}-{}",
self.stream_type.rid(),
self.stream_type.port()
))
.exists()
}
pub fn add_encryption_info(&mut self, info: EncryptionInfo) {
self.encryption = info;
}
pub fn running(&self) -> bool {
self.running
}
pub fn clear_history(&mut self) {
self.received_messages.clear();
self.sent_messages.clear();
}
pub fn _read(&self) -> Vec<String> {
sleep(Duration::from_micros(15));
let reader = BufReader::new(
File::options()
.read(true)
.open(&format!(
"/tmp/darklight/connections/_dl_{}-{}",
self.stream_type.rid(),
self.stream_type.port()
))
.unwrap(),
);
let mut ret = vec![];
for line in reader.lines() {
if line.is_ok() {
ret.push(line.unwrap());
}
}
ret
}
pub fn read(&mut self) -> Vec<Message> {
let mut ret = vec![];
let strings = self._read();
for i in 0..strings.len() {
let received_message = Message::decode(&strings[i].to_owned(), self.encryption);
println!("message ti: {:?}", received_message.ti);
ret.push(received_message);
}
File::create(format!(
"/tmp/darklight/connections/_dl_{}-{}",
self.stream_type.rid(),
self.stream_type.port()
))
.unwrap();
ret
}
pub fn write_message(&self, message: Message) {
let encoded = message.encode(self.encryption);
send_dlcmd(SEND, encoded.split(" ").collect::<Vec<&str>>());
}
pub fn server_write(&mut self, ti: TransmitInfo, write: String, code: Code) {
if self.stream_type.is_client() {
return;
}
let ri = ti.into_ri(self.instance_id, self.stream_type.port());
self.connections
.current
.get_mut(&ri)
.unwrap()
.write(write, code);
}
pub fn write(&self, write: String, code: Code) {
if self.stream_type.is_client() {
self.write_message(Message {
ri: ReceiveInfo {
rid: self.stream_type.rid(),
rdid: self.stream_type.rdid(),
port: self.stream_type.port(),
instance_id: self.instance_id,
},
ti: TransmitInfo {
tid: local_user_id().unwrap(),
tdid: distributor_id().unwrap(),
code: code.value(),
},
day: self.encryption.info[0],
week: self.encryption.info[1],
month: self.encryption.info[2],
contents: string_to_contents(write),
});
}
}
fn _server_start(&mut self) -> Code {
let decode_info = self.encryption.info;
let local_did = distributor_id().expect("Local Distributor Id is not set");
let local_id = local_user_id().expect("Failed to get Local Id");
send_dlcmd(
CONNECT,
vec![
&local_did.to_string(),
&local_id.to_string(),
&self.stream_type.port().to_string(),
&self.instance_id.to_string(),
&decode_info[0].to_string(),
&decode_info[1].to_string(),
&decode_info[2].to_string(),
],
);
self.running = true;
STATUS_OK
}
fn _client_start(&mut self) -> Code {
let decode_info = self.encryption.info;
send_dlcmd(
CONNECT,
vec![
&self.stream_type.rdid().to_string(),
&self.stream_type.rid().to_string(),
&self.stream_type.port().to_string(),
&self.instance_id.to_string(),
&decode_info[0].to_string(),
&decode_info[1].to_string(),
&decode_info[2].to_string(),
],
);
sleep(Duration::from_millis(100));
if self.stream_file_exists() == false {
return UNKNOWN_STATUS;
}
self.write_message(Message {
ti: TransmitInfo {
tdid: distributor_id().expect("Failed to get local Distributor ID"),
tid: local_user_id().expect("Failed to get local ID"),
code: REQUEST_CONNECTION.value(),
},
ri: ReceiveInfo {
rid: self.stream_type.rid(),
rdid: self.stream_type.rdid(),
port: self.stream_type.port(),
instance_id: self.instance_id,
},
contents: [0; 4096],
day: 0,
week: 0,
month: 0,
});
self.running = true;
STATUS_OK
}
pub fn start(&mut self) -> Code {
let ret = if self.stream_type.is_client() {
self._client_start()
} else {
self._server_start()
};
self.running = true;
ret
}
pub fn stop(&mut self) -> Code {
self.running = false;
self.write(String::new(), REMOVE_CLIENT);
send_dlcmd(
DISCONNECT,
vec![
&self.stream_type.rid().to_string(),
&self.stream_type.port().to_string(),
&self.stream_type.rdid().to_string(),
],
);
sleep(Duration::from_micros(500));
REMOVE_CLIENT
}
}