1
1
use log:: * ;
2
2
use url:: Url ;
3
3
use tungstenite:: Message ;
4
- use tokio:: net:: TcpListener ;
4
+ use tokio:: net:: { TcpListener , UdpSocket } ;
5
5
use std:: io:: { Error , ErrorKind } ;
6
6
use futures_util:: { StreamExt , SinkExt } ;
7
7
use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
@@ -10,6 +10,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
10
10
struct Properties {
11
11
local : String ,
12
12
ws : String ,
13
+ udp : String ,
13
14
}
14
15
15
16
fn parse_args ( ) -> Option < Properties > {
@@ -40,6 +41,15 @@ fn parse_args() -> Option<Properties> {
40
41
} ;
41
42
config. ws = ws;
42
43
} ,
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
+ } ,
43
53
_ => { }
44
54
}
45
55
}
@@ -77,7 +87,38 @@ async fn friendly_bind(local: &str) -> Result<TcpListener, Error> {
77
87
}
78
88
}
79
89
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
+
80
120
async fn server ( config : & Properties ) -> Result < ( ) , Error > {
121
+ let _ = server_udp ( config) . await ;
81
122
let server = match friendly_bind ( & config. local ) . await {
82
123
Ok ( it) => it,
83
124
Err ( e) if e. kind ( ) == ErrorKind :: InvalidInput => { // 如果用户只提供了端口号
0 commit comments