Advertisement
Python253

server_byte_stuffing_demo

May 30th, 2024
721
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.70 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Filename: server_byte_stuffing_demo.py
  4. # Version: 1.0.0
  5. # Author: Jeoi Reqi
  6.  
  7. """
  8. Description:
  9.    - This script demonstrates a byte-stuffing algorithm and a TCP server function to process byte-stuffed data over TCP.
  10.    - Byte stuffing is a technique used in data transmission to avoid ambiguity caused by control characters.
  11.    - The script showcases how byte stuffing can be applied to data and how a server can handle byte-stuffed data over TCP.
  12.  
  13. Requirements:
  14.    - Python 3.x
  15.  
  16. Functions:
  17.    - byte_stuffing(data):
  18.        Performs byte stuffing on the input data.
  19.    - process_data(data):
  20.        Processes the byte-stuffed data received from the client.
  21.    - start_server(host, port, duration, received_data_list):
  22.        Starts a TCP server that listens for incoming connections from clients and processes byte-stuffed data for a specified duration.
  23.    - send_data(host, port, data):
  24.        Sends byte-stuffed data to the server.
  25.    - save_output(output, received_data_list):
  26.        Saves the terminal output and received data to a file.
  27.    - main():
  28.        Main function to automate the process of starting the server, sending data, and handling user interaction for saving output.
  29.  
  30. Expected Example Output:
  31.  
  32.        Byte-stuffed data: 017d5e027d5d03
  33.  
  34.        Server listening on 127.0.0.1:1337...
  35.  
  36.        Data sent to the server: b'\x01}^\x02}]\x03'
  37.  
  38.        Connection from ('127.0.0.1', 52261)
  39.  
  40.        Processed data: b'\x01~\x02}\x03'
  41.  
  42.        Received data from the server: b'\x01~\x02}\x03'
  43.  
  44.        Output saved successfully!
  45.  
  46.        Received:       017e027d03
  47.  
  48.        Sent:       017d5e027d5d03
  49.        Received:       017e027d03
  50.  
  51. Additional Notes:
  52.    - This script is for demonstration purposes only and does not represent a full-fledged server implementation.
  53. """
  54.  
  55. import socket
  56. import threading
  57. import time
  58. import logging
  59. from typing import List, Tuple
  60.  
  61. def byte_stuffing(data: bytes) -> bytes:
  62.     """
  63.    Performs byte stuffing on the input data.
  64.  
  65.    Args:
  66.        data (bytes): The input data to be byte-stuffed.
  67.  
  68.    Returns:
  69.        bytes: The byte-stuffed data.
  70.    """
  71.     stuffed_data = []
  72.     for byte in data:
  73.         if byte in (0x7E, 0x7D):
  74.             stuffed_data.append(
  75.                 0x7D
  76.             )  # Byte stuffing: Replace 0x7E and 0x7D with 0x7D, 0x5E and 0x5D respectively
  77.             stuffed_data.append(byte ^ 0x20)  # XOR with 0x20 to toggle the fifth bit
  78.         else:
  79.             stuffed_data.append(byte)
  80.     return bytes(stuffed_data)
  81.  
  82. def process_data(data: bytes) -> bytes:
  83.     """
  84.    Processes the byte-stuffed data received from the client.
  85.  
  86.    Args:
  87.        data (bytes): The byte-stuffed data received from the client.
  88.  
  89.    Returns:
  90.        bytes: The processed data.
  91.    """
  92.     processed_data = []
  93.     escape_next = False
  94.     for byte in data:
  95.         if escape_next:
  96.             processed_data.append(
  97.                 byte ^ 0x20
  98.             )  # XOR with 0x20 to remove the escape character
  99.             escape_next = False
  100.         elif byte == 0x7D:
  101.             escape_next = True  # Set escape_next flag if 0x7D is encountered
  102.         else:
  103.             processed_data.append(byte)
  104.     return bytes(processed_data)
  105.  
  106. def start_server(
  107.     host: str, port: int, duration: int, received_data_list: List[Tuple[bytes, bytes]]
  108. ):
  109.     """
  110.    Starts a TCP server that listens for incoming connections from clients and processes byte-stuffed data for a specified duration.
  111.  
  112.    Args:
  113.        host (str): The IP address or hostname of the server.
  114.        port (int): The port number on which the server listens.
  115.        duration (int): The duration (in seconds) for which the server should run.
  116.        received_data_list (List[Tuple[bytes, bytes]]): A list to store the received data and processed data.
  117.    """
  118.     start_time = time.time()  # Record the start time
  119.     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
  120.         server_socket.bind((host, port))  # Bind the socket to the host and port
  121.         server_socket.listen(
  122.             5
  123.         )  # Start listening for incoming connections, with a backlog of 5
  124.  
  125.         logging.info(
  126.             f"\nServer listening on {host}:{port}..."
  127.         )  # Log the server listening status
  128.  
  129.         # Loop until the specified duration is reached
  130.         while (time.time() - start_time) < duration:
  131.             # Set the timeout for the server socket
  132.             server_socket.settimeout(duration - (time.time() - start_time))
  133.             try:
  134.                 # Accept incoming connection and get the client socket and address
  135.                 client_socket, client_address = server_socket.accept()
  136.                 logging.info(
  137.                     f"\nConnection from {client_address}"
  138.                 )  # Log the connection
  139.  
  140.                 with client_socket:
  141.                     # Loop until the client closes the connection
  142.                     while True:
  143.                         data = client_socket.recv(1024)  # Receive data from the client
  144.                         if not data:
  145.                             break  # Break the loop if no data is received
  146.  
  147.                         if data.startswith(b"GET"):
  148.                             logging.info(
  149.                                 f"\nReceived HTTP request: {data!r}"
  150.                             )  # Log HTTP request
  151.                             continue  # Skip processing if it's an HTTP request
  152.  
  153.                         processed_data = process_data(data)  # Process received data
  154.                         logging.info(
  155.                             f"\nProcessed data: {processed_data!r}"
  156.                         )  # Log processed data
  157.  
  158.                         received_data_list.append(
  159.                             (data, processed_data)
  160.                         )  # Append to received data list
  161.                         client_socket.sendall(
  162.                             processed_data
  163.                         )  # Send processed data back to the client
  164.             except socket.timeout:
  165.                 break  # Break the loop if timeout occurs
  166.             except ConnectionResetError:
  167.                 logging.warning(
  168.                     "\nConnection was reset by the client!"
  169.                 )  # Log connection reset by client
  170.                 continue  # Continue to the next iteration of the loop
  171.  
  172. def send_data(host: str, port: int, data: bytes) -> bytes:
  173.     """
  174.    Sends byte-stuffed data to the server.
  175.  
  176.    Args:
  177.        host (str): The IP address or hostname of the server.
  178.        port (int): The port number on which the server is listening.
  179.        data (bytes): The byte-stuffed data to be sent to the server.
  180.  
  181.    Returns:
  182.        bytes: The received data from the server.
  183.    """
  184.     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
  185.         try:
  186.             client_socket.connect((host, port))  # Connect to the server
  187.             client_socket.sendall(data)  # Send the byte-stuffed data
  188.             logging.info(f"\nData sent to the server: {data!r}")  # Log the sent data
  189.             received_data = client_socket.recv(1024)  # Receive data from the server
  190.             logging.info(
  191.                 f"\nReceived data from the server: {received_data!r}"
  192.             )  # Log the received data
  193.             return received_data  # Return the received data
  194.         except ConnectionResetError:
  195.             logging.warning(
  196.                 "\nConnection was reset by the server!"
  197.             )  # Log connection reset by server
  198.             raise  # Raise an exception instead of returning None
  199.  
  200. def save_output(output: str, received_data_list: List[Tuple[bytes, bytes]]):
  201.     """
  202.    Save the terminal output and received data to a file, excluding specific lines.
  203.  
  204.    Args:
  205.        output (str): The terminal output to be saved.
  206.        received_data_list (List[Tuple[bytes, bytes]]): A list containing tuples of sent and received byte-stuffed data.
  207.  
  208.    Notes:
  209.        Lines containing the specified exclusion patterns are not written to the output file.
  210.    """
  211.     lines_to_exclude = [
  212.         "027d5d03",
  213.         "Received:    017e027d03",
  214.     ]  # Lines to exclude from output
  215.     output_lines = output.split("\n")  # Split the output into lines
  216.     with open("output.txt", "a", encoding="utf-8") as file:
  217.         for line in output_lines:
  218.             if not any(exclude_line in line for exclude_line in lines_to_exclude):
  219.                 file.write(line + "\n")  # Write the line to the output file
  220.  
  221.         # Write received data
  222.         for sent, received in received_data_list:
  223.             if received is not None:
  224.                 file.write(f"Sent:       {sent.hex()}\n")  # Write sent data to the file
  225.                 file.write(
  226.                     f"Received:       {received.hex()}\n\n"
  227.                 )  # Write received data to the file
  228.  
  229. def main():
  230.     """
  231.    Main function to automate the process of starting the server, sending data, and handling user interaction for saving output.
  232.    """
  233.     # Define server parameters
  234.     HOST = "127.0.0.1"
  235.     PORT = 1337
  236.     DURATION = 1
  237.  
  238.     # Prepare test data for byte-stuffing
  239.     test_data = bytes([0x01, 0x7E, 0x02, 0x7D, 0x03])
  240.  
  241.     # Perform byte stuffing on the test data
  242.     stuffed_data = byte_stuffing(test_data)
  243.     logging.info("Byte-stuffed data: %s", stuffed_data.hex())
  244.  
  245.     # List to store received data tuples
  246.     received_data_list: List[Tuple[bytes, bytes]] = []
  247.  
  248.     # Start the server in a separate thread
  249.     server_thread = threading.Thread(
  250.         target=start_server, args=(HOST, PORT, DURATION, received_data_list)
  251.     )
  252.     server_thread.start()
  253.  
  254.     # Send stuffed data to the server
  255.     received_data = send_data(HOST, PORT, stuffed_data)
  256.     if received_data is not None:
  257.         received_data_list.append(
  258.             (stuffed_data, received_data)
  259.         )  # Append received data only
  260.  
  261.     # Wait for the server thread to complete
  262.     server_thread.join()
  263.  
  264.     # Prompt user to save the output
  265.     save = input("\nDo you want to save the output? (y/n): ")
  266.     if save.lower() == "y":
  267.         # Format example data for saving
  268.         example_data = f"\nSent:    {stuffed_data.hex()}\nReceived:    {received_data.hex() if received_data else 'None'}\n"
  269.         # Save the output to a file
  270.         save_output(example_data, received_data_list)
  271.         logging.info("\nOutput saved successfully!\n")
  272.  
  273. if __name__ == "__main__":
  274.     # Configure logging settings
  275.     logging.basicConfig(
  276.         level=logging.INFO,
  277.         format="%(message)s",
  278.         handlers=[logging.FileHandler("output.txt", mode="w"), logging.StreamHandler()],
  279.     )
  280.  
  281.     # Execute the main function
  282.     main()
  283.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement