-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented DCC get for downloading files.
Does not yet support sending files. Closes #206 Added connection timeout Fixed NOTICE format which was causing an issue. Spawn regular task instead of local for file download. Only read number of bytes read.
- Loading branch information
Showing
9 changed files
with
425 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
use std::fmt; | ||
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | ||
use std::str::FromStr; | ||
|
||
#[derive(Debug)] | ||
pub struct DCCRecord { | ||
/// SEND or CHAT (only supporting SEND right now) | ||
dcc_type: DCCType, | ||
/// IP address and port | ||
address: SocketAddr, | ||
/// Nickname of person who wants to send | ||
origin: String, | ||
/// Client nickname | ||
receiver: String, | ||
/// Argument - filename or string "chat" | ||
argument: String, | ||
/// File size of file that will be sent in bytes | ||
file_size: Option<u32>, | ||
} | ||
|
||
#[derive(Debug, Copy, Clone)] | ||
pub enum DCCType { | ||
SEND, | ||
CHAT, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct DCCTypeParseError; | ||
|
||
impl std::error::Error for DCCTypeParseError {} | ||
|
||
impl fmt::Display for DCCTypeParseError { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "DCCType could not be parsed from string.") | ||
} | ||
} | ||
|
||
impl FromStr for DCCType { | ||
type Err = DCCTypeParseError; | ||
fn from_str(input: &str) -> Result<DCCType, DCCTypeParseError> { | ||
match input { | ||
"SEND" => Ok(DCCType::SEND), | ||
"CHAT" => Ok(DCCType::CHAT), | ||
_ => Err(DCCTypeParseError), | ||
} | ||
} | ||
} | ||
|
||
impl fmt::Display for DCCType { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match self { | ||
DCCType::CHAT => write!(f, "CHAT"), | ||
DCCType::SEND => write!(f, "SEND"), | ||
} | ||
} | ||
} | ||
|
||
impl DCCRecord { | ||
/// DCC type argument address port [size] | ||
/// | ||
/// type - The connection type. | ||
/// argument - The connectin type dependant argument. | ||
/// address - The host address of the initiator as an integer. | ||
/// port - The port or the socket on which the initiator expects | ||
/// to receive the connection. | ||
/// size - If the connection type is "SEND" (see below), then size | ||
/// will indicate the size of the file being offered. Obsolete | ||
/// IRCII clients do not send this, so be prepared if this is | ||
/// not present. | ||
/// The following DCC connection types are defined: | ||
/// | ||
/// Type Purpose Argument | ||
/// CHAT To carry on a semi-secure conversation the string "chat" | ||
/// SEND To send a file to the recipient the file name | ||
pub fn from( | ||
origin: &str, | ||
receiver: &str, | ||
msg: &str, | ||
) -> Result<DCCRecord, Box<dyn std::error::Error>> { | ||
let mut param_iter = msg.split_whitespace(); | ||
let dcc_type: DCCType = param_iter.next().unwrap().parse()?; | ||
let argument = param_iter.next().unwrap(); | ||
let address: u32 = param_iter.next().unwrap().parse()?; | ||
let address_dot_decimal: Ipv4Addr = Ipv4Addr::new( | ||
(address >> 24) as u8, | ||
(address >> 16) as u8, | ||
(address >> 8) as u8, | ||
(address) as u8, | ||
); | ||
let port: u16 = param_iter.next().unwrap().parse()?; | ||
let socket_address = SocketAddr::new(IpAddr::V4(address_dot_decimal), port); | ||
|
||
let file_size = param_iter.next().and_then(|fs| fs.parse::<u32>().ok()); | ||
|
||
Ok(DCCRecord { | ||
dcc_type, | ||
address: socket_address, | ||
origin: origin.to_string(), | ||
receiver: receiver.to_string(), | ||
argument: argument.to_string(), | ||
file_size, | ||
}) | ||
} | ||
|
||
pub fn get_type(&self) -> DCCType { | ||
self.dcc_type | ||
} | ||
|
||
pub fn get_addr(&self) -> &SocketAddr { | ||
&self.address | ||
} | ||
|
||
pub fn get_argument(&self) -> &String { | ||
&self.argument | ||
} | ||
|
||
pub fn get_file_size(&self) -> Option<u32> { | ||
self.file_size | ||
} | ||
|
||
pub fn get_receiver(&self) -> &String { | ||
&self.receiver | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.