This commit is contained in:
RocketGod
2022-09-22 13:46:47 -07:00
parent f65104c2ab
commit e7667c1d93
565 changed files with 165005 additions and 0 deletions

View File

@ -0,0 +1,710 @@
import locale
import numpy
import numpy as np
from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtGui import QFontMetrics
from PyQt5.QtWidgets import QInputDialog, QWidget, QUndoStack, QApplication
from urh import settings
from urh.controller.CompareFrameController import CompareFrameController
from urh.controller.dialogs.ContinuousSendDialog import ContinuousSendDialog
from urh.controller.dialogs.FuzzingDialog import FuzzingDialog
from urh.controller.dialogs.ModulatorDialog import ModulatorDialog
from urh.controller.dialogs.SendDialog import SendDialog
from urh.models.GeneratorListModel import GeneratorListModel
from urh.models.GeneratorTableModel import GeneratorTableModel
from urh.models.GeneratorTreeModel import GeneratorTreeModel
from urh.plugins.NetworkSDRInterface.NetworkSDRInterfacePlugin import NetworkSDRInterfacePlugin
from urh.plugins.PluginManager import PluginManager
from urh.plugins.RfCat.RfCatPlugin import RfCatPlugin
from urh.signalprocessing.IQArray import IQArray
from urh.signalprocessing.Message import Message
from urh.signalprocessing.MessageType import MessageType
from urh.signalprocessing.Modulator import Modulator
from urh.signalprocessing.ProtocoLabel import ProtocolLabel
from urh.signalprocessing.ProtocolAnalyzer import ProtocolAnalyzer
from urh.ui.actions.Fuzz import Fuzz
from urh.ui.ui_generator import Ui_GeneratorTab
from urh.util import FileOperator, util
from urh.util.Errors import Errors
from urh.util.Formatter import Formatter
from urh.util.Logger import logger
from urh.util.ProjectManager import ProjectManager
class GeneratorTabController(QWidget):
def __init__(self, compare_frame_controller: CompareFrameController, project_manager: ProjectManager, parent=None):
super().__init__(parent)
self.ui = Ui_GeneratorTab()
self.ui.setupUi(self)
util.set_splitter_stylesheet(self.ui.splitter)
self.project_manager = project_manager
self.ui.treeProtocols.setHeaderHidden(True)
self.tree_model = GeneratorTreeModel(compare_frame_controller)
self.tree_model.set_root_item(compare_frame_controller.proto_tree_model.rootItem)
self.tree_model.controller = self
self.ui.treeProtocols.setModel(self.tree_model)
self.table_model = GeneratorTableModel(compare_frame_controller.proto_tree_model.rootItem,
compare_frame_controller.decodings)
self.table_model.controller = self
self.ui.tableMessages.setModel(self.table_model)
self.label_list_model = GeneratorListModel(None)
self.ui.listViewProtoLabels.setModel(self.label_list_model)
self.network_sdr_button_orig_tooltip = self.ui.btnNetworkSDRSend.toolTip()
self.set_network_sdr_send_button_visibility()
self.set_rfcat_button_visibility()
self.network_sdr_plugin = NetworkSDRInterfacePlugin()
self.rfcat_plugin = RfCatPlugin()
self.init_rfcat_plugin()
self.modulation_msg_indices = []
self.refresh_modulators()
self.on_selected_modulation_changed()
self.set_fuzzing_ui_status()
self.ui.prBarGeneration.hide()
self.create_connects(compare_frame_controller)
self.set_modulation_profile_status()
def __get_modulator_of_message(self, message: Message) -> Modulator:
if message.modulator_index > len(self.modulators) - 1:
message.modulator_index = 0
return self.modulators[message.modulator_index]
@property
def selected_message_index(self) -> int:
min_row, _, _, _ = self.ui.tableMessages.selection_range()
return min_row #
@property
def selected_message(self) -> Message:
selected_msg_index = self.selected_message_index
if selected_msg_index == -1 or selected_msg_index >= len(self.table_model.protocol.messages):
return None
return self.table_model.protocol.messages[selected_msg_index]
@property
def active_groups(self):
return self.tree_model.groups
@property
def modulators(self):
return self.project_manager.modulators
@property
def total_modulated_samples(self) -> int:
return sum(int(len(msg.encoded_bits) * self.__get_modulator_of_message(msg).samples_per_symbol + msg.pause)
for msg in self.table_model.protocol.messages)
@modulators.setter
def modulators(self, value):
assert type(value) == list
self.project_manager.modulators = value
def create_connects(self, compare_frame_controller):
compare_frame_controller.proto_tree_model.modelReset.connect(self.refresh_tree)
compare_frame_controller.participant_changed.connect(self.table_model.refresh_vertical_header)
self.ui.btnEditModulation.clicked.connect(self.show_modulation_dialog)
self.ui.cBoxModulations.currentIndexChanged.connect(self.on_selected_modulation_changed)
self.ui.tableMessages.selectionModel().selectionChanged.connect(self.on_table_selection_changed)
self.ui.tableMessages.encodings_updated.connect(self.on_table_selection_changed)
self.table_model.undo_stack.indexChanged.connect(self.on_undo_stack_index_changed)
self.table_model.protocol.qt_signals.line_duplicated.connect(self.refresh_pause_list)
self.table_model.protocol.qt_signals.fuzzing_started.connect(self.on_fuzzing_started)
self.table_model.protocol.qt_signals.current_fuzzing_message_changed.connect(
self.on_current_fuzzing_message_changed)
self.table_model.protocol.qt_signals.fuzzing_finished.connect(self.on_fuzzing_finished)
self.table_model.first_protocol_added.connect(self.on_first_protocol_added)
self.label_list_model.protolabel_fuzzing_status_changed.connect(self.set_fuzzing_ui_status)
self.ui.cbViewType.currentIndexChanged.connect(self.on_view_type_changed)
self.ui.btnSend.clicked.connect(self.on_btn_send_clicked)
self.ui.btnSave.clicked.connect(self.on_btn_save_clicked)
self.ui.btnOpen.clicked.connect(self.on_btn_open_clicked)
self.project_manager.project_updated.connect(self.on_project_updated)
self.table_model.vertical_header_color_status_changed.connect(
self.ui.tableMessages.on_vertical_header_color_status_changed)
self.label_list_model.protolabel_removed.connect(self.handle_proto_label_removed)
self.ui.lWPauses.item_edit_clicked.connect(self.edit_pause_item)
self.ui.lWPauses.edit_all_items_clicked.connect(self.edit_all_pause_items)
self.ui.lWPauses.itemSelectionChanged.connect(self.on_lWpauses_selection_changed)
self.ui.lWPauses.lost_focus.connect(self.on_lWPauses_lost_focus)
self.ui.lWPauses.doubleClicked.connect(self.on_lWPauses_double_clicked)
self.ui.btnGenerate.clicked.connect(self.generate_file)
self.label_list_model.protolabel_fuzzing_status_changed.connect(self.handle_plabel_fuzzing_state_changed)
self.ui.btnFuzz.clicked.connect(self.on_btn_fuzzing_clicked)
self.ui.tableMessages.create_label_triggered.connect(self.create_fuzzing_label)
self.ui.tableMessages.edit_label_triggered.connect(self.show_fuzzing_dialog)
self.ui.listViewProtoLabels.selection_changed.connect(self.handle_label_selection_changed)
self.ui.listViewProtoLabels.edit_on_item_triggered.connect(self.show_fuzzing_dialog)
self.ui.btnNetworkSDRSend.clicked.connect(self.on_btn_network_sdr_clicked)
self.ui.btnRfCatSend.clicked.connect(self.on_btn_rfcat_clicked)
self.network_sdr_plugin.sending_status_changed.connect(self.on_network_sdr_sending_status_changed)
self.network_sdr_plugin.sending_stop_requested.connect(self.on_network_sdr_sending_stop_requested)
self.network_sdr_plugin.current_send_message_changed.connect(self.on_send_message_changed)
@pyqtSlot()
def refresh_tree(self):
self.tree_model.beginResetModel()
self.tree_model.endResetModel()
self.ui.treeProtocols.expandAll()
@pyqtSlot()
def refresh_table(self):
self.table_model.update()
self.ui.tableMessages.resize_columns()
is_data_there = self.table_model.display_data is not None and len(self.table_model.display_data) > 0
self.ui.btnSend.setEnabled(is_data_there)
self.ui.btnGenerate.setEnabled(is_data_there)
@pyqtSlot()
def refresh_label_list(self):
self.label_list_model.message = self.selected_message
self.label_list_model.update()
@property
def generator_undo_stack(self) -> QUndoStack:
return self.table_model.undo_stack
@pyqtSlot()
def on_selected_modulation_changed(self):
cur_ind = self.ui.cBoxModulations.currentIndex()
min_row, max_row, _, _ = self.ui.tableMessages.selection_range()
if min_row > -1:
# set modulation for selected messages
for row in range(min_row, max_row + 1):
try:
self.table_model.protocol.messages[row].modulator_index = cur_ind
except IndexError:
continue
self.show_modulation_info()
def refresh_modulators(self):
current_index = 0
if type(self.sender()) == ModulatorDialog:
current_index = self.sender().ui.comboBoxCustomModulations.currentIndex()
self.ui.cBoxModulations.clear()
for modulator in self.modulators:
self.ui.cBoxModulations.addItem(modulator.name)
self.ui.cBoxModulations.setCurrentIndex(current_index)
def bootstrap_modulator(self, protocol: ProtocolAnalyzer):
"""
Set initial parameters for default modulator if it was not edited by user previously
:return:
"""
if len(self.modulators) != 1 or len(self.table_model.protocol.messages) == 0:
return
modulator = self.modulators[0]
modulator.samples_per_symbol = protocol.messages[0].samples_per_symbol
modulator.bits_per_symbol = protocol.messages[0].bits_per_symbol
if protocol.signal:
modulator.sample_rate = protocol.signal.sample_rate
modulator.modulation_type = protocol.signal.modulation_type
auto_freq = modulator.estimate_carrier_frequency(protocol.signal, protocol)
if auto_freq is not None and auto_freq != 0:
modulator.carrier_freq_hz = auto_freq
modulator.parameters = modulator.get_default_parameters()
self.show_modulation_info()
def show_modulation_info(self):
cur_ind = self.ui.cBoxModulations.currentIndex()
mod = self.modulators[cur_ind]
self.ui.lCarrierFreqValue.setText(mod.carrier_frequency_str)
self.ui.lCarrierPhaseValue.setText(mod.carrier_phase_str)
self.ui.lBitLenValue.setText(mod.samples_per_symbol_str)
self.ui.lSampleRateValue.setText(mod.sample_rate_str)
mod_type = mod.modulation_type
self.ui.lModTypeValue.setText(mod_type)
self.ui.lParamCaption.setText(mod.parameter_type_str)
self.ui.labelParameterValues.setText(mod.parameters_string)
self.ui.labelBitsPerSymbol.setText(str(mod.bits_per_symbol))
def prepare_modulation_dialog(self) -> (ModulatorDialog, Message):
preselected_index = self.ui.cBoxModulations.currentIndex()
min_row, max_row, start, end = self.ui.tableMessages.selection_range()
if min_row > -1:
try:
selected_message = self.table_model.protocol.messages[min_row]
preselected_index = selected_message.modulator_index
except IndexError:
selected_message = Message([1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0], 0, [], MessageType("empty"))
else:
selected_message = Message([1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0], 0, [], MessageType("empty"))
if len(self.table_model.protocol.messages) > 0:
selected_message.samples_per_symbol = self.table_model.protocol.messages[0].samples_per_symbol
for m in self.modulators:
m.default_sample_rate = self.project_manager.device_conf["sample_rate"]
modulator_dialog = ModulatorDialog(self.modulators, tree_model=self.tree_model, parent=self.parent())
modulator_dialog.ui.comboBoxCustomModulations.setCurrentIndex(preselected_index)
modulator_dialog.finished.connect(self.refresh_modulators)
modulator_dialog.finished.connect(self.refresh_pause_list)
return modulator_dialog, selected_message
def set_modulation_profile_status(self):
visible = settings.read("multiple_modulations", False, bool)
self.ui.cBoxModulations.setVisible(visible)
def init_rfcat_plugin(self):
self.set_rfcat_button_visibility()
self.rfcat_plugin = RfCatPlugin()
self.rfcat_plugin.current_send_message_changed.connect(self.on_send_message_changed)
self.ui.btnRfCatSend.setEnabled(self.rfcat_plugin.rfcat_is_found)
@pyqtSlot()
def on_undo_stack_index_changed(self):
self.refresh_table()
self.refresh_pause_list()
self.refresh_label_list()
self.refresh_estimated_time()
self.set_fuzzing_ui_status()
@pyqtSlot()
def show_modulation_dialog(self):
modulator_dialog, message = self.prepare_modulation_dialog()
modulator_dialog.showMaximized()
modulator_dialog.initialize(message.encoded_bits_str[0:16])
self.project_manager.modulation_was_edited = True
@pyqtSlot()
def on_table_selection_changed(self):
min_row, max_row, start, end = self.ui.tableMessages.selection_range()
if min_row == -1:
self.ui.lEncodingValue.setText("-") #
self.ui.lEncodingValue.setToolTip("")
self.label_list_model.message = None
return
container = self.table_model.protocol
message = container.messages[min_row]
self.label_list_model.message = message
decoder_name = message.decoder.name
metrics = QFontMetrics(self.ui.lEncodingValue.font())
elidedName = metrics.elidedText(decoder_name, Qt.ElideRight, self.ui.lEncodingValue.width())
self.ui.lEncodingValue.setText(elidedName)
self.ui.lEncodingValue.setToolTip(decoder_name)
self.ui.cBoxModulations.blockSignals(True)
self.ui.cBoxModulations.setCurrentIndex(message.modulator_index)
self.show_modulation_info()
self.ui.cBoxModulations.blockSignals(False)
@pyqtSlot(int)
def edit_pause_item(self, index: int):
message = self.table_model.protocol.messages[index]
cur_len = message.pause
new_len, ok = QInputDialog.getInt(self, self.tr("Enter new Pause Length"),
self.tr("Pause Length:"), cur_len, 0)
if ok:
message.pause = new_len
self.refresh_pause_list()
@pyqtSlot()
def edit_all_pause_items(self):
message = self.table_model.protocol.messages[0]
cur_len = message.pause
new_len, ok = QInputDialog.getInt(self, self.tr("Enter new Pause Length"),
self.tr("Pause Length:"), cur_len, 0)
if ok:
for message in self.table_model.protocol.messages:
message.pause = new_len
self.refresh_pause_list()
@pyqtSlot()
def on_lWPauses_double_clicked(self):
sel_indexes = [index.row() for index in self.ui.lWPauses.selectedIndexes()]
if len(sel_indexes) > 0:
self.edit_pause_item(sel_indexes[0])
@pyqtSlot()
def refresh_pause_list(self):
self.ui.lWPauses.clear()
fmt_str = "Pause ({1:d}-{2:d}) <{0:d} samples ({3})>"
for i, pause in enumerate(self.table_model.protocol.pauses):
sr = self.__get_modulator_of_message(self.table_model.protocol.messages[i]).sample_rate
item = fmt_str.format(pause, i + 1, i + 2, Formatter.science_time(pause / sr))
self.ui.lWPauses.addItem(item)
self.refresh_estimated_time()
@pyqtSlot()
def on_lWpauses_selection_changed(self):
rows = [index.row() for index in self.ui.lWPauses.selectedIndexes()]
if len(rows) == 0:
return
self.ui.tableMessages.show_pause_active = True
self.ui.tableMessages.pause_row = rows[0]
self.ui.tableMessages.viewport().update()
self.ui.tableMessages.scrollTo(self.table_model.index(rows[0], 0))
@pyqtSlot()
def on_lWPauses_lost_focus(self):
self.ui.tableMessages.show_pause_active = False
self.ui.tableMessages.viewport().update()
@pyqtSlot()
def generate_file(self):
try:
total_samples = self.total_modulated_samples
buffer = self.prepare_modulation_buffer(total_samples, show_error=False)
if buffer is None:
Errors.generic_error(self.tr("File too big"), self.tr("This file would get too big to save."))
self.unsetCursor()
return
modulated_samples = self.modulate_data(buffer)
try:
sample_rate = self.modulators[0].sample_rate
except Exception as e:
logger.exception(e)
sample_rate = 1e6
FileOperator.ask_signal_file_name_and_save("generated", modulated_samples, sample_rate=sample_rate, parent=self)
except Exception as e:
Errors.exception(e)
self.unsetCursor()
def prepare_modulation_buffer(self, total_samples: int, show_error=True) -> IQArray:
dtype = Modulator.get_dtype()
n = 2 if dtype == np.int8 else 4 if dtype == np.int16 else 8
memory_size_for_buffer = total_samples * n
logger.debug("Allocating {0:.2f}MB for modulated samples".format(memory_size_for_buffer / (1024 ** 2)))
try:
# allocate it three times as we need the same amount for the sending process
IQArray(None, dtype=dtype, n=3*total_samples)
except MemoryError:
# will go into continuous mode in this case
if show_error:
Errors.not_enough_ram_for_sending_precache(3*memory_size_for_buffer)
return None
return IQArray(None, dtype=dtype, n=total_samples)
def modulate_data(self, buffer: IQArray) -> IQArray:
"""
:param buffer: Buffer in which the modulated data shall be written, initialized with zeros
:return:
"""
self.ui.prBarGeneration.show()
self.ui.prBarGeneration.setValue(0)
self.ui.prBarGeneration.setMaximum(self.table_model.row_count)
self.modulation_msg_indices.clear()
pos = 0
for i in range(0, self.table_model.row_count):
message = self.table_model.protocol.messages[i]
modulator = self.__get_modulator_of_message(message)
# We do not need to modulate the pause extra, as result is already initialized with zeros
modulated = modulator.modulate(start=0, data=message.encoded_bits, pause=0)
buffer[pos:pos + len(modulated)] = modulated
pos += len(modulated) + message.pause
self.modulation_msg_indices.append(pos)
self.ui.prBarGeneration.setValue(i + 1)
QApplication.instance().processEvents()
self.ui.prBarGeneration.hide()
return buffer
@pyqtSlot(int)
def show_fuzzing_dialog(self, label_index: int):
view = self.ui.cbViewType.currentIndex()
if self.label_list_model.message is not None:
msg_index = self.table_model.protocol.messages.index(self.label_list_model.message)
fdc = FuzzingDialog(protocol=self.table_model.protocol, label_index=label_index,
msg_index=msg_index, proto_view=view, parent=self)
fdc.show()
fdc.finished.connect(self.on_fuzzing_dialog_finished)
@pyqtSlot()
def on_fuzzing_dialog_finished(self):
self.refresh_label_list()
self.refresh_table()
self.set_fuzzing_ui_status()
self.ui.tabWidget.setCurrentIndex(2)
@pyqtSlot()
def handle_plabel_fuzzing_state_changed(self):
self.refresh_table()
self.label_list_model.update()
@pyqtSlot(ProtocolLabel)
def handle_proto_label_removed(self, plabel: ProtocolLabel):
self.refresh_label_list()
self.refresh_table()
self.set_fuzzing_ui_status()
@pyqtSlot()
def on_btn_fuzzing_clicked(self):
fuz_mode = "Successive"
if self.ui.rbConcurrent.isChecked():
fuz_mode = "Concurrent"
elif self.ui.rBExhaustive.isChecked():
fuz_mode = "Exhaustive"
self.setCursor(Qt.WaitCursor)
fuzz_action = Fuzz(self.table_model.protocol, fuz_mode)
self.table_model.undo_stack.push(fuzz_action)
for row in fuzz_action.added_message_indices:
self.table_model.update_checksums_for_row(row)
self.unsetCursor()
self.ui.tableMessages.setFocus()
@pyqtSlot()
def set_fuzzing_ui_status(self):
btn_was_enabled = self.ui.btnFuzz.isEnabled()
fuzz_active = any(lbl.active_fuzzing for msg in self.table_model.protocol.messages for lbl in msg.message_type)
self.ui.btnFuzz.setEnabled(fuzz_active)
if self.ui.btnFuzz.isEnabled() and not btn_was_enabled:
font = self.ui.btnFuzz.font()
font.setBold(True)
self.ui.btnFuzz.setFont(font)
else:
font = self.ui.btnFuzz.font()
font.setBold(False)
self.ui.btnFuzz.setFont(font)
self.ui.btnFuzz.setStyleSheet("")
has_same_message = self.table_model.protocol.multiple_fuzz_labels_per_message
self.ui.rBSuccessive.setEnabled(has_same_message)
self.ui.rBExhaustive.setEnabled(has_same_message)
self.ui.rbConcurrent.setEnabled(has_same_message)
def refresh_existing_encodings(self, encodings_from_file):
"""
Refresh existing encodings for messages, when encoding was changed by user in dialog
:return:
"""
update = False
for msg in self.table_model.protocol.messages:
i = next((i for i, d in enumerate(encodings_from_file) if d.name == msg.decoder.name), 0)
if msg.decoder != encodings_from_file[i]:
update = True
msg.decoder = encodings_from_file[i]
msg.clear_decoded_bits()
msg.clear_encoded_bits()
if update:
self.refresh_table()
self.refresh_estimated_time()
@pyqtSlot()
def refresh_estimated_time(self):
c = self.table_model.protocol
if c.num_messages == 0:
self.ui.lEstimatedTime.setText("Estimated Time: ")
return
avg_msg_len = numpy.mean([len(msg.encoded_bits) for msg in c.messages])
avg_samples_per_symbol = numpy.mean([m.samples_per_symbol for m in self.modulators])
avg_sample_rate = numpy.mean([m.sample_rate for m in self.modulators])
pause_samples = sum(c.pauses)
nsamples = c.num_messages * avg_msg_len * avg_samples_per_symbol + pause_samples
self.ui.lEstimatedTime.setText(
locale.format_string("Estimated Time: %.04f seconds", nsamples / avg_sample_rate))
@pyqtSlot(int, int, int)
def create_fuzzing_label(self, msg_index: int, start: int, end: int):
con = self.table_model.protocol
start, end = con.convert_range(start, end - 1, self.ui.cbViewType.currentIndex(), 0, False, msg_index)
lbl = con.create_fuzzing_label(start, end, msg_index)
self.show_fuzzing_dialog(con.protocol_labels.index(lbl))
@pyqtSlot()
def handle_label_selection_changed(self):
rows = [index.row() for index in self.ui.listViewProtoLabels.selectedIndexes()]
if len(rows) == 0:
return
maxrow = numpy.max(rows)
try:
label = self.table_model.protocol.protocol_labels[maxrow]
except IndexError:
return
if label.show and self.selected_message:
start, end = self.selected_message.get_label_range(lbl=label, view=self.table_model.proto_view,
decode=False)
indx = self.table_model.index(0, int((start + end) / 2))
self.ui.tableMessages.scrollTo(indx)
@pyqtSlot()
def on_view_type_changed(self):
self.setCursor(Qt.WaitCursor)
self.table_model.proto_view = self.ui.cbViewType.currentIndex()
self.ui.tableMessages.resize_columns()
self.unsetCursor()
@pyqtSlot()
def on_btn_send_clicked(self):
try:
total_samples = self.total_modulated_samples
buffer = self.prepare_modulation_buffer(total_samples)
if buffer is not None:
modulated_data = self.modulate_data(buffer)
else:
# Enter continuous mode
modulated_data = None
try:
if modulated_data is not None:
try:
dialog = SendDialog(self.project_manager, modulated_data=modulated_data,
modulation_msg_indices=self.modulation_msg_indices, parent=self)
except MemoryError:
# Not enough memory for device buffer so we need to create a continuous send dialog
del modulated_data
Errors.not_enough_ram_for_sending_precache(None)
dialog = ContinuousSendDialog(self.project_manager,
self.table_model.protocol.messages,
self.modulators, total_samples, parent=self)
else:
dialog = ContinuousSendDialog(self.project_manager, self.table_model.protocol.messages,
self.modulators, total_samples, parent=self)
except OSError as e:
logger.exception(e)
return
if dialog.has_empty_device_list:
Errors.no_device()
dialog.close()
return
dialog.device_parameters_changed.connect(self.project_manager.set_device_parameters)
dialog.show()
dialog.graphics_view.show_full_scene(reinitialize=True)
except Exception as e:
Errors.exception(e)
self.unsetCursor()
@pyqtSlot()
def on_btn_save_clicked(self):
filename = FileOperator.ask_save_file_name("profile.fuzz.xml", caption="Save fuzzing profile")
if filename:
self.table_model.protocol.to_xml_file(filename,
decoders=self.project_manager.decodings,
participants=self.project_manager.participants,
modulators=self.modulators)
@pyqtSlot()
def on_btn_open_clicked(self):
dialog = FileOperator.get_open_dialog(directory_mode=False, parent=self, name_filter="fuzz")
if dialog.exec_():
for filename in dialog.selectedFiles():
self.load_from_file(filename)
def load_from_file(self, filename: str):
try:
self.modulators = ProjectManager.read_modulators_from_file(filename)
self.table_model.protocol.from_xml_file(filename)
self.refresh_pause_list()
self.refresh_estimated_time()
self.refresh_modulators()
self.show_modulation_info()
self.refresh_table()
self.set_fuzzing_ui_status()
except:
logger.error("You done something wrong to the xml fuzzing profile.")
@pyqtSlot()
def on_project_updated(self):
self.table_model.refresh_vertical_header()
def set_network_sdr_send_button_visibility(self):
is_plugin_enabled = PluginManager().is_plugin_enabled("NetworkSDRInterface")
self.ui.btnNetworkSDRSend.setVisible(is_plugin_enabled)
def set_rfcat_button_visibility(self):
is_plugin_enabled = PluginManager().is_plugin_enabled("RfCat")
self.ui.btnRfCatSend.setVisible(is_plugin_enabled)
@pyqtSlot()
def on_btn_network_sdr_clicked(self):
if not self.network_sdr_plugin.is_sending:
messages = self.table_model.protocol.messages
sample_rates = [self.__get_modulator_of_message(msg).sample_rate for msg in messages]
self.network_sdr_plugin.start_message_sending_thread(messages, sample_rates)
else:
self.network_sdr_plugin.stop_sending_thread()
@pyqtSlot(bool)
def on_network_sdr_sending_status_changed(self, is_sending: bool):
self.ui.btnNetworkSDRSend.setChecked(is_sending)
self.ui.btnNetworkSDRSend.setEnabled(True)
self.ui.btnNetworkSDRSend.setToolTip(
"Sending in progress" if is_sending else self.network_sdr_button_orig_tooltip)
if not is_sending:
self.ui.tableMessages.clearSelection()
@pyqtSlot()
def on_network_sdr_sending_stop_requested(self):
self.ui.btnNetworkSDRSend.setToolTip("Stopping sending")
self.ui.btnNetworkSDRSend.setEnabled(False)
@pyqtSlot(int)
def on_send_message_changed(self, message_index: int):
self.ui.tableMessages.selectRow(message_index)
@pyqtSlot()
def on_btn_rfcat_clicked(self):
if not self.rfcat_plugin.is_sending:
messages = self.table_model.protocol.messages
sample_rates = [self.__get_modulator_of_message(msg).sample_rate for msg in messages]
self.rfcat_plugin.start_message_sending_thread(messages, sample_rates, self.modulators,
self.project_manager)
else:
self.rfcat_plugin.stop_sending_thread()
@pyqtSlot(int)
def on_fuzzing_started(self, num_values: int):
self.ui.stackedWidgetFuzzing.setCurrentWidget(self.ui.pageFuzzingProgressBar)
self.ui.progressBarFuzzing.setMaximum(num_values)
self.ui.progressBarFuzzing.setValue(0)
QApplication.instance().processEvents()
@pyqtSlot()
def on_fuzzing_finished(self):
self.ui.stackedWidgetFuzzing.setCurrentWidget(self.ui.pageFuzzingUI)
# Calculate Checksums for Fuzzed Messages
self.setCursor(Qt.WaitCursor)
self.unsetCursor()
@pyqtSlot(int)
def on_current_fuzzing_message_changed(self, current_message: int):
self.ui.progressBarFuzzing.setValue(current_message)
QApplication.instance().processEvents()
@pyqtSlot(ProtocolAnalyzer)
def on_first_protocol_added(self, protocol: ProtocolAnalyzer):
if not self.project_manager.modulation_was_edited:
self.bootstrap_modulator(protocol)