A multiplayer VR framework w/voice chat
1use std::{fs, io::{Read, Write}, net::{SocketAddr, TcpStream, UdpSocket}, sync::mpsc::Sender, thread};
2
3use nanoid::nanoid;
4
5#[cfg(feature = "client")]
6use crate::net::{client::NetClientCommand, packets::link_udp::LinkUDP};
7#[cfg(not(feature = "client"))]
8use crate::net::{server::NetServerCommand, packets::notify_connection_info::NotifyConnectionInfo};
9
10use crate::net::packet::{self, Packet, PacketTypes};
11
12#[derive(Debug)]
13pub struct Connection{
14 tcp: TcpStream,
15
16 #[cfg(not(feature = "client"))]
17 udp: Option<SocketAddr>,
18 #[cfg(not(feature = "client"))]
19 main_thread_sender: Sender<NetServerCommand>,
20
21 #[cfg(feature = "client")]
22 udp: UdpSocket,
23 #[cfg(feature = "client")]
24 udp_server_address: SocketAddr,
25
26 pub id: String
27}
28
29impl Connection{
30 #[cfg(not(feature = "client"))]
31 pub fn new( stream: TcpStream, cmd: Sender<NetServerCommand> ) -> Self{
32 let mut conn = Self {
33 tcp: stream,
34 main_thread_sender: cmd.clone(),
35 udp: None,
36
37 id: nanoid!()
38 };
39
40 conn.start_listener_thread(cmd).unwrap();
41
42 let packet = NotifyConnectionInfo::from(&conn);
43 conn.send_reliable(packet).unwrap();
44
45 conn
46 }
47
48 #[cfg(not(feature = "client"))]
49 fn start_listener_thread(&self, cmd: Sender<NetServerCommand>) -> anyhow::Result<()>{
50 let mut stream = self.tcp.try_clone()?;
51 let id = self.id.clone();
52
53 thread::spawn(move || {
54 let mut buf = [0; 1024];
55 while let Ok(length) = stream.read(&mut buf) {
56 if length == 0 { break; }
57 let msg = &buf[0..length];
58
59 let packet = packet::parse(msg.into());
60 }
61
62 cmd.send(NetServerCommand::PlayerDisconnect(id)).unwrap();
63 });
64
65 Ok(())
66 }
67
68 #[cfg(feature = "client")]
69 pub fn new( tcp: TcpStream, udp: UdpSocket, udp_server_address: SocketAddr, cmd: Sender<NetClientCommand> ) -> Self{
70 let mut conn = Self {
71 tcp: tcp,
72 udp: udp,
73 udp_server_address: udp_server_address,
74
75 id: "".to_owned()
76 };
77
78 conn.start_listener_thread(cmd).unwrap();
79
80 conn
81 }
82
83 #[cfg(feature = "client")]
84 fn start_listener_thread(&self, cmd: Sender<NetClientCommand>) -> anyhow::Result<()>{
85 let mut tcp = self.tcp.try_clone()?;
86 let udp = self.udp.try_clone()?;
87
88 let udp_1 = self.udp.try_clone()?;
89 let cmd_1 = cmd.clone();
90
91 let srv_addr = self.udp_server_address.clone();
92
93 thread::spawn(move || { // UDP RECV THREAD
94 let mut buf = [0; 1024];
95
96 while let Ok((length, addr)) = udp_1.recv_from(&mut buf){
97 if addr != srv_addr{ continue; }
98
99 let msg = &buf[0..length];
100 let packet = packet::parse(msg.into());
101
102 cmd_1.send(NetClientCommand::RecvPacket(packet)).unwrap();
103 }
104 });
105
106 thread::spawn(move || { // TCP RECV THREAD
107 let mut buf = [0; 1024];
108
109 while let Ok(length) = tcp.read(&mut buf){
110 if length == 0 { break; }
111
112 let msg = &buf[0..length];
113 let packet = packet::parse(msg.into());
114
115 match packet{
116 PacketTypes::NotifyConnectionInfo(info) => {
117 cmd.send(NetClientCommand::Connected(info.id.clone())).unwrap();
118
119 let packet = LinkUDP { id: info.id };
120 let packet: Vec<_> = packet.to_buf().into();
121
122 udp.send_to(&packet, "127.0.0.1:2603").unwrap();
123 },
124 _ => {
125 cmd.send(NetClientCommand::RecvPacket(packet)).unwrap();
126 }
127 }
128 }
129
130 cmd.send(NetClientCommand::Disconnected).unwrap();
131 });
132
133 Ok(())
134 }
135
136 #[cfg(not(feature = "client"))]
137 pub fn connect_udp(&mut self, address: SocketAddr){
138 self.udp = Some(address);
139 }
140
141 pub fn send_reliable(&mut self, packet: impl Packet) -> anyhow::Result<()>{
142 let buf: Vec<u8> = packet.to_buf().into();
143 self.tcp.write(&buf)?;
144
145 Ok(())
146 }
147
148 pub fn try_send_unreliable(&mut self, packet: impl Packet) -> anyhow::Result<()>{
149 let buf: Vec<u8> = packet.to_buf().into();
150
151 #[cfg(not(feature = "client"))]
152 {
153 if let Some(addr) = self.udp{
154 self.main_thread_sender.send(NetServerCommand::SendOverUDP(buf, addr))?;
155 } else{
156 println!("[WARN] Cannot send unreliable packet to {}, using TCP instead.", self.id);
157 self.tcp.write(&buf)?;
158 }
159 }
160
161 #[cfg(feature = "client")]
162 self.udp.send_to(&buf, self.udp_server_address)?;
163
164 Ok(())
165 }
166}