vinegar.tftp.server
TFTP server component of Vinegar.
- exception vinegar.tftp.server.TftpError(message: str = '', error_code: ErrorCode = ErrorCode.NOT_DEFINED)
Exception raised by
TftpRequestHandler.handleto indicate that it cannot proceed with processing a request.This exception can be constructed with an optional
messageand an optionalerror_codethat must be an instance ofErrorCode.
- class vinegar.tftp.server.TftpRequestHandler
Interface for a request handler. A request handler should be derived from this class and implement the
can_handleandhandlemethods.The
can_handleandhandlemethods are separate, so that the TFTP server only has to create a new socket and thread when it can actually handle the request.A request handler can also implement
prepare_context. In this case,prepare_contextis called before callingcan_handleand the object returned by it is passed tocan_handleandhandle. This is useful when both function need to do some processing on the filename or client address. This processing can be implemented inprepare_contextand passed to the two other methods through the context so that it does not have to be done twice.- abstract can_handle(filename: str, context: Any) bool
Tell whether the request can be handled by this request handler.
Returns
Trueif the request can be handled andFalseif it cannot be handled and the next request handler should be tried.- Parameters:
filename – filename that has been requested by the client.
context – context object that was returned by
prepare_context.
- Returns:
Trueif this request handler can handle the specified request,Falseif the request should be deferred to the next handler.
- abstract handle(filename: str, client_address: Tuple[str, int] | Tuple[str, int, int, int], server_address: Tuple[str, int] | Tuple[str, int, int, int], context: Any) BufferedIOBase
Handle the request. This method returns a file-like object from which the data for the requested file can be read. The returned file-like object must supply its data in binary form.
If the request handler detects that it actually cannot send data to the client (e.g. because the client lacks the required permissions), it should signal that by raising a
TftpError.- Parameters:
filename – filename that has been requested by the client.
client_address – client address. The structure of the tuple depends on the address family in use, but typically the first element is the client’s host address and the second element is the client’s port number.
server_address – server address. The structure of the tuple depends on the address family in use, but typically the first element is the server’s host address and the second element is the server’s port number. Please note that determining the actual address specified by the client might not be possible if the sever binds to all interfaces (
::) and the platform does not support theIPV6_PKTINFOsocket option. In this case, this will be the address to which the server is bound and not the address on which the request was actually received.context – context object that was returned by
prepare_context.
- Returns:
file-like object that provides the data that is transferred to the client. The file-like object must provide binary data.
- prepare_context(filename: str) Any
Prepare a context object for use by
can_handleandhandle. This method is called for each request before callingcan_handle.This is useful when both function need to do some processing on the filename or client address. This processing can be implemented in
prepare_contextand passed to the two other methods through the context so that it does not have to be done twice.The return value of this method is passed to
can_handleandhandle. The default implementation simply returnsNone.- Parameters:
filename – filename that has been requested by the client.
- Returns:
context object that is passed to
can_handleandhandle.
- class vinegar.tftp.server.TftpServer(request_handlers: List[TftpRequestHandler], bind_address: str = '::', bind_port: int = 69, default_timeout: float = 10.0, max_timeout: float = 30.0, max_retries: int = 3, max_block_size: int = 65464, block_counter_wrap_value: int = 0)
Server implementing the TFTP (RFC 1350) protocol. This server can serve arbitrary resources (read-only), not just files on the file system.
This implementation supports the TFTP blocksize option (RFC 2348), the TFTP timeout interval option (RFC 2349), and the TFTP transfer size option. Support for the transfer size option is limited to binary transfers and request handlers that provide a file object for which we can actually determine the size.
The server internally uses a daemon thread that processes incoming requests. For each request, it creates a new thread that processes this request and sends the requested data to the client.
- start()
Starts this server instance. This opens the server socket, binds it, and creates a deamon thread that processes requests.
If the server is already running, this method does nothing.
- stop()
Stops this server instance.
This closes the server socket and stops the daemon thread that has been created. Please note that this will not close the sockets or shutdown the threads that have been created for requests. Each of these threads will shutdown when its associated request is fully processed or its timeout is reached.
- vinegar.tftp.server.create_tftp_server(request_handlers: List[TftpRequestHandler], bind_address: str = '::', bind_port: int = 69, default_timeout: float = 10.0, max_timeout: float = 30.0, max_retries: int = 3, max_block_size: int = 65464, block_counter_wrap_value: int = 0)
Create a new TFTP server. The server is not started and its socket is not opened or bound when constructing the server object. Instead,
start()must be called to start the server.- Parameters:
request_handlers – List of request handlers than can handle read requests for this server. The request handlers are tried in order. The first request handler that can handle a request is used. If no request handler that can handle the request is found, an error is signaled to the client.
bind_address – Address of the interface on which the TFTP server shall listen for incoming connections. By default, the server listens on all local interfaces.
bind_port – Number of the UDP port on which the TFTP server shall listen for incoming connections. By default, the server listens on UDP port 69, this is the officially registered port for TFTP.
default_timeout – Timeout (in seconds) that is used for connections if the client does not specify a timeout. This number must be greater than or equal to 1 and less than
max_timeout. If it it is outside this range, it is silently changed to be within this range. The default is 10.max_timeout – Max. timeout interval (in seconds) that may be specified by a client. If a client requests a timeout that is greater, the timeout is limited to this number. This number must be greater than or equal to 1 and less than or equal to 255. The default is 30.
max_retries – Max. number of attempts to resend a packet before giving up. This limit is important because it keeps a connection (and the associated thread) from stalling forever when the connection to a client is lost. This number must be greater than or equal to 1. The default value is 3.
max_block_size – Max. size of a single block (in bytes). This setting is only used when a client requests a different than the default block size (512 bytes). In that case, if the client requests a block size that is greater than this setting, the block size is reduces to this setting. This can be useful when a client requests a block size that would result in IP fragmentation, but IP fragmentation is not desired. This setting must be a number between 512 (the default block size) and 65464 (the max. block size allowed by the protocol). The default value is 65464.
block_counter_wrap_value – Block at which to start counting again after reaching the max. possible block count. This value should be 0 or 1. As the TFTP standard (RFC 1350) does not specify what should happen if the block count range is exceeded, some clients expect it to wrap around to 0 while other expect it to wrap around to 1. If this parameter is set to
None, the block counter will never wrap which means that large files cannot be transferred. This is only necessary if dealing with clients that show unexpected behavior when the block counter wraps. In the context of PXE boot, most clients seem to expect 0, so that is what we use by default.
- Returns:
server object that is ready to be started.