Skip to content

Commit

Permalink
Implement basic server-client communication
Browse files Browse the repository at this point in the history
  • Loading branch information
AzureMarker committed Jan 30, 2022
1 parent 566cd12 commit 0924fbe
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 37 deletions.
92 changes: 56 additions & 36 deletions n3ds-controller-client/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,73 +1,93 @@
use ctru::applets::swkbd::{Button, Swkbd};
use ctru::services::soc::Soc;
use ctru::{
console::Console,
services::{hid::KeyPad, Apt, Hid},
Gfx,
};
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::net::{Ipv4Addr, TcpListener, TcpStream};
use std::str::FromStr;
use std::time::Duration;

fn main() {
ctru::init();
let gfx = Gfx::default();
gfx.top_screen.borrow_mut().set_wide_mode(true);
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");
let soc = Soc::init().expect("Couldn't initialize networking");
let _console = Console::init(gfx.top_screen.borrow_mut());

println!("Hello, world!");

let tcp_listener = match TcpListener::bind("0.0.0.0:80") {
Ok(socket) => socket,
Err(e) => {
println!("Error while binding: {}", e);
std::thread::sleep(Duration::from_secs(2));
return;
}
println!("Enter the n3ds-controller server IP");
let server_ip = match get_server_ip() {
Some(server_ip) => server_ip,
None => return,
};

let mut connection =
TcpStream::connect((server_ip, 3535)).expect("Failed to connect to server");
connection.set_nonblocking(true).unwrap();

println!(
"Started server socket.\nConnect to {}:80",
soc.host_address()
"Connected to server. Button presses will be sent to the server. Press START to exit."
);
tcp_listener
.set_nonblocking(true)
.expect("Couldn't make socket nonblocking");

// Main loop
while apt.main_loop() {
// Scan all the inputs. This should be done once for each frame
hid.scan_input();

if hid.keys_down().contains(KeyPad::KEY_START) {
let keys_down = hid.keys_down();
let keys_up = hid.keys_up();

if keys_down.contains(KeyPad::KEY_START) {
break;
}

match tcp_listener.accept() {
Ok((stream, socket_addr)) => {
println!("Got connection from {}", socket_addr);
if let Err(e) = write_hello_world(stream) {
println!("Error writing response: {}", e);
}
}
Err(e) => match e.kind() {
std::io::ErrorKind::WouldBlock => {}
_ => {
println!("Error accepting connection: {}", e)
}
},
if keys_down.contains(KeyPad::KEY_A) {
connection.write_all(b"DOWN: A\n").unwrap();
}

if keys_up.contains(KeyPad::KEY_A) {
connection.write_all(b"UP: A\n").unwrap();
}

// Flush and swap frame buffers
gfx.flush_buffers();
gfx.swap_buffers();

// Wait for VBlank
gfx.wait_for_vblank();
}
}

fn write_hello_world(mut stream: TcpStream) -> std::io::Result<()> {
stream.set_nonblocking(false)?;
stream.write_all(b"Hello world!\n")
fn get_server_ip() -> Option<Ipv4Addr> {
let mut keyboard = Swkbd::default();
let mut input = String::new();

loop {
match keyboard.get_utf8(&mut input) {
Ok(Button::Right) => {
// Clicked "OK"
let ip_addr = match Ipv4Addr::from_str(&input) {
Ok(ip_addr) => ip_addr,
Err(_) => {
println!("Invalid IP address, try again");
continue;
}
};
return Some(ip_addr);
}
Ok(Button::Left) => {
// Clicked "Cancel"
println!("Cancel was clicked, exiting in 5 seconds...");
std::thread::sleep(Duration::from_secs(5));
return None;
}
Ok(Button::Middle) => {
// This button wasn't shown
unreachable!()
}
Err(e) => {
panic!("Error: {:?}", e)
}
}
}
}
39 changes: 38 additions & 1 deletion n3ds-controller-server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,40 @@
use std::io::{BufRead, BufReader, Read};
use std::net::TcpListener;

fn main() {
println!("Hello, world!");
println!("Starting n3ds-controller server on 0.0.0.0:3535");
let tcp_listener = TcpListener::bind(("0.0.0.0", 3535)).expect("Failed to bind address");

for connection in tcp_listener.incoming() {
let connection = match connection {
Ok(connection) => BufReader::new(connection),
Err(e) => {
eprintln!("New connection error: {e}");
continue;
}
};
let peer_addr = match connection.get_ref().peer_addr() {
Ok(peer_addr) => peer_addr,
Err(e) => {
eprintln!("Error while getting peer address: {e}");
continue;
}
};

println!("New connection from {peer_addr}");

for line in connection.lines() {
match line {
Ok(line) => println!("[{peer_addr}] {line}"),
Err(e) => {
eprintln!("Error while reading stream: {e}");
if e.kind() == std::io::ErrorKind::ConnectionReset {
break;
}
}
}
}

println!("Closing connection with [{peer_addr}]");
}
}

0 comments on commit 0924fbe

Please sign in to comment.