Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
"""
Deals with incoming RRQ packets. This is called by `run_once` when data
is available on the listening socket.
This method deals with extracting all the relevant information from the
request (like file, transfer mode, path, and options).
If all is good it will run the `get_handler` method, which returns a
`BaseHandler` object. `BaseHandler` is a subclass of a
`multiprocessing.Process` class so calling `start()` on it will cause
a `fork()`.
"""
data, peer = self._listener.recvfrom(constants.DEFAULT_BLKSIZE)
code = struct.unpack('!H', data[:2])[0]
if code != constants.OPCODE_RRQ:
logging.warning(
'unexpected TFTP opcode %d, expected %d' %
(code, constants.OPCODE_RRQ)
)
return
# extract options
tokens = list(filter(bool, data[2:].decode('latin-1').split('\x00')))
if len(tokens) < 2 or len(tokens) % 2 != 0:
logging.error(
'Received malformed packet, ignoring '
'(tokens length: {tl})'.format(tl=len(tokens))
)
return
path = tokens[0]
options = collections.OrderedDict([
('mode', tokens[1].lower()),
('default_timeout', self._timeout),
def on_new_data(self):
"""
Deals with incoming RRQ packets. This is called by `run_once` when data
is available on the listening socket.
This method deals with extracting all the relevant information from the
request (like file, transfer mode, path, and options).
If all is good it will run the `get_handler` method, which returns a
`BaseHandler` object. `BaseHandler` is a subclass of a
`multiprocessing.Process` class so calling `start()` on it will cause
a `fork()`.
"""
data, peer = self._listener.recvfrom(constants.DEFAULT_BLKSIZE)
code = struct.unpack("!H", data[:2])[0]
if code != constants.OPCODE_RRQ:
logging.warning(
"unexpected TFTP opcode %d, expected %d" % (code, constants.OPCODE_RRQ)
)
return
# extract options
tokens = list(filter(bool, data[2:].decode("latin-1").split("\x00")))
if len(tokens) < 2 or len(tokens) % 2 != 0:
logging.error(
"Received malformed packet, ignoring "
"(tokens length: {tl})".format(tl=len(tokens))
)
return
path = tokens[0]
options = collections.OrderedDict(
def on_new_data(self):
"""
Deals with incoming RRQ packets. This is called by `run_once` when data
is available on the listening socket.
This method deals with extracting all the relevant information from the
request (like file, transfer mode, path, and options).
If all is good it will run the `get_handler` method, which returns a
`BaseHandler` object. `BaseHandler` is a subclass of a
`multiprocessing.Process` class so calling `start()` on it will cause
a `fork()`.
"""
data, peer = self._listener.recvfrom(constants.DEFAULT_BLKSIZE)
code = struct.unpack("!H", data[:2])[0]
if code != constants.OPCODE_RRQ:
logging.warning(
"unexpected TFTP opcode %d, expected %d" % (code, constants.OPCODE_RRQ)
)
return
# extract options
tokens = list(filter(bool, data[2:].decode("latin-1").split("\x00")))
if len(tokens) < 2 or len(tokens) % 2 != 0:
logging.error(
"Received malformed packet, ignoring "
"(tokens length: {tl})".format(tl=len(tokens))
)
return
def on_new_data(self):
"""
Deals with incoming RRQ packets. This is called by `run_once` when data
is available on the listening socket.
This method deals with extracting all the relevant information from the
request (like file, transfer mode, path, and options).
If all is good it will run the `get_handler` method, which returns a
`BaseHandler` object. `BaseHandler` is a subclass of a
`multiprocessing.Process` class so calling `start()` on it will cause
a `fork()`.
"""
data, peer = self._listener.recvfrom(constants.DEFAULT_BLKSIZE)
code = struct.unpack('!H', data[:2])[0]
if code != constants.OPCODE_RRQ:
logging.warning(
'unexpected TFTP opcode %d, expected %d' %
(code, constants.OPCODE_RRQ)
)
return
# extract options
tokens = list(filter(bool, data[2:].decode('latin-1').split('\x00')))
if len(tokens) < 2 or len(tokens) % 2 != 0:
logging.error(
'Received malformed packet, ignoring '
'(tokens length: {tl})'.format(tl=len(tokens))
)
return
def on_new_data(self):
"""
Deals with incoming RRQ packets. This is called by `run_once` when data
is available on the listening socket.
This method deals with extracting all the relevant information from the
request (like file, transfer mode, path, and options).
If all is good it will run the `get_handler` method, which returns a
`BaseHandler` object. `BaseHandler` is a subclass of a
`multiprocessing.Process` class so calling `start()` on it will cause
a `fork()`.
"""
data, peer = self._listener.recvfrom(constants.DEFAULT_BLKSIZE)
code = struct.unpack('!H', data[:2])[0]
if code != constants.OPCODE_RRQ:
logging.warning(
'unexpected TFTP opcode %d, expected %d' %
(code, constants.OPCODE_RRQ)
)
return
# extract options
tokens = list(filter(bool, data[2:].decode('latin-1').split('\x00')))
if len(tokens) < 2 or len(tokens) % 2 != 0:
logging.error(
'Received malformed packet, ignoring '
'(tokens length: {tl})'.format(tl=len(tokens))
)
return
path = tokens[0]
def _transmit_oack(self):
"""Method that deals with sending OACK datagrams on the wire."""
opts = []
for key, val in self._options.items():
fmt = str("%dsx%ds" % (len(key), len(val)))
opts.append(
struct.pack(
fmt, bytes(key.encode("latin-1")), bytes(val.encode("latin-1"))
)
)
opts.append(b"")
fmt = str("!H")
packet = struct.pack(fmt, constants.OPCODE_OACK) + b"\x00".join(opts)
self._get_listener().sendto(packet, self._peer)
self._stats.packets_sent += 1
def __init__(
self,
address,
port,
retries,
timeout,
server_stats_callback=None,
stats_interval_seconds=constants.DATAPOINTS_INTERVAL_SECONDS
):
"""
This base class implements the process which deals with accepting new
requests.
Note:
This class doesn't have to be used directly, you must inherit from
it and override the `get_handler()`` method to return an instance
of `BaseHandler`.
Args:
address (str): address (IPv4 or IPv6) the server needs to bind to.
port (int): the port the server needs to bind to.
code, block_number = struct.unpack("!HH", data[:4])
if code == constants.OPCODE_ERROR:
# When the client sends an OPCODE_ERROR#
# the block number is the ERR codes in constants.py
self._stats.error = {
"error_code": block_number,
"error_message": data[4:-1].decode("ascii", "ignore"),
}
# An error was reported by the client which terminates the exchange
logging.error(
"Error reported from client: %s" % self._stats.error["error_message"]
)
self._transmit_error()
self._should_stop = True
return
if code != constants.OPCODE_ACK:
logging.error(
"Expected an ACK opcode from %s, got: %d" % (self._peer, code)
)
self._stats.error = {
"error_code": constants.ERR_ILLEGAL_OPERATION,
"error_message": "I only do reads, really",
}
self._transmit_error()
self._should_stop = True
return
self._handle_ack(block_number)
)
self._family = socket.AF_INET6
# the format of the peer tuple is different for v4 and v6
if isinstance(ipaddress.ip_address(server_addr[0]), ipaddress.IPv4Address):
self._family = socket.AF_INET
# peer address format is different in v4 world
self._peer = (self._peer[0].replace("::ffff:", ""), self._peer[1])
self._stats = SessionStats(self._server_addr, self._peer, self._path)
try:
self._response_data = self.get_response_data()
except FileNotFoundError as e:
logging.warning(str(e))
self._stats.error = {
"error_code": constants.ERR_FILE_NOT_FOUND,
"error_message": str(e),
}
except Exception as e:
logging.exception("Caught exception: %s." % e)
self._stats.error = {
"error_code": constants.ERR_UNDEFINED,
"error_message": str(e),
}
super().__init__()
def __init__(
self,
address,
port,
retries,
timeout,
server_stats_callback=None,
stats_interval_seconds=constants.DATAPOINTS_INTERVAL_SECONDS,
):
"""
This base class implements the process which deals with accepting new
requests.
Note:
This class doesn't have to be used directly, you must inherit from
it and override the `get_handler()`` method to return an instance
of `BaseHandler`.
Args:
address (str): address (IPv4 or IPv6) the server needs to bind to.
port (int): the port the server needs to bind to.