use ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Clear, Paragraph};
use ratatui::Frame;
pub fn render(f: &mut Frame<'_>, area: Rect) {
f.render_widget(Clear, area);
let outer = Block::default()
.borders(Borders::ALL)
.title(" TLS Handshake Reference [d] close ");
let inner = outer.inner(area);
f.render_widget(outer, area);
let cols = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(55), Constraint::Percentage(45)])
.split(inner);
f.render_widget(tls12_widget(), cols[0]);
f.render_widget(tls13_widget(), cols[1]);
}
fn tls12_widget() -> Paragraph<'static> {
let h = Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD);
let arrow = Style::default().fg(Color::Cyan);
let enc = Style::default().fg(Color::Magenta);
let bar = Style::default().fg(Color::DarkGray);
let note = Style::default().fg(Color::DarkGray);
let b = |s: &'static str| Span::styled(s, bar);
let a = |s: &'static str| Span::styled(s, arrow);
let e = |s: &'static str| Span::styled(s, enc);
let n = |s: &'static str| Span::styled(s, note);
let lines: Vec<Line> = vec![
Line::from(vec![
Span::styled("CLIENT", h),
Span::raw(" "),
Span::styled("SERVER", h),
]),
Line::from(vec![b(" │ │")]),
Line::from(vec![a("① ├──── ClientHello ─────────►│")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![a(" │◄──── ServerHello ──────────┤"), Span::raw(" ②")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![a(" │◄──── ServerCert ───────────┤"), Span::raw(" ③")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![
a(" │◄──── SvrKeyExchange ────────┤"),
Span::raw(" ④"),
n(" (DHE)"),
]),
Line::from(vec![b(" │ │")]),
Line::from(vec![
a(" │◄──── SvrHelloDone ──────────┤"),
Span::raw(" ⑥"),
]),
Line::from(vec![b(" │ │")]),
Line::from(vec![a("⑦ ├──── CltKeyExchange ─────────►│")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![n(" ├╌╌╌╌ ChangeCipherSpec ╌╌╌╌╌►│")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![e("⑩ ├──── Clt Finished ───────────►│ E")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![n(" │◄╌╌╌╌ ChangeCipherSpec ╌╌╌╌╌╌┤")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![e(" │◄──── Svr Finished ───────────┤"), e(" ⑫E")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![e("⑬ ├◄─── App Data ──────────────►│ E")]),
Line::from(vec![b(" │ │")]),
];
Paragraph::new(lines).block(
Block::default()
.borders(Borders::RIGHT)
.title("TLS 1.2 (Full Handshake)"),
)
}
fn tls13_widget() -> Paragraph<'static> {
let h = Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD);
let arrow = Style::default().fg(Color::Cyan);
let enc = Style::default().fg(Color::Magenta);
let bar = Style::default().fg(Color::DarkGray);
let b = |s: &'static str| Span::styled(s, bar);
let a = |s: &'static str| Span::styled(s, arrow);
let e = |s: &'static str| Span::styled(s, enc);
let lines: Vec<Line> = vec![
Line::from(vec![
Span::styled("CLIENT", h),
Span::raw(" "),
Span::styled("SERVER", h),
]),
Line::from(vec![b(" │ │")]),
Line::from(vec![a("① ├── ClientHello ──────►│")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![a(" │◄── ServerHello ───────┤"), Span::raw(" ②")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![e(" │◄── Certificate ────────┤"), e(" ③E")]),
Line::from(vec![e(" │ (EncExt+Cert+Verify) │")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![e("④ ├── Clt Finished ─────►│ E")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![e(" │◄── Svr Finished ───────┤"), e(" ⑤E")]),
Line::from(vec![b(" │ │")]),
Line::from(vec![e("⑥ ├◄── App Data ──────────►│ E")]),
Line::from(vec![b(" │ │")]),
Line::from(""),
Line::from(""),
Line::from(""),
Line::from(""),
Line::from(""),
Line::from(""),
Line::from(""),
];
Paragraph::new(lines).block(
Block::default()
.borders(Borders::NONE)
.title("TLS 1.3 (1-RTT)"),
)
}