use log::error;
use crate::{CommandHeader, CommandId, SmppError, SmppReply};
#[derive(Debug, Clone)]
pub struct unbind {
header: CommandHeader,
}
impl unbind {
pub(crate) fn with_sequence_number(sequence_number: u32) -> unbind {
unbind {
header: CommandHeader {
command_length: 16,
command_id: CommandId::unbind as u32,
command_status: SmppError::ESME_ROK as u32,
sequence_number,
},
}
}
pub(crate) fn decode(header: CommandHeader, pdu: &[u8]) -> Result<unbind, SmppError> {
if header.command_id == CommandId::unbind as u32 {
if pdu.len() == 16 {
Ok(unbind { header })
} else {
Err(SmppError::ESME_ROPTPARNOTALLWD) }
} else {
error!(
"Passed a non unbind PDU to unbind::decode(), command_id: 0x{:08X}",
header.command_id
);
Err(SmppError::ESME_RINVCMDID)
}
}
pub fn encode(self) -> Vec<u8> {
self.header.encode()
}
pub fn accept(self) -> unbind_resp {
unbind_resp {
header: CommandHeader {
command_length: 16, command_id: CommandId::unbind_resp as u32,
command_status: SmppError::ESME_ROK as u32,
sequence_number: self.header.sequence_number,
},
}
}
pub fn reject(self, error: SmppError) -> unbind_resp {
unbind_resp {
header: CommandHeader {
command_length: 16,
command_id: CommandId::unbind_resp as u32,
command_status: error as u32,
sequence_number: self.header.sequence_number,
},
}
}
pub fn generic_reject(sequence_number: u32, error: SmppError) -> unbind_resp {
unbind_resp {
header: CommandHeader {
command_length: 16,
command_id: CommandId::unbind_resp as u32,
command_status: error as u32,
sequence_number,
},
}
}
}
#[derive(Debug, Clone)]
pub struct unbind_resp {
header: CommandHeader,
}
impl SmppReply for unbind_resp {}
impl unbind_resp {
pub fn is_success(&self) -> bool {
self.header.command_status == SmppError::ESME_ROK as u32
}
pub fn command_status(&self) -> u32 {
self.header.command_status
}
pub fn get_error(&self) -> SmppError {
SmppError::from_command_status(self.header.command_status)
}
pub fn encode(self) -> Vec<u8> {
self.header.encode()
}
pub fn decode(header: CommandHeader, pdu: &[u8]) -> Result<unbind_resp, SmppError> {
if header.command_id == CommandId::unbind_resp as u32 {
if pdu.len() == 16 {
Ok(unbind_resp { header })
} else {
Err(SmppError::ESME_ROPTPARNOTALLWD) }
} else {
error!(
"Passed a non unbind_resp PDU to unbind_resp::decode(), command_id: 0x{:08X}",
header.command_id
);
Err(SmppError::ESME_RINVCMDID)
}
}
}
#[cfg(test)]
mod all_unbind_tests {
#[cfg(test)]
mod unbind_tests {
use crate::{unbind, CommandHeader, CommandId, SmppError};
#[test]
fn encode_unbind1() {
let unbind = unbind::with_sequence_number(0x12344567);
let pdu = unbind.encode();
assert_eq!(
pdu,
vec![
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x12,
0x34, 0x45, 0x67
]
);
}
#[test]
fn encode_unbind2() {
let unbind = unbind {
header: CommandHeader {
command_length: 16,
command_id: CommandId::unbind as u32,
command_status: SmppError::ESME_ROK as u32,
sequence_number: 0x12344567,
},
};
let pdu = unbind.encode();
assert_eq!(
pdu,
vec![
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x12,
0x34, 0x45, 0x67
]
);
}
#[test]
fn decode_unbind() {
let pdu = vec![
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34,
0x45, 0x67,
];
let decoded_command_header =
CommandHeader::decode(&pdu).expect("Can not decode command header");
let decoded =
unbind::decode(decoded_command_header, &pdu).expect("Unable to decode unbind");
assert_eq!(decoded.header.command_length, 16);
assert_eq!(decoded.header.command_id, CommandId::unbind as u32);
assert_eq!(decoded.header.command_status, SmppError::ESME_ROK as u32);
assert_eq!(decoded.header.sequence_number, 0x12344567);
}
#[test]
fn decode_unbind_with_body() {
let pdu = vec![
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34,
0x45, 0x67, 0xde, 0xad, 0xbe, 0xef,
];
let decoded_command_header =
CommandHeader::decode(&pdu).expect("Can not decode command header");
let decoded = unbind::decode(decoded_command_header, &pdu).unwrap_err();
assert_eq!(decoded, SmppError::ESME_ROPTPARNOTALLWD)
}
#[test]
fn decode_generic_nack_with_invalid_command_id() {
let pdu = vec![
0x00, 0x00, 0x00, 0x10, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x34,
0x45, 0x67,
];
let decoded_command_header =
CommandHeader::decode(&pdu).expect("Can not decode command header");
let result = unbind::decode(decoded_command_header, &pdu);
assert!(result.is_err());
}
#[test]
fn unbind_accept() {
let unbind = unbind {
header: CommandHeader {
command_length: 16,
command_id: CommandId::unbind as u32,
command_status: SmppError::ESME_ROK as u32,
sequence_number: 0x12344567,
},
};
let unbind_resp = unbind.accept();
assert_eq!(unbind_resp.header.command_length, 16);
assert_eq!(unbind_resp.header.command_id, CommandId::unbind_resp as u32);
assert_eq!(
unbind_resp.header.command_status,
SmppError::ESME_ROK as u32
);
assert_eq!(unbind_resp.header.sequence_number, 0x12344567);
}
#[test]
fn unbind_reject() {
let unbind = unbind {
header: CommandHeader {
command_length: 16,
command_id: CommandId::unbind as u32,
command_status: SmppError::ESME_ROK as u32,
sequence_number: 0x12344567,
},
};
let unbind_resp = unbind.reject(SmppError::ESME_RINVBNDSTS);
assert_eq!(unbind_resp.header.command_length, 16);
assert_eq!(unbind_resp.header.command_id, CommandId::unbind_resp as u32);
assert_eq!(
unbind_resp.header.command_status,
SmppError::ESME_RINVBNDSTS as u32
);
assert_eq!(unbind_resp.header.sequence_number, 0x12344567);
}
#[test]
fn unbind_generic_reject() {
let unbind_resp = unbind::generic_reject(0x12344567, SmppError::ESME_RINVBNDSTS);
assert_eq!(unbind_resp.header.command_length, 16);
assert_eq!(unbind_resp.header.command_id, CommandId::unbind_resp as u32);
assert_eq!(
unbind_resp.header.command_status,
SmppError::ESME_RINVBNDSTS as u32
);
assert_eq!(unbind_resp.header.sequence_number, 0x12344567);
}
}
#[cfg(test)]
mod unbind_resp_tests {
use crate::{unbind, SmppError};
#[test]
fn unbind_resp_is_success() {
let unbind_resp = unbind::generic_reject(0x1234567, SmppError::ESME_ROK);
assert!(unbind_resp.is_success());
let unbind_resp = unbind::generic_reject(0x1234567, SmppError::ESME_RINVBNDSTS);
assert!(!unbind_resp.is_success());
}
#[test]
fn unbind_resp_command_status() {
let unbind_resp = unbind::generic_reject(0x1234567, SmppError::ESME_RINVBNDSTS);
assert_eq!(unbind_resp.header.command_status, 0x00000004);
}
#[test]
fn unbind_resp_get_error() {
let unbind_resp = unbind::generic_reject(0x1234567, SmppError::ESME_RINVBNDSTS);
assert_eq!(unbind_resp.get_error(), SmppError::ESME_RINVBNDSTS);
}
#[test]
fn encode_unbind_resp() {
let unbind_resp = unbind::generic_reject(0x12344567, SmppError::ESME_RINVBNDSTS);
let pdu = unbind_resp.encode();
assert_eq!(
pdu,
vec![
0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x12,
0x34, 0x45, 0x67
]
);
}
}
}