This project implements a hybrid P2P chat system that combines:
- HTTP Client-Server: Authentication, peer discovery, session management
- Direct P2P TCP: Real-time messaging between peers without server relay
The system strictly adheres to CO3094 course restrictions: no external libraries, pure Python standard library only, vanilla HTML/CSS/JS with no frameworks.
- Cookie-based authentication with session management
- Real-time peer discovery via HTTP polling (short-poll; frontend polls the backend periodically)
- Request/accept pattern for P2P connection establishment
- Direct TCP messaging between peers (no server relay)
- Connection health monitoring with PING/PONG keepalive
- Graceful session termination with bidirectional notification
- Automatic offline peer detection (45s timeout)
- Rejection notification system
- Fixed footer overlap in chat UI
- Session end notification to peer
| Component | Port | Purpose |
|---|---|---|
| Proxy Server | 8080 | Routes HTTP requests to backend, load balancing |
| Backend/WebApp | 9001 | Authentication, peer registry, static files, P2P management |
| P2P Daemons | 9100-9199 | One TCP daemon per user for direct peer messaging |
Data Flow:
Browser → Proxy:8080 → Backend:9001 → P2P Daemon:910x ⟷ P2P Daemon:910y
┌─────────────┐ ┌─────────────┐
│ Browser A │ │ Browser B │
│ (user1) │ │ (user2) │
└──────┬──────┘ └──────┬──────┘
│ │
│ HTTP (polling) │ HTTP (polling)
│ │
▼ ▼
┌─────────────────────────────────────────────────┐
│ Proxy Server (Port 8080) │
│ Routes all HTTP to Backend │
└─────────────────┬───────────────────────────────┘
│
│ HTTP Forward
▼
┌─────────────────────────────────────────────────┐
│ Backend/WebApp Server (Port 9001) │
│ - Authentication & Session Management │
│ - Peer Registry (Tracker) │
│ - P2P Daemon Manager │
│ - Static File Serving │
└───────────┬─────────────────────┬───────────────┘
│ │
│ Manages │ Manages
▼ ▼
┌──────────────┐ ┌──────────────┐
│ P2P Daemon A │◄────►│ P2P Daemon B │
│ Port 9100 │ TCP │ Port 9101 │
│ (user1) │Direct│ (user2) │
└──────────────┘ └──────────────┘
▲ ▲
│ Callbacks │ Callbacks
│ (on_message) │ (on_message)
└──────────────────────┘
Key Points:
- HTTP: Browser ↔ Proxy ↔ Backend (auth, peer discovery, events)
- TCP: P2P Daemon A ↔ P2P Daemon B (direct messaging, no server relay)
- Backend creates one P2P daemon per logged-in user
- P2P daemons call backend callbacks to queue messages for browser polling
- Python 3.8 or higher
- No external dependencies required (stdlib only)
Option 1: All-in-one (Windows)
start_all.batOption 2: Manual start
Terminal 1 - Start Proxy:
python start_proxy.pyTerminal 2 - Start Backend/WebApp:
python start_sampleapp.pyAccess the application at: http://localhost:8080
- User 1:
user1/pass123 - User 2:
user2/pass456 - Admin:
admin/password
Step 1: Start the System
start_all.bat # Windows
# Wait 5 seconds for all services to startStep 2: Open Two Browser Windows
- Browser A (or normal window):
http://localhost:8080 - Browser B (or incognito window):
http://localhost:8080
Step 3: Login
- Browser A: Login as
user1/pass123 - Browser B: Login as
user2/pass456
Step 4: Initiate Chat
- In Browser A: Click on "user2" in the peer list
- System automatically sends connection request to user2
Step 5: Accept Connection
- In Browser B: A popup appears asking to accept/reject
- Click "Accept" button
Step 6: Start Chatting
- Both browsers now have active chat windows
- Type message in input field and press Enter or click Send
- Messages appear in real-time (via P2P TCP connection)
Step 7: End Session
- Click "End Session" button to close the chat
- Other peer will receive notification: "user1 has ended the session"
Tip: You can test rejection by clicking "Reject" in Step 5. The requester will see a rejection message and the chat window will close automatically.
| File | Purpose | Key Features |
|---|---|---|
start_all.bat |
Windows batch launcher | Starts proxy + backend automatically in separate windows |
start_proxy.py |
Proxy server entry point | Listens on port 8080, forwards to backend:9001 |
start_sampleapp.py |
Backend/WebApp server | Handles auth, peer registry, manages P2P daemons |
| File | Purpose | Key Features |
|---|---|---|
backend.py |
Base HTTP server | Multi-threaded TCP server, handles client connections |
weaprous.py |
Lightweight web framework | Route registration, hook system, static file serving |
httpadapter.py |
HTTP request/response handler | Parses requests, builds responses, executes route hooks |
request.py |
HTTP request parser | Parses headers, body, query strings, cookies |
response.py |
HTTP response builder | Builds HTTP responses with headers, cookies, redirects |
proxy.py |
Reverse proxy | Round-robin load balancing, forwards HTTP to backend |
p2p_daemon.py |
P2P TCP daemon | Manages P2P connections, handshake, PING/PONG keepalive |
tracker.py |
Peer tracker | Registers peers, health monitoring, timeout detection |
dictionary.py |
In-memory data structure | Thread-safe peer registry |
utils.py |
Utility functions | Helper functions (cookie parsing, URL decoding, etc.) |
P2P Daemon Key Features:
- TCP handshake protocol: CONNECT → ACCEPT/REJECT
- Message types: CHAT, PING, PONG, CLOSE
- Keepalive: 10s PING, 30s idle timeout
- Thread-safe with RLock on all shared state
- Callback system for on_message events
| File | Purpose | Key Features |
|---|---|---|
static/css/login.css |
Login page styles | Centered form, gradient background, responsive |
static/css/chat.css |
Chat UI styles | Flexbox layout, message bubbles, scrollable containers |
Chat.css Notable Features:
- Fixed footer with
min-height: 0to prevent overlap (Bug #2 fix) - Smooth scrolling in message container
- Status badges for online/offline peers
- Responsive design for mobile devices
| File | Purpose | Key Features |
|---|---|---|
static/js/chat.js |
Chat application logic | Polling, P2P connection, messaging, UI updates |
Chat.js Core Functions:
- Authentication:
loadCurrentUser(),registerP2P() - Peer Discovery:
loadPeers(),pollPeerEvents()(every 3s) - Connection Management:
requestConnection()- Send connection requestpollConnectionRequests()- Poll incoming requests (every 2s)pollConnectionResponses()- Poll accept/reject (every 2s) - Bug #1 fixconnectToPeer()- Establish P2P connection
- Messaging:
sendMessage()- Send CHAT messagepollMessages()- Poll new messages (every 2s)appendMessage()- Display message in UI
- Session Control:
endChat()- End session, send CLOSE message - Bug #3 fix
- Health:
sendHeartbeat()(every 15s),updateP2PStatus()(every 5s)
| File | Purpose | Key Features |
|---|---|---|
www/login.html |
Login page | Form with username/password, POST to /login |
www/login_error.html |
Error page | Shows authentication failure message |
www/index.html |
Main chat interface | Peer list, chat window, message input |
index.html Layout:
- Left sidebar: Online peers list with status indicators
- Main area: Chat window with messages container
- Footer: Message input + send button
- Header: Current user, P2P status, logout
| File | Purpose | Content |
|---|---|---|
ARCHITECTURE.md |
System design | Architecture diagrams, data flows, threading model |
PROTOCOL.md |
API specification | HTTP endpoints, P2P messages, JSON schemas |
| File | Purpose |
|---|---|
config/proxy.conf |
Proxy routing rules (maps paths to backend hosts) |
| File | Purpose |
|---|---|
LICENSE |
MIT License |
CLEANUP_SUMMARY.md |
Documentation of cleanup process and bug fixes |
IMPLEMENTATION_SUMMARY.md |
Original implementation notes (Vietnamese) |
- Cookie-based authentication
- Session management
- Peer registration and discovery
- HTTP polling (short-poll) for real-time events
- TCP handshake protocol (CONNECT/ACCEPT/REJECT)
- Direct peer-to-peer messaging
- Connection health monitoring (PING/PONG)
- Graceful session termination
- Request/accept pattern for connection establishment
- Bidirectional session end notifications
- Automatic peer offline detection (45s timeout)
- Real-time UI updates via polling
This project adheres to strict course requirements:
- Vanilla HTML/CSS/JS only (no frameworks)
- No WebSocket or WebRTC
- HTTP polling (short-poll) for events
- No external CDNs or libraries
- Python standard library only
- No external frameworks (no Flask, Django, FastAPI)
- Threading only (no asyncio)
- Pure TCP sockets for P2P
- In-memory state (no database)
- Fixed ports: 8080 (proxy), 9001 (backend), 9100-9199 (P2P)
- Static files served by Python HTTP stack
- No external web servers
This version includes three critical bug fixes:
Problem: When User B rejected a connection request, User A would wait indefinitely with "Waiting for response..." message.
Solution:
- Backend: Added
connection_responsesstorage and/api/p2p-get-responsesendpoint - Frontend: Added
pollConnectionResponses()function (polls every 2s) - Result: User A now sees rejection message and chat window closes after 2 seconds
Files Modified: start_sampleapp.py, static/js/chat.js
Problem: With many messages, the message input field would scroll below the footer and become invisible.
Solution:
- Added
min-height: 0to.chat-activeand.messages-containerin CSS - Added
overflow: hiddento.chat-active - Result: Messages scroll independently while input stays fixed at bottom
Files Modified: static/css/chat.css
Problem: When User A ended the session, User B saw no notification and the UI remained active.
Solution:
- Modified P2P daemon to add body field for CLOSE messages
- Forward CLOSE messages to callback before closing connection
- Frontend detects CLOSE message and shows red notification
- Result: User B sees "User A has ended the session" and input is disabled
Files Modified: daemon/p2p_daemon.py, backend forwards CLOSE to message queue
- NAT Traversal: P2P connections work on local networks only. NAT hole punching not implemented.
- Long-Poll Latency: Event updates have 2-3 second delay due to polling intervals.
- Scalability: In-memory state limits concurrent users.
- No Persistence: All data lost on restart.
- Python: PEP8, snake_case, structured logging
- JavaScript: 2-space indent, strict mode, BEM-style naming
- HTML/CSS: Semantic tags, no inline styles
MIT License - See LICENSE file
HCMUT - CO3094 Network Lab Date: 2025-11-03