mirror of
https://github.com/mii443/miibgpd.git
synced 2025-08-22 15:55:26 +00:00
connect state
This commit is contained in:
14
src/bgp_type.rs
Normal file
14
src/bgp_type.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash, PartialOrd, Ord)]
|
||||
pub struct AutonomousSystemNumber(u16);
|
||||
|
||||
impl From<AutonomousSystemNumber> for u16 {
|
||||
fn from(as_number: AutonomousSystemNumber) -> u16 {
|
||||
as_number.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for AutonomousSystemNumber {
|
||||
fn from(as_number: u16) -> Self {
|
||||
Self(as_number)
|
||||
}
|
||||
}
|
76
src/config.rs
Normal file
76
src/config.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
use crate::{bgp_type::AutonomousSystemNumber, error::ConfigParseError};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, PartialOrd, Ord)]
|
||||
pub struct Config {
|
||||
pub local_as: AutonomousSystemNumber,
|
||||
pub local_ip: IpAddr,
|
||||
pub remote_as: AutonomousSystemNumber,
|
||||
pub remote_ip: IpAddr,
|
||||
pub mode: Mode,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash, PartialOrd, Ord)]
|
||||
pub enum Mode {
|
||||
Passive,
|
||||
Active,
|
||||
}
|
||||
|
||||
impl FromStr for Mode {
|
||||
type Err = ConfigParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"passive" | "Passive" => Ok(Mode::Passive),
|
||||
"active" | "Active" => Ok(Mode::Active),
|
||||
_ => Err(ConfigParseError::from(anyhow::anyhow!("cannot parse {s}"))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Config {
|
||||
type Err = ConfigParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let config: Vec<&str> = s.split(' ').collect();
|
||||
|
||||
let local_as = AutonomousSystemNumber::from(config[0].parse::<u16>().context(format!(
|
||||
"cannot parse 1st part of config, '{0}', as as-number and config is {1}",
|
||||
config[0], s
|
||||
))?);
|
||||
|
||||
let local_ip: Ipv4Addr = config[1].parse().context(format!(
|
||||
"cannot parse 2nd part of config, '{0}', as ip-address and config is {1}",
|
||||
config[1], s
|
||||
))?;
|
||||
|
||||
let remote_as = AutonomousSystemNumber::from(config[2].parse::<u16>().context(format!(
|
||||
"cannot parse 3rd part of config, '{0}', as as-number and config is {1}",
|
||||
config[2], s
|
||||
))?);
|
||||
|
||||
let remote_ip: Ipv4Addr = config[3].parse().context(format!(
|
||||
"cannot parse 4th part of config, '{0}', as ip-address and config is {1}",
|
||||
config[3], s
|
||||
))?;
|
||||
|
||||
let mode = Mode::from_str(config[4]).context(format!(
|
||||
"cannot parse 5th part of config, '{0}', as mode and config is {1}",
|
||||
config[4], s
|
||||
))?;
|
||||
|
||||
Ok(Config {
|
||||
local_as,
|
||||
local_ip: IpAddr::V4(local_ip),
|
||||
remote_as,
|
||||
remote_ip: IpAddr::V4(remote_ip),
|
||||
mode,
|
||||
})
|
||||
}
|
||||
}
|
8
src/error.rs
Normal file
8
src/error.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct ConfigParseError {
|
||||
#[from]
|
||||
source: anyhow::Error,
|
||||
}
|
4
src/event.rs
Normal file
4
src/event.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash)]
|
||||
pub enum Event {
|
||||
ManualStart,
|
||||
}
|
20
src/event_queue.rs
Normal file
20
src/event_queue.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use crate::event::Event;
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct EventQueue(VecDeque<Event>);
|
||||
|
||||
impl EventQueue {
|
||||
pub fn new() -> Self {
|
||||
Self(VecDeque::new())
|
||||
}
|
||||
|
||||
pub fn enqueue(&mut self, event: Event) {
|
||||
self.0.push_front(event);
|
||||
}
|
||||
|
||||
pub fn dequeue(&mut self) -> Option<Event> {
|
||||
self.0.pop_back()
|
||||
}
|
||||
}
|
9
src/lib.rs
Normal file
9
src/lib.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![allow(dead_code, unused)]
|
||||
|
||||
mod bgp_type;
|
||||
pub mod config;
|
||||
mod error;
|
||||
mod event;
|
||||
mod event_queue;
|
||||
pub mod peer;
|
||||
mod state;
|
@ -1,3 +1 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
fn main() {}
|
||||
|
63
src/peer.rs
Normal file
63
src/peer.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use tracing::info;
|
||||
|
||||
use crate::{config::Config, event::Event, event_queue::EventQueue, state::State};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Peer {
|
||||
state: State,
|
||||
event_queue: EventQueue,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl Peer {
|
||||
pub fn new(config: Config) -> Self {
|
||||
let state = State::Idle;
|
||||
let event_queue = EventQueue::new();
|
||||
|
||||
Self {
|
||||
state,
|
||||
event_queue,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
info!("peer started");
|
||||
self.event_queue.enqueue(Event::ManualStart);
|
||||
}
|
||||
|
||||
pub async fn next(&mut self) {
|
||||
if let Some(event) = self.event_queue.dequeue() {
|
||||
info!("event occurred, event={:?}", event);
|
||||
self.handle_event(event).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_event(&mut self, event: Event) {
|
||||
match &self.state {
|
||||
State::Idle => match event {
|
||||
Event::ManualStart => {
|
||||
self.state = State::Connect;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::config::Config;
|
||||
use crate::peer::Peer;
|
||||
use crate::state::State;
|
||||
|
||||
#[tokio::test]
|
||||
async fn peer_can_transition_to_connect_state() {
|
||||
let config: Config = "64512 127.0.0.1 65413 127.0.0.2 active".parse().unwrap();
|
||||
let mut peer = Peer::new(config);
|
||||
peer.start();
|
||||
peer.next().await;
|
||||
assert_eq!(peer.state, State::Connect);
|
||||
}
|
||||
}
|
5
src/state.rs
Normal file
5
src/state.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
|
||||
pub enum State {
|
||||
Idle,
|
||||
Connect,
|
||||
}
|
Reference in New Issue
Block a user