Nothing to see here, move along
at main 183 lines 5.7 kB view raw
1#![no_std] 2#![no_main] 3 4use lancer_user::io::write_bytes; 5use lancer_user::net; 6use lancer_user::syscall; 7 8const DEFAULT_TIMEOUT_S: i64 = 10; 9const MAX_TIMEOUT_S: i64 = 60; 10 11#[unsafe(no_mangle)] 12pub extern "C" fn lancer_main() -> ! { 13 let (rx, tx) = match net::init() { 14 Some(pair) => pair, 15 None => { 16 lancer_user::show!(net, error, "netsock init failed"); 17 syscall::exit(); 18 } 19 }; 20 21 if !net::has_relay() { 22 write_bytes(b"networking not available (use SSH)\n"); 23 syscall::exit(); 24 } 25 26 let mut args_buf = [0u8; 128]; 27 let args_len = net::recv_args(&rx, &mut args_buf); 28 let args = &args_buf[..args_len]; 29 30 let (_cmd_tok, rest) = net::next_token(args); 31 let (sub, remainder) = net::next_token(rest); 32 33 match sub { 34 _ if net::bytes_eq(sub, b"send") => cmd_send(&tx, remainder), 35 _ if net::bytes_eq(sub, b"listen") => cmd_listen(&rx, &tx, remainder), 36 _ if net::bytes_eq(sub, b"close") => cmd_close(&tx), 37 _ => { 38 write_bytes(b"usage: udp send <ip> <port> <data>\n udp listen <port> [timeout]\n udp close\n"); 39 } 40 } 41 42 syscall::exit() 43} 44 45fn cmd_send(tx: &lancer_core::packet_ring::PacketRingWriter, args: &[u8]) { 46 let (ip_tok, r1) = net::next_token(args); 47 let ip = match net::parse_ip(ip_tok) { 48 Some(ip) => ip, 49 None => { 50 write_bytes(b"invalid IP\n"); 51 return; 52 } 53 }; 54 55 let (port_tok, r2) = net::next_token(r1); 56 let port = match net::parse_decimal_u16(port_tok) { 57 Some(p) => p, 58 None => { 59 write_bytes(b"invalid port\n"); 60 return; 61 } 62 }; 63 64 let data = net::skip_spaces(r2); 65 match data.is_empty() { 66 true => { 67 write_bytes(b"no data\n"); 68 } 69 false => { 70 let mut msg = [0u8; 62]; 71 let payload_len = data.len().min(54); 72 msg[0] = net::MSG_UDP_SEND; 73 msg[1] = ip[0]; 74 msg[2] = ip[1]; 75 msg[3] = ip[2]; 76 msg[4] = ip[3]; 77 msg[5] = (port >> 8) as u8; 78 msg[6] = port as u8; 79 msg[7..7 + payload_len].copy_from_slice(&data[..payload_len]); 80 net::send_request(tx, &msg[..7 + payload_len]); 81 write_bytes(b"sent\n"); 82 } 83 } 84} 85 86fn cmd_listen( 87 rx: &lancer_core::packet_ring::PacketRingReader, 88 tx: &lancer_core::packet_ring::PacketRingWriter, 89 args: &[u8], 90) { 91 let (port_tok, remainder) = net::next_token(args); 92 let port = match net::parse_decimal_u16(port_tok) { 93 Some(p) => p, 94 None => { 95 write_bytes(b"invalid port\n"); 96 return; 97 } 98 }; 99 100 let (timeout_tok, _) = net::next_token(remainder); 101 let timeout_s = match timeout_tok.is_empty() { 102 true => DEFAULT_TIMEOUT_S, 103 false => match net::parse_decimal_u16(timeout_tok) { 104 Some(t) => (t as i64).clamp(1, MAX_TIMEOUT_S), 105 None => DEFAULT_TIMEOUT_S, 106 }, 107 }; 108 109 let bind_msg = [net::MSG_UDP_BIND, (port >> 8) as u8, port as u8]; 110 net::send_request(tx, &bind_msg); 111 112 let mut resp_buf = [0u8; 64]; 113 let n = net::recv_response_blocking(rx, &mut resp_buf); 114 match n >= 2 && resp_buf[0] == net::MSG_UDP_BOUND { 115 true => match resp_buf[1] { 116 0 => write_bytes(b"bound, listening...\n"), 117 _ => { 118 write_bytes(b"bind failed\n"); 119 return; 120 } 121 }, 122 false => { 123 write_bytes(b"bind failed\n"); 124 return; 125 } 126 } 127 128 let start_ms = syscall::clock_monotonic_ms(); 129 let deadline_ms = start_ms + timeout_s * 1000; 130 131 let mut running = true; 132 core::iter::from_fn(|| match running { 133 false => None, 134 true => { 135 let now = syscall::clock_monotonic_ms(); 136 match now >= deadline_ms { 137 true => { 138 running = false; 139 None 140 } 141 false => match net::recv_response(rx, &mut resp_buf) { 142 Some(rn) if rn >= 2 && resp_buf[0] == net::MSG_UDP_RECV && rn >= 7 => { 143 let mut out = [0u8; 128]; 144 let mut pos = 0usize; 145 let prefix = b"from "; 146 out[..prefix.len()].copy_from_slice(prefix); 147 pos += prefix.len(); 148 pos += net::write_ip_decimal(&mut out[pos..], &resp_buf[1..5]); 149 out[pos] = b':'; 150 pos += 1; 151 let src_port = ((resp_buf[5] as u16) << 8) | resp_buf[6] as u16; 152 pos += net::write_u16_decimal(&mut out[pos..], src_port); 153 let mid = b": "; 154 out[pos..pos + mid.len()].copy_from_slice(mid); 155 pos += mid.len(); 156 write_bytes(&out[..pos]); 157 if rn > 7 { 158 write_bytes(&resp_buf[7..rn]); 159 } 160 write_bytes(b"\n"); 161 Some(()) 162 } 163 _ => { 164 syscall::notify_wait(net::NETSOCK_NOTIF_SLOT); 165 Some(()) 166 } 167 }, 168 } 169 } 170 }) 171 .take(10_000) 172 .count(); 173 174 let close_msg = [net::MSG_UDP_CLOSE]; 175 net::send_request(tx, &close_msg); 176 write_bytes(b"closed\n"); 177} 178 179fn cmd_close(tx: &lancer_core::packet_ring::PacketRingWriter) { 180 let close_msg = [net::MSG_UDP_CLOSE]; 181 net::send_request(tx, &close_msg); 182 write_bytes(b"closed\n"); 183}