11use log:: * ;
22use url:: Url ;
33use tungstenite:: Message ;
4- use tokio:: net:: TcpListener ;
4+ use tokio:: net:: { TcpListener , UdpSocket } ;
55use std:: io:: { Error , ErrorKind } ;
66use futures_util:: { StreamExt , SinkExt } ;
77use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
@@ -10,6 +10,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
1010struct Properties {
1111 local : String ,
1212 ws : String ,
13+ udp : String ,
1314}
1415
1516fn parse_args ( ) -> Option < Properties > {
@@ -40,6 +41,15 @@ fn parse_args() -> Option<Properties> {
4041 } ;
4142 config. ws = ws;
4243 } ,
44+ "--udp" | "-udp" | "-u" => {
45+ let udp = match args. next ( ) {
46+ Some ( udp) => {
47+ udp
48+ } ,
49+ _ => "" . to_string ( ) ,
50+ } ;
51+ config. udp = udp;
52+ } ,
4353 _ => { }
4454 }
4555 }
@@ -77,7 +87,38 @@ async fn friendly_bind(local: &str) -> Result<TcpListener, Error> {
7787 }
7888}
7989
90+ async fn server_udp ( config : & Properties ) -> Result < ( ) , Error > {
91+ let bind = {
92+ let it = UdpSocket :: bind ( & config. local ) . await ;
93+ if matches ! ( it, Ok ( _) ) { it } else {
94+ UdpSocket :: bind ( & format ! ( "127.0.0.1:{}" , & config. local) ) . await
95+ }
96+ } ;
97+ match bind {
98+ Ok ( udp) => {
99+ let u = config. udp . clone ( ) ;
100+ tokio:: spawn ( async move {
101+ loop {
102+ let mut buf = vec ! [ 0u8 ; 1024 ] ;
103+ let ( le, who) = udp. recv_from ( & mut buf) . await . unwrap ( ) ;
104+ debug ! ( "udp: {le}Bytes from {who:?}" ) ;
105+ let c = UdpSocket :: bind ( "0.0.0.0:0" ) . await . unwrap ( ) ;
106+ c. connect ( & u) . await . unwrap ( ) ;
107+ c. send ( & buf[ ..le] ) . await . unwrap ( ) ;
108+ let le = c. recv ( & mut buf) . await . unwrap ( ) ;
109+ udp. send_to ( & buf[ ..le] , who) . await . unwrap ( ) ;
110+ }
111+ } ) ;
112+ }
113+ Err ( e) => {
114+ error ! ( "{e}" ) ;
115+ }
116+ }
117+ Ok ( ( ) )
118+ }
119+
80120async fn server ( config : & Properties ) -> Result < ( ) , Error > {
121+ let _ = server_udp ( config) . await ;
81122 let server = match friendly_bind ( & config. local ) . await {
82123 Ok ( it) => it,
83124 Err ( e) if e. kind ( ) == ErrorKind :: InvalidInput => { // 如果用户只提供了端口号
0 commit comments