Also
Check out PeerChat
1. protocol.py
This file defines the message formats and provides utility functions for creating and parsing protocol messages used in both client-server and peer-to-peer communication.
Function | Description | Importance |
---|---|---|
parse_register(msg) | Parses a REGISTER message string. | Extracts nickname and udp_port from the raw message. Returns None if malformed. Essential for server to process client registrations. |
make_joined(nickname, ip, udp_port, tcp_port) | Creates a JOINED message string. | Used by the server to inform clients when a new peer (including themselves) has joined the chat, providing their network details. |
make_left(nickname) | Creates a LEFT message string. | Used by the server to inform clients when a peer has disconnected. |
make_broadcast(message) | Creates a BROADCAST message string. | Used by clients to send a message that the server should relay to all other connected clients. |
parse_port(msg) | Parses a PORT message string. | Extracts nickname and tcp_port from the raw message. Used by the server to get the client’s TCP port for peer-to-peer connections. |
make_port(nickname, tcp_port) | Creates a PORT message string. | Used by clients to inform the server of their TCP port for peer-to-peer connections, sent after REGISTER. |
make_chat_request(nickname) | Creates a CHAT_REQUEST message string. | Used by a client to initiate a peer-to-peer chat session with another client. |
is_chat_request(msg) | Checks if a message string is a CHAT_REQUEST. | Helper to identify incoming chat requests. |
parse_chat_request(msg) | Parses a CHAT_REQUEST message string. | Extracts the requesting nickname. Returns None if malformed. |
make_chat_accept(nickname) | Creates a CHAT_ACCEPT message string. | Used by a client to accept an incoming peer-to-peer chat request. |
is_chat_accept(msg) | Checks if a message string is a CHAT_ACCEPT. | Helper to identify incoming chat acceptances. |
parse_chat_accept(msg) | Parses a CHAT_ACCEPT message string. | Extracts the accepting nickname. Returns None if malformed. |
make_chat_reject(nickname) | Creates a CHAT_REJECT message string. | Used by a client to reject an incoming peer-to-peer chat request. |
is_chat_reject(msg) | Checks if a message string is a CHAT_REJECT. | Helper to identify incoming chat rejections. |
parse_chat_reject(msg) | Parses a CHAT_REJECT message string. | Extracts the rejecting nickname. Returns None if malformed. |
make_left_chat(nickname) | Creates a LEFT_CHAT message string. | Used by a client to inform a peer that they are leaving the current peer-to-peer chat session. |
is_left_chat(msg) | Checks if a message string is a LEFT_CHAT. | Helper to identify when a peer has left a chat session. |
parse_left_chat(msg) | Parses a LEFT_CHAT message string. | Extracts the nickname of the peer who left. Returns None if malformed. |
make_chat_msg(nickname, message) | Creates a CHAT_MSG message string. | Used by clients to send an actual chat message text to a connected peer during a peer-to-peer session. |
is_chat_msg(msg) | Checks if a message string is a CHAT_MSG. | Helper to identify incoming peer-to-peer chat messages. |
parse_chat_msg(msg) | Parses a CHAT_MSG message string. | Extracts the sender’s nickname and the message content. Returns None if malformed. |
make_error(reason) | Creates an ERROR message string. | Used by both server and clients to signal a protocol error or unexpected situation, providing a reason. |
is_error(msg) | Checks if a message string is an ERROR. | Helper to identify incoming error messages. |
parse_error(msg) | Parses an ERROR message string. | Extracts the reason for the error. Returns None if malformed. |
make_nickname_taken() | Creates a NICKNAME_TAKEN message string. | Used by the server to inform a client that their chosen nickname is already in use. |
is_nickname_taken(msg) | Checks if a message string is NICKNAME_TAKEN. | Helper for the client to identify if their registration was rejected due to a nickname conflict. |
2. tcp.py
This file handles the low-level TCP communication, specifically message framing by prefixing messages with their length.
Function | Description | Importance |
---|---|---|
recv_all(conn, length) | Receives exactly length bytes from the socket conn. | Ensures that the complete message (or length prefix) is read, handling cases where TCP packets might be fragmented. Crucial for reliable message boundary detection. |
recv_message(conn) | Receives a complete message from the socket conn. | First, it reads a 10-byte length prefix, decodes it to get the message length, then calls recv_all to read the actual message content. Decodes the message to a string. |
send_message(conn, msg) | Sends a message string over the socket conn. | Encodes the message to bytes, prepends a 10-byte length prefix (left-padded with spaces), and sends both the prefix and the message. Ensures the receiver can delimit messages. |
3. udp.py
This file handles UDP communication, providing functions to listen for UDP messages and send them.
Function | Description | Importance |
---|---|---|
listen_for_udp(port, on_message) | Starts a UDP server in a daemon thread to listen for incoming messages on the specified port. | When a message is received, it calls the on_message callback with the message data and sender’s address. Used by clients for peer discovery or direct UDP messages. |
send_udp(target_ip, target_port, message) | Sends a UDP message to the specified target_ip and target_port. | Encodes the message string to bytes before sending. Used for sending UDP messages, like peer discovery pings or direct UDP chat (if implemented). |
4. core.py (Server class)
This file contains the main logic for the PeerChat server.
Method | Description | Importance |
---|---|---|
init(host, port) | Initializes the server with the host and port to listen on. Sets up clients dictionary and a lock for thread safety. | Basic setup for the server instance. |
broadcast(msg, exclude_nick) | Sends a message to all connected clients, optionally excluding one client by exclude_nick. | Core server functionality for relaying messages (like JOINED, LEFT, BROADCAST) to all relevant clients. Uses the lock to safely iterate over the clients dictionary. |
handle_client(conn, addr) | Manages a single client connection from registration through the message loop. | This is the main entry point for a new client. It handles the initial REGISTER and PORT message sequence, nickname conflicts, and then hands off to _client_message_loop. It also handles client disconnection and cleanup. |
_client_message_loop(conn, nickname) | Processes messages from a connected and registered client. | Handles ongoing communication with a client after successful registration. It processes BROADCAST and PORT (update) messages. It enforces protocol rules (e.g., client cannot send JOINED or ERROR). |
start() | Starts the main server loop, listening for incoming client connections. | Binds to the host/port and accepts new connections, spawning a new thread running handle_client for each. Includes try-except for graceful shutdown on KeyboardInterrupt and prints status messages. |
_cleanup_client(conn, nickname) | (Implicit within handle_client’s finally block) Removes a client from the clients list and broadcasts a LEFT message. | Ensures proper state management when a client disconnects or an error occurs. |
5. core.py (Client class)
This file contains the main logic for the PeerChat client.
Method | Description | Importance |
---|---|---|
init(server_ip, server_port, nickname, udp_port, tcp_port) | Initializes the client with server details, user’s nickname, and network ports. | Basic setup for the client instance, including state variables for peer connections, callbacks, etc. |
set_callbacks(**kwargs) | Allows the GUI (or other frontends) to register callback functions for various client events (e.g., on_message, on_peer_joined). | Decouples the client core logic from the UI. The core logic calls these callbacks to update the UI or notify about events. |
_cb(name, *args, **kwargs) | Internal helper to safely invoke a registered callback by its name. | Prevents errors if a callback is not set and simplifies calling callbacks. |
register() | Connects to the server and sends REGISTER and PORT messages. Starts _listen_to_server thread. | Initiates the client’s session with the server. Handles potential connection or registration errors. |
_listen_to_server() | Listens for messages from the server (e.g., JOINED, LEFT, BROADCAST, ERROR, NICKNAME_TAKEN) and processes them. | Handles all server-to-client communication after registration. Updates internal peer list and triggers UI callbacks. |
start_peer_server(tcp_port) | Starts a TCP server socket to listen for incoming peer-to-peer chat connection requests. | Allows other clients to initiate direct TCP connections for P2P chat. Each incoming connection is handled in a new thread by _handle_peer_connection. |
_handle_peer_connection(conn, addr) | Manages an incoming peer-to-peer TCP connection, listening for messages from that peer. | Dedicated loop for receiving messages from a single connected peer. Passes messages to _handle_peer_message. |
send_tcp_to_peer(peer_ip, peer_port) | Initiates a TCP connection to another peer and sends a CHAT_REQUEST. | Starts the P2P chat process from the initiator’s side. Handles connection timeouts and errors. |
send_message_to_peer(addr, message) | Sends a CHAT_MSG to an already connected peer. | Used to send actual chat text during an active P2P session. |
close_chat(addr) | Closes an active peer-to-peer chat session, sending LEFT_CHAT to the peer. | Gracefully ends a P2P chat. |
get_peer_nickname(addr) | Retrieves the nickname associated with a peer’s address. | Utility for displaying peer information. |
_handle_peer_message(addr, msg, sock) | Processes incoming messages from a peer (e.g., CHAT_REQUEST, CHAT_ACCEPT, CHAT_REJECT, LEFT_CHAT, CHAT_MSG, ERROR). | Core logic for P2P communication. It manages chat session states (request, accept, reject), handles chat messages, and processes errors or disconnections. Includes timeout logic for chat requests. |
start_udp_listener(on_message) | Starts a UDP listener using network.udp.listen_for_udp. | Allows the client to receive UDP messages, typically for peer discovery or other UDP-based features. The on_message callback (often _handle_udp_message) processes these. |
_handle_udp_message(data, addr) | (If implemented and connected to start_udp_listener) Processes incoming UDP messages. | Placeholder or actual handler for UDP messages. Could be used for peer discovery responses or direct UDP chat. |
shutdown() | Gracefully shuts down the client, closing server and peer connections. | Ensures resources are released and threads are stopped cleanly. |