Server Byte Stuffing Demo
Server Byte Stuffing Demo
/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: server_byte_stuffing_demo.py
# Version: 1.0.0
# Author: Jeoi Reqi
"""
Description:
- This script demonstrates a byte-stuffing algorithm and a TCP server function
to process byte-stuffed data over TCP.
- Byte stuffing is a technique used in data transmission to avoid ambiguity
caused by control characters.
- The script showcases how byte stuffing can be applied to data and how a
server can handle byte-stuffed data over TCP.
Requirements:
- Python 3.x
Functions:
- byte_stuffing(data):
Performs byte stuffing on the input data.
- process_data(data):
Processes the byte-stuffed data received from the client.
- start_server(host, port, duration, received_data_list):
Starts a TCP server that listens for incoming connections from clients and
processes byte-stuffed data for a specified duration.
- send_data(host, port, data):
Sends byte-stuffed data to the server.
- save_output(output, received_data_list):
Saves the terminal output and received data to a file.
- main():
Main function to automate the process of starting the server, sending data,
and handling user interaction for saving output.
Received: 017e027d03
Sent: 017d5e027d5d03
Received: 017e027d03
Additional Notes:
- This script is for demonstration purposes only and does not represent a full-
fledged server implementation.
"""
import socket
import threading
import time
import logging
from typing import List, Tuple
Args:
data (bytes): The input data to be byte-stuffed.
Returns:
bytes: The byte-stuffed data.
"""
stuffed_data = []
for byte in data:
if byte in (0x7E, 0x7D):
stuffed_data.append(
0x7D
) # Byte stuffing: Replace 0x7E and 0x7D with 0x7D, 0x5E and 0x5D
respectively
stuffed_data.append(byte ^ 0x20) # XOR with 0x20 to toggle the fifth
bit
else:
stuffed_data.append(byte)
return bytes(stuffed_data)
Args:
data (bytes): The byte-stuffed data received from the client.
Returns:
bytes: The processed data.
"""
processed_data = []
escape_next = False
for byte in data:
if escape_next:
processed_data.append(
byte ^ 0x20
) # XOR with 0x20 to remove the escape character
escape_next = False
elif byte == 0x7D:
escape_next = True # Set escape_next flag if 0x7D is encountered
else:
processed_data.append(byte)
return bytes(processed_data)
def start_server(
host: str, port: int, duration: int, received_data_list: List[Tuple[bytes,
bytes]]
):
"""
Starts a TCP server that listens for incoming connections from clients and
processes byte-stuffed data for a specified duration.
Args:
host (str): The IP address or hostname of the server.
port (int): The port number on which the server listens.
duration (int): The duration (in seconds) for which the server should run.
received_data_list (List[Tuple[bytes, bytes]]): A list to store the
received data and processed data.
"""
start_time = time.time() # Record the start time
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind((host, port)) # Bind the socket to the host and port
server_socket.listen(
5
) # Start listening for incoming connections, with a backlog of 5
logging.info(
f"\nServer listening on {host}:{port}..."
) # Log the server listening status
with client_socket:
# Loop until the client closes the connection
while True:
data = client_socket.recv(1024) # Receive data from the
client
if not data:
break # Break the loop if no data is received
if data.startswith(b"GET"):
logging.info(
f"\nReceived HTTP request: {data!r}"
) # Log HTTP request
continue # Skip processing if it's an HTTP request
received_data_list.append(
(data, processed_data)
) # Append to received data list
client_socket.sendall(
processed_data
) # Send processed data back to the client
except socket.timeout:
break # Break the loop if timeout occurs
except ConnectionResetError:
logging.warning(
"\nConnection was reset by the client!"
) # Log connection reset by client
continue # Continue to the next iteration of the loop
Args:
host (str): The IP address or hostname of the server.
port (int): The port number on which the server is listening.
data (bytes): The byte-stuffed data to be sent to the server.
Returns:
bytes: The received data from the server.
"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
try:
client_socket.connect((host, port)) # Connect to the server
client_socket.sendall(data) # Send the byte-stuffed data
logging.info(f"\nData sent to the server: {data!r}") # Log the sent
data
received_data = client_socket.recv(1024) # Receive data from the
server
logging.info(
f"\nReceived data from the server: {received_data!r}"
) # Log the received data
return received_data # Return the received data
except ConnectionResetError:
logging.warning(
"\nConnection was reset by the server!"
) # Log connection reset by server
raise # Raise an exception instead of returning None
Args:
output (str): The terminal output to be saved.
received_data_list (List[Tuple[bytes, bytes]]): A list containing tuples of
sent and received byte-stuffed data.
Notes:
Lines containing the specified exclusion patterns are not written to the
output file.
"""
lines_to_exclude = [
"027d5d03",
"Received: 017e027d03",
] # Lines to exclude from output
output_lines = output.split("\n") # Split the output into lines
with open("output.txt", "a", encoding="utf-8") as file:
for line in output_lines:
if not any(exclude_line in line for exclude_line in lines_to_exclude):
file.write(line + "\n") # Write the line to the output file
# Write received data
for sent, received in received_data_list:
if received is not None:
file.write(f"Sent: {sent.hex()}\n") # Write sent data to the
file
file.write(
f"Received: {received.hex()}\n\n"
) # Write received data to the file
def main():
"""
Main function to automate the process of starting the server, sending data, and
handling user interaction for saving output.
"""
# Define server parameters
HOST = "127.0.0.1"
PORT = 1337
DURATION = 1
if __name__ == "__main__":
# Configure logging settings
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
handlers=[logging.FileHandler("output.txt", mode="w"),
logging.StreamHandler()],
)