Protocol Plugins API Reference¤
Overview¤
This reference documents the public API for the PANTHER protocol plugins system. All protocol implementations follow the interface defined by IProtocolManager and use the @register_protocol decorator for metadata registration.
Core Classes¤
IProtocolManager¤
Base class for all protocol implementations.
Module: panther.plugins.protocols.protocol_interface
class IProtocolManager(IPlugin):
"""Manage protocol configurations for network testing services."""
Constructor¤
def __init__(self, service_type: str)
Initialize protocol manager with service type configuration.
Parameters:
- service_type (str): Type of service protocol to manage (e.g., 'quic', 'http')
Raises:
- FileNotFoundError: If the protocol configuration file doesn't exist
- yaml.YAMLError: If the configuration file contains invalid YAML
Methods¤
validate_config()¤
def validate_config(self) -> None
Validate the loaded protocol configuration.
This method should be overridden by concrete implementations to provide protocol-specific validation logic. The default implementation performs no validation.
Raises:
- ValueError: If configuration contains invalid or missing required fields
load_config()¤
def load_config(self) -> dict
Load protocol configuration from YAML file.
Reads and parses the YAML configuration file for this protocol type. The configuration file path is determined by the service_type provided during initialization.
Returns:
- dict: Parsed configuration data from the YAML file
Raises:
- FileNotFoundError: If the configuration file doesn't exist
- yaml.YAMLError: If the YAML file is malformed
- PermissionError: If the file cannot be read due to permissions
Example:
config = self.load_config()
print(config['protocol_version']) # 'quic-1.0'
Protocol Implementations¤
QUICProtocol¤
QUIC transport protocol implementation.
Module: panther.plugins.protocols.client_server.quic.quic
@register_protocol(
name="quic",
type="client_server",
versions=["rfc9000", "draft29", "draft27", "draft27-vuln1", "draft27-vuln2"],
default_version="rfc9000",
capabilities=["0-rtt", "connection-migration", "stream-multiplexing", ...],
config_schema={...}
)
class QUICProtocol(IProtocolManager):
"""QUIC Protocol Manager."""
Constructor¤
def __init__(self)
Initialize QUIC protocol manager.
Sets up logging and skips parent YAML loading since configuration is handled through the decorator metadata system.
Methods¤
validate_config()¤
def validate_config(self) -> None
Validate QUIC protocol configuration.
Configuration validation is handled automatically through the schema defined in the register_protocol decorator. This method serves as a placeholder for any additional runtime validation.
load_config()¤
def load_config(self) -> dict
Load QUIC protocol configuration from decorator metadata.
Returns:
- dict: Default QUIC configuration parameters including stream limits, data limits, timeout values, and ALPN protocols
Example:
config = self.load_config()
print(config['initial_max_data']) # 10485760
get_version_parameters()¤
def get_version_parameters(self, version: str) -> dict
Get version-specific QUIC protocol parameters.
Retrieves configuration parameters that are specific to a particular QUIC version, including version negotiation settings and vulnerability testing parameters.
Parameters:
- version (str): QUIC version identifier (e.g., 'rfc9000', 'draft-27')
Returns:
- dict: Version-specific parameters including initial version hex, version negotiation flag, compatible versions list, and optional vulnerability test settings
Example:
params = self.get_version_parameters('rfc9000')
print(params['initial_version']) # '00000001'
get_default_server_port()¤
@classmethod
def get_default_server_port(cls) -> int
Get the default server port for QUIC connections.
Returns:
- int: Default QUIC server port (4443)
Note: Port 4443 is commonly used for QUIC as it's the HTTPS port (443) plus 4000, making it easy to remember and unlikely to conflict.
get_default_client_port()¤
@classmethod
def get_default_client_port(cls) -> int
Get the default client port for QUIC connections.
Returns:
- int: Ephemeral port (0), allowing the OS to assign an available port
Note: QUIC clients typically use ephemeral ports assigned by the operating system to avoid port conflicts and enable multiple concurrent connections.
MiniPProtocol¤
Minimal protocol for basic testing functionality.
Module: panther.plugins.protocols.client_server.minip.minip
@register_protocol(
name="minip",
description="MiniP Protocol Manager",
versions=["flaky", "fail", "functional", "random", "vulnerable"],
tags=["transport", "secure", "multiplexed"]
)
class MiniPProtocol(IProtocolManager):
"""MiniP Protocol Manager."""
Constructor¤
def __init__(self)
Initialize MiniP protocol manager.
Skip parent init since we don't need the old YAML loading.
Methods¤
validate_config()¤
def validate_config(self) -> None
Validate protocol configuration.
Configuration is validated through the schema.
load_config()¤
def load_config(self) -> dict
Load protocol configuration.
Returns:
- dict: The default config from decorator
get_version_parameters()¤
def get_version_parameters(self, version: str) -> dict
Get version-specific parameters.
Parameters:
- version (str): Protocol version identifier
Returns:
- dict: Version-specific parameters
get_default_server_port()¤
@classmethod
def get_default_server_port(cls) -> int
Get the default server port for QUIC.
Returns:
- int: Default server port (4443)
get_default_client_port()¤
@classmethod
def get_default_client_port(cls) -> int
Get the default client port for QUIC (usually ephemeral).
Returns:
- int: Ephemeral port (0)
Decorators¤
@register_protocol¤
Decorator for registering protocol plugins with metadata.
Module: panther.plugins.core.plugin_decorators
@register_protocol(
name: str,
type: str = "client_server",
versions: List[str] = None,
default_version: str = None,
description: str = "",
author: str = "",
license: str = "",
homepage: str = "",
capabilities: List[str] = None,
tags: List[str] = None,
config_schema: Dict = None,
default_config: Dict = None
)
Parameters:
- name (str): Protocol identifier (e.g., "quic", "http")
- type (str): Protocol category ("client_server" or "peer_to_peer")
- versions (List[str]): Supported protocol versions
- default_version (str): Default version to use
- description (str): Human-readable protocol description
- author (str): Protocol implementation author
- license (str): Protocol license information
- homepage (str): Protocol specification or documentation URL
- capabilities (List[str]): Protocol capabilities and features
- tags (List[str]): Categorization tags
- config_schema (Dict): JSON schema for configuration validation
- default_config (Dict): Default configuration values
Example:
@register_protocol(
name="custom_protocol",
type="client_server",
versions=["v1.0", "v1.1"],
default_version="v1.0",
capabilities=["encryption", "compression"],
config_schema={
"port": {"type": "integer", "default": 8080},
"timeout": {"type": "integer", "default": 30}
},
default_config={
"port": 8080,
"timeout": 30
}
)
class CustomProtocol(IProtocolManager):
...
Configuration Schema¤
QUIC Configuration Schema¤
{
"initial_max_data": {
"type": "integer",
"default": 10485760,
"description": "Initial maximum data limit for the connection"
},
"initial_max_stream_data_bidi_local": {
"type": "integer",
"default": 1048576,
"description": "Initial maximum data for locally-initiated bidirectional streams"
},
"initial_max_stream_data_bidi_remote": {
"type": "integer",
"default": 1048576,
"description": "Initial maximum data for remotely-initiated bidirectional streams"
},
"initial_max_stream_data_uni": {
"type": "integer",
"default": 1048576,
"description": "Initial maximum data for unidirectional streams"
},
"initial_max_streams_bidi": {
"type": "integer",
"default": 100,
"description": "Initial maximum number of bidirectional streams"
},
"initial_max_streams_uni": {
"type": "integer",
"default": 100,
"description": "Initial maximum number of unidirectional streams"
},
"max_idle_timeout": {
"type": "integer",
"default": 30000,
"description": "Maximum idle timeout in milliseconds"
},
"alpn_protocols": {
"type": "array",
"items": {"type": "string"},
"default": ["h3", "hq-interop"],
"description": "ALPN protocols to negotiate"
}
}
Version Parameters¤
QUIC Version Parameters¤
{
"rfc9000": {
"initial_version": "00000001",
"version_negotiation": True,
"compatible_versions": ["rfc9000"]
},
"draft-29": {
"initial_version": "ff00001d", # 0xFF00001D
"version_negotiation": True,
"compatible_versions": ["draft-29"]
},
"draft-27": {
"initial_version": "ff00001b", # 0xFF00001B
"version_negotiation": True,
"compatible_versions": ["draft-27"]
},
"draft-27-vuln1": {
"initial_version": "ff00001b",
"version_negotiation": True,
"compatible_versions": ["draft-27"],
"enable_vuln_test": "vuln1"
},
"draft-27-vuln2": {
"initial_version": "ff00001b",
"version_negotiation": True,
"compatible_versions": ["draft-27"],
"enable_vuln_test": "vuln2"
}
}
Usage Examples¤
Basic Protocol Usage¤
from panther.plugins.protocols.client_server.quic import QUICProtocol
# Initialize protocol
protocol = QUICProtocol()
# Load configuration
config = protocol.load_config()
print(f"Max data: {config['initial_max_data']}")
# Get version parameters
rfc9000_params = protocol.get_version_parameters('rfc9000')
print(f"Version: {rfc9000_params['initial_version']}")
# Get default ports
server_port = protocol.get_default_server_port() # 4443
client_port = protocol.get_default_client_port() # 0
Protocol Discovery¤
from panther.plugins.core.plugin_catalog import PluginCatalog
# Get all protocols
catalog = PluginCatalog()
protocols = catalog.get_protocols()
# Filter by type
quic_protocols = catalog.get_protocols_by_name("quic")
client_server_protocols = catalog.get_protocols_by_type("client_server")
# Get protocol metadata
for protocol in protocols:
print(f"Name: {protocol.name}")
print(f"Versions: {protocol.versions}")
print(f"Capabilities: {protocol.capabilities}")
Custom Protocol Implementation¤
from panther.plugins.protocols.protocol_interface import IProtocolManager
from panther.plugins.core.plugin_decorators import register_protocol
@register_protocol(
name="my_protocol",
type="client_server",
versions=["v1.0"],
config_schema={
"custom_param": {
"type": "string",
"default": "default_value"
}
}
)
class MyProtocol(IProtocolManager):
"""Custom protocol implementation."""
def __init__(self):
self.logger = logging.getLogger("MyProtocol")
def validate_config(self):
"""Validate configuration."""
pass
def load_config(self) -> dict:
"""Load configuration."""
return self.get_protocol_metadata().get("default_config", {})
def get_version_parameters(self, version: str) -> dict:
"""Get version parameters."""
return {"version": version}
@classmethod
def get_default_server_port(cls) -> int:
return 9999
@classmethod
def get_default_client_port(cls) -> int:
return 0
Error Handling¤
Common Exceptions¤
FileNotFoundError: Configuration file not foundyaml.YAMLError: Invalid YAML configurationValueError: Invalid configuration valuesKeyError: Missing required configuration fieldsTypeError: Incorrect parameter types
Error Handling Patterns¤
try:
protocol = QUICProtocol()
config = protocol.load_config()
except FileNotFoundError as e:
logger.error(f"Configuration file not found: {e}")
except yaml.YAMLError as e:
logger.error(f"Invalid YAML configuration: {e}")
except ValueError as e:
logger.error(f"Configuration validation failed: {e}")
Type Hints¤
All public APIs include complete type hints for better IDE support and static analysis:
from typing import Dict, List, Optional, Union
def get_version_parameters(self, version: str) -> Dict[str, Union[str, bool, List[str]]]:
"""Get version-specific parameters with full type hints."""
pass
Thread Safety¤
Protocol instances are designed to be thread-safe for concurrent testing scenarios:
- Configuration loading is performed once during initialization
- Version parameters are computed dynamically without state modification
- Class methods for default ports are stateless
- Logger instances are thread-safe
Performance Considerations¤
- Lazy Loading: Configuration loaded only when needed
- Caching: Version parameters computed on-demand but can be cached
- Memory Efficiency: Minimal memory footprint per protocol instance
- No Network I/O: All operations are local configuration access