use super::{
scenarioprinter::StrLit,
types::{Endpoint, ScenarioPrintingEnvironment},
};
pub fn tcp_common_bind_options(o: &mut String, env: &ScenarioPrintingEnvironment<'_>) {
if let Some(v) = env.opts.reuseaddr {
o.push_str(&format!("reuseaddr: {v},"));
}
if env.opts.reuseport {
o.push_str("reuseport: true,");
}
if let Some(ref v) = env.opts.socket_bind_to_device {
o.push_str(&format!("bind_device: {},", StrLit(v)));
}
if env.opts.socket_freebind {
o.push_str("freebind: true,");
}
if env.opts.socket_transparent {
o.push_str("transparent: true,");
}
if let Some(v) = env.opts.socket_only_v6 {
o.push_str(&format!("only_v6: {v},"));
}
}
fn tcp_common_stream_options(o: &mut String, env: &ScenarioPrintingEnvironment<'_>) {
if let Some(v) = env.opts.socket_tclass_v6 {
o.push_str(&format!("tclass_v6: {v},"));
}
if let Some(v) = env.opts.socket_tos_v4 {
o.push_str(&format!("tos_v4: {v},"));
}
if let Some(v) = env.opts.socket_ttl {
o.push_str(&format!("ttl: {v},"));
}
if let Some(v) = env.opts.socket_linger_s {
o.push_str(&format!("linger_s: {v},"));
}
if env.opts.socket_out_of_band_inline {
o.push_str("out_of_band_inline: true,");
}
if let Some(v) = env.opts.socket_nodelay {
o.push_str(&format!("nodelay: {v},"));
}
if let Some(ref v) = env.opts.socket_tcp_congestion {
o.push_str(&format!("tcp_congestion: {},", StrLit(v)));
}
if let Some(v) = env.opts.socket_cpu_affinity {
o.push_str(&format!("cpu_affinity: {v},"));
}
if let Some(v) = env.opts.socket_user_timeout_s {
o.push_str(&format!("user_timeout_s: {v},"));
}
if let Some(v) = env.opts.socket_priority {
o.push_str(&format!("priority: {v},"));
}
if let Some(v) = env.opts.socket_recv_buffer_size {
o.push_str(&format!("recv_buffer_size: {v},"));
}
if let Some(v) = env.opts.socket_send_buffer_size {
o.push_str(&format!("send_buffer_size: {v},"));
}
if let Some(v) = env.opts.socket_mss {
o.push_str(&format!("mss: {v},"));
}
if let Some(v) = env.opts.socket_mark {
o.push_str(&format!("mark: {v},"));
}
if let Some(v) = env.opts.socket_thin_linear_timeouts {
o.push_str(&format!("thin_linear_timeouts: {v},"));
}
if let Some(v) = env.opts.socket_notsent_lowat {
o.push_str(&format!("notsent_lowat: {v},"));
}
if let Some(v) = env.opts.socket_keepalive {
o.push_str(&format!("keepalive: {v},"));
}
if let Some(v) = env.opts.socket_keepalive_retries {
o.push_str(&format!("keepalive_retries: {v},"));
}
if let Some(v) = env.opts.socket_keepalive_interval_s {
o.push_str(&format!("keepalive_interval_s: {v},"));
}
if let Some(v) = env.opts.socket_keepalive_idletime_s {
o.push_str(&format!("keepalive_idletime_s: {v},"));
}
}
fn tcp_options_for_connect(o: &mut String, env: &ScenarioPrintingEnvironment<'_>) {
if !(env.used_for_a_websocket && env.opts.exclude_ws_from_sockopts) {
if let Some(bbc) = env.opts.bind_before_connect {
o.push_str(&format!("bind: {},", StrLit(bbc)));
}
tcp_common_bind_options(o, env);
tcp_common_stream_options(o, env);
}
}
impl Endpoint {
pub(super) fn begin_print_tcp(
&self,
env: &mut ScenarioPrintingEnvironment<'_>,
) -> anyhow::Result<String> {
match self {
Endpoint::TcpConnectByIp(addr) => {
let varnam = env.vars.getnewvarname("tcp");
let mut o = String::with_capacity(32);
o.push_str("addr: ");
o.push_str(&format!("{},", StrLit(addr)));
tcp_options_for_connect(&mut o, env);
env.printer
.print_line(&format!("connect_tcp(#{{{o}}}, |{varnam}| {{"));
env.printer.increase_indent();
Ok(varnam)
}
Endpoint::TcpConnectByEarlyHostname { varname_for_addrs } => {
let mut o = String::with_capacity(0);
tcp_options_for_connect(&mut o, env);
o.push_str(&format!(
"race_interval_ms: {},",
env.opts.tcp_race_interval_ms
));
let varnam = env.vars.getnewvarname("tcp");
env.printer.print_line(&format!(
"connect_tcp_race(#{{{o}}}, {varname_for_addrs}, |{varnam}| {{"
));
env.printer.increase_indent();
Ok(varnam)
}
Endpoint::TcpConnectByLateHostname { hostname } => {
let addrs = env.vars.getnewvarname("addrs");
env.printer.print_line(&format!(
"lookup_host({h}, |{addrs}| {{",
h = StrLit(hostname)
));
env.printer.increase_indent();
let varnam = env.vars.getnewvarname("tcp");
let mut o = String::with_capacity(0);
o.push_str(&format!(
"race_interval_ms: {},",
env.opts.tcp_race_interval_ms
));
tcp_options_for_connect(&mut o, env);
env.printer.print_line(&format!(
"connect_tcp_race(#{{{o}}}, {addrs}, |{varnam}| {{"
));
env.printer.increase_indent();
Ok(varnam)
}
Endpoint::TcpListen(..)
| Endpoint::TcpListenFd(..)
| Endpoint::TcpListenFdNamed(..) => {
let varnam = env.vars.getnewvarname("tcp");
let fromaddr = env.vars.getnewvarname("from");
let listenparams = env.opts.listening_parameters(env.position);
let addrpart = match self {
Endpoint::TcpListen(addr) => {
format!("addr: {a}", a = StrLit(addr),)
}
Endpoint::TcpListenFd(fd) => {
format!("fd: {fd}",)
}
Endpoint::TcpListenFdNamed(fdname) => {
format!("named_fd: {a}", a = StrLit(fdname),)
}
_ => unreachable!(),
};
let mut o = String::with_capacity(0);
if matches!(self, Endpoint::TcpListen(..))
&& !(env.used_for_a_websocket && env.opts.exclude_ws_from_sockopts)
{
tcp_common_bind_options(&mut o, env);
if let Some(v) = env.opts.socket_listen_backlog {
o.push_str(&format!("backlog: {v},"));
}
}
if !(env.used_for_a_websocket && env.opts.exclude_ws_from_sockopts) {
tcp_common_stream_options(&mut o, env);
}
env.printer.print_line(&format!(
"listen_tcp(#{{{listenparams}, {addrpart}, {o}}}, |listen_addr|{{sequential([",
));
env.printer.increase_indent();
if env.opts.stdout_announce_listening_ports {
env.printer.print_line("print_stdout(\"LISTEN proto=tcp,ip=\"+listen_addr.get_ip()+\",port=\"+str(listen_addr.get_port())+\"\\n\"),");
}
if let Some(ref x) = env.opts.exec_after_listen {
if env.opts.exec_after_listen_append_port {
env.printer.print_line(&format!(
"system({} + \" \" + str(listen_addr.get_port())),",
StrLit(x)
));
} else {
env.printer.print_line(&format!("system({}),", StrLit(x)));
}
}
env.printer.decrease_indent();
env.printer
.print_line(&format!("])}}, |{varnam}, {fromaddr}| {{",));
env.printer.increase_indent();
Ok(varnam)
}
_ => panic!(),
}
}
pub(super) fn end_print_tcp(&self, env: &mut ScenarioPrintingEnvironment<'_>) {
match self {
Endpoint::TcpConnectByIp(_) => {
env.printer.decrease_indent();
env.printer.print_line("})");
}
Endpoint::TcpConnectByEarlyHostname { .. } => {
env.printer.decrease_indent();
env.printer.print_line("})");
}
Endpoint::TcpListen(..)
| Endpoint::TcpListenFd(..)
| Endpoint::TcpListenFdNamed(..) => {
env.printer.decrease_indent();
env.printer.print_line("})");
}
Endpoint::TcpConnectByLateHostname { hostname: _ } => {
env.printer.decrease_indent();
env.printer.print_line("})");
env.printer.decrease_indent();
env.printer.print_line("})");
}
_ => panic!(),
}
}
}