A simple peer-to-peer (P2P) chat application written in Rust that demonstrates UDP hole punching. This project allows two clients, both potentially behind NATs, to establish a direct connection with each other for communication, using a central relay server for the initial introduction.
- UDP Hole Punching: Establishes direct P2P connections between clients behind NATs.
- Relay Server: A simple server that introduces peers to each other.
- Peer-to-Peer Chat: Once connected, clients can chat directly with each other.
- Usernames: Users can choose a username for the chat session.
- Keep-Alive Mechanism: Periodically sends ping messages to keep the NAT pinhole open.
- Graceful Shutdown: Peers notify each other when they are leaving the chat.
- Connect by Username: Users can connect to a specific peer by their username.
- Registration: Both clients register with the relay server, providing their username.
- Connection Request: One client requests to connect to another client by their username.
- Introduction: The relay server sends the public IP address and port of each client to the other.
- Hole Punching: Both clients send a message to the other client's public address. This "punches a hole" in their respective NATs, allowing direct communication.
- Direct Connection: The clients can now communicate directly with each other without the need for the relay server.
Clone the repository and build the project:
git clone https://github.com/dev-dhanushkumar/Peer-Punch-POC/
cd Peer-Punch-POC
cargo build-
Start the Relay Server:
cargo run --bin relay_server
-
Start the First Peer Client:
Open a new terminal and run:
cargo run --bin peer
Enter a username when prompted.
-
Start the Second Peer Client:
Open another new terminal and run:
cargo run --bin peer
Enter a different username.
- After starting both peer clients, one client will be prompted to enter the username of the peer they want to connect to.
- Once the connection is established, you can type messages in either peer's terminal, and they will appear in the other peer's terminal.
- To exit, press
Ctrl+C.
The communication between the clients and the server is done using a simple JSON-based messaging protocol. The messages are defined in src/lib.rs.
Register { username: String }: Registers the client with the relay server.Connect { target_username: String }: Requests to connect to a specific user.SessionFinished: Informs the server that the chat session has ended.
RegisterAck: Acknowledges the registration.PeerInfo { peer: SocketAddr, username: String }: Provides the address and username of the other peer.TargetNotFound: Indicates that the target user could not be found.TargetBusy: Indicates that the target user is already in a chat session.
DirectMessage { content: String }: A chat message.Ping: A keep-alive message.Pong: The response to aPing.Goodbye: A message indicating that the peer is leaving the chat.
- Encryption: Encrypt the communication between peers.
- File Transfer: Allow peers to send files to each other.
- Multiple Peers: Allow more than two peers to join a chat session.
- GUI: Create a graphical user interface for the chat client.