use crate::error::PfcpError;
use crate::ie::{Ie, IeType};
use crate::message::{header::Header, Message, MsgType};
use crate::types::{Seid, SequenceNumber};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionModificationResponse {
pub header: Header,
pub cause: Ie, pub offending_ie: Option<Ie>, pub created_pdr: Option<Ie>, pub load_control_information: Option<Ie>, pub overload_control_information: Option<Ie>, pub usage_reports: Vec<Ie>, pub failed_rule_id: Option<Ie>, pub partial_failure_information: Vec<Ie>, pub additional_usage_reports_information: Option<Ie>, pub created_traffic_endpoints: Vec<Ie>, pub tsc_management_information: Vec<Ie>, pub atsss_control_parameters: Option<Ie>, pub updated_pdrs: Vec<Ie>, pub packet_rate_status_reports: Vec<Ie>, pub mbs_session_n4_information: Vec<Ie>, pub pdn_type: Option<Ie>, pub ies: Vec<Ie>,
}
impl Message for SessionModificationResponse {
fn marshal(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(self.marshaled_size());
self.marshal_into(&mut buf);
buf
}
fn marshal_into(&self, buf: &mut Vec<u8>) {
buf.reserve(self.marshaled_size());
self.header.marshal_into(buf);
self.cause.marshal_into(buf);
if let Some(ref ie) = self.offending_ie {
ie.marshal_into(buf);
}
if let Some(ref ie) = self.created_pdr {
ie.marshal_into(buf);
}
if let Some(ref ie) = self.load_control_information {
ie.marshal_into(buf);
}
if let Some(ref ie) = self.overload_control_information {
ie.marshal_into(buf);
}
if let Some(ref ie) = self.pdn_type {
ie.marshal_into(buf);
}
for ie in &self.usage_reports {
ie.marshal_into(buf);
}
if let Some(ref ie) = self.failed_rule_id {
ie.marshal_into(buf);
}
for ie in &self.partial_failure_information {
ie.marshal_into(buf);
}
if let Some(ref ie) = self.additional_usage_reports_information {
ie.marshal_into(buf);
}
for ie in &self.created_traffic_endpoints {
ie.marshal_into(buf);
}
for ie in &self.tsc_management_information {
ie.marshal_into(buf);
}
if let Some(ref ie) = self.atsss_control_parameters {
ie.marshal_into(buf);
}
for ie in &self.updated_pdrs {
ie.marshal_into(buf);
}
for ie in &self.packet_rate_status_reports {
ie.marshal_into(buf);
}
for ie in &self.mbs_session_n4_information {
ie.marshal_into(buf);
}
for ie in &self.ies {
ie.marshal_into(buf);
}
}
fn marshaled_size(&self) -> usize {
let mut size = self.header.len() as usize;
size += self.cause.len() as usize;
if let Some(ref ie) = self.offending_ie {
size += ie.len() as usize;
}
if let Some(ref ie) = self.created_pdr {
size += ie.len() as usize;
}
if let Some(ref ie) = self.load_control_information {
size += ie.len() as usize;
}
if let Some(ref ie) = self.overload_control_information {
size += ie.len() as usize;
}
if let Some(ref ie) = self.pdn_type {
size += ie.len() as usize;
}
for ie in &self.usage_reports {
size += ie.len() as usize;
}
if let Some(ref ie) = self.failed_rule_id {
size += ie.len() as usize;
}
for ie in &self.partial_failure_information {
size += ie.len() as usize;
}
if let Some(ref ie) = self.additional_usage_reports_information {
size += ie.len() as usize;
}
for ie in &self.created_traffic_endpoints {
size += ie.len() as usize;
}
for ie in &self.tsc_management_information {
size += ie.len() as usize;
}
if let Some(ref ie) = self.atsss_control_parameters {
size += ie.len() as usize;
}
for ie in &self.updated_pdrs {
size += ie.len() as usize;
}
for ie in &self.packet_rate_status_reports {
size += ie.len() as usize;
}
for ie in &self.mbs_session_n4_information {
size += ie.len() as usize;
}
for ie in &self.ies {
size += ie.len() as usize;
}
size
}
fn unmarshal(data: &[u8]) -> Result<Self, PfcpError> {
let header = Header::unmarshal(data)?;
let mut cause = None;
let mut offending_ie = None;
let mut created_pdr = None;
let mut load_control_information = None;
let mut overload_control_information = None;
let mut pdn_type = None;
let mut usage_reports = Vec::new();
let mut failed_rule_id = None;
let mut partial_failure_information = Vec::new();
let mut additional_usage_reports_information = None;
let mut created_traffic_endpoints = Vec::new();
let mut tsc_management_information = Vec::new();
let mut atsss_control_parameters = None;
let mut updated_pdrs = Vec::new();
let mut packet_rate_status_reports = Vec::new();
let mut mbs_session_n4_information = Vec::new();
let mut ies = Vec::new();
let mut offset = header.len() as usize;
while offset < data.len() {
let ie = Ie::unmarshal(&data[offset..])?;
let ie_len = ie.len() as usize;
match ie.ie_type {
IeType::Cause => cause = Some(ie),
IeType::OffendingIe => offending_ie = Some(ie),
IeType::CreatedPdr => created_pdr = Some(ie),
IeType::LoadControlInformation => load_control_information = Some(ie),
IeType::OverloadControlInformation => overload_control_information = Some(ie),
IeType::PdnType => pdn_type = Some(ie),
IeType::UsageReportWithinSessionModificationResponse => usage_reports.push(ie),
IeType::FailedRuleId => failed_rule_id = Some(ie),
IeType::PartialFailureInformation => partial_failure_information.push(ie),
IeType::AdditionalUsageReportsInformation => {
additional_usage_reports_information = Some(ie)
}
IeType::CreatedTrafficEndpoint => created_traffic_endpoints.push(ie),
IeType::TscManagementInformationWithinSessionModificationResponse => {
tsc_management_information.push(ie)
}
IeType::AtsssControlParameters => atsss_control_parameters = Some(ie),
IeType::UpdatedPdr => updated_pdrs.push(ie),
IeType::PacketRateStatusReportWithinSessionModificationResponse => {
packet_rate_status_reports.push(ie)
}
IeType::MbsSessionN4Information => mbs_session_n4_information.push(ie),
_ => ies.push(ie),
}
offset += ie_len;
}
Ok(SessionModificationResponse {
header,
cause: cause.ok_or(PfcpError::MissingMandatoryIe {
ie_type: IeType::Cause,
message_type: Some(MsgType::SessionModificationResponse),
parent_ie: None,
})?,
offending_ie,
created_pdr,
load_control_information,
overload_control_information,
pdn_type,
usage_reports,
failed_rule_id,
partial_failure_information,
additional_usage_reports_information,
created_traffic_endpoints,
tsc_management_information,
atsss_control_parameters,
updated_pdrs,
packet_rate_status_reports,
mbs_session_n4_information,
ies,
})
}
fn msg_type(&self) -> MsgType {
MsgType::SessionModificationResponse
}
fn seid(&self) -> Option<Seid> {
if self.header.has_seid {
Some(self.header.seid)
} else {
None
}
}
fn sequence(&self) -> SequenceNumber {
self.header.sequence_number
}
fn set_sequence(&mut self, seq: SequenceNumber) {
self.header.sequence_number = seq;
}
fn ies(&self, ie_type: IeType) -> crate::message::IeIter<'_> {
use crate::message::IeIter;
match ie_type {
IeType::Cause => IeIter::single(Some(&self.cause), ie_type),
IeType::OffendingIe => IeIter::single(self.offending_ie.as_ref(), ie_type),
IeType::CreatedPdr => IeIter::single(self.created_pdr.as_ref(), ie_type),
IeType::LoadControlInformation => {
IeIter::single(self.load_control_information.as_ref(), ie_type)
}
IeType::OverloadControlInformation => {
IeIter::single(self.overload_control_information.as_ref(), ie_type)
}
IeType::PdnType => IeIter::single(self.pdn_type.as_ref(), ie_type),
IeType::UsageReportWithinSessionModificationResponse => {
IeIter::multiple(&self.usage_reports, ie_type)
}
IeType::FailedRuleId => IeIter::single(self.failed_rule_id.as_ref(), ie_type),
IeType::PartialFailureInformation => {
IeIter::multiple(&self.partial_failure_information, ie_type)
}
IeType::AdditionalUsageReportsInformation => {
IeIter::single(self.additional_usage_reports_information.as_ref(), ie_type)
}
IeType::CreatedTrafficEndpoint => {
IeIter::multiple(&self.created_traffic_endpoints, ie_type)
}
IeType::TscManagementInformationWithinSessionModificationResponse => {
IeIter::multiple(&self.tsc_management_information, ie_type)
}
IeType::AtsssControlParameters => {
IeIter::single(self.atsss_control_parameters.as_ref(), ie_type)
}
IeType::UpdatedPdr => IeIter::multiple(&self.updated_pdrs, ie_type),
IeType::PacketRateStatusReportWithinSessionModificationResponse => {
IeIter::multiple(&self.packet_rate_status_reports, ie_type)
}
IeType::MbsSessionN4Information => {
IeIter::multiple(&self.mbs_session_n4_information, ie_type)
}
_ => IeIter::generic(&self.ies, ie_type),
}
}
fn all_ies(&self) -> Vec<&Ie> {
let mut result = vec![&self.cause];
if let Some(ref ie) = self.offending_ie {
result.push(ie);
}
if let Some(ref ie) = self.created_pdr {
result.push(ie);
}
if let Some(ref ie) = self.load_control_information {
result.push(ie);
}
if let Some(ref ie) = self.overload_control_information {
result.push(ie);
}
if let Some(ref ie) = self.pdn_type {
result.push(ie);
}
result.extend(self.usage_reports.iter());
if let Some(ref ie) = self.failed_rule_id {
result.push(ie);
}
result.extend(self.partial_failure_information.iter());
if let Some(ref ie) = self.additional_usage_reports_information {
result.push(ie);
}
result.extend(self.created_traffic_endpoints.iter());
result.extend(self.tsc_management_information.iter());
if let Some(ref ie) = self.atsss_control_parameters {
result.push(ie);
}
result.extend(self.updated_pdrs.iter());
result.extend(self.packet_rate_status_reports.iter());
result.extend(self.mbs_session_n4_information.iter());
result.extend(self.ies.iter());
result
}
}
impl SessionModificationResponse {
#[allow(clippy::too_many_arguments)]
pub fn new(
seid: impl Into<Seid>,
seq: impl Into<SequenceNumber>,
cause_ie: Ie,
offending_ie: Option<Ie>,
created_pdr: Option<Ie>,
load_control_information: Option<Ie>,
overload_control_information: Option<Ie>,
pdn_type: Option<Ie>,
usage_reports: Vec<Ie>,
failed_rule_id: Option<Ie>,
partial_failure_information: Vec<Ie>,
additional_usage_reports_information: Option<Ie>,
created_traffic_endpoints: Vec<Ie>,
updated_pdrs: Vec<Ie>,
ies: Vec<Ie>,
) -> Self {
let mut header = Header::new(MsgType::SessionModificationResponse, true, seid, seq);
let mut payload_len = cause_ie.len();
if let Some(ie) = &offending_ie {
payload_len += ie.len();
}
if let Some(ie) = &created_pdr {
payload_len += ie.len();
}
if let Some(ie) = &load_control_information {
payload_len += ie.len();
}
if let Some(ie) = &overload_control_information {
payload_len += ie.len();
}
if let Some(ie) = &pdn_type {
payload_len += ie.len();
}
for ie in &usage_reports {
payload_len += ie.len();
}
if let Some(ie) = &failed_rule_id {
payload_len += ie.len();
}
for ie in &partial_failure_information {
payload_len += ie.len();
}
if let Some(ie) = &additional_usage_reports_information {
payload_len += ie.len();
}
for ie in &created_traffic_endpoints {
payload_len += ie.len();
}
for ie in &updated_pdrs {
payload_len += ie.len();
}
for ie in &ies {
payload_len += ie.len();
}
header.length = payload_len + header.len() - 4;
SessionModificationResponse {
header,
cause: cause_ie,
offending_ie,
created_pdr,
load_control_information,
overload_control_information,
pdn_type,
usage_reports,
failed_rule_id,
partial_failure_information,
additional_usage_reports_information,
created_traffic_endpoints,
tsc_management_information: Vec::new(),
atsss_control_parameters: None,
updated_pdrs,
packet_rate_status_reports: Vec::new(),
mbs_session_n4_information: Vec::new(),
ies,
}
}
}
#[derive(Debug, Default)]
pub struct SessionModificationResponseBuilder {
seid: Seid,
sequence: SequenceNumber,
cause: Option<Ie>,
offending_ie: Option<Ie>,
created_pdr: Option<Ie>,
load_control_information: Option<Ie>,
overload_control_information: Option<Ie>,
pdn_type: Option<Ie>,
usage_reports: Vec<Ie>,
failed_rule_id: Option<Ie>,
partial_failure_information: Vec<Ie>,
additional_usage_reports_information: Option<Ie>,
created_traffic_endpoints: Vec<Ie>,
tsc_management_information: Vec<Ie>,
atsss_control_parameters: Option<Ie>,
updated_pdrs: Vec<Ie>,
packet_rate_status_reports: Vec<Ie>,
mbs_session_n4_information: Vec<Ie>,
ies: Vec<Ie>,
}
impl SessionModificationResponseBuilder {
pub fn accepted(seid: impl Into<Seid>, sequence: impl Into<SequenceNumber>) -> Self {
Self::new(seid, sequence).cause_accepted()
}
pub fn new(seid: impl Into<Seid>, sequence: impl Into<SequenceNumber>) -> Self {
Self {
seid: seid.into(),
sequence: sequence.into(),
cause: None,
offending_ie: None,
created_pdr: None,
load_control_information: None,
overload_control_information: None,
pdn_type: None,
usage_reports: Vec::new(),
failed_rule_id: None,
partial_failure_information: Vec::new(),
additional_usage_reports_information: None,
created_traffic_endpoints: Vec::new(),
tsc_management_information: Vec::new(),
atsss_control_parameters: None,
updated_pdrs: Vec::new(),
packet_rate_status_reports: Vec::new(),
mbs_session_n4_information: Vec::new(),
ies: Vec::new(),
}
}
pub fn cause(mut self, cause_value: crate::ie::cause::CauseValue) -> Self {
use crate::ie::cause::Cause;
use crate::ie::{Ie, IeType};
let cause = Cause::new(cause_value);
self.cause = Some(Ie::new(IeType::Cause, cause.marshal().to_vec()));
self
}
pub fn cause_accepted(self) -> Self {
self.cause(crate::ie::cause::CauseValue::RequestAccepted)
}
pub fn cause_rejected(self) -> Self {
self.cause(crate::ie::cause::CauseValue::RequestRejected)
}
pub fn cause_ie(mut self, cause: Ie) -> Self {
self.cause = Some(cause);
self
}
pub fn offending_ie(mut self, offending_ie: Ie) -> Self {
self.offending_ie = Some(offending_ie);
self
}
pub fn created_pdr(mut self, created_pdr: Ie) -> Self {
self.created_pdr = Some(created_pdr);
self
}
pub fn load_control_information(mut self, load_control_information: Ie) -> Self {
self.load_control_information = Some(load_control_information);
self
}
pub fn overload_control_information(mut self, overload_control_information: Ie) -> Self {
self.overload_control_information = Some(overload_control_information);
self
}
pub fn pdn_type(mut self, pdn_type: Ie) -> Self {
self.pdn_type = Some(pdn_type);
self
}
pub fn usage_reports(mut self, mut usage_reports: Vec<Ie>) -> Self {
self.usage_reports.append(&mut usage_reports);
self
}
pub fn usage_report(mut self, usage_report: Ie) -> Self {
self.usage_reports.push(usage_report);
self
}
pub fn failed_rule_id(mut self, ie: Ie) -> Self {
self.failed_rule_id = Some(ie);
self
}
pub fn partial_failure_information(mut self, ie: Ie) -> Self {
self.partial_failure_information.push(ie);
self
}
pub fn additional_usage_reports_information(mut self, ie: Ie) -> Self {
self.additional_usage_reports_information = Some(ie);
self
}
pub fn created_traffic_endpoint(mut self, ie: Ie) -> Self {
self.created_traffic_endpoints.push(ie);
self
}
pub fn tsc_management_information(mut self, ie: Ie) -> Self {
self.tsc_management_information.push(ie);
self
}
pub fn atsss_control_parameters(mut self, ie: Ie) -> Self {
self.atsss_control_parameters = Some(ie);
self
}
pub fn updated_pdr(mut self, ie: Ie) -> Self {
self.updated_pdrs.push(ie);
self
}
pub fn packet_rate_status_report(mut self, ie: Ie) -> Self {
self.packet_rate_status_reports.push(ie);
self
}
pub fn add_mbs_session_n4_information(mut self, ie: Ie) -> Self {
self.mbs_session_n4_information.push(ie);
self
}
pub fn ie(mut self, ie: Ie) -> Self {
self.ies.push(ie);
self
}
pub fn ies(mut self, mut ies: Vec<Ie>) -> Self {
self.ies.append(&mut ies);
self
}
pub fn build(self) -> SessionModificationResponse {
self.try_build()
.expect("Cause IE is required for SessionModificationResponse")
}
pub fn try_build(self) -> Result<SessionModificationResponse, &'static str> {
let cause = self
.cause
.ok_or("Cause IE is required for SessionModificationResponse")?;
let mut header = Header::new(
MsgType::SessionModificationResponse,
true,
self.seid,
self.sequence,
);
let mut payload_len = cause.len();
if let Some(ie) = &self.offending_ie {
payload_len += ie.len();
}
if let Some(ie) = &self.created_pdr {
payload_len += ie.len();
}
if let Some(ie) = &self.load_control_information {
payload_len += ie.len();
}
if let Some(ie) = &self.overload_control_information {
payload_len += ie.len();
}
if let Some(ie) = &self.pdn_type {
payload_len += ie.len();
}
for ie in &self.usage_reports {
payload_len += ie.len();
}
if let Some(ie) = &self.failed_rule_id {
payload_len += ie.len();
}
for ie in &self.partial_failure_information {
payload_len += ie.len();
}
if let Some(ie) = &self.additional_usage_reports_information {
payload_len += ie.len();
}
for ie in &self.created_traffic_endpoints {
payload_len += ie.len();
}
for ie in &self.tsc_management_information {
payload_len += ie.len();
}
if let Some(ie) = &self.atsss_control_parameters {
payload_len += ie.len();
}
for ie in &self.updated_pdrs {
payload_len += ie.len();
}
for ie in &self.packet_rate_status_reports {
payload_len += ie.len();
}
for ie in &self.mbs_session_n4_information {
payload_len += ie.len();
}
for ie in &self.ies {
payload_len += ie.len();
}
header.length = payload_len + header.len() - 4;
Ok(SessionModificationResponse {
header,
cause,
offending_ie: self.offending_ie,
created_pdr: self.created_pdr,
load_control_information: self.load_control_information,
overload_control_information: self.overload_control_information,
pdn_type: self.pdn_type,
usage_reports: self.usage_reports,
failed_rule_id: self.failed_rule_id,
partial_failure_information: self.partial_failure_information,
additional_usage_reports_information: self.additional_usage_reports_information,
created_traffic_endpoints: self.created_traffic_endpoints,
tsc_management_information: self.tsc_management_information,
atsss_control_parameters: self.atsss_control_parameters,
updated_pdrs: self.updated_pdrs,
packet_rate_status_reports: self.packet_rate_status_reports,
mbs_session_n4_information: self.mbs_session_n4_information,
ies: self.ies,
})
}
pub fn marshal(self) -> Vec<u8> {
self.build().marshal()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ie::cause::*;
use crate::ie::sequence_number::SequenceNumber;
use crate::ie::urr_id::UrrId;
use crate::ie::usage_report::UsageReportBuilder;
use crate::ie::usage_report_smr::UsageReportSmr;
#[test]
fn test_session_modification_response_builder_minimal() {
let cause = Cause::new(CauseValue::RequestAccepted);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let response = SessionModificationResponseBuilder::new(12345, 67890)
.cause_ie(cause_ie.clone())
.build();
assert_eq!(*response.sequence(), 67890);
assert_eq!(response.seid(), Some(Seid(12345)));
assert_eq!(response.msg_type(), MsgType::SessionModificationResponse);
assert_eq!(response.cause, cause_ie);
assert!(response.offending_ie.is_none());
assert!(response.created_pdr.is_none());
assert!(response.pdn_type.is_none());
assert!(response.ies.is_empty());
}
#[test]
fn test_session_modification_response_builder_with_offending_ie() {
let cause = Cause::new(CauseValue::MandatoryIeMissing);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let offending_ie = Ie::new(IeType::OffendingIe, vec![0x00, 0x01]);
let response = SessionModificationResponseBuilder::new(11111, 22222)
.cause_ie(cause_ie.clone())
.offending_ie(offending_ie.clone())
.build();
assert_eq!(*response.sequence(), 22222);
assert_eq!(response.seid(), Some(Seid(11111)));
assert_eq!(response.cause, cause_ie);
assert_eq!(response.offending_ie, Some(offending_ie));
assert!(response.created_pdr.is_none());
assert!(response.pdn_type.is_none());
}
#[test]
fn test_session_modification_response_builder_with_created_pdr() {
let cause = Cause::new(CauseValue::RequestAccepted);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let created_pdr_ie = Ie::new(IeType::CreatedPdr, vec![0x01, 0x02, 0x03, 0x04]);
let response = SessionModificationResponseBuilder::new(33333, 44444)
.cause_ie(cause_ie.clone())
.created_pdr(created_pdr_ie.clone())
.build();
assert_eq!(*response.sequence(), 44444);
assert_eq!(response.seid(), Some(Seid(33333)));
assert_eq!(response.cause, cause_ie);
assert_eq!(response.created_pdr, Some(created_pdr_ie));
assert!(response.offending_ie.is_none());
assert!(response.pdn_type.is_none());
}
#[test]
fn test_session_modification_response_builder_with_pdn_type() {
let cause = Cause::new(CauseValue::RequestAccepted);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let pdn_type_ie = Ie::new(IeType::PdnType, vec![0x01]);
let response = SessionModificationResponseBuilder::new(55555, 66666)
.cause_ie(cause_ie.clone())
.pdn_type(pdn_type_ie.clone())
.build();
assert_eq!(*response.sequence(), 66666);
assert_eq!(response.seid(), Some(Seid(55555)));
assert_eq!(response.cause, cause_ie);
assert_eq!(response.pdn_type, Some(pdn_type_ie));
assert!(response.offending_ie.is_none());
assert!(response.created_pdr.is_none());
}
#[test]
fn test_session_modification_response_builder_with_additional_ies() {
let cause = Cause::new(CauseValue::RequestAccepted);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let ie1 = Ie::new(IeType::Unknown, vec![0xAA, 0xBB]);
let ie2 = Ie::new(IeType::Unknown, vec![0xCC, 0xDD]);
let ie3 = Ie::new(IeType::Unknown, vec![0xEE, 0xFF]);
let response = SessionModificationResponseBuilder::new(77777, 88888)
.cause_ie(cause_ie.clone())
.ie(ie1.clone())
.ies(vec![ie2.clone(), ie3.clone()])
.build();
assert_eq!(*response.sequence(), 88888);
assert_eq!(response.seid(), Some(Seid(77777)));
assert_eq!(response.cause, cause_ie);
assert_eq!(response.ies.len(), 3);
assert_eq!(response.ies[0], ie1);
assert_eq!(response.ies[1], ie2);
assert_eq!(response.ies[2], ie3);
}
#[test]
fn test_session_modification_response_builder_full() {
let cause = Cause::new(CauseValue::RequestAccepted);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let created_pdr_ie = Ie::new(IeType::CreatedPdr, vec![0x01, 0x02, 0x03]);
let pdn_type_ie = Ie::new(IeType::PdnType, vec![0x02]); let additional_ie = Ie::new(IeType::Unknown, vec![0xFF, 0xEE, 0xDD]);
let response = SessionModificationResponseBuilder::new(99999, 11110)
.cause_ie(cause_ie.clone())
.created_pdr(created_pdr_ie.clone())
.pdn_type(pdn_type_ie.clone())
.ie(additional_ie.clone())
.build();
assert_eq!(*response.sequence(), 11110);
assert_eq!(response.seid(), Some(Seid(99999)));
assert_eq!(response.cause, cause_ie);
assert_eq!(response.created_pdr, Some(created_pdr_ie));
assert_eq!(response.pdn_type, Some(pdn_type_ie));
assert_eq!(response.ies.len(), 1);
assert_eq!(response.ies[0], additional_ie);
}
#[test]
fn test_session_modification_response_builder_try_build_success() {
let cause = Cause::new(CauseValue::RequestAccepted);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let result = SessionModificationResponseBuilder::new(12345, 67890)
.cause_ie(cause_ie.clone())
.try_build();
assert!(result.is_ok());
let response = result.unwrap();
assert_eq!(*response.sequence(), 67890);
assert_eq!(response.seid(), Some(Seid(12345)));
assert_eq!(response.cause, cause_ie);
}
#[test]
fn test_session_modification_response_builder_try_build_missing_cause() {
let result = SessionModificationResponseBuilder::new(12345, 67890).try_build();
assert!(result.is_err());
assert_eq!(
result.unwrap_err(),
"Cause IE is required for SessionModificationResponse"
);
}
#[test]
#[should_panic(expected = "Cause IE is required for SessionModificationResponse")]
fn test_session_modification_response_builder_build_panic() {
SessionModificationResponseBuilder::new(12345, 67890).build();
}
#[test]
fn test_session_modification_response_builder_roundtrip() {
let cause = Cause::new(CauseValue::RuleCreationModificationFailure);
let cause_ie = Ie::new(IeType::Cause, cause.marshal().to_vec());
let offending_ie = Ie::new(IeType::OffendingIe, vec![0x12, 0x34]);
let created_pdr_ie = Ie::new(IeType::CreatedPdr, vec![0xAB, 0xCD, 0xEF]);
let original = SessionModificationResponseBuilder::new(12345, 67890)
.cause_ie(cause_ie)
.offending_ie(offending_ie)
.created_pdr(created_pdr_ie)
.build();
let marshaled = original.marshal();
let unmarshaled = SessionModificationResponse::unmarshal(&marshaled).unwrap();
assert_eq!(original, unmarshaled);
}
#[test]
fn test_session_modification_response_with_usage_reports() {
let usage_report =
UsageReportBuilder::quota_exhausted_report(UrrId::new(1), SequenceNumber::new(100))
.with_volume_data(5000000, 3000000, 2000000)
.build()
.unwrap();
let usage_report_smr = UsageReportSmr::new(usage_report);
let usage_report_ie = usage_report_smr.to_ie();
assert_eq!(
usage_report_ie.ie_type,
IeType::UsageReportWithinSessionModificationResponse
);
let response = SessionModificationResponseBuilder::new(12345, 67890)
.cause_accepted()
.usage_report(usage_report_ie.clone())
.build();
assert_eq!(response.usage_reports.len(), 1);
assert_eq!(response.usage_reports[0], usage_report_ie);
assert_eq!(
response
.ies(IeType::UsageReportWithinSessionModificationResponse)
.next(),
Some(&usage_report_ie)
);
let marshaled = response.marshal();
let unmarshaled = SessionModificationResponse::unmarshal(&marshaled).unwrap();
assert_eq!(response, unmarshaled);
assert_eq!(unmarshaled.usage_reports.len(), 1);
}
#[test]
fn test_session_modification_response_with_multiple_usage_reports() {
let usage_report1 = UsageReportSmr::new(
UsageReportBuilder::periodic_usage_report(UrrId::new(1), SequenceNumber::new(1))
.build()
.unwrap(),
);
let usage_report2 = UsageReportSmr::new(
UsageReportBuilder::volume_threshold_report(UrrId::new(2), SequenceNumber::new(2))
.build()
.unwrap(),
);
let response = SessionModificationResponseBuilder::new(11111, 22222)
.cause_accepted()
.usage_reports(vec![usage_report1.to_ie(), usage_report2.to_ie()])
.build();
assert_eq!(response.usage_reports.len(), 2);
let marshaled = response.marshal();
let unmarshaled = SessionModificationResponse::unmarshal(&marshaled).unwrap();
assert_eq!(response, unmarshaled);
}
}