@@ -7,6 +7,7 @@ A robust async TCP networking library for Rust that provides:
77- Keep-alive mechanisms
88- Broadcast capabilities
99- Automatic reconnection
10+ - Relay/proxy functionality
1011
1112
1213## Features
@@ -18,6 +19,9 @@ A robust async TCP networking library for Rust that provides:
1819- 📢 ** Broadcasting** - Send messages to multiple clients
1920- 🔌 ** Reconnection** - Resilient connections with automatic reconnection and exponential backoff
2021- 🚀 ** Async/Await** - Built on tokio for high performance
22+ - 🌐 ** Relay/Proxy** - Network traffic relay with the phantom client/server system
23+ - 🎯 ** Attribute Macros** - Easy handler registration with the ` #[tlisten_for("PACKET_TYPE")] ` macro
24+ - 🏷️ ** Derive Macros** - Generate packet header types with ` #[derive(PacketHeader)] `
2125
2226
2327## Example Usage
@@ -116,28 +120,51 @@ impl ImplResource for MyResource {
116120 }
117121}
118122
119- #[tokio:: main]
120- async fn main () {
121- // Define handlers
122- async fn handle_ok (
123- socket : TSocket <MySession >,
124- packet : MyPacket ,
125- pools : PoolRef <MySession >,
126- resources : ResourceRef <MyResource >
127- ) {
128- println! (" Received packet: {:?}" , packet );
129- socket . send (MyPacket :: ok ()). await . unwrap ();
130- }
123+ // Define packet handlers with the tlisten_for attribute macro
124+ #[tlisten_for(" LOGIN" )]
125+ async fn handle_login (
126+ sources : HandlerSources <MySession , MyResource >,
127+ packet : MyPacket
128+ ) {
129+ let mut socket = sources . socket;
130+ println! (" Processing login request" );
131+
132+ // Access resources if needed
133+ let mut resources = sources . resources. write (). await ;
134+ resources . data. push (" Login processed" . to_string ());
135+
136+ // Send response
137+ socket . send (MyPacket :: ok ()). await . unwrap ();
138+ }
131139
132- async fn handle_error (
133- socket : TSocket <MySession >,
134- error : Error ,
135- pools : PoolRef <MySession >,
136- resources : ResourceRef <MyResource >
137- ) {
138- println! (" Error occurred: {:?}" , error );
139- }
140+ #[tlisten_for(" LOGOUT" )]
141+ async fn handle_logout (
142+ sources : HandlerSources <MySession , MyResource >,
143+ packet : MyPacket
144+ ) {
145+ let mut socket = sources . socket;
146+ println! (" Processing logout request" );
147+ socket . send (MyPacket :: ok ()). await . unwrap ();
148+ }
149+
150+ // For packets without specific handlers, we use these default handlers
151+ async fn handle_ok (
152+ sources : HandlerSources <MySession , MyResource >,
153+ packet : MyPacket
154+ ) {
155+ println! (" Received packet: {:?}" , packet );
156+ sources . socket. send (MyPacket :: ok ()). await . unwrap ();
157+ }
140158
159+ async fn handle_error (
160+ sources : HandlerSources <MySession , MyResource >,
161+ error : Error
162+ ) {
163+ println! (" Error occurred: {:?}" , error );
164+ }
165+
166+ #[tokio:: main]
167+ async fn main () {
141168 // Create and configure server
142169 let server = AsyncListener :: new (
143170 (" 127.0.0.1" , 8080 ),
@@ -157,6 +184,9 @@ async fn main() {
157184 }))
158185 );
159186
187+ // Create connection pools if needed
188+ server . with_pool (" authenticated" ). await ;
189+
160190 // Run the server
161191 server . run (). await ;
162192}
@@ -186,11 +216,52 @@ async fn main() {
186216 // Send a packet and get response
187217 let response = client . send_recv (MyPacket :: ok ()). await . unwrap ();
188218 println! (" Server response: {:?}" , response );
219+
220+ // Send a login packet
221+ let mut login_packet = MyPacket :: ok ();
222+ login_packet . header = " LOGIN" . to_string ();
223+ let login_response = client . send_recv (login_packet ). await . unwrap ();
224+ println! (" Login response: {:?}" , login_response );
189225}
190226```
191227
192228## Advanced Usage
193229
230+ ### Packet Header Enum with Derive Macro
231+
232+ ``` rust
233+ use tnet :: prelude :: * ;
234+
235+ // Define packet headers as an enum
236+ #[derive(Debug , Clone , PacketHeader )]
237+ enum MyHeaders {
238+ Login ,
239+ Logout ,
240+ Message ,
241+ KeepAlive ,
242+ Error ,
243+ Ok ,
244+ }
245+
246+ // Now you can use MyHeaders with automatic string conversion
247+ #[tlisten_for(" Login" )]
248+ async fn handle_login (sources : HandlerSources <MySession , MyResource >, packet : MyPacket ) {
249+ // Login logic here
250+
251+ // The enum provides automatic string conversion
252+ let response_header = MyHeaders :: Ok . to_string ();
253+ let mut response = MyPacket :: ok ();
254+ response . header = response_header ;
255+
256+ sources . socket. send (response ). await . unwrap ();
257+ }
258+
259+ // Parse strings to enum values
260+ fn process_header (header_str : & str ) -> Result <MyHeaders , String > {
261+ header_str . parse :: <MyHeaders >()
262+ }
263+ ```
264+
194265### Auto-Reconnection
195266
196267The client can automatically reconnect when the connection is lost, preserving session state:
@@ -287,6 +358,55 @@ match client.send_recv(MyPacket::ok()).await {
287358}
288359```
289360
361+ ### Network Relay/Proxy with PhantomClient and PhantomListener
362+
363+ The phantom system allows relaying packets through an intermediary server:
364+
365+ ``` rust
366+ // 1. Set up a phantom listener (relay server)
367+ let phantom_listener = PhantomListener :: new (Some ((" 127.0.0.1" . to_string (), 9090 ))). await ;
368+
369+ // 2. Create a client config for the destination server
370+ let client_config = ClientConfig {
371+ encryption_config : EncryptionConfig :: default_on (),
372+ server_addr : " destination.server.com" . to_string (),
373+ server_port : 8080 ,
374+ user : Some (" user" . to_string ()),
375+ pass : Some (" pass" . to_string ()),
376+ };
377+
378+ // 3. Create a phantom configuration
379+ let phantom_conf = PhantomConf {
380+ header : " relay" ,
381+ username : Some (" user" ),
382+ password : Some (" pass" ),
383+ server_addr : " destination.server.com" ,
384+ server_port : 8080 ,
385+ enc_conf : EncryptionConfig :: default_on (),
386+ };
387+
388+ // 4. Create a packet to send to the destination
389+ let packet_to_relay = MyPacket :: ok ();
390+
391+ // 5. Create a phantom packet that wraps the real packet
392+ let phantom_packet = PhantomPacket :: produce_from_conf (& phantom_conf , & packet_to_relay );
393+
394+ // 6. Connect to the phantom server and send the relay request
395+ let mut client = AsyncClient :: <PhantomPacket >:: new (" 127.0.0.1" , 9090 )
396+ . await
397+ . unwrap ();
398+
399+ // 7. Send and get response
400+ let relay_response = client . send_recv (phantom_packet ). await . unwrap ();
401+
402+ // 8. Extract the response from the destination server
403+ if let Some (response_data ) = relay_response . recv_packet {
404+ // Parse the response from the destination
405+ let destination_response : MyPacket = serde_json :: from_str (& response_data ). unwrap ();
406+ println! (" Response from destination: {:?}" , destination_response );
407+ }
408+ ```
409+
290410## License
291411
292412MIT
0 commit comments