Skip to content

A LAN-based terminal chat application built in Rust using asynchronous TCP networking with Tokio.

Notifications You must be signed in to change notification settings

suraniharsh/rchat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rchat - LAN Terminal Chat Application

A LAN-based terminal chat application built in Rust using asynchronous TCP networking with Tokio.

Features

  • 🌐 TCP-based LAN chat - Connect multiple users on the same network
  • 🔐 Server-controlled identity - [username@ip] format, prevents spoofing
  • 🎨 Colored terminal output - Different colors for users and system messages
  • 📡 Async architecture - Built on Tokio for efficient concurrent handling
  • 💬 Private messaging - Send direct messages with /pm
  • 👥 User listing - See who's online with /who

Project Structure

rchat/
├── Cargo.toml
└── src/
    ├── server/
    │   ├── main.rs       # Server entry point, connection handling
    │   ├── hub.rs        # Central message router, client registry
    │   ├── client.rs     # Per-connection handler
    │   ├── identity.rs   # Client identity management
    │   └── protocol.rs   # JSON message protocol definitions
    └── client/
        ├── main.rs       # Client entry point, connection setup
        ├── input.rs      # Terminal input handling, command parsing
        ├── receiver.rs   # Message receiving and display
        └── protocol.rs   # JSON message protocol definitions

Building

cargo build --release

Running

Start the Server

cargo run --bin server

The server binds to 0.0.0.0:8080 by default.

Connect a Client

cargo run --bin client <server_ip:port>

# Examples:
cargo run --bin client 127.0.0.1:8080      # localhost
cargo run --bin client 192.168.1.10:8080   # LAN IP

Commands

Command Description
/who List all connected users
/pm <user@ip> <message> Send a private message
/quit or /exit Disconnect from the server

Protocol

Messages are JSON-encoded with the following structure:

{
  "type": "message",
  "content": "hello world",
  "sender": "harsh@192.168.1.23",
  "timestamp": "14:30:45"
}

Message Types

Type Description
join Client joining the server
message Regular chat message
system Server announcements
leave Client disconnecting
who Request user list
privatemessage Private message to specific user

Architecture

Concurrency Model

The application uses Tokio's async runtime with the following concurrency patterns:

  1. Server Hub (Actor Pattern)

    • Central hub runs as a single task
    • Receives messages via mpsc channel
    • Maintains client registry in a HashMap
    • No shared mutable state - all state is local to the hub
  2. Client Handlers

    • Each connection spawns a dedicated handler task
    • Bidirectional communication via tokio::select!
    • Sends to hub via channel, receives via dedicated channel
  3. Client Tasks

    • Input task: Reads stdin, parses commands, sends to server
    • Receiver task: Reads from server, displays formatted messages
    • Writer task: Sends messages from channel to TCP stream

Broadcast Architecture

┌─────────────────────────────────────────────────────────────┐
│                         SERVER                               │
│  ┌─────────┐                                                │
│  │   Hub   │◄──── HubMessage channel ◄──┬──┬──┬──           │
│  │         │                             │  │  │            │
│  │ clients │                             │  │  │            │
│  │  map    │─────► Per-client channels ─►│  │  │            │
│  └─────────┘                             │  │  │            │
│       │                               ┌──┴──┴──┴──┐         │
│       │                               │  Client   │         │
│       └───────────────────────────────│ Handlers  │         │
│                                       └───────────┘         │
└─────────────────────────────────────────────────────────────┘

Identity Generation

  1. Client sends only system username ($USER env var) in join message
  2. Server extracts IP from socket.peer_addr()
  3. Server constructs identity: username@ip
  4. Port is stored internally for uniqueness (multiple connections from same user/IP)
  5. Client cannot spoof identity - server always controls it

Client Lifecycle

1. Parse args (server address)
         │
         ▼
2. Get $USER environment variable
         │
         ▼
3. TCP connect to server
         │
         ▼
4. Send join message with username
         │
         ▼
5. Receive identity confirmation
         │
         ▼
6. Spawn tasks: input, receiver, writer
         │
         ▼
7. Run until quit or disconnect
         │
         ▼
8. Clean shutdown

Security Notes

  • No TLS - Messages are transmitted in plaintext
  • No authentication - Any user can connect with any username
  • LAN use only - Not designed for internet exposure
  • Server-controlled identity - IP cannot be spoofed by client

Example Session

Server Output:

🌐 Server listening on 0.0.0.0:8080
📡 Clients can connect using your LAN IP on port 8080
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔗 New connection from 192.168.1.23:54321
✅ 192.168.1.23:54321 authenticated as [harsh@192.168.1.23]
>>> harsh@192.168.1.23 joined
📊 Active clients: 1

Client Output:

Connecting to 192.168.1.10:8080
Username: harsh

Connected!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Type your message and press Enter to send.
Commands: /who, /pm <user@ip> <message>, /quit
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[14:30:45] Welcome to rchat! You are connected as [harsh@192.168.1.23]
>>> harsh@192.168.1.23 joined

harsh@192.168.1.23 > hello everyone!
[14:30:52] [harsh@192.168.1.23] hello everyone!

License

MIT

About

A LAN-based terminal chat application built in Rust using asynchronous TCP networking with Tokio.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages