diff options
-rw-r--r-- | epan/dissectors/packet-lbtru.c | 1 | ||||
-rw-r--r-- | ui/qt/CMakeLists.txt | 12 | ||||
-rw-r--r-- | ui/qt/Makefile.am | 8 | ||||
-rw-r--r-- | ui/qt/Makefile.common | 16 | ||||
-rw-r--r-- | ui/qt/QtShark.pro | 12 | ||||
-rw-r--r-- | ui/qt/lbm_lbtrm_transport_dialog.cpp | 1655 | ||||
-rw-r--r-- | ui/qt/lbm_lbtrm_transport_dialog.h | 132 | ||||
-rw-r--r-- | ui/qt/lbm_lbtrm_transport_dialog.ui | 836 | ||||
-rw-r--r-- | ui/qt/lbm_lbtru_transport_dialog.cpp | 2251 | ||||
-rw-r--r-- | ui/qt/lbm_lbtru_transport_dialog.h | 156 | ||||
-rw-r--r-- | ui/qt/lbm_lbtru_transport_dialog.ui | 1301 | ||||
-rw-r--r-- | ui/qt/lbm_stream_dialog.cpp | 455 | ||||
-rw-r--r-- | ui/qt/lbm_stream_dialog.h | 85 | ||||
-rw-r--r-- | ui/qt/lbm_stream_dialog.ui | 159 | ||||
-rw-r--r-- | ui/qt/lbm_uimflow_dialog.cpp | 668 | ||||
-rw-r--r-- | ui/qt/lbm_uimflow_dialog.h | 117 | ||||
-rw-r--r-- | ui/qt/lbm_uimflow_dialog.ui | 326 | ||||
-rw-r--r-- | ui/qt/main_window.h | 15 | ||||
-rw-r--r-- | ui/qt/main_window.ui | 119 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 100 |
20 files changed, 8423 insertions, 1 deletions
diff --git a/epan/dissectors/packet-lbtru.c b/epan/dissectors/packet-lbtru.c index 64a87d8d7e..b557f088d0 100644 --- a/epan/dissectors/packet-lbtru.c +++ b/epan/dissectors/packet-lbtru.c @@ -2025,6 +2025,7 @@ void proto_reg_handoff_lbtru(void) lbtru_dissector_handle = new_create_dissector_handle(dissect_lbtru, proto_lbtru); dissector_add_handle("udp.port", lbtru_dissector_handle); /* for "decode as" */ heur_dissector_add("udp", test_lbtru_packet, proto_lbtru); + lbtru_tap_handle = register_tap("lbtru"); } /* Make sure the low source port is <= the high source port. If not, don't change them. */ diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index b8b50ba6e3..8f3702f7cd 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -54,6 +54,10 @@ set(WIRESHARK_QT_HEADERS io_graph_dialog.h label_stack.h layout_preferences_frame.h + lbm_lbtrm_transport_dialog.h + lbm_lbtru_transport_dialog.h + lbm_stream_dialog.h + lbm_uimflow_dialog.h main_status_bar.h main_welcome.h main_window.h @@ -130,6 +134,10 @@ set(WIRESHARK_QT_SRC io_graph_dialog.cpp label_stack.cpp layout_preferences_frame.cpp + lbm_lbtrm_transport_dialog.cpp + lbm_lbtru_transport_dialog.cpp + lbm_stream_dialog.cpp + lbm_uimflow_dialog.cpp main.cpp main_status_bar.cpp main_welcome.cpp @@ -199,6 +207,10 @@ set(WIRESHARK_QT_UI import_text_dialog.ui io_graph_dialog.ui layout_preferences_frame.ui + lbm_lbtrm_transport_dialog.ui + lbm_lbtru_transport_dialog.ui + lbm_stream_dialog.ui + lbm_uimflow_dialog.ui main_welcome.ui main_window.ui main_window_preferences_frame.ui diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 1196fcc1d8..71175e8b92 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -153,6 +153,14 @@ io_graph_dialog.cpp io_graph_dialog.h: ui_io_graph_dialog.h layout_preferences_frame.cpp layout_preferences_frame.h: ui_layout_preferences_frame.h +lbm_lbtrm_transport_dialog.cpp lbm_lbtrm_transport_dialog.h: ui_lbm_lbtrm_transport_dialog.h + +lbm_lbtru_transport_dialog.cpp lbm_lbtru_transport_dialog.h: ui_lbm_lbtru_transport_dialog.h + +lbm_stream_dialog.cpp lbm_stream_dialog.h: ui_lbm_stream_dialog.h + +lbm_uimflow_dialog.cpp lbm_uimflow_dialog.h: ui_lbm_uimflow_dialog.h + main_welcome.cpp main_welcome.h: ui_main_welcome.h main_window.cpp main_window_slots.cpp main_window.h: ui_main_window.h diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index eeac2f572f..7dac9f025d 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -43,6 +43,10 @@ NODIST_GENERATED_HEADER_FILES = \ ui_import_text_dialog.h \ ui_io_graph_dialog.h \ ui_layout_preferences_frame.h \ + ui_lbm_lbtrm_transport_dialog.h \ + ui_lbm_lbtru_transport_dialog.h \ + ui_lbm_stream_dialog.h \ + ui_lbm_uimflow_dialog.h \ ui_main_welcome.h \ ui_main_window.h \ ui_main_window_preferences_frame.h \ @@ -134,6 +138,10 @@ MOC_HDRS = \ io_graph_dialog.h \ label_stack.h \ layout_preferences_frame.h \ + lbm_lbtrm_transport_dialog.h \ + lbm_lbtru_transport_dialog.h \ + lbm_stream_dialog.h \ + lbm_uimflow_dialog.h \ main_status_bar.h \ main_welcome.h \ main_window.h \ @@ -191,6 +199,10 @@ UI_FILES = \ import_text_dialog.ui \ io_graph_dialog.ui \ layout_preferences_frame.ui \ + lbm_lbtrm_transport_dialog.ui \ + lbm_lbtru_transport_dialog.ui \ + lbm_stream_dialog.ui \ + lbm_uimflow_dialog.ui \ main_welcome.ui \ main_window.ui \ main_window_preferences_frame.ui \ @@ -298,6 +310,10 @@ WIRESHARK_QT_SRC = \ io_graph_dialog.cpp \ label_stack.cpp \ layout_preferences_frame.cpp \ + lbm_lbtrm_transport_dialog.cpp \ + lbm_lbtru_transport_dialog.cpp \ + lbm_stream_dialog.cpp \ + lbm_uimflow_dialog.cpp \ main.cpp \ main_status_bar.cpp \ main_welcome.cpp \ diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro index 672b634170..13f5f82502 100644 --- a/ui/qt/QtShark.pro +++ b/ui/qt/QtShark.pro @@ -233,6 +233,10 @@ FORMS += \ import_text_dialog.ui \ io_graph_dialog.ui \ layout_preferences_frame.ui \ + lbm_lbtrm_transport_dialog.ui \ + lbm_lbtru_transport_dialog.ui \ + lbm_stream_dialog.ui \ + lbm_uimflow_dialog.ui \ main_welcome.ui \ main_window.ui \ main_window_preferences_frame.ui \ @@ -274,6 +278,10 @@ HEADERS += $$HEADERS_WS_C \ follow_stream_text.h \ font_color_preferences_frame.h \ layout_preferences_frame.h \ + lbm_lbtrm_transport_dialog.h \ + lbm_lbtru_transport_dialog.h \ + lbm_stream_dialog.h \ + lbm_uimflow_dialog.h \ main_window_preferences_frame.h \ module_preferences_scroll_area.h \ packet_comment_dialog.h \ @@ -588,6 +596,10 @@ SOURCES += \ io_graph_dialog.cpp \ label_stack.cpp \ layout_preferences_frame.cpp \ + lbm_lbtrm_transport_dialog.cpp \ + lbm_lbtru_transport_dialog.cpp \ + lbm_stream_dialog.cpp \ + lbm_uimflow_dialog.cpp \ main.cpp \ main_status_bar.cpp \ main_welcome.cpp \ diff --git a/ui/qt/lbm_lbtrm_transport_dialog.cpp b/ui/qt/lbm_lbtrm_transport_dialog.cpp new file mode 100644 index 0000000000..775f7f3c64 --- /dev/null +++ b/ui/qt/lbm_lbtrm_transport_dialog.cpp @@ -0,0 +1,1655 @@ +/* lbm_lbtrm_transport_dialog.cpp + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "lbm_lbtrm_transport_dialog.h" +#include "ui_lbm_lbtrm_transport_dialog.h" + +#include "file.h" + +#include "wireshark_application.h" + +#include <QClipboard> +#include <QMessageBox> +#include <QTreeWidget> +#include <QTreeWidgetItemIterator> +#include <QMenu> +#include <epan/packet_info.h> +#include <epan/tap.h> +#include <epan/to_str.h> +#include <epan/wmem/wmem.h> +#include <epan/dissectors/packet-lbm.h> +#include <wsutil/nstime.h> + +#include <QDebug> + +namespace +{ + static const int Source_AddressTransport_Column = 0; + static const int Source_DataFrames_Column = 1; + static const int Source_DataBytes_Column = 2; + static const int Source_DataFramesBytes_Column = 3; + static const int Source_DataRate_Column = 4; + static const int Source_RXDataFrames_Column = 5; + static const int Source_RXDataBytes_Column = 6; + static const int Source_RXDataFramesBytes_Column = 7; + static const int Source_RXDataRate_Column = 8; + static const int Source_NCFFrames_Column = 9; + static const int Source_NCFCount_Column = 10; + static const int Source_NCFBytes_Column = 11; + static const int Source_NCFFramesBytes_Column = 12; + static const int Source_NCFCountBytes_Column = 13; + static const int Source_NCFFramesCount_Column = 14; + static const int Source_NCFFramesCountBytes_Column = 15; + static const int Source_NCFRate_Column = 16; + static const int Source_SMFrames_Column = 17; + static const int Source_SMBytes_Column = 18; + static const int Source_SMFramesBytes_Column = 19; + static const int Source_SMRate_Column = 20; + + static const int Receiver_AddressTransport_Column = 0; + static const int Receiver_NAKFrames_Column = 1; + static const int Receiver_NAKCount_Column = 2; + static const int Receiver_NAKBytes_Column = 3; + static const int Receiver_NAKRate_Column = 4; + + static const int Detail_SQN_Column = 0; + static const int Detail_Count_Column = 1; + static const int Detail_Frame_Column = 2; + + static const double OneKilobit = 1000.0; + static const double OneMegabit = OneKilobit * OneKilobit; + static const double OneGigabit = OneMegabit * OneKilobit; +} + +static QString format_rate(const nstime_t & elapsed, guint64 bytes) +{ + QString result; + double elapsed_sec; + double rate; + + if (((elapsed.secs == 0) && (elapsed.nsecs == 0)) || (bytes == 0)) + { + return (QString("0")); + } + + elapsed_sec = elapsed.secs + (((double)elapsed.nsecs) / 1000000000.0); + rate = ((double)(bytes * 8)) / elapsed_sec; + + // Currently rate is in bps + if (rate >= OneGigabit) + { + rate /= OneGigabit; + result = QString("%1G").arg(rate, 0, 'f', 2); + } + else if (rate >= OneMegabit) + { + rate /= OneMegabit; + result = QString("%1M").arg(rate, 0, 'f', 2); + } + else if (rate >= OneKilobit) + { + rate /= OneKilobit; + result = QString("%1K").arg(rate, 0, 'f', 2); + } + else + { + result = QString("%1").arg(rate, 0, 'f', 2); + } + return (result); +} + +// Note: +// LBMLBTRMFrameEntry, LBMLBTRMSQNEntry, LBMLBTRMNCFReasonEntry, LBMLBTRMNCFSQNEntry, LBMLBTRMSourceTransportEntry, LBMLBTRMSourceEntry, +// LBMLBTRMReceiverTransportEntry, and LBMLBTRMReceiverEntry are all derived from a QTreeWidgetItem. Each instantiation can exist +// in two places: in a QTreeWidget, and in a containing QMap. +// +// For example: +// - LBMLBTRMTransportDialogInfo contains a QMap of the sources (LBMLBTRMSourceEntry) and receivers (LBMLBTRMReceiverEntry) +// - A source (LBMLBTRMSourceEntry) contains a QMap of the source transports originating from it (LBMLBTRMSourceTransportEntry) +// - A source transport (LBMLBTRMSourceTransportEntry) contains QMaps of data, RX data, and SM SQNs (LBMLBTRMSQNEntry) and NCF SQNs +// (LBMLBTRMNCFSQNEntry) +// - A data SQN (LBMLBTRMSQNEntry) contains a QMap of the frames (LBMLBTRMFrameEntry) in which that SQN appears +// +// Not all of the entries actually appear in a QTreeWidget at one time. For example, in the source details, if no specific source +// transport is selected, nothing is in the source details tree. If Data SQNs is selected, then those details appear in the source +// details tree. Switching to RX Data SQNs removes whatever is currently in the source details tree, and adds the RX details for +// the selected transport. +// +// The actual owner of one of the above QTreeWidgetItem-derived items is the QMap container in its parent. The item is "loaned" to +// the QTreeWidget for display. +// +// All of this is to explain why +// 1) we are frequently adding things to a QTreeWidget +// 2) things are removed (takeTopLevelItem) from a QTreeWidget +// 3) destruction involves removing all items from all QTreeWidgets (rather than letting QTreeWidget delete them) +// 4) the destructor for each item has the form +// <for each QMap container> +// for (XXXMapIterator it = m_xxx.begin(); it != m_xxx.end(); it++) +// { +// delete *it; +// } +// m_xxx.clear(); +// The for-loop calls the destructor for each item, while the clear() cleans up the space used by the QMap itself. + +// A frame entry +class LBMLBTRMFrameEntry : public QTreeWidgetItem +{ + public: + LBMLBTRMFrameEntry(guint32 frame); + virtual ~LBMLBTRMFrameEntry(void) { } + guint32 getFrame(void) { return (m_frame); } + + private: + LBMLBTRMFrameEntry(void) { } + guint32 m_frame; +}; + +LBMLBTRMFrameEntry::LBMLBTRMFrameEntry(guint32 frame) : + QTreeWidgetItem(), + m_frame(frame) +{ + setText(Detail_SQN_Column, QString(" ")); + setText(Detail_Count_Column, QString(" ")); + setText(Detail_Frame_Column, QString("%1").arg(m_frame)); +} + +typedef QMap<guint32, LBMLBTRMFrameEntry *> LBMLBTRMFrameMap; +typedef QMap<guint32, LBMLBTRMFrameEntry *>::iterator LBMLBTRMFrameMapIterator; + +// A SQN (SeQuence Number) entry +class LBMLBTRMSQNEntry : public QTreeWidgetItem +{ + public: + LBMLBTRMSQNEntry(guint32 sqn); + virtual ~LBMLBTRMSQNEntry(void); + void processFrame(guint32 frame); + + private: + LBMLBTRMSQNEntry(void); + guint32 m_sqn; + guint32 m_count; + LBMLBTRMFrameMap m_frames; +}; + +LBMLBTRMSQNEntry::LBMLBTRMSQNEntry(guint32 sqn) : + QTreeWidgetItem(), + m_sqn(sqn), + m_count(0), + m_frames() +{ + setText(Detail_SQN_Column, QString("%1").arg(m_sqn)); + setTextAlignment(Detail_SQN_Column, Qt::AlignRight); + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRMSQNEntry::~LBMLBTRMSQNEntry(void) +{ + for (LBMLBTRMFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++) + { + delete *it; + } + m_frames.clear(); +} + +void LBMLBTRMSQNEntry::processFrame(guint32 frame) +{ + LBMLBTRMFrameMapIterator it; + + it = m_frames.find(frame); + if (m_frames.end() == it) + { + LBMLBTRMFrameEntry * entry = new LBMLBTRMFrameEntry(frame); + m_frames.insert(frame, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); +} + +// An NCF (Nak ConFirmation) Reason entry +class LBMLBTRMNCFReasonEntry : public QTreeWidgetItem +{ + public: + LBMLBTRMNCFReasonEntry(guint8 reason); + virtual ~LBMLBTRMNCFReasonEntry(void); + void processFrame(guint32 frame); + + private: + LBMLBTRMNCFReasonEntry(void); + guint8 m_reason; + QString m_reason_string; + guint32 m_count; + LBMLBTRMFrameMap m_frames; +}; + +LBMLBTRMNCFReasonEntry::LBMLBTRMNCFReasonEntry(guint8 reason) : + QTreeWidgetItem(), + m_reason(reason), + m_reason_string(), + m_count(0), + m_frames() +{ + switch (m_reason) + { + case LBTRM_NCF_REASON_NO_RETRY: + m_reason_string = "No Retry"; + break; + case LBTRM_NCF_REASON_IGNORED: + m_reason_string = "Ignored"; + break; + case LBTRM_NCF_REASON_RX_DELAY: + m_reason_string = "Retransmit Delay"; + break; + case LBTRM_NCF_REASON_SHED: + m_reason_string = "Shed"; + break; + default: + m_reason_string = QString("Unknown (%1)").arg(m_reason); + break; + } + setText(Detail_SQN_Column, m_reason_string); + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRMNCFReasonEntry::~LBMLBTRMNCFReasonEntry(void) +{ + for (LBMLBTRMFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++) + { + delete *it; + } + m_frames.clear(); +} + +void LBMLBTRMNCFReasonEntry::processFrame(guint32 frame) +{ + LBMLBTRMFrameMapIterator it; + + it = m_frames.find(frame); + if (m_frames.end() == it) + { + LBMLBTRMFrameEntry * entry = new LBMLBTRMFrameEntry(frame); + m_frames.insert(frame, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); +} + +typedef QMap<guint32, LBMLBTRMNCFReasonEntry *> LBMLBTRMNCFReasonMap; +typedef QMap<guint32, LBMLBTRMNCFReasonEntry *>::iterator LBMLBTRMNCFReasonMapIterator; + +// An NCF SQN entry +class LBMLBTRMNCFSQNEntry : public QTreeWidgetItem +{ + public: + LBMLBTRMNCFSQNEntry(guint32 sqn); + virtual ~LBMLBTRMNCFSQNEntry(void); + void processFrame(guint8 reason, guint32 frame); + + private: + LBMLBTRMNCFSQNEntry(void); + guint32 m_sqn; + guint32 m_count; + LBMLBTRMNCFReasonMap m_reasons; +}; + +LBMLBTRMNCFSQNEntry::LBMLBTRMNCFSQNEntry(guint32 sqn) : + QTreeWidgetItem(), + m_sqn(sqn), + m_count(0), + m_reasons() +{ + setText(Detail_SQN_Column, QString("%1").arg(m_sqn)); + setTextAlignment(Detail_SQN_Column, Qt::AlignRight); + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRMNCFSQNEntry::~LBMLBTRMNCFSQNEntry(void) +{ + for (LBMLBTRMNCFReasonMapIterator it = m_reasons.begin(); it != m_reasons.end(); it++) + { + delete *it; + } + m_reasons.clear(); +} + +void LBMLBTRMNCFSQNEntry::processFrame(guint8 reason, guint32 frame) +{ + LBMLBTRMNCFReasonMapIterator it; + LBMLBTRMNCFReasonEntry * entry = NULL; + + it = m_reasons.find(reason); + if (m_reasons.end() == it) + { + entry = new LBMLBTRMNCFReasonEntry(reason); + m_reasons.insert(reason, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + else + { + entry = it.value(); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + entry->processFrame(frame); +} + +typedef QMap<guint32, LBMLBTRMSQNEntry *> LBMLBTRMSQNMap; +typedef QMap<guint32, LBMLBTRMSQNEntry *>::iterator LBMLBTRMSQNMapIterator; +typedef QMap<guint32, LBMLBTRMNCFSQNEntry *> LBMLBTRMNCFSQNMap; +typedef QMap<guint32, LBMLBTRMNCFSQNEntry *>::iterator LBMLBTRMNCFSQNMapIterator; + +// A source transport entry +class LBMLBTRMSourceTransportEntry : public QTreeWidgetItem +{ + friend class LBMLBTRMTransportDialog; + + public: + LBMLBTRMSourceTransportEntry(const QString & transport); + virtual ~LBMLBTRMSourceTransportEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info); + + protected: + QString m_transport; + + private: + LBMLBTRMSourceTransportEntry(void) { } + void fillItem(void); + guint64 m_data_frames; + guint64 m_data_bytes; + guint64 m_rx_data_frames; + guint64 m_rx_data_bytes; + guint64 m_ncf_frames; + guint64 m_ncf_count; + guint64 m_ncf_bytes; + guint64 m_sm_frames; + guint64 m_sm_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + + protected: + LBMLBTRMSQNMap m_data_sqns; + LBMLBTRMSQNMap m_rx_data_sqns; + LBMLBTRMNCFSQNMap m_ncf_sqns; + LBMLBTRMSQNMap m_sm_sqns; +}; + +LBMLBTRMSourceTransportEntry::LBMLBTRMSourceTransportEntry(const QString & transport) : + QTreeWidgetItem(), + m_transport(transport), + m_data_frames(0), + m_data_bytes(0), + m_rx_data_frames(0), + m_rx_data_bytes(0), + m_ncf_frames(0), + m_ncf_count(0), + m_ncf_bytes(0), + m_sm_frames(0), + m_sm_bytes(0), + m_first_frame_timestamp_valid(false), + m_data_sqns(), + m_rx_data_sqns(), + m_ncf_sqns(), + m_sm_sqns() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Source_AddressTransport_Column, m_transport); +} + +LBMLBTRMSourceTransportEntry::~LBMLBTRMSourceTransportEntry(void) +{ + for (LBMLBTRMSQNMapIterator it = m_data_sqns.begin(); it != m_data_sqns.end(); it++) + { + delete *it; + } + m_data_sqns.clear(); + + for (LBMLBTRMSQNMapIterator it = m_rx_data_sqns.begin(); it != m_rx_data_sqns.end(); it++) + { + delete *it; + } + m_rx_data_sqns.clear(); + + for (LBMLBTRMNCFSQNMapIterator it = m_ncf_sqns.begin(); it != m_ncf_sqns.end(); it++) + { + delete *it; + } + m_ncf_sqns.clear(); + + for (LBMLBTRMSQNMapIterator it = m_sm_sqns.begin(); it != m_sm_sqns.end(); it++) + { + delete *it; + } + m_sm_sqns.clear(); +} + +void LBMLBTRMSourceTransportEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info) +{ + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + if (tap_info->type == LBTRM_PACKET_TYPE_DATA) + { + LBMLBTRMSQNEntry * sqn = NULL; + LBMLBTRMSQNMapIterator it; + + if (tap_info->retransmission) + { + m_rx_data_frames++; + m_rx_data_bytes += pinfo->fd->pkt_len; + it = m_rx_data_sqns.find(tap_info->sqn); + if (m_rx_data_sqns.end() == it) + { + sqn = new LBMLBTRMSQNEntry(tap_info->sqn); + m_rx_data_sqns.insert(tap_info->sqn, sqn); + } + else + { + sqn = it.value(); + } + } + else + { + m_data_frames++; + m_data_bytes += pinfo->fd->pkt_len; + it = m_data_sqns.find(tap_info->sqn); + if (m_data_sqns.end() == it) + { + sqn = new LBMLBTRMSQNEntry(tap_info->sqn); + m_data_sqns.insert(tap_info->sqn, sqn); + } + else + { + sqn = it.value(); + } + } + sqn->processFrame(pinfo->fd->num); + } + else if (tap_info->type == LBTRM_PACKET_TYPE_NCF) + { + guint16 idx; + LBMLBTRMNCFSQNMapIterator it; + LBMLBTRMNCFSQNEntry * sqn = NULL; + + m_ncf_frames++; + m_ncf_bytes += pinfo->fd->pkt_len; + m_ncf_count += (guint64)tap_info->num_sqns; + for (idx = 0; idx < tap_info->num_sqns; idx++) + { + it = m_ncf_sqns.find(tap_info->sqns[idx]); + if (m_ncf_sqns.end() == it) + { + sqn = new LBMLBTRMNCFSQNEntry(tap_info->sqns[idx]); + m_ncf_sqns.insert(tap_info->sqns[idx], sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(tap_info->ncf_reason, pinfo->fd->num); + } + } + else if (tap_info->type == LBTRM_PACKET_TYPE_SM) + { + LBMLBTRMSQNEntry * sqn = NULL; + LBMLBTRMSQNMapIterator it; + + m_sm_frames++; + m_sm_bytes += pinfo->fd->pkt_len; + it = m_sm_sqns.find(tap_info->sqn); + if (m_sm_sqns.end() == it) + { + sqn = new LBMLBTRMSQNEntry(tap_info->sqn); + m_sm_sqns.insert(tap_info->sqn, sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(pinfo->fd->num); + } + else + { + return; + } + fillItem(); +} + +void LBMLBTRMSourceTransportEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Source_DataFrames_Column, QString("%1").arg(m_data_frames)); + setTextAlignment(Source_DataFrames_Column, Qt::AlignRight); + setText(Source_DataBytes_Column, QString("%1").arg(m_data_bytes)); + setTextAlignment(Source_DataBytes_Column, Qt::AlignRight); + setText(Source_DataFramesBytes_Column, QString("%1/%2").arg(m_data_frames).arg(m_data_bytes)); + setTextAlignment(Source_DataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_DataRate_Column, format_rate(delta, m_data_bytes)); + setTextAlignment(Source_DataRate_Column, Qt::AlignRight); + setText(Source_RXDataFrames_Column, QString("%1").arg(m_rx_data_frames)); + setTextAlignment(Source_RXDataFrames_Column, Qt::AlignRight); + setText(Source_RXDataBytes_Column, QString("%1").arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataBytes_Column, Qt::AlignRight); + setText(Source_RXDataFramesBytes_Column, QString("%1/%2").arg(m_rx_data_frames).arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_RXDataRate_Column, format_rate(delta, m_rx_data_bytes)); + setTextAlignment(Source_RXDataRate_Column, Qt::AlignRight); + setText(Source_NCFFrames_Column, QString("%1").arg(m_ncf_frames)); + setTextAlignment(Source_NCFFrames_Column, Qt::AlignRight); + setText(Source_NCFCount_Column, QString("%1").arg(m_ncf_count)); + setTextAlignment(Source_NCFCount_Column, Qt::AlignRight); + setText(Source_NCFBytes_Column, QString("%1").arg(m_ncf_bytes)); + setTextAlignment(Source_NCFBytes_Column, Qt::AlignRight); + setText(Source_NCFFramesBytes_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesBytes_Column, Qt::AlignHCenter); + setText(Source_NCFCountBytes_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCount_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_count)); + setTextAlignment(Source_NCFFramesCount_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCountBytes_Column, QString("%1/%2/%3").arg(m_ncf_frames).arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFRate_Column, format_rate(delta, m_ncf_bytes)); + setTextAlignment(Source_NCFRate_Column, Qt::AlignRight); + setText(Source_SMFrames_Column, QString("%1").arg(m_sm_frames)); + setTextAlignment(Source_SMFrames_Column, Qt::AlignRight); + setText(Source_SMBytes_Column, QString("%1").arg(m_sm_bytes)); + setTextAlignment(Source_SMBytes_Column, Qt::AlignRight); + setText(Source_SMFramesBytes_Column, QString("%1/%2").arg(m_sm_frames).arg(m_sm_bytes)); + setTextAlignment(Source_SMFramesBytes_Column, Qt::AlignHCenter); + setText(Source_SMRate_Column, format_rate(delta, m_sm_bytes)); + setTextAlignment(Source_SMRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRMSourceTransportEntry *> LBMLBTRMSourceTransportMap; +typedef QMap<QString, LBMLBTRMSourceTransportEntry *>::iterator LBMLBTRMSourceTransportMapIterator; + +// A source (address) entry +class LBMLBTRMSourceEntry : public QTreeWidgetItem +{ + public: + LBMLBTRMSourceEntry(const QString & source_address); + virtual ~LBMLBTRMSourceEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info); + + private: + LBMLBTRMSourceEntry(void) { } + void fillItem(void); + QString m_address; + QString m_transport; + guint64 m_data_frames; + guint64 m_data_bytes; + guint64 m_rx_data_frames; + guint64 m_rx_data_bytes; + guint64 m_ncf_frames; + guint64 m_ncf_count; + guint64 m_ncf_bytes; + guint64 m_sm_frames; + guint64 m_sm_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + LBMLBTRMSourceTransportMap m_transports; +}; + +LBMLBTRMSourceEntry::LBMLBTRMSourceEntry(const QString & source_address) : + QTreeWidgetItem(), + m_address(source_address), + m_data_frames(0), + m_data_bytes(0), + m_rx_data_frames(0), + m_rx_data_bytes(0), + m_ncf_frames(0), + m_ncf_count(0), + m_ncf_bytes(0), + m_sm_frames(0), + m_sm_bytes(0), + m_first_frame_timestamp_valid(false), + m_transports() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Source_AddressTransport_Column, m_address); +} + +LBMLBTRMSourceEntry::~LBMLBTRMSourceEntry(void) +{ + for (LBMLBTRMSourceTransportMapIterator it = m_transports.begin(); it != m_transports.end(); it++) + { + delete *it; + } + m_transports.clear(); +} + +void LBMLBTRMSourceEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info) +{ + LBMLBTRMSourceTransportEntry * transport = NULL; + LBMLBTRMSourceTransportMapIterator it; + + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + if (tap_info->type == LBTRM_PACKET_TYPE_DATA) + { + if (tap_info->retransmission) + { + m_rx_data_frames++; + m_rx_data_bytes += pinfo->fd->pkt_len; + } + else + { + m_data_frames++; + m_data_bytes += pinfo->fd->pkt_len; + } + } + else if (tap_info->type == LBTRM_PACKET_TYPE_NCF) + { + m_ncf_frames++; + m_ncf_bytes += pinfo->fd->pkt_len; + m_ncf_count += tap_info->num_sqns; + } + else if (tap_info->type == LBTRM_PACKET_TYPE_SM) + { + m_sm_frames++; + m_sm_bytes += pinfo->fd->pkt_len; + } + + it = m_transports.find(tap_info->transport); + if (m_transports.end() == it) + { + transport = new LBMLBTRMSourceTransportEntry(tap_info->transport); + m_transports.insert(tap_info->transport, transport); + addChild(transport); + sortChildren(Source_AddressTransport_Column, Qt::AscendingOrder); + } + else + { + transport = it.value(); + } + fillItem(); + transport->processPacket(pinfo, tap_info); +} + +void LBMLBTRMSourceEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Source_DataFrames_Column, QString("%1").arg(m_data_frames)); + setTextAlignment(Source_DataFrames_Column, Qt::AlignRight); + setText(Source_DataBytes_Column, QString("%1").arg(m_data_bytes)); + setTextAlignment(Source_DataBytes_Column, Qt::AlignRight); + setText(Source_DataFramesBytes_Column, QString("%1/%2").arg(m_data_frames).arg(m_data_bytes)); + setTextAlignment(Source_DataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_DataRate_Column, format_rate(delta, m_data_bytes)); + setTextAlignment(Source_DataRate_Column, Qt::AlignRight); + setText(Source_RXDataFrames_Column, QString("%1").arg(m_rx_data_frames)); + setTextAlignment(Source_RXDataFrames_Column, Qt::AlignRight); + setText(Source_RXDataBytes_Column, QString("%1").arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataBytes_Column, Qt::AlignRight); + setText(Source_RXDataFramesBytes_Column, QString("%1/%2").arg(m_rx_data_frames).arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_RXDataRate_Column, format_rate(delta, m_rx_data_bytes)); + setTextAlignment(Source_RXDataRate_Column, Qt::AlignRight); + setText(Source_NCFFrames_Column, QString("%1").arg(m_ncf_frames)); + setTextAlignment(Source_NCFFrames_Column, Qt::AlignRight); + setText(Source_NCFCount_Column, QString("%1").arg(m_ncf_count)); + setTextAlignment(Source_NCFCount_Column, Qt::AlignRight); + setText(Source_NCFBytes_Column, QString("%1").arg(m_ncf_bytes)); + setTextAlignment(Source_NCFBytes_Column, Qt::AlignRight); + setText(Source_NCFFramesBytes_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesBytes_Column, Qt::AlignHCenter); + setText(Source_NCFCountBytes_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCount_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_count)); + setTextAlignment(Source_NCFFramesCount_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCountBytes_Column, QString("%1/%2/%3").arg(m_ncf_frames).arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFRate_Column, format_rate(delta, m_ncf_bytes)); + setTextAlignment(Source_NCFRate_Column, Qt::AlignRight); + setText(Source_SMFrames_Column, QString("%1").arg(m_sm_frames)); + setTextAlignment(Source_SMFrames_Column, Qt::AlignRight); + setText(Source_SMBytes_Column, QString("%1").arg(m_sm_bytes)); + setTextAlignment(Source_SMBytes_Column, Qt::AlignRight); + setText(Source_SMFramesBytes_Column, QString("%1/%2").arg(m_sm_frames).arg(m_sm_bytes)); + setTextAlignment(Source_SMFramesBytes_Column, Qt::AlignRight); + setText(Source_SMRate_Column, format_rate(delta, m_sm_bytes)); + setTextAlignment(Source_SMRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRMSourceEntry *> LBMLBTRMSourceMap; +typedef QMap<QString, LBMLBTRMSourceEntry *>::iterator LBMLBTRMSourceMapIterator; + +// A receiver transport entry +class LBMLBTRMReceiverTransportEntry : public QTreeWidgetItem +{ + friend class LBMLBTRMTransportDialog; + + public: + LBMLBTRMReceiverTransportEntry(const QString & transport); + virtual ~LBMLBTRMReceiverTransportEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info); + + private: + LBMLBTRMReceiverTransportEntry(void) { } + void fillItem(void); + QString m_transport; + guint64 m_nak_frames; + guint64 m_nak_count; + guint64 m_nak_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + + protected: + LBMLBTRMSQNMap m_nak_sqns; +}; + +LBMLBTRMReceiverTransportEntry::LBMLBTRMReceiverTransportEntry(const QString & transport) : + QTreeWidgetItem(), + m_transport(transport), + m_nak_frames(0), + m_nak_count(0), + m_nak_bytes(0), + m_first_frame_timestamp_valid(false), + m_nak_sqns() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Receiver_AddressTransport_Column, m_transport); +} + +LBMLBTRMReceiverTransportEntry::~LBMLBTRMReceiverTransportEntry(void) +{ + for (LBMLBTRMSQNMapIterator it = m_nak_sqns.begin(); it != m_nak_sqns.end(); it++) + { + delete *it; + } + m_nak_sqns.clear(); +} + +void LBMLBTRMReceiverTransportEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info) +{ + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + if (tap_info->type == LBTRM_PACKET_TYPE_NAK) + { + guint16 idx; + LBMLBTRMSQNEntry * sqn = NULL; + LBMLBTRMSQNMapIterator it; + + m_nak_frames++; + m_nak_bytes += pinfo->fd->pkt_len; + m_nak_count += tap_info->num_sqns; + for (idx = 0; idx < tap_info->num_sqns; idx++) + { + it = m_nak_sqns.find(tap_info->sqns[idx]); + if (m_nak_sqns.end() == it) + { + sqn = new LBMLBTRMSQNEntry(tap_info->sqns[idx]); + m_nak_sqns.insert(tap_info->sqns[idx], sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(pinfo->fd->num); + } + } + else + { + return; + } + fillItem(); +} + +void LBMLBTRMReceiverTransportEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Receiver_NAKFrames_Column, QString("%1").arg(m_nak_frames)); + setTextAlignment(Receiver_NAKFrames_Column, Qt::AlignRight); + setText(Receiver_NAKCount_Column, QString("%1").arg(m_nak_count)); + setTextAlignment(Receiver_NAKCount_Column, Qt::AlignRight); + setText(Receiver_NAKBytes_Column, QString("%1").arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKBytes_Column, Qt::AlignRight); + setText(Receiver_NAKRate_Column, format_rate(delta, m_nak_bytes)); + setTextAlignment(Receiver_NAKRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRMReceiverTransportEntry *> LBMLBTRMReceiverTransportMap; +typedef QMap<QString, LBMLBTRMReceiverTransportEntry *>::iterator LBMLBTRMReceiverTransportMapIterator; + +// A receiver (address) entry +class LBMLBTRMReceiverEntry : public QTreeWidgetItem +{ + public: + LBMLBTRMReceiverEntry(const QString & receiver_address); + virtual ~LBMLBTRMReceiverEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info); + + private: + LBMLBTRMReceiverEntry(void); + void fillItem(void); + QString m_address; + QString m_transport; + guint64 m_nak_frames; + guint64 m_nak_count; + guint64 m_nak_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + LBMLBTRMReceiverTransportMap m_transports; +}; + +LBMLBTRMReceiverEntry::LBMLBTRMReceiverEntry(const QString & receiver_address) : + QTreeWidgetItem(), + m_address(receiver_address), + m_nak_frames(0), + m_nak_count(0), + m_nak_bytes(0), + m_first_frame_timestamp_valid(false), + m_transports() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Receiver_AddressTransport_Column, m_address); +} + +LBMLBTRMReceiverEntry::~LBMLBTRMReceiverEntry(void) +{ + for (LBMLBTRMReceiverTransportMapIterator it = m_transports.begin(); it != m_transports.end(); it++) + { + delete *it; + } + m_transports.clear(); +} + +void LBMLBTRMReceiverEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info) +{ + LBMLBTRMReceiverTransportEntry * transport = NULL; + LBMLBTRMReceiverTransportMapIterator it; + + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + if (tap_info->type == LBTRM_PACKET_TYPE_NAK) + { + m_nak_frames++; + m_nak_bytes += pinfo->fd->pkt_len; + m_nak_count += tap_info->num_sqns; + } + + it = m_transports.find(tap_info->transport); + if (m_transports.end() == it) + { + transport = new LBMLBTRMReceiverTransportEntry(tap_info->transport); + m_transports.insert(tap_info->transport, transport); + addChild(transport); + sortChildren(Receiver_AddressTransport_Column, Qt::AscendingOrder); + } + else + { + transport = it.value(); + } + fillItem(); + transport->processPacket(pinfo, tap_info); +} + +void LBMLBTRMReceiverEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Receiver_NAKFrames_Column, QString("%1").arg(m_nak_frames)); + setTextAlignment(Receiver_NAKFrames_Column, Qt::AlignRight); + setText(Receiver_NAKCount_Column, QString("%1").arg(m_nak_count)); + setTextAlignment(Receiver_NAKCount_Column, Qt::AlignRight); + setText(Receiver_NAKBytes_Column, QString("%1").arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKBytes_Column, Qt::AlignRight); + setText(Receiver_NAKRate_Column, format_rate(delta, m_nak_bytes)); + setTextAlignment(Receiver_NAKRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRMReceiverEntry *> LBMLBTRMReceiverMap; +typedef QMap<QString, LBMLBTRMReceiverEntry *>::iterator LBMLBTRMReceiverMapIterator; + +class LBMLBTRMTransportDialogInfo +{ + public: + LBMLBTRMTransportDialogInfo(void); + ~LBMLBTRMTransportDialogInfo(void); + void setDialog(LBMLBTRMTransportDialog * dialog); + LBMLBTRMTransportDialog * getDialog(void); + void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info); + void clearMaps(void); + + private: + LBMLBTRMTransportDialog * m_dialog; + LBMLBTRMSourceMap m_sources; + LBMLBTRMReceiverMap m_receivers; +}; + +LBMLBTRMTransportDialogInfo::LBMLBTRMTransportDialogInfo(void) : + m_dialog(NULL), + m_sources(), + m_receivers() +{ +} + +LBMLBTRMTransportDialogInfo::~LBMLBTRMTransportDialogInfo(void) +{ + clearMaps(); +} + +void LBMLBTRMTransportDialogInfo::setDialog(LBMLBTRMTransportDialog * dialog) +{ + m_dialog = dialog; +} + +LBMLBTRMTransportDialog * LBMLBTRMTransportDialogInfo::getDialog(void) +{ + return (m_dialog); +} + +void LBMLBTRMTransportDialogInfo::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info) +{ + switch (tap_info->type) + { + case LBTRM_PACKET_TYPE_DATA: + case LBTRM_PACKET_TYPE_SM: + case LBTRM_PACKET_TYPE_NCF: + { + LBMLBTRMSourceEntry * source = NULL; + LBMLBTRMSourceMapIterator it; + QString src_address = QString(address_to_str(wmem_packet_scope(), &(pinfo->src))); + + it = m_sources.find(src_address); + if (m_sources.end() == it) + { + QTreeWidgetItem * parent = NULL; + Ui::LBMLBTRMTransportDialog * ui = NULL; + + source = new LBMLBTRMSourceEntry(src_address); + it = m_sources.insert(src_address, source); + ui = m_dialog->getUI(); + ui->sources_TreeWidget->addTopLevelItem(source); + parent = ui->sources_TreeWidget->invisibleRootItem(); + parent->sortChildren(Source_AddressTransport_Column, Qt::AscendingOrder); + ui->sources_TreeWidget->resizeColumnToContents(Source_AddressTransport_Column); + } + else + { + source = it.value(); + } + source->processPacket(pinfo, tap_info); + } + break; + case LBTRM_PACKET_TYPE_NAK: + { + LBMLBTRMReceiverEntry * receiver = NULL; + LBMLBTRMReceiverMapIterator it; + QString src_address = QString(address_to_str(wmem_packet_scope(), &(pinfo->src))); + + it = m_receivers.find(src_address); + if (m_receivers.end() == it) + { + QTreeWidgetItem * parent = NULL; + Ui::LBMLBTRMTransportDialog * ui = NULL; + + receiver = new LBMLBTRMReceiverEntry(src_address); + it = m_receivers.insert(src_address, receiver); + ui = m_dialog->getUI(); + ui->receivers_TreeWidget->addTopLevelItem(receiver); + parent = ui->receivers_TreeWidget->invisibleRootItem(); + parent->sortChildren(Receiver_AddressTransport_Column, Qt::AscendingOrder); + ui->receivers_TreeWidget->resizeColumnToContents(Receiver_AddressTransport_Column); + } + else + { + receiver = it.value(); + } + receiver->processPacket(pinfo, tap_info); + } + break; + default: + break; + } +} + +void LBMLBTRMTransportDialogInfo::clearMaps(void) +{ + for (LBMLBTRMSourceMapIterator it = m_sources.begin(); it != m_sources.end(); it++) + { + delete *it; + } + m_sources.clear(); + + for (LBMLBTRMReceiverMapIterator it = m_receivers.begin(); it != m_receivers.end(); it++) + { + delete *it; + } + m_receivers.clear(); +} + +LBMLBTRMTransportDialog::LBMLBTRMTransportDialog(QWidget * parent, capture_file * cfile) : + QDialog(parent), + m_ui(new Ui::LBMLBTRMTransportDialog), + m_dialog_info(NULL), + m_capture_file(cfile), + m_current_source_transport(NULL), + m_current_receiver_transport(NULL), + m_source_context_menu(NULL), + m_source_header(NULL) +{ + m_ui->setupUi(this); + m_dialog_info = new LBMLBTRMTransportDialogInfo(); + + m_ui->tabWidget->setCurrentIndex(0); + m_ui->sources_detail_ComboBox->setCurrentIndex(0); + m_ui->sources_detail_transport_Label->setText(QString(" ")); + m_ui->receivers_detail_transport_Label->setText(QString(" ")); + m_ui->stackedWidget->setCurrentIndex(0); + + m_source_header = m_ui->sources_TreeWidget->header(); + m_source_context_menu = new QMenu(m_source_header); + + m_source_context_menu->addAction(m_ui->action_SourceAutoResizeColumns); + connect(m_ui->action_SourceAutoResizeColumns, SIGNAL(triggered()), this, SLOT(actionSourceAutoResizeColumns_triggered())); + m_source_context_menu->addSeparator(); + + m_ui->action_SourceDataFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceDataFrames); + connect(m_ui->action_SourceDataFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataFrames_triggered(bool))); + m_ui->action_SourceDataBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceDataBytes); + connect(m_ui->action_SourceDataBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataBytes_triggered(bool))); + m_ui->action_SourceDataFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceDataFramesBytes); + connect(m_ui->action_SourceDataFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataFramesBytes_triggered(bool))); + m_ui->action_SourceDataRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceDataRate); + connect(m_ui->action_SourceDataRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataRate_triggered(bool))); + + m_ui->action_SourceRXDataFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceRXDataFrames); + connect(m_ui->action_SourceRXDataFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataFrames_triggered(bool))); + m_ui->action_SourceRXDataBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceRXDataBytes); + connect(m_ui->action_SourceRXDataBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataBytes_triggered(bool))); + m_ui->action_SourceRXDataFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceRXDataFramesBytes); + connect(m_ui->action_SourceRXDataFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataFramesBytes_triggered(bool))); + m_ui->action_SourceRXDataRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceRXDataRate); + connect(m_ui->action_SourceRXDataRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataRate_triggered(bool))); + + m_ui->action_SourceNCFFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFFrames); + connect(m_ui->action_SourceNCFFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFrames_triggered(bool))); + m_ui->action_SourceNCFCount->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFCount); + connect(m_ui->action_SourceNCFCount, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFCount_triggered(bool))); + m_ui->action_SourceNCFBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFBytes); + connect(m_ui->action_SourceNCFBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFBytes_triggered(bool))); + m_ui->action_SourceNCFFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFFramesBytes); + connect(m_ui->action_SourceNCFFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesBytes_triggered(bool))); + m_ui->action_SourceNCFCountBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFCountBytes); + connect(m_ui->action_SourceNCFCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFCountBytes_triggered(bool))); + m_ui->action_SourceNCFFramesCount->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFFramesCount); + connect(m_ui->action_SourceNCFFramesCount, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesCount_triggered(bool))); + m_ui->action_SourceNCFFramesCountBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFFramesCountBytes); + connect(m_ui->action_SourceNCFFramesCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesCountBytes_triggered(bool))); + m_ui->action_SourceNCFRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFRate); + connect(m_ui->action_SourceNCFRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFRate_triggered(bool))); + + m_ui->action_SourceSMFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceSMFrames); + connect(m_ui->action_SourceSMFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMFrames_triggered(bool))); + m_ui->action_SourceSMBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceSMBytes); + connect(m_ui->action_SourceSMBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMBytes_triggered(bool))); + m_ui->action_SourceSMFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceSMFramesBytes); + connect(m_ui->action_SourceSMFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMFramesBytes_triggered(bool))); + m_ui->action_SourceSMRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceSMRate); + connect(m_ui->action_SourceSMRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMRate_triggered(bool))); + + m_source_header->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_source_header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(custom_source_context_menuRequested(const QPoint &))); + + m_ui->sources_TreeWidget->setColumnHidden(Source_DataFramesBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFramesBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCountBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCount_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCountBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_SMFramesBytes_Column, true); + + connect(this, SIGNAL(accepted()), this, SLOT(closeDialog())); + connect(this, SIGNAL(rejected()), this, SLOT(closeDialog())); + fillTree(); +} + +LBMLBTRMTransportDialog::~LBMLBTRMTransportDialog(void) +{ + resetSourcesDetail(); + resetSources(); + resetReceiversDetail(); + resetReceivers(); + if (m_dialog_info != NULL) + { + delete m_dialog_info; + m_dialog_info = NULL; + } + delete m_source_context_menu; + m_source_context_menu = NULL; + delete m_ui; + m_ui = NULL; + m_capture_file = NULL; +} + +void LBMLBTRMTransportDialog::setCaptureFile(capture_file * cfile) +{ + if (cfile == NULL) // We only want to know when the file closes. + { + m_capture_file = NULL; + m_ui->displayFilterLineEdit->setEnabled(false); + m_ui->applyFilterButton->setEnabled(false); + } +} + +void LBMLBTRMTransportDialog::resetSources(void) +{ + while (m_ui->sources_TreeWidget->takeTopLevelItem(0) != NULL) + {} +} + +void LBMLBTRMTransportDialog::resetReceivers(void) +{ + while (m_ui->receivers_TreeWidget->takeTopLevelItem(0) != NULL) + {} +} + +void LBMLBTRMTransportDialog::resetSourcesDetail(void) +{ + while (m_ui->sources_detail_sqn_TreeWidget->takeTopLevelItem(0) != NULL) + {} + while (m_ui->sources_detail_ncf_sqn_TreeWidget->takeTopLevelItem(0) != NULL) + {} + m_ui->sources_detail_transport_Label->setText(QString(" ")); + m_current_source_transport = NULL; +} + +void LBMLBTRMTransportDialog::resetReceiversDetail(void) +{ + while (m_ui->receivers_detail_TreeWidget->takeTopLevelItem(0) != NULL) + {} + m_ui->receivers_detail_transport_Label->setText(QString(" ")); + m_current_receiver_transport = NULL; +} + +void LBMLBTRMTransportDialog::fillTree(void) +{ + GString * error_string; + + if (m_capture_file == NULL) + { + return; + } + m_dialog_info->setDialog(this); + + error_string = register_tap_listener("lbtrm", + (void *)m_dialog_info, + m_ui->displayFilterLineEdit->text().toUtf8().constData(), + TL_REQUIRES_COLUMNS, + resetTap, + tapPacket, + drawTreeItems); + if (error_string) + { + QMessageBox::critical(this, tr("LBT-RM Statistics failed to attach to tap"), + error_string->str); + g_string_free(error_string, TRUE); + reject(); + } + + cf_retap_packets(m_capture_file); + drawTreeItems(&m_dialog_info); + remove_tap_listener((void *)m_dialog_info); +} + +void LBMLBTRMTransportDialog::resetTap(void * tap_data) +{ + LBMLBTRMTransportDialogInfo * info = (LBMLBTRMTransportDialogInfo *) tap_data; + LBMLBTRMTransportDialog * dialog = info->getDialog(); + if (dialog == NULL) + { + return; + } + dialog->resetSourcesDetail(); + dialog->resetSources(); + dialog->resetReceiversDetail(); + dialog->resetReceivers(); + info->clearMaps(); +} + +gboolean LBMLBTRMTransportDialog::tapPacket(void * tap_data, packet_info * pinfo, epan_dissect_t * edt, const void * tap_info) +{ + Q_UNUSED(edt) + + if (pinfo->fd->flags.passed_dfilter == 1) + { + const lbm_lbtrm_tap_info_t * tapinfo = (const lbm_lbtrm_tap_info_t *)tap_info; + LBMLBTRMTransportDialogInfo * info = (LBMLBTRMTransportDialogInfo *)tap_data; + + info->processPacket(pinfo, tapinfo); + } + return (TRUE); +} + +void LBMLBTRMTransportDialog::drawTreeItems(void * tap_data) +{ + Q_UNUSED(tap_data) +} + +void LBMLBTRMTransportDialog::on_applyFilterButton_clicked(void) +{ + fillTree(); +} + +void LBMLBTRMTransportDialog::closeDialog(void) +{ + delete this; +} + +void LBMLBTRMTransportDialog::sourcesDetailCurrentChanged(int index) +{ + // Index 0: Data + // Index 1: RX data + // Index 2: NCF + // Index 3: SM + switch (index) + { + case 0: + case 1: + case 3: + m_ui->stackedWidget->setCurrentIndex(0); + break; + case 2: + m_ui->stackedWidget->setCurrentIndex(1); + break; + default: + return; + } + sourcesItemClicked(m_current_source_transport, 0); +} + +void LBMLBTRMTransportDialog::sourcesItemClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRMSourceTransportEntry * transport = dynamic_cast<LBMLBTRMSourceTransportEntry *>(item); + + resetSourcesDetail(); + if (transport == NULL) + { + // Must be a source item, ignore it? + return; + } + m_current_source_transport = transport; + m_ui->sources_detail_transport_Label->setText(transport->m_transport); + int cur_idx = m_ui->sources_detail_ComboBox->currentIndex(); + switch (cur_idx) + { + case 0: + loadSourceDataDetails(transport); + break; + case 1: + loadSourceRXDataDetails(transport); + break; + case 2: + loadSourceNCFDetails(transport); + break; + case 3: + loadSourceSMDetails(transport); + break; + default: + break; + } +} + +void LBMLBTRMTransportDialog::loadSourceDataDetails(LBMLBTRMSourceTransportEntry * transport) +{ + for (LBMLBTRMSQNMapIterator it = transport->m_data_sqns.begin(); it != transport->m_data_sqns.end(); it++) + { + LBMLBTRMSQNEntry * sqn = it.value(); + m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRMTransportDialog::loadSourceRXDataDetails(LBMLBTRMSourceTransportEntry * transport) +{ + for (LBMLBTRMSQNMapIterator it = transport->m_rx_data_sqns.begin(); it != transport->m_rx_data_sqns.end(); it++) + { + LBMLBTRMSQNEntry * sqn = it.value(); + m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRMTransportDialog::loadSourceNCFDetails(LBMLBTRMSourceTransportEntry * transport) +{ + for (LBMLBTRMNCFSQNMapIterator it = transport->m_ncf_sqns.begin(); it != transport->m_ncf_sqns.end(); it++) + { + LBMLBTRMNCFSQNEntry * sqn = it.value(); + m_ui->sources_detail_ncf_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRMTransportDialog::loadSourceSMDetails(LBMLBTRMSourceTransportEntry * transport) +{ + for (LBMLBTRMSQNMapIterator it = transport->m_sm_sqns.begin(); it != transport->m_sm_sqns.end(); it++) + { + LBMLBTRMSQNEntry * sqn = it.value(); + m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRMTransportDialog::receiversItemClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRMReceiverTransportEntry * transport = dynamic_cast<LBMLBTRMReceiverTransportEntry *>(item); + + resetReceiversDetail(); + if (transport == NULL) + { + // Must be a receiver item, ignore it? + return; + } + m_current_receiver_transport = transport; + m_ui->receivers_detail_transport_Label->setText(transport->m_transport); + loadReceiverNAKDetails(transport); +} + +void LBMLBTRMTransportDialog::loadReceiverNAKDetails(LBMLBTRMReceiverTransportEntry * transport) +{ + for (LBMLBTRMSQNMapIterator it = transport->m_nak_sqns.begin(); it != transport->m_nak_sqns.end(); it++) + { + LBMLBTRMSQNEntry * sqn = it.value(); + m_ui->receivers_detail_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRMTransportDialog::sourcesDetailItemDoubleClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRMFrameEntry * frame = dynamic_cast<LBMLBTRMFrameEntry *>(item); + if (frame == NULL) + { + // Must have double-clicked on something other than an expanded frame entry + return; + } + emit goToPacket((int)frame->getFrame()); +} + +void LBMLBTRMTransportDialog::receiversDetailItemDoubleClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRMFrameEntry * frame = dynamic_cast<LBMLBTRMFrameEntry *>(item); + if (frame == NULL) + { + // Must have double-clicked on something other than an expanded frame entry + return; + } + emit goToPacket((int)frame->getFrame()); +} + +void LBMLBTRMTransportDialog::custom_source_context_menuRequested(const QPoint & pos) +{ + m_source_context_menu->exec(m_source_header->mapToGlobal(pos)); +} + +void LBMLBTRMTransportDialog::actionSourceDataFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataFrames_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceDataBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceDataFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataFramesBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceDataRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataRate_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceRXDataFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFrames_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceRXDataBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceRXDataFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFramesBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceRXDataRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataRate_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFrames_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFCount_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCount_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFrames_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFCountBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCountBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFFramesCount_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCount_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFFramesCountBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCountBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceNCFRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFRate_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceSMFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMFrames_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceSMBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceSMFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMFramesBytes_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceSMRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMRate_Column, !checked); +} + +void LBMLBTRMTransportDialog::actionSourceAutoResizeColumns_triggered(void) +{ + m_ui->sources_TreeWidget->resizeColumnToContents(Source_AddressTransport_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataRate_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataRate_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFCount_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFCountBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesCount_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesCountBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFRate_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMRate_Column); +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_lbtrm_transport_dialog.h b/ui/qt/lbm_lbtrm_transport_dialog.h new file mode 100644 index 0000000000..c46898e549 --- /dev/null +++ b/ui/qt/lbm_lbtrm_transport_dialog.h @@ -0,0 +1,132 @@ +/* lbm_lbtrm_transport_dialog.h + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LBM_LBTRM_TRANSPORT_DIALOG_H +#define LBM_LBTRM_TRANSPORT_DIALOG_H + +#include "config.h" + +#include <glib.h> + +#include "cfile.h" +#include <epan/packet_info.h> +#include <QDialog> +#include <QTreeWidgetItem> + +namespace Ui +{ + class LBMLBTRMTransportDialog; +} + +class LBMLBTRMTransportDialogInfo; +class LBMLBTRMSourceTransportEntry; +class LBMLBTRMReceiverTransportEntry; + +class LBMLBTRMTransportDialog : public QDialog +{ + Q_OBJECT + + public: + explicit LBMLBTRMTransportDialog(QWidget * parent = 0, capture_file * cfile = NULL); + Ui::LBMLBTRMTransportDialog * getUI(void) + { + return (m_ui); + } + public slots: + void setCaptureFile(capture_file * cfile); + + signals: + void goToPacket(int PacketNum); + + private: + Ui::LBMLBTRMTransportDialog * m_ui; + LBMLBTRMTransportDialogInfo * m_dialog_info; + capture_file * m_capture_file; + LBMLBTRMSourceTransportEntry * m_current_source_transport; + LBMLBTRMReceiverTransportEntry * m_current_receiver_transport; + QMenu * m_source_context_menu; + QHeaderView * m_source_header; + + virtual ~LBMLBTRMTransportDialog(void); + void resetSources(void); + void resetReceivers(void); + void resetSourcesDetail(void); + void resetReceiversDetail(void); + void fillTree(void); + static void resetTap(void * tap_data); + static gboolean tapPacket(void * tap_data, packet_info * pinfo, epan_dissect_t * edt, const void * stream_info); + static void drawTreeItems(void * tap_data); + void loadSourceDataDetails(LBMLBTRMSourceTransportEntry * transport); + void loadSourceRXDataDetails(LBMLBTRMSourceTransportEntry * transport); + void loadSourceNCFDetails(LBMLBTRMSourceTransportEntry * transport); + void loadSourceSMDetails(LBMLBTRMSourceTransportEntry * transport); + void loadSourceRSTDetails(LBMLBTRMSourceTransportEntry * transport); + void loadReceiverNAKDetails(LBMLBTRMReceiverTransportEntry * transport); + + private slots: + void closeDialog(void); + void on_applyFilterButton_clicked(void); + + void sourcesDetailCurrentChanged(int Index); + void sourcesItemClicked(QTreeWidgetItem * item, int column); + void receiversItemClicked(QTreeWidgetItem * item, int column); + void sourcesDetailItemDoubleClicked(QTreeWidgetItem * item, int column); + void receiversDetailItemDoubleClicked(QTreeWidgetItem * item, int column); + void actionSourceDataFrames_triggered(bool checked); + void actionSourceDataBytes_triggered(bool checked); + void actionSourceDataFramesBytes_triggered(bool checked); + void actionSourceDataRate_triggered(bool checked); + void actionSourceRXDataFrames_triggered(bool checked); + void actionSourceRXDataBytes_triggered(bool checked); + void actionSourceRXDataFramesBytes_triggered(bool checked); + void actionSourceRXDataRate_triggered(bool checked); + void actionSourceNCFFrames_triggered(bool checked); + void actionSourceNCFCount_triggered(bool checked); + void actionSourceNCFBytes_triggered(bool checked); + void actionSourceNCFFramesBytes_triggered(bool checked); + void actionSourceNCFCountBytes_triggered(bool checked); + void actionSourceNCFFramesCount_triggered(bool checked); + void actionSourceNCFFramesCountBytes_triggered(bool checked); + void actionSourceNCFRate_triggered(bool checked); + void actionSourceSMFrames_triggered(bool checked); + void actionSourceSMBytes_triggered(bool checked); + void actionSourceSMFramesBytes_triggered(bool checked); + void actionSourceSMRate_triggered(bool checked); + void actionSourceAutoResizeColumns_triggered(void); + void custom_source_context_menuRequested(const QPoint & pos); +}; + +#endif + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_lbtrm_transport_dialog.ui b/ui/qt/lbm_lbtrm_transport_dialog.ui new file mode 100644 index 0000000000..c24057cf96 --- /dev/null +++ b/ui/qt/lbm_lbtrm_transport_dialog.ui @@ -0,0 +1,836 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LBMLBTRMTransportDialog</class> + <widget class="QDialog" name="LBMLBTRMTransportDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>841</width> + <height>563</height> + </rect> + </property> + <property name="windowTitle"> + <string>LBTRM Transport Statistics</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="sourcesTab"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <attribute name="title"> + <string>Sources</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="handleWidth"> + <number>10</number> + </property> + <widget class="QTreeWidget" name="sources_TreeWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <attribute name="headerDefaultSectionSize"> + <number>80</number> + </attribute> + <column> + <property name="text"> + <string>Address/Transport</string> + </property> + </column> + <column> + <property name="text"> + <string>Data frames</string> + </property> + </column> + <column> + <property name="text"> + <string>Data bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>Data frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>Data rate</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data frames</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data rate</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF count</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF count/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames/count</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames/count/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF rate</string> + </property> + </column> + <column> + <property name="text"> + <string>SM frames</string> + </property> + </column> + <column> + <property name="text"> + <string>SM bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>SM frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>SM rate</string> + </property> + </column> + </widget> + <widget class="QWidget" name="layoutWidget"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Show</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="sources_detail_ComboBox"> + <item> + <property name="text"> + <string>Data</string> + </property> + </item> + <item> + <property name="text"> + <string>RX Data</string> + </property> + </item> + <item> + <property name="text"> + <string>NCF</string> + </property> + </item> + <item> + <property name="text"> + <string>SM</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>sequence numbers for transport</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="sources_detail_transport_Label"> + <property name="text"> + <string>XXXXX:XXX.XXX.XXX.XXX:XXXXX:XXXXXXXX:XXX.XXX.XXX.XXX:XXXXX</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="lineWidth"> + <number>1</number> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="sources_detail_sqn_page"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QTreeWidget" name="sources_detail_sqn_TreeWidget"> + <column> + <property name="text"> + <string>SQN</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="sources_detail_ncf_sqn_page"> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QTreeWidget" name="sources_detail_ncf_sqn_TreeWidget"> + <column> + <property name="text"> + <string>SQN/Reason</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="receiversTab"> + <attribute name="title"> + <string>Receivers</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QSplitter" name="splitter_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="handleWidth"> + <number>10</number> + </property> + <widget class="QTreeWidget" name="receivers_TreeWidget"> + <column> + <property name="text"> + <string>Address/Transport</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK frames</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK count</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK rate</string> + </property> + </column> + </widget> + <widget class="QWidget" name="layoutWidget_2"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>NAK sequence numbers for transport</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="receivers_detail_transport_Label"> + <property name="text"> + <string>XXXXX:XXX.XXX.XXX.XXX:XXXXX:XXXXXXXX:XXX.XXX.XXX.XXX:XXXXX</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QTreeWidget" name="receivers_detail_TreeWidget"> + <column> + <property name="text"> + <string>SQN</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Display filter:</string> + </property> + </widget> + </item> + <item> + <widget class="DisplayFilterEdit" name="displayFilterLineEdit"/> + </item> + <item> + <widget class="QPushButton" name="applyFilterButton"> + <property name="toolTip"> + <string>Regenerate statistics using this display filter</string> + </property> + <property name="text"> + <string>Apply</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close|QDialogButtonBox::Help</set> + </property> + </widget> + </item> + </layout> + <action name="actionCopyAsCSV"> + <property name="text"> + <string>Copy as CSV</string> + </property> + <property name="toolTip"> + <string>Copy the tree as CSV</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + </action> + <action name="actionCopyAsYAML"> + <property name="text"> + <string>Copy as YAML</string> + </property> + <property name="toolTip"> + <string>Copy the tree as YAML</string> + </property> + <property name="shortcut"> + <string>Ctrl+Y</string> + </property> + </action> + <action name="action_SourceDataFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data frames</string> + </property> + <property name="toolTip"> + <string>Show the data frames column</string> + </property> + </action> + <action name="action_SourceDataBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data bytes</string> + </property> + <property name="toolTip"> + <string>Show the data bytes column</string> + </property> + </action> + <action name="action_SourceDataFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the data frames/bytes column</string> + </property> + </action> + <action name="action_SourceRXDataFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data frames</string> + </property> + <property name="toolTip"> + <string>Show the RX data frames column</string> + </property> + </action> + <action name="action_SourceRXDataBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data bytes</string> + </property> + <property name="toolTip"> + <string>Show the RX data bytes column</string> + </property> + </action> + <action name="action_SourceRXDataFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the RX data frames/bytes column</string> + </property> + </action> + <action name="action_SourceNCFFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames</string> + </property> + <property name="toolTip"> + <string>Show the NCF frames column</string> + </property> + </action> + <action name="action_SourceNCFBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF bytes</string> + </property> + <property name="toolTip"> + <string>Show the NCF bytes column</string> + </property> + </action> + <action name="action_SourceNCFCount"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF count</string> + </property> + <property name="toolTip"> + <string>Show the NCF count column</string> + </property> + </action> + <action name="action_SourceDataRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data rate</string> + </property> + <property name="toolTip"> + <string>Show the data rate column</string> + </property> + </action> + <action name="action_SourceRXDataRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data rate</string> + </property> + <property name="toolTip"> + <string>Show the RX data rate column</string> + </property> + </action> + <action name="action_SourceNCFFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NCF frames/bytes column</string> + </property> + </action> + <action name="action_SourceNCFCountBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF count/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NCF count/bytes column</string> + </property> + </action> + <action name="action_SourceNCFFramesCount"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames/count</string> + </property> + <property name="toolTip"> + <string>Show the NCF frames/count column</string> + </property> + </action> + <action name="action_SourceNCFFramesCountBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames/count/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NCF frames/count/bytes column</string> + </property> + </action> + <action name="action_SourceNCFRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF rate</string> + </property> + <property name="toolTip"> + <string>Show the NCF rate column</string> + </property> + </action> + <action name="action_SourceSMFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM frames</string> + </property> + <property name="toolTip"> + <string>Show the SM frames column</string> + </property> + </action> + <action name="action_SourceSMBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM bytes</string> + </property> + <property name="toolTip"> + <string>Show the SM bytes column</string> + </property> + </action> + <action name="action_SourceSMFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the SM frames/bytes column</string> + </property> + </action> + <action name="action_SourceSMRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM rate</string> + </property> + <property name="toolTip"> + <string>Show the SM rate column</string> + </property> + </action> + <action name="action_SourceAutoResizeColumns"> + <property name="text"> + <string>Auto-resize columns to content</string> + </property> + <property name="toolTip"> + <string>Resize columns to content size</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>DisplayFilterEdit</class> + <extends>QLineEdit</extends> + <header location="global">display_filter_edit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>255</x> + <y>555</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>323</x> + <y>555</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_detail_ComboBox</sender> + <signal>currentIndexChanged(int)</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>sourcesDetailCurrentChanged(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>135</x> + <y>269</y> + </hint> + <hint type="destinationlabel"> + <x>446</x> + <y>310</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_TreeWidget</sender> + <signal>itemClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>sourcesItemClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>440</x> + <y>149</y> + </hint> + <hint type="destinationlabel"> + <x>446</x> + <y>310</y> + </hint> + </hints> + </connection> + <connection> + <sender>receivers_TreeWidget</sender> + <signal>itemClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>receiversItemClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>420</x> + <y>141</y> + </hint> + <hint type="destinationlabel"> + <x>420</x> + <y>281</y> + </hint> + </hints> + </connection> + <connection> + <sender>receivers_detail_TreeWidget</sender> + <signal>itemDoubleClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>receiversDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>75</x> + <y>328</y> + </hint> + <hint type="destinationlabel"> + <x>420</x> + <y>281</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_detail_sqn_TreeWidget</sender> + <signal>itemDoubleClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>sourcesDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>420</x> + <y>377</y> + </hint> + <hint type="destinationlabel"> + <x>420</x> + <y>281</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_detail_ncf_sqn_TreeWidget</sender> + <signal>itemDoubleClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRMTransportDialog</receiver> + <slot>sourcesDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>66</x> + <y>290</y> + </hint> + <hint type="destinationlabel"> + <x>420</x> + <y>281</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <signal>goToPacket(int)</signal> + <slot>sourcesDetailCurrentChanged(int)</slot> + <slot>sourcesItemClicked(QTreeWidgetItem*,int)</slot> + <slot>receiversItemClicked(QTreeWidgetItem*,int)</slot> + <slot>sourcesDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <slot>receiversDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + </slots> +</ui> diff --git a/ui/qt/lbm_lbtru_transport_dialog.cpp b/ui/qt/lbm_lbtru_transport_dialog.cpp new file mode 100644 index 0000000000..6ad608edb0 --- /dev/null +++ b/ui/qt/lbm_lbtru_transport_dialog.cpp @@ -0,0 +1,2251 @@ +/* lbm_lbtru_transport_dialog.cpp + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "lbm_lbtru_transport_dialog.h" +#include "ui_lbm_lbtru_transport_dialog.h" + +#include "file.h" + +#include "wireshark_application.h" + +#include <QClipboard> +#include <QMessageBox> +#include <QTreeWidget> +#include <QTreeWidgetItemIterator> +#include <QMenu> +#include <epan/packet_info.h> +#include <epan/tap.h> +#include <epan/to_str.h> +#include <epan/wmem/wmem.h> +#include <epan/dissectors/packet-lbm.h> +#include <wsutil/nstime.h> + +#include <QDebug> + +namespace +{ + static const int Source_AddressTransport_Column = 0; + static const int Source_DataFrames_Column = 1; + static const int Source_DataBytes_Column = 2; + static const int Source_DataFramesBytes_Column = 3; + static const int Source_DataRate_Column = 4; + static const int Source_RXDataFrames_Column = 5; + static const int Source_RXDataBytes_Column = 6; + static const int Source_RXDataFramesBytes_Column = 7; + static const int Source_RXDataRate_Column = 8; + static const int Source_NCFFrames_Column = 9; + static const int Source_NCFCount_Column = 10; + static const int Source_NCFBytes_Column = 11; + static const int Source_NCFFramesBytes_Column = 12; + static const int Source_NCFCountBytes_Column = 13; + static const int Source_NCFFramesCount_Column = 14; + static const int Source_NCFFramesCountBytes_Column = 15; + static const int Source_NCFRate_Column = 16; + static const int Source_SMFrames_Column = 17; + static const int Source_SMBytes_Column = 18; + static const int Source_SMFramesBytes_Column = 19; + static const int Source_SMRate_Column = 20; + static const int Source_RSTFrames_Column = 21; + static const int Source_RSTBytes_Column = 22; + static const int Source_RSTFramesBytes_Column = 23; + static const int Source_RSTRate_Column = 24; + + static const int Receiver_AddressTransport_Column = 0; + static const int Receiver_NAKFrames_Column = 1; + static const int Receiver_NAKCount_Column = 2; + static const int Receiver_NAKBytes_Column = 3; + static const int Receiver_NAKFramesCount_Column = 4; + static const int Receiver_NAKCountBytes_Column = 5; + static const int Receiver_NAKFramesBytes_Column = 6; + static const int Receiver_NAKFramesCountBytes_Column = 7; + static const int Receiver_NAKRate_Column = 8; + static const int Receiver_ACKFrames_Column = 9; + static const int Receiver_ACKBytes_Column = 10; + static const int Receiver_ACKFramesBytes_Column = 11; + static const int Receiver_ACKRate_Column = 12; + static const int Receiver_CREQFrames_Column = 13; + static const int Receiver_CREQBytes_Column = 14; + static const int Receiver_CREQFramesBytes_Column = 15; + static const int Receiver_CREQRate_Column = 16; + + static const int Detail_SQNReasonType_Column = 0; + static const int Detail_Count_Column = 1; + static const int Detail_Frame_Column = 2; + + static const double OneKilobit = 1000.0; + static const double OneMegabit = OneKilobit * OneKilobit; + static const double OneGigabit = OneMegabit * OneKilobit; +} + +static QString format_rate(const nstime_t & elapsed, guint64 bytes) +{ + QString result; + double elapsed_sec; + double rate; + + if (((elapsed.secs == 0) && (elapsed.nsecs == 0)) || (bytes == 0)) + { + return (QString("0")); + } + + elapsed_sec = elapsed.secs + (((double)elapsed.nsecs) / 1000000000.0); + rate = ((double)(bytes * 8)) / elapsed_sec; + + // Currently rate is in bps + if (rate >= OneGigabit) + { + rate /= OneGigabit; + result = QString("%1G").arg(rate, 0, 'f', 2); + } + else if (rate >= OneMegabit) + { + rate /= OneMegabit; + result = QString("%1M").arg(rate, 0, 'f', 2); + } + else if (rate >= OneKilobit) + { + rate /= OneKilobit; + result = QString("%1K").arg(rate, 0, 'f', 2); + } + else + { + result = QString("%1").arg(rate, 0, 'f', 2); + } + return (result); +} + +// Note: +// LBMLBTRUFrameEntry, LBMLBTRUSQNEntry, LBMLBTRUNCFReasonEntry, LBMLBTRUNCFSQNEntry, LBMLBTRURSTReasonEntry, LBMLBTRUCREQRequestEntry, +// LBMLBTRUSourceTransportEntry, LBMLBTRUSourceEntry, LBMLBTRUReceiverTransportEntry, and LBMLBTRUReceiverEntry are all derived from +// a QTreeWidgetItem. Each instantiation can exist in two places: in a QTreeWidget, and in a containing QMap. +// +// For example: +// - LBMLBTRUTransportDialogInfo contains a QMap of the sources (LBMLBTRUSourceEntry) and receivers (LBMLBTRUReceiverEntry) +// - A source (LBMLBTRUSourceEntry) contains a QMap of the source transports originating from it (LBMLBTRUSourceTransportEntry) +// - A source transport (LBMLBTRUSourceTransportEntry) contains QMaps of data, RX data, and SM SQNs (LBMLBTRUSQNEntry), NCF SQNs +// (LBMLBTRUNCFSQNEntry), and RST reasons (LBMLBTRURSTReasonEntry) +// - A data SQN (LBMLBTRUSQNEntry) contains a QMap of the frames (LBMLBTRUFrameEntry) in which that SQN appears +// +// Not all of the entries actually appear in a QTreeWidget at one time. For example, in the source details, if no specific source +// transport is selected, nothing is in the source details tree. If Data SQNs is selected, then those details appear in the source +// details tree. Switching to RX Data SQNs removes whatever is currently in the source details tree, and adds the RX details for +// the selected transport. +// +// The actual owner of one of the above QTreeWidgetItem-derived items is the QMap container in its parent. The item is "loaned" to +// the QTreeWidget for display. +// +// All of this is to explain why +// 1) we are frequently adding things to a QTreeWidget +// 2) things are removed (takeTopLevelItem) from a QTreeWidget +// 3) destruction involves removing all items from all QTreeWidgets (rather than letting QTreeWidget delete them) +// 4) the destructor for each item has the form +// <for each QMap container> +// for (XXXMapIterator it = m_xxx.begin(); it != m_xxx.end(); it++) +// { +// delete *it; +// } +// m_xxx.clear(); +// The for-loop calls the destructor for each item, while the clear() cleans up the space used by the QMap itself. + +// A frame entry +class LBMLBTRUFrameEntry : public QTreeWidgetItem +{ + public: + LBMLBTRUFrameEntry(guint32 frame); + virtual ~LBMLBTRUFrameEntry(void) { } + guint32 getFrame(void) { return (m_frame); } + + private: + LBMLBTRUFrameEntry(void) { } + guint32 m_frame; +}; + +LBMLBTRUFrameEntry::LBMLBTRUFrameEntry(guint32 frame) : + QTreeWidgetItem(), + m_frame(frame) +{ + setText(Detail_SQNReasonType_Column, QString(" ")); + setText(Detail_Count_Column, QString(" ")); + setText(Detail_Frame_Column, QString("%1").arg(m_frame)); +} + +typedef QMap<guint32, LBMLBTRUFrameEntry *> LBMLBTRUFrameMap; +typedef QMap<guint32, LBMLBTRUFrameEntry *>::iterator LBMLBTRUFrameMapIterator; + +// An SQN (SeQuence Number) entry +class LBMLBTRUSQNEntry : public QTreeWidgetItem +{ + public: + LBMLBTRUSQNEntry(guint32 sqn); + virtual ~LBMLBTRUSQNEntry(void); + void processFrame(guint32 frame); + + private: + LBMLBTRUSQNEntry(void); + guint32 m_sqn; + guint32 m_count; + LBMLBTRUFrameMap m_frames; +}; + +LBMLBTRUSQNEntry::LBMLBTRUSQNEntry(guint32 sqn) : + QTreeWidgetItem(), + m_sqn(sqn), + m_count(0), + m_frames() +{ + setText(Detail_SQNReasonType_Column, QString("%1").arg(m_sqn)); + setTextAlignment(Detail_SQNReasonType_Column, Qt::AlignRight); + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRUSQNEntry::~LBMLBTRUSQNEntry(void) +{ + for (LBMLBTRUFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++) + { + delete *it; + } + m_frames.clear(); +} + +void LBMLBTRUSQNEntry::processFrame(guint32 frame) +{ + LBMLBTRUFrameMapIterator it; + + it = m_frames.find(frame); + if (m_frames.end() == it) + { + LBMLBTRUFrameEntry * entry = new LBMLBTRUFrameEntry(frame); + m_frames.insert(frame, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); +} + +// An NCF (Nak ConFirmation) Reason entry +class LBMLBTRUNCFReasonEntry : public QTreeWidgetItem +{ + public: + LBMLBTRUNCFReasonEntry(guint8 reason); + virtual ~LBMLBTRUNCFReasonEntry(void); + void processFrame(guint32 frame); + + private: + LBMLBTRUNCFReasonEntry(void); + guint8 m_reason; + guint32 m_count; + LBMLBTRUFrameMap m_frames; +}; + +LBMLBTRUNCFReasonEntry::LBMLBTRUNCFReasonEntry(guint8 reason) : + QTreeWidgetItem(), + m_reason(reason), + m_count(0), + m_frames() +{ + switch (m_reason) + { + case LBTRU_NCF_REASON_NO_RETRY: + setText(Detail_SQNReasonType_Column, QString("No Retry")); + break; + case LBTRU_NCF_REASON_IGNORED: + setText(Detail_SQNReasonType_Column, QString("Ignored")); + break; + case LBTRU_NCF_REASON_RX_DELAY: + setText(Detail_SQNReasonType_Column, QString("Retransmit Delay")); + break; + case LBTRU_NCF_REASON_SHED: + setText(Detail_SQNReasonType_Column, QString("Shed")); + break; + default: + setText(Detail_SQNReasonType_Column, QString("Unknown")); + break; + } + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRUNCFReasonEntry::~LBMLBTRUNCFReasonEntry(void) +{ + for (LBMLBTRUFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++) + { + delete *it; + } + m_frames.clear(); +} + +void LBMLBTRUNCFReasonEntry::processFrame(guint32 frame) +{ + LBMLBTRUFrameMapIterator it; + + it = m_frames.find(frame); + if (m_frames.end() == it) + { + LBMLBTRUFrameEntry * entry = new LBMLBTRUFrameEntry(frame); + m_frames.insert(frame, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); +} + +typedef QMap<guint8, LBMLBTRUNCFReasonEntry *> LBMLBTRUNCFReasonMap; +typedef QMap<guint8, LBMLBTRUNCFReasonEntry *>::iterator LBMLBTRUNCFReasonMapIterator; + +// An NCF SQN entry +class LBMLBTRUNCFSQNEntry : public QTreeWidgetItem +{ + public: + LBMLBTRUNCFSQNEntry(guint32 sqn); + virtual ~LBMLBTRUNCFSQNEntry(void); + void processFrame(guint8 reason, guint32 frame); + + private: + LBMLBTRUNCFSQNEntry(void); + guint32 m_sqn; + guint32 m_count; + LBMLBTRUNCFReasonMap m_reasons; +}; + +LBMLBTRUNCFSQNEntry::LBMLBTRUNCFSQNEntry(guint32 sqn) : + QTreeWidgetItem(), + m_sqn(sqn), + m_count(0), + m_reasons() +{ + setText(Detail_SQNReasonType_Column, QString("%1").arg(m_sqn)); + setTextAlignment(Detail_SQNReasonType_Column, Qt::AlignRight); + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRUNCFSQNEntry::~LBMLBTRUNCFSQNEntry(void) +{ + for (LBMLBTRUNCFReasonMapIterator it = m_reasons.begin(); it != m_reasons.end(); it++) + { + delete *it; + } + m_reasons.clear(); +} + +void LBMLBTRUNCFSQNEntry::processFrame(guint8 reason, guint32 frame) +{ + LBMLBTRUNCFReasonMapIterator it; + LBMLBTRUNCFReasonEntry * entry = NULL; + + it = m_reasons.find(reason); + if (m_reasons.end() == it) + { + entry = new LBMLBTRUNCFReasonEntry(reason); + m_reasons.insert(reason, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + else + { + entry = it.value(); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + entry->processFrame(frame); +} + +// An RST (ReSeT) Reason entry +class LBMLBTRURSTReasonEntry : public QTreeWidgetItem +{ + public: + LBMLBTRURSTReasonEntry(guint32 reason); + virtual ~LBMLBTRURSTReasonEntry(void); + void processFrame(guint32 frame); + + private: + LBMLBTRURSTReasonEntry(void); + guint32 m_reason; + QString m_reason_string; + guint32 m_count; + LBMLBTRUFrameMap m_frames; +}; + +LBMLBTRURSTReasonEntry::LBMLBTRURSTReasonEntry(guint32 reason) : + QTreeWidgetItem(), + m_reason(reason), + m_reason_string(), + m_count(0), + m_frames() +{ + switch (m_reason) + { + case LBTRU_RST_REASON_DEFAULT: + m_reason_string = "Default"; + break; + default: + m_reason_string = QString("Unknown (%1)").arg(m_reason); + break; + } + setText(Detail_SQNReasonType_Column, m_reason_string); + setTextAlignment(Detail_SQNReasonType_Column, Qt::AlignLeft); + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRURSTReasonEntry::~LBMLBTRURSTReasonEntry(void) +{ + for (LBMLBTRUFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++) + { + delete *it; + } + m_frames.clear(); +} + +void LBMLBTRURSTReasonEntry::processFrame(guint32 frame) +{ + LBMLBTRUFrameMapIterator it; + + it = m_frames.find(frame); + if (m_frames.end() == it) + { + LBMLBTRUFrameEntry * entry = new LBMLBTRUFrameEntry(frame); + m_frames.insert(frame, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); +} + +// A CREQ (Connection REQuest) Request entry +class LBMLBTRUCREQRequestEntry : public QTreeWidgetItem +{ + public: + LBMLBTRUCREQRequestEntry(guint32 request); + virtual ~LBMLBTRUCREQRequestEntry(void); + void processFrame(guint32 frame); + + private: + LBMLBTRUCREQRequestEntry(void); + guint32 m_request; + QString m_request_string; + guint32 m_count; + LBMLBTRUFrameMap m_frames; +}; + +LBMLBTRUCREQRequestEntry::LBMLBTRUCREQRequestEntry(guint32 request) : + QTreeWidgetItem(), + m_request(request), + m_request_string(), + m_count(0), + m_frames() +{ + switch (m_request) + { + case LBTRU_CREQ_REQUEST_SYN: + m_request_string = "SYN"; + break; + default: + m_request_string = QString("Unknown (%1)").arg(m_request); + break; + } + setText(Detail_SQNReasonType_Column, m_request_string); + setTextAlignment(Detail_SQNReasonType_Column, Qt::AlignLeft); + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); + setText(Detail_Frame_Column, QString(" ")); +} + +LBMLBTRUCREQRequestEntry::~LBMLBTRUCREQRequestEntry(void) +{ + for (LBMLBTRUFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++) + { + delete *it; + } + m_frames.clear(); +} + +void LBMLBTRUCREQRequestEntry::processFrame(guint32 frame) +{ + LBMLBTRUFrameMapIterator it; + + it = m_frames.find(frame); + if (m_frames.end() == it) + { + LBMLBTRUFrameEntry * entry = new LBMLBTRUFrameEntry(frame); + m_frames.insert(frame, entry); + addChild(entry); + sortChildren(Detail_Frame_Column, Qt::AscendingOrder); + } + m_count++; + setText(Detail_Count_Column, QString("%1").arg(m_count)); + setTextAlignment(Detail_Count_Column, Qt::AlignRight); +} + +typedef QMap<guint32, LBMLBTRUSQNEntry *> LBMLBTRUSQNMap; +typedef QMap<guint32, LBMLBTRUSQNEntry *>::iterator LBMLBTRUSQNMapIterator; +typedef QMap<guint32, LBMLBTRUNCFSQNEntry *> LBMLBTRUNCFSQNMap; +typedef QMap<guint32, LBMLBTRUNCFSQNEntry *>::iterator LBMLBTRUNCFSQNMapIterator; +typedef QMap<guint32, LBMLBTRURSTReasonEntry *> LBMLBTRURSTReasonMap; +typedef QMap<guint32, LBMLBTRURSTReasonEntry *>::iterator LBMLBTRURSTReasonMapIterator; +typedef QMap<guint32, LBMLBTRUCREQRequestEntry *> LBMLBTRUCREQRequestMap; +typedef QMap<guint32, LBMLBTRUCREQRequestEntry *>::iterator LBMLBTRUCREQRequestMapIterator; + +// A source transport entry +class LBMLBTRUSourceTransportEntry : public QTreeWidgetItem +{ + friend class LBMLBTRUTransportDialog; + + public: + LBMLBTRUSourceTransportEntry(const QString & transport); + virtual ~LBMLBTRUSourceTransportEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info); + + protected: + QString m_transport; + + private: + LBMLBTRUSourceTransportEntry(void) { } + void fillItem(void); + guint64 m_data_frames; + guint64 m_data_bytes; + guint64 m_rx_data_frames; + guint64 m_rx_data_bytes; + guint64 m_ncf_frames; + guint64 m_ncf_count; + guint64 m_ncf_bytes; + guint64 m_sm_frames; + guint64 m_sm_bytes; + guint64 m_rst_frames; + guint64 m_rst_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + + protected: + LBMLBTRUSQNMap m_data_sqns; + LBMLBTRUSQNMap m_rx_data_sqns; + LBMLBTRUNCFSQNMap m_ncf_sqns; + LBMLBTRUSQNMap m_sm_sqns; + LBMLBTRURSTReasonMap m_rst_reasons; +}; + +LBMLBTRUSourceTransportEntry::LBMLBTRUSourceTransportEntry(const QString & transport) : + QTreeWidgetItem(), + m_transport(transport), + m_data_frames(0), + m_data_bytes(0), + m_rx_data_frames(0), + m_rx_data_bytes(0), + m_ncf_frames(0), + m_ncf_count(0), + m_ncf_bytes(0), + m_sm_frames(0), + m_sm_bytes(0), + m_rst_frames(0), + m_rst_bytes(0), + m_first_frame_timestamp_valid(false), + m_data_sqns(), + m_rx_data_sqns(), + m_ncf_sqns(), + m_sm_sqns(), + m_rst_reasons() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Source_AddressTransport_Column, m_transport); +} + +LBMLBTRUSourceTransportEntry::~LBMLBTRUSourceTransportEntry(void) +{ + for (LBMLBTRUSQNMapIterator it = m_data_sqns.begin(); it != m_data_sqns.end(); it++) + { + delete *it; + } + m_data_sqns.clear(); + + for (LBMLBTRUSQNMapIterator it = m_rx_data_sqns.begin(); it != m_rx_data_sqns.end(); it++) + { + delete *it; + } + m_rx_data_sqns.clear(); + + for (LBMLBTRUNCFSQNMapIterator it = m_ncf_sqns.begin(); it != m_ncf_sqns.end(); it++) + { + delete *it; + } + m_ncf_sqns.clear(); + + for (LBMLBTRUSQNMapIterator it = m_sm_sqns.begin(); it != m_sm_sqns.end(); it++) + { + delete *it; + } + m_sm_sqns.clear(); + + for (LBMLBTRURSTReasonMapIterator it = m_rst_reasons.begin(); it != m_rst_reasons.end(); it++) + { + delete *it; + } + m_rst_reasons.clear(); +} + +void LBMLBTRUSourceTransportEntry::processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info) +{ + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + if (tap_info->type == LBTRU_PACKET_TYPE_DATA) + { + LBMLBTRUSQNEntry * sqn = NULL; + LBMLBTRUSQNMapIterator it; + + if (tap_info->retransmission) + { + m_rx_data_frames++; + m_rx_data_bytes += pinfo->fd->pkt_len; + it = m_rx_data_sqns.find(tap_info->sqn); + if (m_rx_data_sqns.end() == it) + { + sqn = new LBMLBTRUSQNEntry(tap_info->sqn); + m_rx_data_sqns.insert(tap_info->sqn, sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(pinfo->fd->num); + } + else + { + m_data_frames++; + m_data_bytes += pinfo->fd->pkt_len; + it = m_data_sqns.find(tap_info->sqn); + if (m_data_sqns.end() == it) + { + sqn = new LBMLBTRUSQNEntry(tap_info->sqn); + m_data_sqns.insert(tap_info->sqn, sqn); + } + else + { + sqn = it.value(); + } + } + sqn->processFrame(pinfo->fd->num); + } + else if (tap_info->type == LBTRU_PACKET_TYPE_NCF) + { + guint16 idx; + LBMLBTRUNCFSQNMapIterator it; + LBMLBTRUNCFSQNEntry * sqn = NULL; + + m_ncf_frames++; + m_ncf_bytes += pinfo->fd->pkt_len; + m_ncf_count += (guint64)tap_info->num_sqns; + for (idx = 0; idx < tap_info->num_sqns; idx++) + { + it = m_ncf_sqns.find(tap_info->sqns[idx]); + if (m_ncf_sqns.end() == it) + { + sqn = new LBMLBTRUNCFSQNEntry(tap_info->sqns[idx]); + m_ncf_sqns.insert(tap_info->sqns[idx], sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(tap_info->ncf_reason, pinfo->fd->num); + } + } + else if (tap_info->type == LBTRU_PACKET_TYPE_SM) + { + LBMLBTRUSQNEntry * sqn = NULL; + LBMLBTRUSQNMapIterator it; + + m_sm_frames++; + m_sm_bytes += pinfo->fd->pkt_len; + it = m_sm_sqns.find(tap_info->sqn); + if (m_sm_sqns.end() == it) + { + sqn = new LBMLBTRUSQNEntry(tap_info->sqn); + m_sm_sqns.insert(tap_info->sqn, sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(pinfo->fd->num); + } + else if (tap_info->type == LBTRU_PACKET_TYPE_RST) + { + LBMLBTRURSTReasonEntry * reason = NULL; + LBMLBTRURSTReasonMapIterator it; + + m_rst_frames++; + m_rst_bytes += pinfo->fd->pkt_len; + it = m_rst_reasons.find(tap_info->rst_type); + if (m_rst_reasons.end() == it) + { + reason = new LBMLBTRURSTReasonEntry(tap_info->rst_type); + m_rst_reasons.insert((unsigned int) tap_info->rst_type, reason); + } + else + { + reason = it.value(); + } + reason->processFrame(pinfo->fd->num); + } + else + { + return; + } + fillItem(); +} + +void LBMLBTRUSourceTransportEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Source_DataFrames_Column, QString("%1").arg(m_data_frames)); + setTextAlignment(Source_DataFrames_Column, Qt::AlignRight); + setText(Source_DataBytes_Column, QString("%1").arg(m_data_bytes)); + setTextAlignment(Source_DataBytes_Column, Qt::AlignRight); + setText(Source_DataFramesBytes_Column, QString("%1/%2").arg(m_data_frames).arg(m_data_bytes)); + setTextAlignment(Source_DataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_DataRate_Column, format_rate(delta, m_data_bytes)); + setTextAlignment(Source_DataRate_Column, Qt::AlignRight); + setText(Source_RXDataFrames_Column, QString("%1").arg(m_rx_data_frames)); + setTextAlignment(Source_RXDataFrames_Column, Qt::AlignRight); + setText(Source_RXDataBytes_Column, QString("%1").arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataBytes_Column, Qt::AlignRight); + setText(Source_RXDataFramesBytes_Column, QString("%1/%2").arg(m_rx_data_frames).arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_RXDataRate_Column, format_rate(delta, m_rx_data_bytes)); + setTextAlignment(Source_RXDataRate_Column, Qt::AlignRight); + setText(Source_NCFFrames_Column, QString("%1").arg(m_ncf_frames)); + setTextAlignment(Source_NCFFrames_Column, Qt::AlignRight); + setText(Source_NCFCount_Column, QString("%1").arg(m_ncf_count)); + setTextAlignment(Source_NCFCount_Column, Qt::AlignRight); + setText(Source_NCFBytes_Column, QString("%1").arg(m_ncf_bytes)); + setTextAlignment(Source_NCFBytes_Column, Qt::AlignRight); + setText(Source_NCFFramesBytes_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesBytes_Column, Qt::AlignHCenter); + setText(Source_NCFCountBytes_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCount_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_count)); + setTextAlignment(Source_NCFFramesCount_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCountBytes_Column, QString("%1/%2/%3").arg(m_ncf_frames).arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFRate_Column, format_rate(delta, m_ncf_bytes)); + setTextAlignment(Source_NCFRate_Column, Qt::AlignRight); + setText(Source_SMFrames_Column, QString("%1").arg(m_sm_frames)); + setTextAlignment(Source_SMFrames_Column, Qt::AlignRight); + setText(Source_SMBytes_Column, QString("%1").arg(m_sm_bytes)); + setTextAlignment(Source_SMBytes_Column, Qt::AlignRight); + setText(Source_SMFramesBytes_Column, QString("%1/%2").arg(m_sm_frames).arg(m_sm_bytes)); + setTextAlignment(Source_SMFramesBytes_Column, Qt::AlignHCenter); + setText(Source_SMRate_Column, format_rate(delta, m_sm_bytes)); + setTextAlignment(Source_SMRate_Column, Qt::AlignRight); + setText(Source_RSTFrames_Column, QString("%1").arg(m_rst_frames)); + setTextAlignment(Source_RSTFrames_Column, Qt::AlignRight); + setText(Source_RSTBytes_Column, QString("%1").arg(m_rst_bytes)); + setTextAlignment(Source_RSTBytes_Column, Qt::AlignRight); + setText(Source_RSTFramesBytes_Column, QString("%1/%2").arg(m_rst_frames).arg(m_rst_bytes)); + setTextAlignment(Source_RSTFramesBytes_Column, Qt::AlignHCenter); + setText(Source_RSTRate_Column, format_rate(delta, m_rst_bytes)); + setTextAlignment(Source_RSTRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRUSourceTransportEntry *> LBMLBTRUSourceTransportMap; +typedef QMap<QString, LBMLBTRUSourceTransportEntry *>::iterator LBMLBTRUSourceTransportMapIterator; + +// A source (address) entry +class LBMLBTRUSourceEntry : public QTreeWidgetItem +{ + public: + LBMLBTRUSourceEntry(const QString & source_address); + virtual ~LBMLBTRUSourceEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info); + + private: + LBMLBTRUSourceEntry(void) { } + void fillItem(void); + QString m_address; + QString m_transport; + guint64 m_data_frames; + guint64 m_data_bytes; + guint64 m_rx_data_frames; + guint64 m_rx_data_bytes; + guint64 m_ncf_frames; + guint64 m_ncf_count; + guint64 m_ncf_bytes; + guint64 m_sm_frames; + guint64 m_sm_bytes; + guint64 m_rst_frames; + guint64 m_rst_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + LBMLBTRUSourceTransportMap m_transports; +}; + +LBMLBTRUSourceEntry::LBMLBTRUSourceEntry(const QString & source_address) : + QTreeWidgetItem(), + m_address(source_address), + m_data_frames(0), + m_data_bytes(0), + m_rx_data_frames(0), + m_rx_data_bytes(0), + m_ncf_frames(0), + m_ncf_count(0), + m_ncf_bytes(0), + m_sm_frames(0), + m_sm_bytes(0), + m_rst_frames(0), + m_rst_bytes(0), + m_first_frame_timestamp_valid(false), + m_transports() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Source_AddressTransport_Column, m_address); +} + +LBMLBTRUSourceEntry::~LBMLBTRUSourceEntry(void) +{ + for (LBMLBTRUSourceTransportMapIterator it = m_transports.begin(); it != m_transports.end(); it++) + { + delete *it; + } + m_transports.clear(); +} + +void LBMLBTRUSourceEntry::processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info) +{ + LBMLBTRUSourceTransportEntry * transport = NULL; + LBMLBTRUSourceTransportMapIterator it; + + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + switch (tap_info->type) + { + case LBTRU_PACKET_TYPE_DATA: + if (tap_info->retransmission) + { + m_rx_data_frames++; + m_rx_data_bytes += pinfo->fd->pkt_len; + } + else + { + m_data_frames++; + m_data_bytes += pinfo->fd->pkt_len; + } + break; + case LBTRU_PACKET_TYPE_NCF: + m_ncf_frames++; + m_ncf_bytes += pinfo->fd->pkt_len; + m_ncf_count += tap_info->num_sqns; + break; + case LBTRU_PACKET_TYPE_SM: + m_sm_frames++; + m_sm_bytes += pinfo->fd->pkt_len; + break; + case LBTRU_PACKET_TYPE_RST: + m_rst_frames++; + m_rst_bytes += pinfo->fd->pkt_len; + break; + } + + it = m_transports.find(tap_info->transport); + if (m_transports.end() == it) + { + transport = new LBMLBTRUSourceTransportEntry(tap_info->transport); + m_transports.insert(tap_info->transport, transport); + addChild(transport); + sortChildren(Source_AddressTransport_Column, Qt::AscendingOrder); + } + else + { + transport = it.value(); + } + fillItem(); + transport->processPacket(pinfo, tap_info); +} + +void LBMLBTRUSourceEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Source_DataFrames_Column, QString("%1").arg(m_data_frames)); + setTextAlignment(Source_DataFrames_Column, Qt::AlignRight); + setText(Source_DataBytes_Column, QString("%1").arg(m_data_bytes)); + setTextAlignment(Source_DataBytes_Column, Qt::AlignRight); + setText(Source_DataFramesBytes_Column, QString("%1/%2").arg(m_data_frames).arg(m_data_bytes)); + setTextAlignment(Source_DataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_DataRate_Column, format_rate(delta, m_data_bytes)); + setTextAlignment(Source_DataRate_Column, Qt::AlignRight); + setText(Source_RXDataFrames_Column, QString("%1").arg(m_rx_data_frames)); + setTextAlignment(Source_RXDataFrames_Column, Qt::AlignRight); + setText(Source_RXDataBytes_Column, QString("%1").arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataBytes_Column, Qt::AlignRight); + setText(Source_RXDataFramesBytes_Column, QString("%1/%2").arg(m_rx_data_frames).arg(m_rx_data_bytes)); + setTextAlignment(Source_RXDataFramesBytes_Column, Qt::AlignHCenter); + setText(Source_RXDataRate_Column, format_rate(delta, m_rx_data_bytes)); + setTextAlignment(Source_RXDataRate_Column, Qt::AlignRight); + setText(Source_NCFFrames_Column, QString("%1").arg(m_ncf_frames)); + setTextAlignment(Source_NCFFrames_Column, Qt::AlignRight); + setText(Source_NCFCount_Column, QString("%1").arg(m_ncf_count)); + setTextAlignment(Source_NCFCount_Column, Qt::AlignRight); + setText(Source_NCFBytes_Column, QString("%1").arg(m_ncf_bytes)); + setTextAlignment(Source_NCFBytes_Column, Qt::AlignRight); + setText(Source_NCFFramesBytes_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesBytes_Column, Qt::AlignHCenter); + setText(Source_NCFCountBytes_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCount_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_count)); + setTextAlignment(Source_NCFFramesCount_Column, Qt::AlignHCenter); + setText(Source_NCFFramesCountBytes_Column, QString("%1/%2/%3").arg(m_ncf_frames).arg(m_ncf_count).arg(m_ncf_bytes)); + setTextAlignment(Source_NCFFramesCountBytes_Column, Qt::AlignHCenter); + setText(Source_NCFRate_Column, format_rate(delta, m_ncf_bytes)); + setTextAlignment(Source_NCFRate_Column, Qt::AlignRight); + setText(Source_SMFrames_Column, QString("%1").arg(m_sm_frames)); + setTextAlignment(Source_SMFrames_Column, Qt::AlignRight); + setText(Source_SMBytes_Column, QString("%1").arg(m_sm_bytes)); + setTextAlignment(Source_SMBytes_Column, Qt::AlignRight); + setText(Source_SMFramesBytes_Column, QString("%1/%2").arg(m_sm_frames).arg(m_sm_bytes)); + setTextAlignment(Source_SMFramesBytes_Column, Qt::AlignRight); + setText(Source_SMRate_Column, format_rate(delta, m_sm_bytes)); + setTextAlignment(Source_SMRate_Column, Qt::AlignRight); + setText(Source_RSTFrames_Column, QString("%1").arg(m_rst_frames)); + setTextAlignment(Source_RSTFrames_Column, Qt::AlignRight); + setText(Source_RSTBytes_Column, QString("%1").arg(m_rst_bytes)); + setTextAlignment(Source_RSTBytes_Column, Qt::AlignRight); + setText(Source_RSTFramesBytes_Column, QString("%1/%2").arg(m_rst_frames).arg(m_rst_bytes)); + setTextAlignment(Source_RSTFramesBytes_Column, Qt::AlignHCenter); + setText(Source_RSTRate_Column, format_rate(delta, m_rst_bytes)); + setTextAlignment(Source_RSTRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRUSourceEntry *> LBMLBTRUSourceMap; +typedef QMap<QString, LBMLBTRUSourceEntry *>::iterator LBMLBTRUSourceMapIterator; + +// A receiver transport entry +class LBMLBTRUReceiverTransportEntry : public QTreeWidgetItem +{ + friend class LBMLBTRUTransportDialog; + + public: + LBMLBTRUReceiverTransportEntry(const QString & transport); + virtual ~LBMLBTRUReceiverTransportEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info); + + private: + LBMLBTRUReceiverTransportEntry(void) { } + void fillItem(void); + QString m_transport; + guint64 m_nak_frames; + guint64 m_nak_count; + guint64 m_nak_bytes; + guint64 m_ack_frames; + guint64 m_ack_bytes; + guint64 m_creq_frames; + guint64 m_creq_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + + protected: + LBMLBTRUSQNMap m_nak_sqns; + LBMLBTRUSQNMap m_ack_sqns; + LBMLBTRUCREQRequestMap m_creq_requests; +}; + +LBMLBTRUReceiverTransportEntry::LBMLBTRUReceiverTransportEntry(const QString & transport) : + QTreeWidgetItem(), + m_transport(transport), + m_nak_frames(0), + m_nak_count(0), + m_nak_bytes(0), + m_ack_frames(0), + m_ack_bytes(0), + m_creq_frames(0), + m_creq_bytes(0), + m_first_frame_timestamp_valid(false), + m_nak_sqns(), + m_ack_sqns(), + m_creq_requests() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Receiver_AddressTransport_Column, m_transport); +} + +LBMLBTRUReceiverTransportEntry::~LBMLBTRUReceiverTransportEntry(void) +{ + for (LBMLBTRUSQNMapIterator it = m_nak_sqns.begin(); it != m_nak_sqns.end(); it++) + { + delete *it; + } + m_nak_sqns.clear(); + + for (LBMLBTRUSQNMapIterator it = m_ack_sqns.begin(); it != m_ack_sqns.end(); it++) + { + delete *it; + } + m_ack_sqns.clear(); + + for (LBMLBTRUCREQRequestMapIterator it = m_creq_requests.begin(); it != m_creq_requests.end(); it++) + { + delete *it; + } + m_creq_requests.clear(); +} + +void LBMLBTRUReceiverTransportEntry::processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info) +{ + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + switch (tap_info->type) + { + case LBTRU_PACKET_TYPE_NAK: + { + guint16 idx; + LBMLBTRUSQNEntry * sqn = NULL; + LBMLBTRUSQNMapIterator it; + + m_nak_frames++; + m_nak_bytes += pinfo->fd->pkt_len; + m_nak_count += tap_info->num_sqns; + for (idx = 0; idx < tap_info->num_sqns; idx++) + { + it = m_nak_sqns.find(tap_info->sqns[idx]); + if (m_nak_sqns.end() == it) + { + sqn = new LBMLBTRUSQNEntry(tap_info->sqns[idx]); + m_nak_sqns.insert(tap_info->sqns[idx], sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(pinfo->fd->num); + } + } + break; + case LBTRU_PACKET_TYPE_ACK: + { + LBMLBTRUSQNEntry * sqn = NULL; + LBMLBTRUSQNMapIterator it; + + m_ack_frames++; + m_ack_bytes += pinfo->fd->pkt_len; + it = m_ack_sqns.find(tap_info->sqn); + if (m_ack_sqns.end() == it) + { + sqn = new LBMLBTRUSQNEntry(tap_info->sqn); + m_ack_sqns.insert(tap_info->sqn, sqn); + } + else + { + sqn = it.value(); + } + sqn->processFrame(pinfo->fd->num); + } + break; + case LBTRU_PACKET_TYPE_CREQ: + { + LBMLBTRUCREQRequestEntry * req = NULL; + LBMLBTRUCREQRequestMapIterator it; + + m_creq_frames++; + m_creq_bytes += pinfo->fd->pkt_len; + it = m_creq_requests.find(tap_info->creq_type); + if (m_creq_requests.end() == it) + { + req = new LBMLBTRUCREQRequestEntry(tap_info->creq_type); + m_creq_requests.insert(tap_info->creq_type, req); + } + else + { + req = it.value(); + } + req->processFrame(pinfo->fd->num); + } + break; + default: + return; + break; + } + fillItem(); +} + +void LBMLBTRUReceiverTransportEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Receiver_NAKFrames_Column, QString("%1").arg(m_nak_frames)); + setTextAlignment(Receiver_NAKFrames_Column, Qt::AlignRight); + setText(Receiver_NAKCount_Column, QString("%1").arg(m_nak_count)); + setTextAlignment(Receiver_NAKCount_Column, Qt::AlignRight); + setText(Receiver_NAKBytes_Column, QString("%1").arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKBytes_Column, Qt::AlignRight); + setText(Receiver_NAKFramesCount_Column, QString("%1/%2").arg(m_nak_frames).arg(m_nak_count)); + setTextAlignment(Receiver_NAKFramesCount_Column, Qt::AlignHCenter); + setText(Receiver_NAKCountBytes_Column, QString("%1/%2").arg(m_nak_count).arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKCountBytes_Column, Qt::AlignHCenter); + setText(Receiver_NAKFramesBytes_Column, QString("%1/%2").arg(m_nak_frames).arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKFramesBytes_Column, Qt::AlignHCenter); + setText(Receiver_NAKFramesCountBytes_Column, QString("%1/%2/%3").arg(m_nak_frames).arg(m_nak_count).arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKFramesCountBytes_Column, Qt::AlignHCenter); + setText(Receiver_NAKRate_Column, format_rate(delta, m_nak_bytes)); + setTextAlignment(Receiver_NAKRate_Column, Qt::AlignRight); + setText(Receiver_ACKFrames_Column, QString("%1").arg(m_ack_frames)); + setTextAlignment(Receiver_ACKFrames_Column, Qt::AlignRight); + setText(Receiver_ACKBytes_Column, QString("%1").arg(m_ack_bytes)); + setTextAlignment(Receiver_ACKBytes_Column, Qt::AlignRight); + setText(Receiver_ACKFramesBytes_Column, QString("%1/%2").arg(m_ack_frames).arg(m_ack_bytes)); + setTextAlignment(Receiver_ACKFramesBytes_Column, Qt::AlignHCenter); + setText(Receiver_ACKRate_Column, format_rate(delta, m_ack_bytes)); + setTextAlignment(Receiver_ACKRate_Column, Qt::AlignRight); + setText(Receiver_CREQFrames_Column, QString("%1").arg(m_creq_frames)); + setTextAlignment(Receiver_CREQFrames_Column, Qt::AlignRight); + setText(Receiver_CREQBytes_Column, QString("%1").arg(m_creq_bytes)); + setTextAlignment(Receiver_CREQBytes_Column, Qt::AlignRight); + setText(Receiver_CREQFramesBytes_Column, QString("%1/%2").arg(m_creq_frames).arg(m_creq_bytes)); + setTextAlignment(Receiver_CREQFramesBytes_Column, Qt::AlignHCenter); + setText(Receiver_CREQRate_Column, format_rate(delta, m_creq_bytes)); + setTextAlignment(Receiver_CREQRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRUReceiverTransportEntry *> LBMLBTRUReceiverTransportMap; +typedef QMap<QString, LBMLBTRUReceiverTransportEntry *>::iterator LBMLBTRUReceiverTransportMapIterator; + +// A receiver (address) entry +class LBMLBTRUReceiverEntry : public QTreeWidgetItem +{ + public: + LBMLBTRUReceiverEntry(const QString & receiver_address); + virtual ~LBMLBTRUReceiverEntry(void); + void processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info); + + private: + LBMLBTRUReceiverEntry(void) { } + void fillItem(void); + QString m_address; + QString m_transport; + guint64 m_nak_frames; + guint64 m_nak_count; + guint64 m_nak_bytes; + guint64 m_ack_frames; + guint64 m_ack_bytes; + guint64 m_creq_frames; + guint64 m_creq_bytes; + nstime_t m_first_frame_timestamp; + bool m_first_frame_timestamp_valid; + nstime_t m_last_frame_timestamp; + LBMLBTRUReceiverTransportMap m_transports; +}; + +LBMLBTRUReceiverEntry::LBMLBTRUReceiverEntry(const QString & receiver_address) : + QTreeWidgetItem(), + m_address(receiver_address), + m_nak_frames(0), + m_nak_count(0), + m_nak_bytes(0), + m_ack_frames(0), + m_ack_bytes(0), + m_creq_frames(0), + m_creq_bytes(0), + m_first_frame_timestamp_valid(false), + m_transports() +{ + m_first_frame_timestamp.secs = 0; + m_first_frame_timestamp.nsecs = 0; + m_last_frame_timestamp.secs = 0; + m_last_frame_timestamp.nsecs = 0; + setText(Receiver_AddressTransport_Column, m_address); +} + +LBMLBTRUReceiverEntry::~LBMLBTRUReceiverEntry(void) +{ + for (LBMLBTRUReceiverTransportMapIterator it = m_transports.begin(); it != m_transports.end(); it++) + { + delete *it; + } + m_transports.clear(); +} + +void LBMLBTRUReceiverEntry::processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info) +{ + LBMLBTRUReceiverTransportEntry * transport = NULL; + LBMLBTRUReceiverTransportMapIterator it; + + if (m_first_frame_timestamp_valid) + { + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_first_frame_timestamp) < 0) + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + } + } + else + { + nstime_copy(&(m_first_frame_timestamp), &(pinfo->fd->abs_ts)); + m_first_frame_timestamp_valid = true; + } + if (nstime_cmp(&(pinfo->fd->abs_ts), &m_last_frame_timestamp) > 0) + { + nstime_copy(&(m_last_frame_timestamp), &(pinfo->fd->abs_ts)); + } + switch (tap_info->type) + { + case LBTRU_PACKET_TYPE_NAK: + m_nak_frames++; + m_nak_bytes += pinfo->fd->pkt_len; + m_nak_count += tap_info->num_sqns; + break; + case LBTRU_PACKET_TYPE_ACK: + m_ack_frames++; + m_ack_bytes += pinfo->fd->pkt_len; + break; + case LBTRU_PACKET_TYPE_CREQ: + m_creq_frames++; + m_creq_bytes += pinfo->fd->pkt_len; + break; + } + + it = m_transports.find(tap_info->transport); + if (m_transports.end() == it) + { + transport = new LBMLBTRUReceiverTransportEntry(tap_info->transport); + m_transports.insert(tap_info->transport, transport); + addChild(transport); + sortChildren(Receiver_AddressTransport_Column, Qt::AscendingOrder); + } + else + { + transport = it.value(); + } + fillItem(); + transport->processPacket(pinfo, tap_info); +} + +void LBMLBTRUReceiverEntry::fillItem(void) +{ + nstime_t delta; + + nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp); + setText(Receiver_NAKFrames_Column, QString("%1").arg(m_nak_frames)); + setTextAlignment(Receiver_NAKFrames_Column, Qt::AlignRight); + setText(Receiver_NAKCount_Column, QString("%1").arg(m_nak_count)); + setTextAlignment(Receiver_NAKCount_Column, Qt::AlignRight); + setText(Receiver_NAKBytes_Column, QString("%1").arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKBytes_Column, Qt::AlignRight); + setText(Receiver_NAKFramesCount_Column, QString("%1/%2").arg(m_nak_frames).arg(m_nak_count)); + setTextAlignment(Receiver_NAKFramesCount_Column, Qt::AlignHCenter); + setText(Receiver_NAKCountBytes_Column, QString("%1/%2").arg(m_nak_count).arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKCountBytes_Column, Qt::AlignHCenter); + setText(Receiver_NAKFramesBytes_Column, QString("%1/%2").arg(m_nak_frames).arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKFramesBytes_Column, Qt::AlignHCenter); + setText(Receiver_NAKFramesCountBytes_Column, QString("%1/%2/%3").arg(m_nak_frames).arg(m_nak_count).arg(m_nak_bytes)); + setTextAlignment(Receiver_NAKFramesCountBytes_Column, Qt::AlignHCenter); + setText(Receiver_NAKRate_Column, format_rate(delta, m_nak_bytes)); + setTextAlignment(Receiver_NAKRate_Column, Qt::AlignRight); + setText(Receiver_ACKFrames_Column, QString("%1").arg(m_ack_frames)); + setTextAlignment(Receiver_ACKFrames_Column, Qt::AlignRight); + setText(Receiver_ACKBytes_Column, QString("%1").arg(m_ack_bytes)); + setTextAlignment(Receiver_ACKBytes_Column, Qt::AlignRight); + setText(Receiver_ACKFramesBytes_Column, QString("%1/%2").arg(m_ack_frames).arg(m_ack_bytes)); + setTextAlignment(Receiver_ACKFramesBytes_Column, Qt::AlignHCenter); + setText(Receiver_ACKRate_Column, format_rate(delta, m_ack_bytes)); + setTextAlignment(Receiver_ACKRate_Column, Qt::AlignRight); + setText(Receiver_CREQFrames_Column, QString("%1").arg(m_creq_frames)); + setTextAlignment(Receiver_CREQFrames_Column, Qt::AlignRight); + setText(Receiver_CREQBytes_Column, QString("%1").arg(m_creq_bytes)); + setTextAlignment(Receiver_CREQBytes_Column, Qt::AlignRight); + setText(Receiver_CREQFramesBytes_Column, QString("%1/%2").arg(m_creq_frames).arg(m_creq_bytes)); + setTextAlignment(Receiver_CREQFramesBytes_Column, Qt::AlignHCenter); + setText(Receiver_CREQRate_Column, format_rate(delta, m_creq_bytes)); + setTextAlignment(Receiver_CREQRate_Column, Qt::AlignRight); +} + +typedef QMap<QString, LBMLBTRUReceiverEntry *> LBMLBTRUReceiverMap; +typedef QMap<QString, LBMLBTRUReceiverEntry *>::iterator LBMLBTRUReceiverMapIterator; + +class LBMLBTRUTransportDialogInfo +{ + public: + LBMLBTRUTransportDialogInfo(void); + ~LBMLBTRUTransportDialogInfo(void); + void setDialog(LBMLBTRUTransportDialog * dialog); + LBMLBTRUTransportDialog * getDialog(void); + void processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info); + void clearMaps(void); + + private: + LBMLBTRUTransportDialog * m_dialog; + LBMLBTRUSourceMap m_sources; + LBMLBTRUReceiverMap m_receivers; +}; + +LBMLBTRUTransportDialogInfo::LBMLBTRUTransportDialogInfo(void) : + m_dialog(NULL), + m_sources(), + m_receivers() +{ +} + +LBMLBTRUTransportDialogInfo::~LBMLBTRUTransportDialogInfo(void) +{ + clearMaps(); +} + +void LBMLBTRUTransportDialogInfo::setDialog(LBMLBTRUTransportDialog * dialog) +{ + m_dialog = dialog; +} + +LBMLBTRUTransportDialog * LBMLBTRUTransportDialogInfo::getDialog(void) +{ + return (m_dialog); +} + +void LBMLBTRUTransportDialogInfo::processPacket(const packet_info * pinfo, const lbm_lbtru_tap_info_t * tap_info) +{ + switch (tap_info->type) + { + case LBTRU_PACKET_TYPE_DATA: + case LBTRU_PACKET_TYPE_SM: + case LBTRU_PACKET_TYPE_NCF: + case LBTRU_PACKET_TYPE_RST: + { + LBMLBTRUSourceEntry * source = NULL; + LBMLBTRUSourceMapIterator it; + QString src_address = QString(address_to_str(wmem_packet_scope(), &(pinfo->src))); + + it = m_sources.find(src_address); + if (m_sources.end() == it) + { + QTreeWidgetItem * parent = NULL; + Ui::LBMLBTRUTransportDialog * ui = NULL; + + source = new LBMLBTRUSourceEntry(src_address); + it = m_sources.insert(src_address, source); + ui = m_dialog->getUI(); + ui->sources_TreeWidget->addTopLevelItem(source); + parent = ui->sources_TreeWidget->invisibleRootItem(); + parent->sortChildren(Source_AddressTransport_Column, Qt::AscendingOrder); + ui->sources_TreeWidget->resizeColumnToContents(Source_AddressTransport_Column); + } + else + { + source = it.value(); + } + source->processPacket(pinfo, tap_info); + } + break; + case LBTRU_PACKET_TYPE_NAK: + case LBTRU_PACKET_TYPE_ACK: + case LBTRU_PACKET_TYPE_CREQ: + { + LBMLBTRUReceiverEntry * receiver = NULL; + LBMLBTRUReceiverMapIterator it; + QString src_address = QString(address_to_str(wmem_packet_scope(), &(pinfo->src))); + + it = m_receivers.find(src_address); + if (m_receivers.end() == it) + { + QTreeWidgetItem * parent = NULL; + Ui::LBMLBTRUTransportDialog * ui = NULL; + + receiver = new LBMLBTRUReceiverEntry(src_address); + it = m_receivers.insert(src_address, receiver); + ui = m_dialog->getUI(); + ui->receivers_TreeWidget->addTopLevelItem(receiver); + parent = ui->receivers_TreeWidget->invisibleRootItem(); + parent->sortChildren(Receiver_AddressTransport_Column, Qt::AscendingOrder); + ui->receivers_TreeWidget->resizeColumnToContents(Receiver_AddressTransport_Column); + } + else + { + receiver = it.value(); + } + receiver->processPacket(pinfo, tap_info); + } + break; + default: + break; + } +} + +void LBMLBTRUTransportDialogInfo::clearMaps(void) +{ + for (LBMLBTRUSourceMapIterator it = m_sources.begin(); it != m_sources.end(); it++) + { + delete *it; + } + m_sources.clear(); + + for (LBMLBTRUReceiverMapIterator it = m_receivers.begin(); it != m_receivers.end(); it++) + { + delete *it; + } + m_receivers.clear(); +} + +LBMLBTRUTransportDialog::LBMLBTRUTransportDialog(QWidget * parent, capture_file * cfile) : + QDialog(parent), + m_ui(new Ui::LBMLBTRUTransportDialog), + m_dialog_info(NULL), + m_capture_file(cfile), + m_current_source_transport(NULL), + m_current_receiver_transport(NULL), + m_source_context_menu(NULL), + m_source_header(NULL) +{ + m_ui->setupUi(this); + + m_dialog_info = new LBMLBTRUTransportDialogInfo(); + m_ui->tabWidget->setCurrentIndex(0); + m_ui->sources_detail_ComboBox->setCurrentIndex(0); + m_ui->sources_detail_transport_Label->setText(QString(" ")); + m_ui->sources_stackedWidget->setCurrentIndex(0); + m_ui->receivers_detail_ComboBox->setCurrentIndex(0); + m_ui->receivers_detail_transport_Label->setText(QString(" ")); + m_ui->receivers_stackedWidget->setCurrentIndex(0); + + // Setup the source context menu + m_source_header = m_ui->sources_TreeWidget->header(); + m_source_context_menu = new QMenu(m_source_header); + + m_source_context_menu->addAction(m_ui->action_SourceAutoResizeColumns); + connect(m_ui->action_SourceAutoResizeColumns, SIGNAL(triggered()), this, SLOT(actionSourceAutoResizeColumns_triggered())); + m_source_context_menu->addSeparator(); + + m_ui->action_SourceDataFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceDataFrames); + connect(m_ui->action_SourceDataFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataFrames_triggered(bool))); + m_ui->action_SourceDataBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceDataBytes); + connect(m_ui->action_SourceDataBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataBytes_triggered(bool))); + m_ui->action_SourceDataFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceDataFramesBytes); + connect(m_ui->action_SourceDataFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataFramesBytes_triggered(bool))); + m_ui->action_SourceDataRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceDataRate); + connect(m_ui->action_SourceDataRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataRate_triggered(bool))); + + m_ui->action_SourceRXDataFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceRXDataFrames); + connect(m_ui->action_SourceRXDataFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataFrames_triggered(bool))); + m_ui->action_SourceRXDataBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceRXDataBytes); + connect(m_ui->action_SourceRXDataBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataBytes_triggered(bool))); + m_ui->action_SourceRXDataFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceRXDataFramesBytes); + connect(m_ui->action_SourceRXDataFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataFramesBytes_triggered(bool))); + m_ui->action_SourceRXDataRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceRXDataRate); + connect(m_ui->action_SourceRXDataRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataRate_triggered(bool))); + + m_ui->action_SourceNCFFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFFrames); + connect(m_ui->action_SourceNCFFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFrames_triggered(bool))); + m_ui->action_SourceNCFCount->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFCount); + connect(m_ui->action_SourceNCFCount, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFCount_triggered(bool))); + m_ui->action_SourceNCFBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFBytes); + connect(m_ui->action_SourceNCFBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFBytes_triggered(bool))); + m_ui->action_SourceNCFFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFFramesBytes); + connect(m_ui->action_SourceNCFFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesBytes_triggered(bool))); + m_ui->action_SourceNCFCountBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFCountBytes); + connect(m_ui->action_SourceNCFCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFCountBytes_triggered(bool))); + m_ui->action_SourceNCFFramesCount->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFFramesCount); + connect(m_ui->action_SourceNCFFramesCount, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesCount_triggered(bool))); + m_ui->action_SourceNCFFramesCountBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceNCFFramesCountBytes); + connect(m_ui->action_SourceNCFFramesCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesCountBytes_triggered(bool))); + m_ui->action_SourceNCFRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceNCFRate); + connect(m_ui->action_SourceNCFRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFRate_triggered(bool))); + + m_ui->action_SourceSMFrames->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceSMFrames); + connect(m_ui->action_SourceSMFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMFrames_triggered(bool))); + m_ui->action_SourceSMBytes->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceSMBytes); + connect(m_ui->action_SourceSMBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMBytes_triggered(bool))); + m_ui->action_SourceSMFramesBytes->setChecked(false); + m_source_context_menu->addAction(m_ui->action_SourceSMFramesBytes); + connect(m_ui->action_SourceSMFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMFramesBytes_triggered(bool))); + m_ui->action_SourceSMRate->setChecked(true); + m_source_context_menu->addAction(m_ui->action_SourceSMRate); + connect(m_ui->action_SourceSMRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMRate_triggered(bool))); + + m_source_header->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_source_header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(custom_source_context_menuRequested(const QPoint &))); + + // Setup the receiver context menu + m_receiver_header = m_ui->receivers_TreeWidget->header(); + m_receiver_context_menu = new QMenu(m_receiver_header); + + m_receiver_context_menu->addAction(m_ui->action_ReceiverAutoResizeColumns); + connect(m_ui->action_ReceiverAutoResizeColumns, SIGNAL(triggered()), this, SLOT(actionReceiverAutoResizeColumns_triggered())); + m_receiver_context_menu->addSeparator(); + + m_ui->action_ReceiverNAKFrames->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKFrames); + connect(m_ui->action_ReceiverNAKFrames, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKFrames_triggered(bool))); + m_ui->action_ReceiverNAKCount->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKCount); + connect(m_ui->action_ReceiverNAKCount, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKCount_triggered(bool))); + m_ui->action_ReceiverNAKBytes->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKBytes); + connect(m_ui->action_ReceiverNAKBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKBytes_triggered(bool))); + m_ui->action_ReceiverNAKFramesBytes->setChecked(false); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKFramesBytes); + connect(m_ui->action_ReceiverNAKFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKFramesBytes_triggered(bool))); + m_ui->action_ReceiverNAKCountBytes->setChecked(false); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKCountBytes); + connect(m_ui->action_ReceiverNAKCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKCountBytes_triggered(bool))); + m_ui->action_ReceiverNAKFramesCount->setChecked(false); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKFramesCount); + connect(m_ui->action_ReceiverNAKFramesCount, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKFramesCount_triggered(bool))); + m_ui->action_ReceiverNAKFramesCountBytes->setChecked(false); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKFramesCountBytes); + connect(m_ui->action_ReceiverNAKFramesCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKFramesCountBytes_triggered(bool))); + m_ui->action_ReceiverNAKRate->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverNAKRate); + connect(m_ui->action_ReceiverNAKRate, SIGNAL(triggered(bool)), this, SLOT(actionReceiverNAKRate_triggered(bool))); + + m_ui->action_ReceiverACKFrames->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverACKFrames); + connect(m_ui->action_ReceiverACKFrames, SIGNAL(triggered(bool)), this, SLOT(actionReceiverACKFrames_triggered(bool))); + m_ui->action_ReceiverACKBytes->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverACKBytes); + connect(m_ui->action_ReceiverACKBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverACKBytes_triggered(bool))); + m_ui->action_ReceiverACKFramesBytes->setChecked(false); + m_receiver_context_menu->addAction(m_ui->action_ReceiverACKFramesBytes); + connect(m_ui->action_ReceiverACKFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverACKFramesBytes_triggered(bool))); + m_ui->action_ReceiverACKRate->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverACKRate); + connect(m_ui->action_ReceiverACKRate, SIGNAL(triggered(bool)), this, SLOT(actionReceiverACKRate_triggered(bool))); + + m_ui->action_ReceiverCREQFrames->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverCREQFrames); + connect(m_ui->action_ReceiverCREQFrames, SIGNAL(triggered(bool)), this, SLOT(actionReceiverCREQFrames_triggered(bool))); + m_ui->action_ReceiverCREQBytes->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverCREQBytes); + connect(m_ui->action_ReceiverCREQBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverCREQBytes_triggered(bool))); + m_ui->action_ReceiverCREQFramesBytes->setChecked(false); + m_receiver_context_menu->addAction(m_ui->action_ReceiverCREQFramesBytes); + connect(m_ui->action_ReceiverCREQFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionReceiverCREQFramesBytes_triggered(bool))); + m_ui->action_ReceiverCREQRate->setChecked(true); + m_receiver_context_menu->addAction(m_ui->action_ReceiverCREQRate); + connect(m_ui->action_ReceiverCREQRate, SIGNAL(triggered(bool)), this, SLOT(actionReceiverCREQRate_triggered(bool))); + + m_receiver_header->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_receiver_header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(custom_receiver_context_menuRequested(const QPoint &))); + + // Setup the source tree widget header + m_ui->sources_TreeWidget->setColumnHidden(Source_DataFramesBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFramesBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCountBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCount_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCountBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_SMFramesBytes_Column, true); + m_ui->sources_TreeWidget->setColumnHidden(Source_RSTFramesBytes_Column, true); + + // Setup the receiver tree widget header + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKFramesBytes_Column, true); + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKCountBytes_Column, true); + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKFramesCount_Column, true); + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKFramesCountBytes_Column, true); + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_ACKFramesBytes_Column, true); + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_CREQFramesBytes_Column, true); + + connect(this, SIGNAL(accepted()), this, SLOT(closeDialog())); + connect(this, SIGNAL(rejected()), this, SLOT(closeDialog())); + fillTree(); +} + +LBMLBTRUTransportDialog::~LBMLBTRUTransportDialog(void) +{ + resetSourcesDetail(); + resetSources(); + resetReceiversDetail(); + resetReceivers(); + if (m_dialog_info != NULL) + { + delete m_dialog_info; + m_dialog_info = NULL; + } + delete m_source_context_menu; + m_source_context_menu = NULL; + delete m_ui; + m_ui = NULL; + m_capture_file = NULL; +} + +void LBMLBTRUTransportDialog::setCaptureFile(capture_file * cfile) +{ + if (cfile == NULL) // We only want to know when the file closes. + { + m_capture_file = NULL; + m_ui->displayFilterLineEdit->setEnabled(false); + m_ui->applyFilterButton->setEnabled(false); + } +} + +void LBMLBTRUTransportDialog::resetSources(void) +{ + while (m_ui->sources_TreeWidget->takeTopLevelItem(0) != NULL) + {} +} + +void LBMLBTRUTransportDialog::resetReceivers(void) +{ + while (m_ui->receivers_TreeWidget->takeTopLevelItem(0) != NULL) + {} +} + +void LBMLBTRUTransportDialog::resetSourcesDetail(void) +{ + while (m_ui->sources_detail_sqn_TreeWidget->takeTopLevelItem(0) != NULL) + {} + while (m_ui->sources_detail_ncf_sqn_TreeWidget->takeTopLevelItem(0) != NULL) + {} + while (m_ui->sources_detail_rst_TreeWidget->takeTopLevelItem(0) != NULL) + {} + m_ui->sources_detail_transport_Label->setText(QString(" ")); + m_current_source_transport = NULL; +} + +void LBMLBTRUTransportDialog::resetReceiversDetail(void) +{ + while (m_ui->receivers_detail_sqn_TreeWidget->takeTopLevelItem(0) != NULL) + {} + while (m_ui->receivers_detail_reason_TreeWidget->takeTopLevelItem(0) != NULL) + {} + m_ui->receivers_detail_transport_Label->setText(QString(" ")); + m_current_receiver_transport = NULL; +} + +void LBMLBTRUTransportDialog::fillTree(void) +{ + GString * error_string; + + if (m_capture_file == NULL) + { + return; + } + m_dialog_info->setDialog(this); + + error_string = register_tap_listener("lbtru", + (void *)m_dialog_info, + m_ui->displayFilterLineEdit->text().toUtf8().constData(), + TL_REQUIRES_COLUMNS, + resetTap, + tapPacket, + drawTreeItems); + if (error_string) + { + QMessageBox::critical(this, tr("LBT-RU Statistics failed to attach to tap"), + error_string->str); + g_string_free(error_string, TRUE); + reject(); + } + + cf_retap_packets(m_capture_file); + drawTreeItems(&m_dialog_info); + remove_tap_listener((void *)m_dialog_info); +} + +void LBMLBTRUTransportDialog::resetTap(void * tap_data) +{ + LBMLBTRUTransportDialogInfo * info = (LBMLBTRUTransportDialogInfo *)tap_data; + LBMLBTRUTransportDialog * dialog = info->getDialog(); + if (dialog == NULL) + { + return; + } + dialog->resetSourcesDetail(); + dialog->resetSources(); + dialog->resetReceiversDetail(); + dialog->resetReceivers(); + info->clearMaps(); +} + +gboolean LBMLBTRUTransportDialog::tapPacket(void * tap_data, packet_info * pinfo, epan_dissect_t * edt, const void * tap_info) +{ + Q_UNUSED(edt) + + if (pinfo->fd->flags.passed_dfilter == 1) + { + const lbm_lbtru_tap_info_t * tapinfo = (const lbm_lbtru_tap_info_t *)tap_info; + LBMLBTRUTransportDialogInfo * info = (LBMLBTRUTransportDialogInfo *)tap_data; + + info->processPacket(pinfo, tapinfo); + } + return (TRUE); +} + +void LBMLBTRUTransportDialog::drawTreeItems(void * tap_data) +{ + Q_UNUSED(tap_data) +} + +void LBMLBTRUTransportDialog::on_applyFilterButton_clicked(void) +{ + fillTree(); +} + +void LBMLBTRUTransportDialog::closeDialog(void) +{ + delete this; +} + +void LBMLBTRUTransportDialog::sourcesDetailCurrentChanged(int index) +{ + // Index 0: Data + // Index 1: RX data + // Index 2: NCF + // Index 3: SM + // Index 4: RST + switch (index) + { + case 0: + case 1: + case 3: + m_ui->sources_stackedWidget->setCurrentIndex(0); + break; + case 2: + m_ui->sources_stackedWidget->setCurrentIndex(2); + break; + case 4: + m_ui->sources_stackedWidget->setCurrentIndex(1); + break; + default: + return; + } + sourcesItemClicked(m_current_source_transport, 0); +} + +void LBMLBTRUTransportDialog::sourcesItemClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRUSourceTransportEntry * transport = dynamic_cast<LBMLBTRUSourceTransportEntry *>(item); + + resetSourcesDetail(); + if (transport == NULL) + { + // Must be a source item, ignore it? + return; + } + m_current_source_transport = transport; + m_ui->sources_detail_transport_Label->setText(transport->m_transport); + int cur_idx = m_ui->sources_detail_ComboBox->currentIndex(); + switch (cur_idx) + { + case 0: + loadSourceDataDetails(transport); + break; + case 1: + loadSourceRXDataDetails(transport); + break; + case 2: + loadSourceNCFDetails(transport); + break; + case 3: + loadSourceSMDetails(transport); + break; + case 4: + loadSourceRSTDetails(transport); + break; + default: + break; + } +} + +void LBMLBTRUTransportDialog::loadSourceDataDetails(LBMLBTRUSourceTransportEntry * transport) +{ + for (LBMLBTRUSQNMapIterator it = transport->m_data_sqns.begin(); it != transport->m_data_sqns.end(); it++) + { + LBMLBTRUSQNEntry * sqn = it.value(); + m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRUTransportDialog::loadSourceRXDataDetails(LBMLBTRUSourceTransportEntry * transport) +{ + for (LBMLBTRUSQNMapIterator it = transport->m_rx_data_sqns.begin(); it != transport->m_rx_data_sqns.end(); it++) + { + LBMLBTRUSQNEntry * sqn = it.value(); + m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRUTransportDialog::loadSourceNCFDetails(LBMLBTRUSourceTransportEntry * transport) +{ + for (LBMLBTRUNCFSQNMapIterator it = transport->m_ncf_sqns.begin(); it != transport->m_ncf_sqns.end(); it++) + { + LBMLBTRUNCFSQNEntry * sqn = it.value(); + m_ui->sources_detail_ncf_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRUTransportDialog::loadSourceSMDetails(LBMLBTRUSourceTransportEntry * transport) +{ + for (LBMLBTRUSQNMapIterator it = transport->m_sm_sqns.begin(); it != transport->m_sm_sqns.end(); it++) + { + LBMLBTRUSQNEntry * sqn = it.value(); + m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRUTransportDialog::loadSourceRSTDetails(LBMLBTRUSourceTransportEntry * transport) +{ + for (LBMLBTRURSTReasonMapIterator it = transport->m_rst_reasons.begin(); it != transport->m_rst_reasons.end(); it++) + { + LBMLBTRURSTReasonEntry * reason = it.value(); + m_ui->sources_detail_rst_TreeWidget->addTopLevelItem(reason); + } +} + +void LBMLBTRUTransportDialog::sourcesDetailItemDoubleClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRUFrameEntry * frame = dynamic_cast<LBMLBTRUFrameEntry *>(item); + if (frame == NULL) + { + // Must have double-clicked on something other than an expanded frame entry + return; + } + emit goToPacket((int)frame->getFrame()); +} + +void LBMLBTRUTransportDialog::receiversDetailCurrentChanged(int index) +{ + // Index 0: NAK + // Index 1: ACK + // Index 2: CREQ + switch (index) + { + case 0: + case 1: + m_ui->receivers_stackedWidget->setCurrentIndex(0); + break; + case 2: + m_ui->receivers_stackedWidget->setCurrentIndex(1); + break; + default: + return; + } + receiversItemClicked(m_current_receiver_transport, 0); +} + +void LBMLBTRUTransportDialog::receiversItemClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRUReceiverTransportEntry * transport = dynamic_cast<LBMLBTRUReceiverTransportEntry *>(item); + + resetReceiversDetail(); + if (transport == NULL) + { + // Must be a receiver item, ignore it? + return; + } + m_current_receiver_transport = transport; + m_ui->receivers_detail_transport_Label->setText(transport->m_transport); + int cur_idx = m_ui->receivers_detail_ComboBox->currentIndex(); + switch (cur_idx) + { + case 0: + loadReceiverNAKDetails(transport); + break; + case 1: + loadReceiverACKDetails(transport); + break; + case 2: + loadReceiverCREQDetails(transport); + break; + default: + break; + } +} + +void LBMLBTRUTransportDialog::loadReceiverNAKDetails(LBMLBTRUReceiverTransportEntry * transport) +{ + for (LBMLBTRUSQNMapIterator it = transport->m_nak_sqns.begin(); it != transport->m_nak_sqns.end(); it++) + { + LBMLBTRUSQNEntry * sqn = it.value(); + m_ui->receivers_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRUTransportDialog::loadReceiverACKDetails(LBMLBTRUReceiverTransportEntry * transport) +{ + for (LBMLBTRUSQNMapIterator it = transport->m_ack_sqns.begin(); it != transport->m_ack_sqns.end(); it++) + { + LBMLBTRUSQNEntry * sqn = it.value(); + m_ui->receivers_detail_sqn_TreeWidget->addTopLevelItem(sqn); + } +} + +void LBMLBTRUTransportDialog::loadReceiverCREQDetails(LBMLBTRUReceiverTransportEntry * transport) +{ + for (LBMLBTRUCREQRequestMapIterator it = transport->m_creq_requests.begin(); it != transport->m_creq_requests.end(); it++) + { + LBMLBTRUCREQRequestEntry * req = it.value(); + m_ui->receivers_detail_reason_TreeWidget->addTopLevelItem(req); + } +} + +void LBMLBTRUTransportDialog::receiversDetailItemDoubleClicked(QTreeWidgetItem * item, int column) +{ + Q_UNUSED(column) + + LBMLBTRUFrameEntry * frame = dynamic_cast<LBMLBTRUFrameEntry *>(item); + if (frame == NULL) + { + // Must have double-clicked on something other than an expanded frame entry + return; + } + emit goToPacket((int)frame->getFrame()); +} + +void LBMLBTRUTransportDialog::custom_source_context_menuRequested(const QPoint & pos) +{ + m_source_context_menu->exec(m_source_header->mapToGlobal(pos)); +} + +void LBMLBTRUTransportDialog::actionSourceDataFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceDataBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceDataFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataFramesBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceDataRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_DataRate_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceRXDataFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceRXDataBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceRXDataFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFramesBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceRXDataRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataRate_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFCount_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCount_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFCountBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCountBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFFramesCount_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCount_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFFramesCountBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCountBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceNCFRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_NCFRate_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceSMFrames_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceSMBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceSMFramesBytes_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMFramesBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceSMRate_triggered(bool checked) +{ + m_ui->sources_TreeWidget->setColumnHidden(Source_SMRate_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionSourceAutoResizeColumns_triggered(void) +{ + m_ui->sources_TreeWidget->resizeColumnToContents(Source_AddressTransport_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataRate_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataRate_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFCount_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFCountBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesCount_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesCountBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFRate_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMRate_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RSTFrames_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RSTBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RSTFramesBytes_Column); + m_ui->sources_TreeWidget->resizeColumnToContents(Source_RSTRate_Column); +} + +void LBMLBTRUTransportDialog::custom_receiver_context_menuRequested(const QPoint & pos) +{ + m_receiver_context_menu->exec(m_receiver_header->mapToGlobal(pos)); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKFrames_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKCount_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKCount_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKFramesCount_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKFramesCount_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKCountBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKCountBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKFramesBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKFramesBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKFramesCountBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKFramesCountBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverNAKRate_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_NAKRate_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverACKFrames_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_ACKFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverACKBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_ACKBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverACKFramesBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_ACKFramesBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverACKRate_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_ACKRate_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverCREQFrames_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_CREQFrames_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverCREQBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_CREQBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverCREQFramesBytes_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_CREQFramesBytes_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverCREQRate_triggered(bool checked) +{ + m_ui->receivers_TreeWidget->setColumnHidden(Receiver_CREQRate_Column, !checked); +} + +void LBMLBTRUTransportDialog::actionReceiverAutoResizeColumns_triggered(void) +{ + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_AddressTransport_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKFrames_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKCount_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKFramesBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKCountBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKFramesCount_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKFramesCountBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_NAKRate_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_ACKFrames_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_ACKBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_ACKFramesBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_ACKRate_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_CREQFrames_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_CREQBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_CREQFramesBytes_Column); + m_ui->receivers_TreeWidget->resizeColumnToContents(Receiver_CREQRate_Column); +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_lbtru_transport_dialog.h b/ui/qt/lbm_lbtru_transport_dialog.h new file mode 100644 index 0000000000..b73e1525a7 --- /dev/null +++ b/ui/qt/lbm_lbtru_transport_dialog.h @@ -0,0 +1,156 @@ +/* lbm_lbtru_transport_dialog.h + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LBM_LBTRU_TRANSPORT_DIALOG_H +#define LBM_LBTRU_TRANSPORT_DIALOG_H + +#include "config.h" + +#include <glib.h> + +#include "cfile.h" +#include <epan/packet_info.h> +#include <QDialog> +#include <QTreeWidgetItem> + +namespace Ui +{ + class LBMLBTRUTransportDialog; +} + +class LBMLBTRUTransportDialogInfo; +class LBMLBTRUSourceTransportEntry; +class LBMLBTRUReceiverTransportEntry; + +class LBMLBTRUTransportDialog : public QDialog +{ + Q_OBJECT + + public: + explicit LBMLBTRUTransportDialog(QWidget * parent = 0, capture_file * cfile = NULL); + Ui::LBMLBTRUTransportDialog * getUI(void) + { + return (m_ui); + } + public slots: + void setCaptureFile(capture_file * cfile); + + signals: + void goToPacket(int packet_num); + + private: + Ui::LBMLBTRUTransportDialog * m_ui; + LBMLBTRUTransportDialogInfo * m_dialog_info; + capture_file * m_capture_file; + LBMLBTRUSourceTransportEntry * m_current_source_transport; + LBMLBTRUReceiverTransportEntry * m_current_receiver_transport; + QMenu * m_source_context_menu; + QHeaderView * m_source_header; + QMenu * m_receiver_context_menu; + QHeaderView * m_receiver_header; + + virtual ~LBMLBTRUTransportDialog(void); + void resetSources(void); + void resetReceivers(void); + void resetSourcesDetail(void); + void resetReceiversDetail(void); + void fillTree(void); + static void resetTap(void * tap_data); + static gboolean tapPacket(void * tap_data, packet_info * pinfo, epan_dissect_t * edt, const void * stream_info); + static void drawTreeItems(void * tap_data); + void loadSourceDataDetails(LBMLBTRUSourceTransportEntry * transport); + void loadSourceRXDataDetails(LBMLBTRUSourceTransportEntry * transport); + void loadSourceNCFDetails(LBMLBTRUSourceTransportEntry * transport); + void loadSourceSMDetails(LBMLBTRUSourceTransportEntry * transport); + void loadSourceRSTDetails(LBMLBTRUSourceTransportEntry * transport); + void loadReceiverNAKDetails(LBMLBTRUReceiverTransportEntry * transport); + void loadReceiverACKDetails(LBMLBTRUReceiverTransportEntry * transport); + void loadReceiverCREQDetails(LBMLBTRUReceiverTransportEntry * transport); + + private slots: + void closeDialog(void); + void on_applyFilterButton_clicked(void); + + void sourcesDetailCurrentChanged(int index); + void sourcesItemClicked(QTreeWidgetItem * item, int column); + void sourcesDetailItemDoubleClicked(QTreeWidgetItem * item, int column); + void receiversDetailCurrentChanged(int index); + void receiversItemClicked(QTreeWidgetItem * item, int column); + void receiversDetailItemDoubleClicked(QTreeWidgetItem * item, int column); + + void custom_source_context_menuRequested(const QPoint & pos); + void actionSourceDataFrames_triggered(bool checked); + void actionSourceDataBytes_triggered(bool checked); + void actionSourceDataFramesBytes_triggered(bool checked); + void actionSourceDataRate_triggered(bool checked); + void actionSourceRXDataFrames_triggered(bool checked); + void actionSourceRXDataBytes_triggered(bool checked); + void actionSourceRXDataFramesBytes_triggered(bool checked); + void actionSourceRXDataRate_triggered(bool checked); + void actionSourceNCFFrames_triggered(bool checked); + void actionSourceNCFCount_triggered(bool checked); + void actionSourceNCFBytes_triggered(bool checked); + void actionSourceNCFFramesBytes_triggered(bool checked); + void actionSourceNCFCountBytes_triggered(bool checked); + void actionSourceNCFFramesCount_triggered(bool checked); + void actionSourceNCFFramesCountBytes_triggered(bool checked); + void actionSourceNCFRate_triggered(bool checked); + void actionSourceSMFrames_triggered(bool checked); + void actionSourceSMBytes_triggered(bool checked); + void actionSourceSMFramesBytes_triggered(bool checked); + void actionSourceSMRate_triggered(bool checked); + void actionSourceAutoResizeColumns_triggered(void); + void custom_receiver_context_menuRequested(const QPoint & pos); + void actionReceiverNAKFrames_triggered(bool checked); + void actionReceiverNAKCount_triggered(bool checked); + void actionReceiverNAKBytes_triggered(bool checked); + void actionReceiverNAKFramesCount_triggered(bool checked); + void actionReceiverNAKCountBytes_triggered(bool checked); + void actionReceiverNAKFramesBytes_triggered(bool checked); + void actionReceiverNAKFramesCountBytes_triggered(bool checked); + void actionReceiverNAKRate_triggered(bool checked); + void actionReceiverACKFrames_triggered(bool checked); + void actionReceiverACKBytes_triggered(bool checked); + void actionReceiverACKFramesBytes_triggered(bool checked); + void actionReceiverACKRate_triggered(bool checked); + void actionReceiverCREQFrames_triggered(bool checked); + void actionReceiverCREQBytes_triggered(bool checked); + void actionReceiverCREQFramesBytes_triggered(bool checked); + void actionReceiverCREQRate_triggered(bool checked); + void actionReceiverAutoResizeColumns_triggered(void); +}; + +#endif + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_lbtru_transport_dialog.ui b/ui/qt/lbm_lbtru_transport_dialog.ui new file mode 100644 index 0000000000..3b2b271152 --- /dev/null +++ b/ui/qt/lbm_lbtru_transport_dialog.ui @@ -0,0 +1,1301 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LBMLBTRUTransportDialog</class> + <widget class="QDialog" name="LBMLBTRUTransportDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>872</width> + <height>667</height> + </rect> + </property> + <property name="windowTitle"> + <string>LBTRU Transport Statistics</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="sourcesTab"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <attribute name="title"> + <string>Sources</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="handleWidth"> + <number>10</number> + </property> + <widget class="QTreeWidget" name="sources_TreeWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <attribute name="headerDefaultSectionSize"> + <number>80</number> + </attribute> + <column> + <property name="text"> + <string>Address/Transport/Client</string> + </property> + </column> + <column> + <property name="text"> + <string>Data frames</string> + </property> + </column> + <column> + <property name="text"> + <string>Data bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>Data frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>Data rate</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data frames</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>RX data rate</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF count</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames/count</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF count/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF frames/count/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NCF rate</string> + </property> + </column> + <column> + <property name="text"> + <string>SM frames</string> + </property> + </column> + <column> + <property name="text"> + <string>SM bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>SM frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>SM rate</string> + </property> + </column> + <column> + <property name="text"> + <string>RST frames</string> + </property> + </column> + <column> + <property name="text"> + <string>RST bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>RST frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>RST rate</string> + </property> + </column> + </widget> + <widget class="QWidget" name="layoutWidget"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Show</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="sources_detail_ComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>120</width> + <height>0</height> + </size> + </property> + <item> + <property name="text"> + <string>Data SQN</string> + </property> + </item> + <item> + <property name="text"> + <string>RX Data SQN</string> + </property> + </item> + <item> + <property name="text"> + <string>NCF SQN</string> + </property> + </item> + <item> + <property name="text"> + <string>SM SQN</string> + </property> + </item> + <item> + <property name="text"> + <string>RST reason</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>details for transport</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="sources_detail_transport_Label"> + <property name="text"> + <string>XXXXX:XXX.XXX.XXX.XXX:XXXXX:XXXXXXXX:XXX.XXX.XXX.XXX:XXXXX</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QStackedWidget" name="sources_stackedWidget"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="lineWidth"> + <number>1</number> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <widget class="QWidget" name="sources_detail_sqn_page"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QTreeWidget" name="sources_detail_sqn_TreeWidget"> + <column> + <property name="text"> + <string>SQN</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="sources_detail_rst_page"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QTreeWidget" name="sources_detail_rst_TreeWidget"> + <column> + <property name="text"> + <string>Reason</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="sources_detail_ncf_sqn_page"> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QTreeWidget" name="sources_detail_ncf_sqn_TreeWidget"> + <column> + <property name="text"> + <string>SQN/Reason</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="receiversTab"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <attribute name="title"> + <string>Receivers</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout_9"> + <item> + <widget class="QSplitter" name="splitter_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="handleWidth"> + <number>10</number> + </property> + <widget class="QTreeWidget" name="receivers_TreeWidget"> + <column> + <property name="text"> + <string>Address/Transport</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK frames</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK count</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK frames/count</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK count/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK frames/count/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>NAK rate</string> + </property> + </column> + <column> + <property name="text"> + <string>ACK frames</string> + </property> + </column> + <column> + <property name="text"> + <string>ACK bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>ACK frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>ACK rate</string> + </property> + </column> + <column> + <property name="text"> + <string>CREQ frames</string> + </property> + </column> + <column> + <property name="text"> + <string>CREQ bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>CREQ frames/bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>CREQ rate</string> + </property> + </column> + </widget> + <widget class="QWidget" name="layoutWidget_2"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Show</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="receivers_detail_ComboBox"> + <property name="minimumSize"> + <size> + <width>130</width> + <height>0</height> + </size> + </property> + <item> + <property name="text"> + <string>NAK SQN</string> + </property> + </item> + <item> + <property name="text"> + <string>ACK SQN</string> + </property> + </item> + <item> + <property name="text"> + <string>CREQ request</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>details for transport</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="receivers_detail_transport_Label"> + <property name="text"> + <string>XXXXX:XXX.XXX.XXX.XXX:XXXXX:XXXXXXXX:XXX.XXX.XXX.XXX:XXXXX</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QStackedWidget" name="receivers_stackedWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <widget class="QWidget" name="receivers_detail_sqn_page"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QTreeWidget" name="receivers_detail_sqn_TreeWidget"> + <column> + <property name="text"> + <string>SQN</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="receivers_detail_reason_page"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <widget class="QTreeWidget" name="receivers_detail_reason_TreeWidget"> + <column> + <property name="text"> + <string>Reason</string> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + </column> + <column> + <property name="text"> + <string>Frame</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Display filter:</string> + </property> + </widget> + </item> + <item> + <widget class="DisplayFilterEdit" name="displayFilterLineEdit"/> + </item> + <item> + <widget class="QPushButton" name="applyFilterButton"> + <property name="toolTip"> + <string>Regenerate statistics using this display filter</string> + </property> + <property name="text"> + <string>Apply</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close|QDialogButtonBox::Help</set> + </property> + </widget> + </item> + </layout> + <action name="actionCopyAsCSV"> + <property name="text"> + <string>Copy as CSV</string> + </property> + <property name="toolTip"> + <string>Copy the tree as CSV</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + </action> + <action name="actionCopyAsYAML"> + <property name="text"> + <string>Copy as YAML</string> + </property> + <property name="toolTip"> + <string>Copy the tree as YAML</string> + </property> + <property name="shortcut"> + <string>Ctrl+Y</string> + </property> + </action> + <action name="action_SourceDataFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data frames</string> + </property> + <property name="toolTip"> + <string>Show the data frames column</string> + </property> + </action> + <action name="action_SourceDataBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data bytes</string> + </property> + <property name="toolTip"> + <string>Show the data bytes column</string> + </property> + </action> + <action name="action_SourceDataFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the data frames/bytes column</string> + </property> + </action> + <action name="action_SourceDataRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Data rate</string> + </property> + <property name="toolTip"> + <string>Show the data rate column</string> + </property> + </action> + <action name="action_SourceRXDataFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data frames</string> + </property> + <property name="toolTip"> + <string>Show the RX data frames column</string> + </property> + </action> + <action name="action_SourceRXDataBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data bytes</string> + </property> + <property name="toolTip"> + <string>Show the RX data bytes column</string> + </property> + </action> + <action name="action_SourceRXDataFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the RX data frames/bytes column</string> + </property> + </action> + <action name="action_SourceRXDataRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RX data rate</string> + </property> + <property name="toolTip"> + <string>Show the RX data rate column</string> + </property> + </action> + <action name="action_SourceNCFFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames</string> + </property> + <property name="toolTip"> + <string>Show the NCF frames column</string> + </property> + </action> + <action name="action_SourceNCFCount"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF count</string> + </property> + <property name="toolTip"> + <string>Show the NCF count column</string> + </property> + </action> + <action name="action_SourceNCFBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF bytes</string> + </property> + <property name="toolTip"> + <string>Show the NCF bytes column</string> + </property> + </action> + <action name="action_SourceNCFFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NCF frames/bytes column</string> + </property> + </action> + <action name="action_SourceNCFCountBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF count/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NCF count/bytes column</string> + </property> + </action> + <action name="action_SourceNCFFramesCount"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames/count</string> + </property> + <property name="toolTip"> + <string>Show the NCF frames/count column</string> + </property> + </action> + <action name="action_SourceNCFFramesCountBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF frames/count/bytes</string> + </property> + <property name="toolTip"> + <string>Sow the NCF frames/count/bytes column</string> + </property> + </action> + <action name="action_SourceSMFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM frames</string> + </property> + <property name="toolTip"> + <string>Show the SM frames column</string> + </property> + </action> + <action name="action_SourceSMBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM bytes</string> + </property> + <property name="toolTip"> + <string>Show the SM bytes column</string> + </property> + </action> + <action name="action_SourceSMFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the SM frames/bytes column</string> + </property> + </action> + <action name="action_SourceSMRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>SM rate</string> + </property> + <property name="toolTip"> + <string>Show the SM rate column</string> + </property> + </action> + <action name="action_SourceRSTFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RST frames</string> + </property> + <property name="toolTip"> + <string>Show the RST frames column</string> + </property> + </action> + <action name="action_SourceRSTBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RST bytes</string> + </property> + <property name="toolTip"> + <string>Show the RST bytes column</string> + </property> + </action> + <action name="action_SourceRSTFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RST frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the RST frames/bytes column</string> + </property> + </action> + <action name="action_SourceRSTRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>RST rate</string> + </property> + <property name="toolTip"> + <string>Show the RST rate column</string> + </property> + </action> + <action name="action_ReceiverNAKFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK frames</string> + </property> + <property name="toolTip"> + <string>Show the NAK frames column</string> + </property> + </action> + <action name="action_ReceiverNAKCount"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK count</string> + </property> + <property name="toolTip"> + <string>Show the NAK count column</string> + </property> + </action> + <action name="action_ReceiverNAKBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK bytes</string> + </property> + <property name="toolTip"> + <string>Show the NAK bytes column</string> + </property> + </action> + <action name="action_ReceiverNAKFramesCount"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK frames/count</string> + </property> + <property name="toolTip"> + <string>Show the NAK frames/count column</string> + </property> + </action> + <action name="action_ReceiverNAKCountBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK count/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NAK count/bytes column</string> + </property> + </action> + <action name="action_ReceiverNAKFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NAK frames/bytes column</string> + </property> + </action> + <action name="action_ReceiverNAKFramesCountBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK frames/count/bytes</string> + </property> + <property name="toolTip"> + <string>Show the NAK frames/count/bytes column</string> + </property> + </action> + <action name="action_ReceiverNAKRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NAK rate</string> + </property> + <property name="toolTip"> + <string>Show the NAK rate column</string> + </property> + </action> + <action name="action_ReceiverACKFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>ACK frames</string> + </property> + <property name="toolTip"> + <string>Show the ACK frames column</string> + </property> + </action> + <action name="action_ReceiverACKBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>ACK bytes</string> + </property> + <property name="toolTip"> + <string>Show the ACK bytes column</string> + </property> + </action> + <action name="action_ReceiverACKFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>ACK frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the ACK frames/bytes column</string> + </property> + </action> + <action name="action_ReceiverACKRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>ACK rate</string> + </property> + <property name="toolTip"> + <string>Show the ACK rate column</string> + </property> + </action> + <action name="action_ReceiverCREQFrames"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>CREQ frames</string> + </property> + <property name="toolTip"> + <string>Show the CREQ frames column</string> + </property> + </action> + <action name="action_ReceiverCREQBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>CREQ bytes</string> + </property> + <property name="toolTip"> + <string>Show the CREQ bytes column</string> + </property> + </action> + <action name="action_ReceiverCREQFramesBytes"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>CREQ frames/bytes</string> + </property> + <property name="toolTip"> + <string>Show the CREQ frames/bytes column</string> + </property> + </action> + <action name="action_ReceiverCREQRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>CREQ rate</string> + </property> + <property name="toolTip"> + <string>Show the CREQ rate column</string> + </property> + </action> + <action name="action_SourceAutoResizeColumns"> + <property name="text"> + <string>Auto-resize columns to content</string> + </property> + <property name="toolTip"> + <string>Resize columns to content size</string> + </property> + </action> + <action name="action_ReceiverAutoResizeColumns"> + <property name="text"> + <string>Auto-resize columns to content</string> + </property> + <property name="toolTip"> + <string>Resize columns to content size</string> + </property> + </action> + <action name="action_SourceNCFRate"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>NCF rate</string> + </property> + <property name="toolTip"> + <string>Show the NCF rate column</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>DisplayFilterEdit</class> + <extends>QLineEdit</extends> + <header location="global">display_filter_edit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>262</x> + <y>659</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>330</x> + <y>659</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_detail_ComboBox</sender> + <signal>currentIndexChanged(int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>sourcesDetailCurrentChanged(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>175</x> + <y>315</y> + </hint> + <hint type="destinationlabel"> + <x>446</x> + <y>310</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_TreeWidget</sender> + <signal>itemClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>sourcesItemClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>440</x> + <y>149</y> + </hint> + <hint type="destinationlabel"> + <x>446</x> + <y>310</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_detail_sqn_TreeWidget</sender> + <signal>itemDoubleClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>sourcesDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>109</x> + <y>344</y> + </hint> + <hint type="destinationlabel"> + <x>420</x> + <y>281</y> + </hint> + </hints> + </connection> + <connection> + <sender>sources_detail_ncf_sqn_TreeWidget</sender> + <signal>itemDoubleClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>sourcesDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>83</x> + <y>344</y> + </hint> + <hint type="destinationlabel"> + <x>420</x> + <y>281</y> + </hint> + </hints> + </connection> + <connection> + <sender>receivers_TreeWidget</sender> + <signal>itemClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>receiversItemClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>420</x> + <y>141</y> + </hint> + <hint type="destinationlabel"> + <x>420</x> + <y>281</y> + </hint> + </hints> + </connection> + <connection> + <sender>receivers_detail_ComboBox</sender> + <signal>currentIndexChanged(int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>receiversDetailCurrentChanged(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>124</x> + <y>315</y> + </hint> + <hint type="destinationlabel"> + <x>155</x> + <y>-8</y> + </hint> + </hints> + </connection> + <connection> + <sender>receivers_detail_sqn_TreeWidget</sender> + <signal>itemDoubleClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>receiversDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>435</x> + <y>452</y> + </hint> + <hint type="destinationlabel"> + <x>435</x> + <y>333</y> + </hint> + </hints> + </connection> + <connection> + <sender>receivers_detail_reason_TreeWidget</sender> + <signal>itemDoubleClicked(QTreeWidgetItem*,int)</signal> + <receiver>LBMLBTRUTransportDialog</receiver> + <slot>receiversDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <hints> + <hint type="sourcelabel"> + <x>66</x> + <y>336</y> + </hint> + <hint type="destinationlabel"> + <x>435</x> + <y>333</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <signal>goToPacket(int)</signal> + <slot>sourcesDetailCurrentChanged(int)</slot> + <slot>sourcesItemClicked(QTreeWidgetItem*,int)</slot> + <slot>receiversItemClicked(QTreeWidgetItem*,int)</slot> + <slot>sourcesDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <slot>receiversDetailItemDoubleClicked(QTreeWidgetItem*,int)</slot> + <slot>receiversDetailCurrentChanged(int)</slot> + </slots> +</ui> diff --git a/ui/qt/lbm_stream_dialog.cpp b/ui/qt/lbm_stream_dialog.cpp new file mode 100644 index 0000000000..ceba6fe39a --- /dev/null +++ b/ui/qt/lbm_stream_dialog.cpp @@ -0,0 +1,455 @@ +/* lbm_stream_dialog.cpp + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +// Adapted from stats_tree_packet.cpp + +#include "lbm_stream_dialog.h" +#include "ui_lbm_stream_dialog.h" + +#include "file.h" + +#include "wireshark_application.h" + +#include <QClipboard> +#include <QMessageBox> +#include <QTreeWidget> +#include <QTreeWidgetItemIterator> +#include <epan/packet_info.h> +#include <epan/wmem/wmem.h> +#include <epan/to_str.h> +#include <epan/tap.h> +#include <epan/dissectors/packet-lbm.h> + +#include <QDebug> + +namespace +{ + static const int Stream_Column = 0; + static const int EndpointA_Column = 1; + static const int EndpointB_Column = 2; + static const int Messages_Column = 3; + static const int Bytes_Column = 4; + static const int FirstFrame_Column = 5; + static const int LastFrame_Column = 6; +} + +class LBMSubstreamEntry +{ + public: + LBMSubstreamEntry(guint64 channel, guint32 substream_id, const address * source_address, guint16 source_port, const address * destination_address, guint16 destination_port); + ~LBMSubstreamEntry(void); + void processPacket(guint32 frame, guint32 bytes); + void setItem(QTreeWidgetItem * item); + QTreeWidgetItem * getItem(void) + { + return (m_item); + } + + private: + LBMSubstreamEntry(void) { } + void fillItem(gboolean update_only = TRUE); + guint64 m_channel; + guint32 m_substream_id; + QString m_endpoint_a; + QString m_endpoint_b; + guint32 m_first_frame; + guint32 m_flast_frame; + guint32 m_messages; + guint32 m_bytes; + QTreeWidgetItem * m_item; +}; + +LBMSubstreamEntry::LBMSubstreamEntry(guint64 channel, guint32 substream_id, const address * source_address, guint16 source_port, const address * destination_address, guint16 destination_port) : + m_channel(channel), + m_substream_id(substream_id), + m_first_frame((guint32)(~0)), + m_flast_frame(0), + m_messages(0), + m_bytes(0), + m_item(NULL) +{ + m_endpoint_a = QString("%1:%2") + .arg(address_to_str(wmem_packet_scope(), source_address)) + .arg(source_port); + m_endpoint_b = QString("%1:%2") + .arg(address_to_str(wmem_packet_scope(), destination_address)) + .arg(destination_port); +} + +LBMSubstreamEntry::~LBMSubstreamEntry(void) +{ +} + +void LBMSubstreamEntry::processPacket(guint32 frame, guint32 bytes) +{ + if (m_first_frame > frame) + { + m_first_frame = frame; + } + if (m_flast_frame < frame) + { + m_flast_frame = frame; + } + m_bytes += bytes; + m_messages++; + fillItem(); +} + +void LBMSubstreamEntry::setItem(QTreeWidgetItem * item) +{ + m_item = item; + fillItem(FALSE); +} + +void LBMSubstreamEntry::fillItem(gboolean update_only) +{ + if (update_only == FALSE) + { + m_item->setText(Stream_Column, QString("%1.%2").arg(m_channel).arg(m_substream_id)); + m_item->setText(EndpointA_Column, m_endpoint_a); + m_item->setText(EndpointB_Column, m_endpoint_b); + } + m_item->setText(Messages_Column, QString("%1").arg(m_messages)); + m_item->setText(Bytes_Column, QString("%1").arg(m_bytes)); + m_item->setText(FirstFrame_Column, QString("%1").arg(m_first_frame)); + m_item->setText(LastFrame_Column, QString("%1").arg(m_flast_frame)); +} + +typedef QMap<guint32, LBMSubstreamEntry *> LBMSubstreamMap; +typedef QMap<guint32, LBMSubstreamEntry *>::iterator LBMSubstreamMapIterator; + +class LBMStreamEntry +{ + public: + LBMStreamEntry(guint64 channel, const lbm_uim_stream_endpoint_t * endpoint_a, const lbm_uim_stream_endpoint_t * endpoint_b); + ~LBMStreamEntry(void); + void processPacket(const packet_info * pinfo, const lbm_uim_stream_tap_info_t * stream_info); + void setItem(QTreeWidgetItem * item); + QTreeWidgetItem * getItem(void) + { + return (m_item); + } + + private: + LBMStreamEntry(void) { } + void fillItem(gboolean update_only = TRUE); + QString formatEndpoint(const lbm_uim_stream_endpoint_t * endpoint); + guint64 m_channel; + QString m_endpoint_a; + QString m_endpoint_b; + guint32 m_first_frame; + guint32 m_flast_frame; + guint32 m_messages; + guint32 m_bytes; + QTreeWidgetItem * m_item; + LBMSubstreamMap m_substreams; +}; + +LBMStreamEntry::LBMStreamEntry(guint64 channel, const lbm_uim_stream_endpoint_t * endpoint_a, const lbm_uim_stream_endpoint_t * endpoint_b) : + m_channel(channel), + m_first_frame((guint32)(~0)), + m_flast_frame(0), + m_messages(0), + m_bytes(0), + m_item(NULL), + m_substreams() +{ + m_endpoint_a = formatEndpoint(endpoint_a); + m_endpoint_b = formatEndpoint(endpoint_b); +} + +LBMStreamEntry::~LBMStreamEntry(void) +{ + LBMSubstreamMapIterator it; + + for (it = m_substreams.begin(); it != m_substreams.end(); it++) + { + delete *it; + } + m_substreams.clear(); +} + +QString LBMStreamEntry::formatEndpoint(const lbm_uim_stream_endpoint_t * endpoint) +{ + if (endpoint->type == lbm_uim_instance_stream) + { + return QString(bytes_to_ep_str(endpoint->stream_info.ctxinst.ctxinst, sizeof(endpoint->stream_info.ctxinst.ctxinst))); + } + else + { + return QString("%1:%2:%3") + .arg(endpoint->stream_info.dest.domain) + .arg(address_to_str(wmem_packet_scope(), &(endpoint->stream_info.dest.addr))) + .arg(endpoint->stream_info.dest.port); + } +} + +void LBMStreamEntry::processPacket(const packet_info * pinfo, const lbm_uim_stream_tap_info_t * stream_info) +{ + LBMSubstreamEntry * substream = NULL; + LBMSubstreamMapIterator it; + + if (m_first_frame > pinfo->fd->num) + { + m_first_frame = pinfo->fd->num; + } + if (m_flast_frame < pinfo->fd->num) + { + m_flast_frame = pinfo->fd->num; + } + m_bytes += stream_info->bytes; + m_messages++; + it = m_substreams.find(stream_info->substream_id); + if (m_substreams.end() == it) + { + QTreeWidgetItem * item = NULL; + + substream = new LBMSubstreamEntry(m_channel, stream_info->substream_id, &(pinfo->src), pinfo->srcport, &(pinfo->dst), pinfo->destport); + m_substreams.insert(stream_info->substream_id, substream); + item = new QTreeWidgetItem(); + substream->setItem(item); + m_item->addChild(item); + m_item->sortChildren(Stream_Column, Qt::AscendingOrder); + } + else + { + substream = it.value(); + } + fillItem(); + substream->processPacket(pinfo->fd->num, stream_info->bytes); +} + +void LBMStreamEntry::setItem(QTreeWidgetItem * item) +{ + m_item = item; + fillItem(FALSE); +} + +void LBMStreamEntry::fillItem(gboolean update_only) +{ + if (update_only == FALSE) + { + m_item->setData(Stream_Column, Qt::DisplayRole, QVariant((qulonglong)m_channel)); + m_item->setText(EndpointA_Column, m_endpoint_a); + m_item->setText(EndpointB_Column, m_endpoint_b); + } + m_item->setText(Messages_Column, QString("%1").arg(m_messages)); + m_item->setText(Bytes_Column, QString("%1").arg(m_bytes)); + m_item->setText(FirstFrame_Column, QString("%1").arg(m_first_frame)); + m_item->setText(LastFrame_Column, QString("%1").arg(m_flast_frame)); +} + +typedef QMap<guint64, LBMStreamEntry *> LBMStreamMap; +typedef QMap<guint64, LBMStreamEntry *>::iterator LBMStreamMapIterator; + +class LBMStreamDialogInfo +{ + public: + LBMStreamDialogInfo(void); + ~LBMStreamDialogInfo(void); + void setDialog(LBMStreamDialog * dialog); + LBMStreamDialog * getDialog(void); + void processPacket(const packet_info * pinfo, const lbm_uim_stream_tap_info_t * stream_info); + void resetStreams(void); + + private: + LBMStreamDialog * m_dialog; + LBMStreamMap m_streams; +}; + +LBMStreamDialogInfo::LBMStreamDialogInfo(void) : + m_dialog(NULL), + m_streams() +{ +} + +LBMStreamDialogInfo::~LBMStreamDialogInfo(void) +{ + resetStreams(); +} + +void LBMStreamDialogInfo::setDialog(LBMStreamDialog * dialog) +{ + m_dialog = dialog; +} + +LBMStreamDialog * LBMStreamDialogInfo::getDialog(void) +{ + return (m_dialog); +} + +void LBMStreamDialogInfo::processPacket(const packet_info * pinfo, const lbm_uim_stream_tap_info_t * stream_info) +{ + LBMStreamEntry * stream = NULL; + LBMStreamMapIterator it; + + it = m_streams.find(stream_info->channel); + if (m_streams.end() == it) + { + QTreeWidgetItem * item = NULL; + QTreeWidgetItem * parent = NULL; + Ui::LBMStreamDialog * ui = NULL; + + stream = new LBMStreamEntry(stream_info->channel, &(stream_info->endpoint_a), &(stream_info->endpoint_b)); + it = m_streams.insert(stream_info->channel, stream); + item = new QTreeWidgetItem(); + stream->setItem(item); + ui = m_dialog->getUI(); + ui->lbm_stream_TreeWidget->addTopLevelItem(item); + parent = ui->lbm_stream_TreeWidget->invisibleRootItem(); + parent->sortChildren(Stream_Column, Qt::AscendingOrder); + } + else + { + stream = it.value(); + } + stream->processPacket(pinfo, stream_info); +} + +void LBMStreamDialogInfo::resetStreams(void) +{ + LBMStreamMapIterator it = m_streams.begin(); + + while (it != m_streams.end()) + { + delete *it; + it++; + } + m_streams.clear(); +} + +LBMStreamDialog::LBMStreamDialog(QWidget * parent, capture_file * cfile) : + QDialog(parent), + m_ui(new Ui::LBMStreamDialog), + m_dialog_info(NULL), + m_capture_file(cfile) +{ + m_ui->setupUi(this); + m_dialog_info = new LBMStreamDialogInfo(); + connect(this, SIGNAL(accepted()), this, SLOT(closeDialog())); + connect(this, SIGNAL(rejected()), this, SLOT(closeDialog())); + fillTree(); +} + +LBMStreamDialog::~LBMStreamDialog(void) +{ + delete m_ui; + if (m_dialog_info != NULL) + { + delete m_dialog_info; + } +} + +void LBMStreamDialog::setCaptureFile(capture_file * cfile) +{ + if (cfile == NULL) // We only want to know when the file closes. + { + m_capture_file = NULL; + m_ui->displayFilterLineEdit->setEnabled(false); + m_ui->applyFilterButton->setEnabled(false); + } +} + +void LBMStreamDialog::fillTree(void) +{ + GString * error_string; + + if (m_capture_file == NULL) + { + return; + } + m_dialog_info->setDialog(this); + + error_string = register_tap_listener("lbm_stream", + (void *)m_dialog_info, + m_ui->displayFilterLineEdit->text().toUtf8().constData(), + TL_REQUIRES_COLUMNS, + resetTap, + tapPacket, + drawTreeItems); + if (error_string) + { + QMessageBox::critical(this, tr("LBM Stream failed to attach to tap"), + error_string->str); + g_string_free(error_string, TRUE); + reject(); + } + + cf_retap_packets(m_capture_file); + drawTreeItems(&m_dialog_info); + remove_tap_listener((void *)m_dialog_info); +} + +void LBMStreamDialog::resetTap(void * tap_data) +{ + LBMStreamDialogInfo * info = (LBMStreamDialogInfo *)tap_data; + LBMStreamDialog * dialog = info->getDialog(); + if (dialog == NULL) + { + return; + } + info->resetStreams(); + dialog->m_ui->lbm_stream_TreeWidget->clear(); +} + +gboolean LBMStreamDialog::tapPacket(void * tap_data, packet_info * pinfo, epan_dissect_t * edt, const void * stream_info) +{ + Q_UNUSED(edt) + + if (pinfo->fd->flags.passed_dfilter == 1) + { + const lbm_uim_stream_tap_info_t * tapinfo = (const lbm_uim_stream_tap_info_t *)stream_info; + LBMStreamDialogInfo * info = (LBMStreamDialogInfo *)tap_data; + + info->processPacket(pinfo, tapinfo); + } + return (TRUE); +} + +void LBMStreamDialog::drawTreeItems(void * tap_data) +{ + Q_UNUSED(tap_data) +} + +void LBMStreamDialog::on_applyFilterButton_clicked(void) +{ + fillTree(); +} + +void LBMStreamDialog::closeDialog(void) +{ + delete this; +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_stream_dialog.h b/ui/qt/lbm_stream_dialog.h new file mode 100644 index 0000000000..6399c0c7a3 --- /dev/null +++ b/ui/qt/lbm_stream_dialog.h @@ -0,0 +1,85 @@ +/* lbm_stream_dialog.h + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LBM_STREAM_DIALOG_H +#define LBM_STREAM_DIALOG_H + +#include "config.h" + +#include <glib.h> + +#include "cfile.h" +#include <epan/packet_info.h> +#include <QDialog> + +namespace Ui +{ + class LBMStreamDialog; +} + +class LBMStreamDialogInfo; + +class LBMStreamDialog : public QDialog +{ + Q_OBJECT + + public: + explicit LBMStreamDialog(QWidget * parent = 0, capture_file * cfile = NULL); + ~LBMStreamDialog(void); + Ui::LBMStreamDialog * getUI(void) + { + return (m_ui); + } + + public slots: + void setCaptureFile(capture_file * cfile); + + private: + Ui::LBMStreamDialog * m_ui; + LBMStreamDialogInfo * m_dialog_info; + capture_file * m_capture_file; + + void fillTree(void); + static void resetTap(void * tap_data); + static gboolean tapPacket(void * tap_data, packet_info * pinfo, epan_dissect_t * edt, const void * stream_info); + static void drawTreeItems(void * tap_data); + + private slots: + void closeDialog(void); + void on_applyFilterButton_clicked(void); +}; + +#endif + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_stream_dialog.ui b/ui/qt/lbm_stream_dialog.ui new file mode 100644 index 0000000000..2f7f16086d --- /dev/null +++ b/ui/qt/lbm_stream_dialog.ui @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LBMStreamDialog</class> + <widget class="QDialog" name="LBMStreamDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>652</width> + <height>459</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTreeWidget" name="lbm_stream_TreeWidget"> + <column> + <property name="text"> + <string>Stream</string> + </property> + </column> + <column> + <property name="text"> + <string>Endpoint A</string> + </property> + </column> + <column> + <property name="text"> + <string>Endpoint B</string> + </property> + </column> + <column> + <property name="text"> + <string>Messages</string> + </property> + <property name="textAlignment"> + <set>AlignLeft|AlignVCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Bytes</string> + </property> + </column> + <column> + <property name="text"> + <string>First Frame</string> + </property> + </column> + <column> + <property name="text"> + <string>Last Frame</string> + </property> + </column> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Display filter:</string> + </property> + </widget> + </item> + <item> + <widget class="DisplayFilterEdit" name="displayFilterLineEdit"/> + </item> + <item> + <widget class="QPushButton" name="applyFilterButton"> + <property name="toolTip"> + <string>Regenerate statistics using this display filter</string> + </property> + <property name="text"> + <string>Apply</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close|QDialogButtonBox::Help</set> + </property> + </widget> + </item> + </layout> + <action name="actionCopyAsCSV"> + <property name="text"> + <string>Copy as CSV</string> + </property> + <property name="toolTip"> + <string>Copy the tree as CSV</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + </action> + <action name="actionCopyAsYAML"> + <property name="text"> + <string>Copy as YAML</string> + </property> + <property name="toolTip"> + <string>Copy the tree as YAML</string> + </property> + <property name="shortcut"> + <string>Ctrl+Y</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>DisplayFilterEdit</class> + <extends>QLineEdit</extends> + <header location="global">display_filter_edit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>LBMStreamDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>LBMStreamDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/ui/qt/lbm_uimflow_dialog.cpp b/ui/qt/lbm_uimflow_dialog.cpp new file mode 100644 index 0000000000..faff6d8a26 --- /dev/null +++ b/ui/qt/lbm_uimflow_dialog.cpp @@ -0,0 +1,668 @@ +/* lbm_uimflow_dialog.cpp + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +// Adapted from sequence_dialog.cpp + +#include "lbm_uimflow_dialog.h" +#include "ui_lbm_uimflow_dialog.h" +#include <epan/dissectors/packet-lbm.h> +#include <epan/packet_info.h> +#include <epan/tap.h> +#include <epan/to_str.h> +#include <epan/addr_resolv.h> +#include <wsutil/nstime.h> + +#include "wireshark_application.h" + +#include <QDir> +#include <QFileDialog> +#include <QFontMetrics> +#include <QPoint> + +#include <QDebug> + +static gboolean lbm_uimflow_add_to_graph(seq_analysis_info_t * seq_info, packet_info * pinfo, const lbm_uim_stream_info_t * stream_info) +{ + lbm_uim_stream_endpoint_t epa; + lbm_uim_stream_endpoint_t epb; + seq_analysis_item_t * item; + gchar * ctxinst1 = NULL; + gchar * ctxinst2 = NULL; + gboolean swap_endpoints = FALSE; + int rc; + + if (stream_info->endpoint_a.type != stream_info->endpoint_b.type) + { + return (FALSE); + } + if (stream_info->endpoint_a.type == lbm_uim_instance_stream) + { + rc = memcmp((void *)stream_info->endpoint_a.stream_info.ctxinst.ctxinst, + (void *)stream_info->endpoint_b.stream_info.ctxinst.ctxinst, + LBM_CONTEXT_INSTANCE_BLOCK_SZ); + if (rc <= 0) + { + swap_endpoints = FALSE; + } + else + { + swap_endpoints = TRUE; + } + } + else + { + if (stream_info->endpoint_a.stream_info.dest.domain < stream_info->endpoint_b.stream_info.dest.domain) + { + swap_endpoints = FALSE; + } + else if (stream_info->endpoint_a.stream_info.dest.domain > stream_info->endpoint_b.stream_info.dest.domain) + { + swap_endpoints = TRUE; + } + else + { + int compare; + + compare = CMP_ADDRESS(&(stream_info->endpoint_a.stream_info.dest.addr), &(stream_info->endpoint_b.stream_info.dest.addr)); + if (compare < 0) + { + swap_endpoints = FALSE; + } + else if (compare > 0) + { + swap_endpoints = TRUE; + } + else + { + if (stream_info->endpoint_a.stream_info.dest.port <= stream_info->endpoint_b.stream_info.dest.port) + { + swap_endpoints = FALSE; + } + else + { + swap_endpoints = TRUE; + } + } + } + } + if (swap_endpoints == FALSE) + { + epa = stream_info->endpoint_a; + epb = stream_info->endpoint_b; + } + else + { + epb = stream_info->endpoint_a; + epa = stream_info->endpoint_b; + } + item = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t)); + COPY_ADDRESS(&(item->src_addr), &(pinfo->src)); + COPY_ADDRESS(&(item->dst_addr), &(pinfo->dst)); + item->fd = pinfo->fd; + item->port_src = pinfo->srcport; + item->port_dst = pinfo->destport; + if (stream_info->description == NULL) + { + item->frame_label = g_strdup_printf("(%" G_GUINT32_FORMAT ")", stream_info->sqn); + } + else + { + item->frame_label = g_strdup_printf("%s (%" G_GUINT32_FORMAT ")", stream_info->description, stream_info->sqn); + } + if (epa.type == lbm_uim_instance_stream) + { + ctxinst1 = bytes_to_ep_str(epa.stream_info.ctxinst.ctxinst, sizeof(epa.stream_info.ctxinst.ctxinst)); + ctxinst2 = bytes_to_ep_str(epb.stream_info.ctxinst.ctxinst, sizeof(epb.stream_info.ctxinst.ctxinst)); + item->comment = g_strdup_printf("%s <-> %s [%" G_GUINT64_FORMAT "]", + ctxinst1, + ctxinst2, + stream_info->channel); + } + else + { + item->comment = g_strdup_printf("%" G_GUINT32_FORMAT ":%s:%" G_GUINT16_FORMAT " <-> %" G_GUINT32_FORMAT ":%s:%" G_GUINT16_FORMAT " [%" G_GUINT64_FORMAT "]", + epa.stream_info.dest.domain, + address_to_str(wmem_packet_scope(), &(epa.stream_info.dest.addr)), + epa.stream_info.dest.port, + epb.stream_info.dest.domain, + address_to_str(wmem_packet_scope(), &(epb.stream_info.dest.addr)), + epb.stream_info.dest.port, + stream_info->channel); + } + item->conv_num = (guint16)LBM_CHANNEL_ID(stream_info->channel); + item->display = TRUE; + item->line_style = 1; + seq_info->list = g_list_prepend(seq_info->list, (gpointer)item); + return (TRUE); +} + +static gboolean lbm_uimflow_tap_packet(void * tap_data, packet_info * pinfo, epan_dissect_t * edt _U_, const void * stream_info) +{ + Q_UNUSED(edt) + + seq_analysis_info_t * sainfo = (seq_analysis_info_t *)tap_data; + const lbm_uim_stream_info_t * info = (const lbm_uim_stream_info_t *)stream_info; + + if ((sainfo->all_packets) || (pinfo->fd->flags.passed_dfilter == 1)) + { + gboolean rc = lbm_uimflow_add_to_graph(sainfo, pinfo, info); + return (rc); + } + return (FALSE); +} + +static void lbm_uimflow_get_analysis(capture_file * cfile, seq_analysis_info_t * seq_info) +{ + GList * list = NULL; + gchar time_str[COL_MAX_LEN]; + + register_tap_listener("lbm_uim", (void *)seq_info, NULL, TL_REQUIRES_COLUMNS, NULL, lbm_uimflow_tap_packet, NULL); + cf_retap_packets(cfile); + seq_info->list = g_list_reverse(seq_info->list); + remove_tap_listener((void *)seq_info); + + /* Fill in the timestamps. */ + list = g_list_first(seq_info->list); + while (list != NULL) + { + seq_analysis_item_t * seq_item = (seq_analysis_item_t *)list->data; + set_fd_time(cfile->epan, seq_item->fd, time_str); + seq_item->time_str = g_strdup(time_str); + list = g_list_next(list); + } +} + +// To do: +// - Add UTF8 to text dump +// - Save to XMI? http://www.umlgraph.org/ +// - Time: abs vs delta +// - Hide nodes +// - Clickable time + comments? +// - Incorporate packet comments? +// - Change line_style to seq_type (i.e. draw ACKs dashed) +// - Create WSGraph subclasses with common behavior. +// - Help button and text + +LBMUIMFlowDialog::LBMUIMFlowDialog(QWidget * parent, capture_file * cfile) : + QDialog(parent), + m_ui(new Ui::LBMUIMFlowDialog), + m_capture_file(cfile), + m_num_items(0), + m_packet_num(0), + m_node_label_width(20) +{ + m_ui->setupUi(this); + QCustomPlot * sp = m_ui->sequencePlot; + + m_sequence_diagram = new SequenceDiagram(sp->yAxis, sp->xAxis2, sp->yAxis2); + sp->addPlottable(m_sequence_diagram); + sp->axisRect()->setRangeDragAxes(sp->xAxis2, sp->yAxis); + + sp->xAxis->setVisible(false); + sp->xAxis->setPadding(0); + sp->xAxis->setLabelPadding(0); + sp->xAxis->setTickLabelPadding(0); + sp->xAxis2->setVisible(true); + sp->yAxis2->setVisible(true); + + m_one_em = QFontMetrics(sp->yAxis->labelFont()).height(); + m_ui->horizontalScrollBar->setSingleStep(100 / m_one_em); + m_ui->verticalScrollBar->setSingleStep(100 / m_one_em); + + sp->setInteractions(QCP::iRangeDrag); + + m_ui->gridLayout->setSpacing(0); + connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), sp->yAxis2, SLOT(setRange(QCPRange))); + + m_context_menu.addAction(m_ui->actionReset); + m_context_menu.addSeparator(); + m_context_menu.addAction(m_ui->actionMoveRight10); + m_context_menu.addAction(m_ui->actionMoveLeft10); + m_context_menu.addAction(m_ui->actionMoveUp10); + m_context_menu.addAction(m_ui->actionMoveDown10); + m_context_menu.addAction(m_ui->actionMoveRight1); + m_context_menu.addAction(m_ui->actionMoveLeft1); + m_context_menu.addAction(m_ui->actionMoveUp1); + m_context_menu.addAction(m_ui->actionMoveDown1); + m_context_menu.addSeparator(); + m_context_menu.addAction(m_ui->actionGoToPacket); + + memset(&m_sequence_analysis, 0, sizeof(m_sequence_analysis)); + + m_ui->showComboBox->blockSignals(true); + m_ui->showComboBox->setCurrentIndex(0); + m_ui->showComboBox->blockSignals(false); + m_sequence_analysis.all_packets = TRUE; + m_sequence_analysis.any_addr = TRUE; + + QPushButton * save_bt = m_ui->buttonBox->button(QDialogButtonBox::Save); + save_bt->setText(tr("Save As...")); + + // XXX Use recent settings instead + if (parent) + { + resize(parent->width(), parent->height() * 4 / 5); + } + + connect(m_ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(hScrollBarChanged(int))); + connect(m_ui->verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(vScrollBarChanged(int))); + connect(sp->xAxis2, SIGNAL(rangeChanged(QCPRange)), this, SLOT(xAxisChanged(QCPRange))); + connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(yAxisChanged(QCPRange))); + connect(sp, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(diagramClicked(QMouseEvent*))); + connect(sp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*))); + connect(sp, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseReleased(QMouseEvent*))); + connect(this, SIGNAL(goToPacket(int)), m_sequence_diagram, SLOT(setSelectedPacket(int))); + + disconnect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + + fillDiagram(); +} + +LBMUIMFlowDialog::~LBMUIMFlowDialog(void) +{ + delete m_ui; +} + +void LBMUIMFlowDialog::setCaptureFile(capture_file * cfile) +{ + if (cfile == NULL) // We only want to know when the file closes. + { + m_capture_file = NULL; + } +} + +void LBMUIMFlowDialog::showEvent(QShowEvent * event) +{ + Q_UNUSED(event); + resetAxes(); +} + +void LBMUIMFlowDialog::resizeEvent(QResizeEvent * event) +{ + Q_UNUSED(event); + resetAxes(true); +} + +void LBMUIMFlowDialog::keyPressEvent(QKeyEvent * event) +{ + int pan_pixels = (event->modifiers() & Qt::ShiftModifier) ? 1 : 10; + + // XXX - Copy some shortcuts from tcp_stream_dialog.cpp + switch (event->key()) + { + case Qt::Key_Right: + case Qt::Key_L: + panAxes(pan_pixels, 0); + break; + case Qt::Key_Left: + case Qt::Key_H: + panAxes(-1 * pan_pixels, 0); + break; + case Qt::Key_Up: + case Qt::Key_K: + panAxes(0, -1 * pan_pixels); + break; + case Qt::Key_Down: + case Qt::Key_J: + panAxes(0, pan_pixels); + break; + case Qt::Key_0: + case Qt::Key_ParenRight: // Shifted 0 on U.S. keyboards + case Qt::Key_R: + case Qt::Key_Home: + resetAxes(); + break; + case Qt::Key_G: + on_actionGoToPacket_triggered(); + break; + } + + QDialog::keyPressEvent(event); +} + +void LBMUIMFlowDialog::mouseReleaseEvent(QMouseEvent * event) +{ + mouseReleased(event); +} + +void LBMUIMFlowDialog::hScrollBarChanged(int value) +{ + if (qAbs(m_ui->sequencePlot->xAxis2->range().center() - value / 100.0) > 0.01) + { + m_ui->sequencePlot->xAxis2->setRange(value / 100.0, m_ui->sequencePlot->xAxis2->range().size(), Qt::AlignCenter); + m_ui->sequencePlot->replot(); + } +} + +void LBMUIMFlowDialog::vScrollBarChanged(int value) +{ + if (qAbs(m_ui->sequencePlot->yAxis->range().center() - value / 100.0) > 0.01) + { + m_ui->sequencePlot->yAxis->setRange(value / 100.0, m_ui->sequencePlot->yAxis->range().size(), Qt::AlignCenter); + m_ui->sequencePlot->replot(); + } +} + +void LBMUIMFlowDialog::xAxisChanged(QCPRange range) +{ + m_ui->horizontalScrollBar->setValue(qRound(range.center() * 100.0)); + m_ui->horizontalScrollBar->setPageStep(qRound(range.size() * 100.0)); +} + +void LBMUIMFlowDialog::yAxisChanged(QCPRange range) +{ + m_ui->verticalScrollBar->setValue(qRound(range.center() * 100.0)); + m_ui->verticalScrollBar->setPageStep(qRound(range.size() * 100.0)); +} + +void LBMUIMFlowDialog::diagramClicked(QMouseEvent * event) +{ + QCustomPlot * sp = m_ui->sequencePlot; + + if (event->button() == Qt::RightButton) + { + // XXX We should find some way to get sequenceDiagram to handle a + // contextMenuEvent instead. + m_context_menu.exec(event->globalPos()); + } + else if (sp->axisRect()->rect().contains(event->pos())) + { + sp->setCursor(QCursor(Qt::ClosedHandCursor)); + } + on_actionGoToPacket_triggered(); +} + +void LBMUIMFlowDialog::mouseMoved(QMouseEvent * event) +{ + QCustomPlot * sp = m_ui->sequencePlot; + Qt::CursorShape shape = Qt::ArrowCursor; + if (event) + { + if (event->buttons().testFlag(Qt::LeftButton)) + { + shape = Qt::ClosedHandCursor; + } + else + { + if (sp->axisRect()->rect().contains(event->pos())) + { + shape = Qt::OpenHandCursor; + } + } + } + sp->setCursor(QCursor(shape)); + + m_packet_num = 0; + QString hint; + if (event) + { + seq_analysis_item_t * sai = m_sequence_diagram->itemForPosY(event->pos().y()); + if (sai) + { + m_packet_num = sai->fd->num; + hint = QString("Packet %1: %2").arg(m_packet_num).arg(sai->comment); + } + } + + if (hint.isEmpty()) + { + hint += tr("%Ln node(s)", "", m_sequence_analysis.num_nodes) + QString(", ") + + tr("%Ln item(s)", "", m_num_items); + } + + hint.prepend("<small><i>"); + hint.append("</i></small>"); + m_ui->hintLabel->setText(hint); +} + +void LBMUIMFlowDialog::mouseReleased(QMouseEvent * event) +{ + Q_UNUSED(event); + if (m_ui->sequencePlot->cursor().shape() == Qt::ClosedHandCursor) + { + m_ui->sequencePlot->setCursor(QCursor(Qt::OpenHandCursor)); + } +} + +void LBMUIMFlowDialog::on_buttonBox_accepted(void) +{ + QString file_name, extension; + QDir path(wsApp->lastOpenDir()); + QString pdf_filter = tr("Portable Document Format (*.pdf)"); + QString png_filter = tr("Portable Network Graphics (*.png)"); + QString bmp_filter = tr("Windows Bitmap (*.bmp)"); + // Gaze upon my beautiful graph with lossy artifacts! + QString jpeg_filter = tr("JPEG File Interchange Format (*.jpeg *.jpg)"); + QString ascii_filter = tr("ASCII (*.txt)"); + + QString filter = QString("%1;;%2;;%3;;%4") + .arg(pdf_filter) + .arg(png_filter) + .arg(bmp_filter) + .arg(jpeg_filter); + if (m_capture_file) + { + filter.append(QString(";;%5").arg(ascii_filter)); + } + + file_name = QFileDialog::getSaveFileName(this, tr("Wireshark: Save Graph As..."), + path.canonicalPath(), filter, &extension); + + if (file_name.length() > 0) + { + bool save_ok = false; + if (extension.compare(pdf_filter) == 0) + { + save_ok = m_ui->sequencePlot->savePdf(file_name); + } + else if (extension.compare(png_filter) == 0) + { + save_ok = m_ui->sequencePlot->savePng(file_name); + } + else if (extension.compare(bmp_filter) == 0) + { + save_ok = m_ui->sequencePlot->saveBmp(file_name); + } + else if (extension.compare(jpeg_filter) == 0) + { + save_ok = m_ui->sequencePlot->saveJpg(file_name); + } + else if (extension.compare(ascii_filter) == 0 && m_capture_file) + { + save_ok = sequence_analysis_dump_to_file(file_name.toUtf8().constData(), &m_sequence_analysis, m_capture_file, 0); + } + // else error dialog? + if (save_ok) + { + path = QDir(file_name); + wsApp->setLastOpenDir(path.canonicalPath().toUtf8().constData()); + } + } +} + +void LBMUIMFlowDialog::fillDiagram(void) +{ + QCustomPlot * sp = m_ui->sequencePlot; + seq_analysis_info_t new_sa; + + new_sa = m_sequence_analysis; + new_sa.list = NULL; + new_sa.ht = NULL; + new_sa.num_nodes = 0; + lbm_uimflow_get_analysis(m_capture_file, &new_sa); + m_num_items = sequence_analysis_get_nodes(&new_sa); + m_sequence_diagram->setData(&new_sa); + sequence_analysis_list_free(&m_sequence_analysis); + m_sequence_analysis = new_sa; + + QFontMetrics vfm = QFontMetrics(sp->xAxis2->labelFont()); + m_node_label_width = 0; + for (guint i = 0; i < m_sequence_analysis.num_nodes; i++) + { + int label_w = vfm.width(ep_address_to_display(&(m_sequence_analysis.nodes[i]))); + if (m_node_label_width < label_w) + { + m_node_label_width = label_w; + } + } + m_node_label_width = (m_node_label_width * 3 / 4) + m_one_em; + + mouseMoved(NULL); + resetAxes(); + + // XXX QCustomPlot doesn't seem to draw any sort of focus indicator. + sp->setFocus(); +} + +void LBMUIMFlowDialog::panAxes(int x_pixels, int y_pixels) +{ + QCustomPlot * sp = m_ui->sequencePlot; + double h_pan = 0.0; + double v_pan = 0.0; + + h_pan = sp->xAxis2->range().size() * x_pixels / sp->xAxis2->axisRect()->width(); + v_pan = sp->yAxis->range().size() * y_pixels / sp->yAxis->axisRect()->height(); + // The GTK+ version won't pan unless we're zoomed. Should we do the same here? + if (h_pan) + { + sp->xAxis2->moveRange(h_pan); + sp->replot(); + } + if (v_pan) + { + sp->yAxis->moveRange(v_pan); + sp->replot(); + } +} + +void LBMUIMFlowDialog::resetAxes(bool keep_lower) +{ + QCustomPlot * sp = m_ui->sequencePlot; + // Allow space for labels on the top and port numbers on the left. + double top_pos = -1.0, left_pos = -0.5; + if (keep_lower) + { + top_pos = sp->yAxis->range().lower; + left_pos = sp->xAxis2->range().lower; + } + + double range_ratio = sp->xAxis2->axisRect()->width() / m_node_label_width; + sp->xAxis2->setRange(left_pos, range_ratio + left_pos); + + range_ratio = sp->yAxis->axisRect()->height() / (m_one_em * 1.5); + sp->yAxis->setRange(top_pos, range_ratio + top_pos); + + double rmin = sp->xAxis2->range().size() / 2; + m_ui->horizontalScrollBar->setRange((rmin - 0.5) * 100, (m_sequence_analysis.num_nodes - 0.5 - rmin) * 100); + xAxisChanged(sp->xAxis2->range()); + + rmin = (sp->yAxis->range().size() / 2); + m_ui->verticalScrollBar->setRange((rmin - 1.0) * 100, (m_num_items - 0.5 - rmin) * 100); + yAxisChanged(sp->yAxis->range()); + + sp->replot(); +} + +void LBMUIMFlowDialog::on_resetButton_clicked(void) +{ + resetAxes(); +} + +void LBMUIMFlowDialog::on_actionGoToPacket_triggered(void) +{ + if (m_capture_file && m_packet_num > 0) + { + emit goToPacket(m_packet_num); + } +} + +void LBMUIMFlowDialog::on_showComboBox_currentIndexChanged(int index) +{ + if (index == 0) + { + m_sequence_analysis.all_packets = TRUE; + } + else + { + m_sequence_analysis.all_packets = FALSE; + } + fillDiagram(); +} + +void LBMUIMFlowDialog::on_actionReset_triggered(void) +{ + on_resetButton_clicked(); +} + +void LBMUIMFlowDialog::on_actionMoveRight10_triggered(void) +{ + panAxes(10, 0); +} + +void LBMUIMFlowDialog::on_actionMoveLeft10_triggered(void) +{ + panAxes(-10, 0); +} + +void LBMUIMFlowDialog::on_actionMoveUp10_triggered(void) +{ + panAxes(0, -10); +} + +void LBMUIMFlowDialog::on_actionMoveDown10_triggered(void) +{ + panAxes(0, 10); +} + +void LBMUIMFlowDialog::on_actionMoveRight1_triggered(void) +{ + panAxes(1, 0); +} + +void LBMUIMFlowDialog::on_actionMoveLeft1_triggered(void) +{ + panAxes(-1, 0); +} + +void LBMUIMFlowDialog::on_actionMoveUp1_triggered(void) +{ + panAxes(0, -1); +} + +void LBMUIMFlowDialog::on_actionMoveDown1_triggered(void) +{ + panAxes(0, 1); +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_uimflow_dialog.h b/ui/qt/lbm_uimflow_dialog.h new file mode 100644 index 0000000000..0d37f90de4 --- /dev/null +++ b/ui/qt/lbm_uimflow_dialog.h @@ -0,0 +1,117 @@ +/* lbm_uimflow_dialog.h + * + * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LBM_UIMFLOW_DIALOG_H +#define LBM_UIMFLOW_DIALOG_H + +#include "config.h" + +#include <glib.h> + +#include "cfile.h" + +#include "epan/packet.h" + +#include "sequence_diagram.h" + +#include <QDialog> +#include <QMenu> + +namespace Ui +{ + class LBMUIMFlowDialog; +} + +class LBMUIMFlowDialog : public QDialog +{ + Q_OBJECT + + public: + explicit LBMUIMFlowDialog(QWidget * parent = 0, capture_file * cfile = NULL); + ~LBMUIMFlowDialog(void); + + signals: + void goToPacket(int packet_number); + + public slots: + void setCaptureFile(capture_file * CaptureFile); + + protected: + void showEvent(QShowEvent * event); + void resizeEvent(QResizeEvent * event); + void keyPressEvent(QKeyEvent * event); + void mouseReleaseEvent(QMouseEvent * event); + + private slots: + void hScrollBarChanged(int value); + void vScrollBarChanged(int value); + void xAxisChanged(QCPRange range); + void yAxisChanged(QCPRange range); + void diagramClicked(QMouseEvent * event); + void mouseMoved(QMouseEvent * event); + void mouseReleased(QMouseEvent * event); + + void on_buttonBox_accepted(void); + void on_resetButton_clicked(void); + void on_actionGoToPacket_triggered(void); + void on_showComboBox_currentIndexChanged(int index); + void on_actionReset_triggered(void); + void on_actionMoveRight10_triggered(void); + void on_actionMoveLeft10_triggered(void); + void on_actionMoveUp10_triggered(void); + void on_actionMoveDown10_triggered(void); + void on_actionMoveRight1_triggered(void); + void on_actionMoveLeft1_triggered(void); + void on_actionMoveUp1_triggered(void); + void on_actionMoveDown1_triggered(void); + + private: + Ui::LBMUIMFlowDialog * m_ui; + SequenceDiagram * m_sequence_diagram; + capture_file * m_capture_file; + seq_analysis_info_t m_sequence_analysis; + int m_num_items; + guint32 m_packet_num; + double m_one_em; + int m_node_label_width; + QMenu m_context_menu; + + void fillDiagram(void); + void panAxes(int x_pixels, int y_pixels); + void resetAxes(bool keep_lower = false); +}; + +#endif + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ diff --git a/ui/qt/lbm_uimflow_dialog.ui b/ui/qt/lbm_uimflow_dialog.ui new file mode 100644 index 0000000000..3519c4e8b8 --- /dev/null +++ b/ui/qt/lbm_uimflow_dialog.ui @@ -0,0 +1,326 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LBMUIMFlowDialog</class> + <widget class="QDialog" name="LBMUIMFlowDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>679</width> + <height>568</height> + </rect> + </property> + <property name="windowTitle"> + <string>LBM UIM Flows</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="1"> + <widget class="QScrollBar" name="verticalScrollBar"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QScrollBar" name="horizontalScrollBar"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QFrame" name="frame"/> + </item> + <item row="0" column="0"> + <widget class="QCustomPlot" name="sequencePlot" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="hintLabel"> + <property name="toolTip"> + <string><html><head/><body> + +<h3>Valuable and amazing time-saving keyboard shortcuts</h3> +<table><tbody> + +<tr><th>0</th><td>Reset graph to its initial state</td></th> + +<tr><th>→</th><td>Move right 10 pixels</td></th> +<tr><th>←</th><td>Move left 10 pixels</td></th> +<tr><th>↑</th><td>Move up 10 pixels</td></th> +<tr><th>↓</th><td>Move down 10 pixels</td></th> +<tr><th><i>Shift+</i>→</th><td>Move right 1 pixel</td></th> +<tr><th><i>Shift+</i>←</th><td>Move left 1 pixel</td></th> +<tr><th><i>Shift+</i>↑</th><td>Move up 1 pixel</td></th> +<tr><th><i>Shift+</i>↓</th><td>Move down 1 pixel</td></th> + +<tr><th>g</th><td>Go to packet under cursor</td></th> + +</tbody></table> +</body></html></string> + </property> + <property name="text"> + <string><small><i>A hint</i></small></string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="controlHorizontalLayout" stretch="0,0,1"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Show:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="showComboBox"> + <item> + <property name="text"> + <string>All packets</string> + </property> + </item> + <item> + <property name="text"> + <string>Displayed packets</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="resetButton"> + <property name="text"> + <string>Reset</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok|QDialogButtonBox::Save</set> + </property> + </widget> + </item> + </layout> + <action name="actionReset"> + <property name="text"> + <string>Reset Diagram</string> + </property> + <property name="toolTip"> + <string>Reset the diagram to its initial state.</string> + </property> + <property name="shortcut"> + <string>0</string> + </property> + </action> + <action name="actionMoveUp10"> + <property name="text"> + <string>Move Up 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move up 10 pixels</string> + </property> + <property name="shortcut"> + <string>Up</string> + </property> + </action> + <action name="actionMoveLeft10"> + <property name="text"> + <string>Move Left 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move left 10 pixels</string> + </property> + <property name="shortcut"> + <string>Left</string> + </property> + </action> + <action name="actionMoveRight10"> + <property name="text"> + <string>Move Right 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move right 10 pixels</string> + </property> + <property name="shortcut"> + <string>Right</string> + </property> + </action> + <action name="actionMoveDown10"> + <property name="text"> + <string>Move Down 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move down 10 pixels</string> + </property> + <property name="shortcut"> + <string>Down</string> + </property> + </action> + <action name="actionMoveUp1"> + <property name="text"> + <string>Move Up 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move up 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Up</string> + </property> + </action> + <action name="actionMoveLeft1"> + <property name="text"> + <string>Move Left 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move left 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Left</string> + </property> + </action> + <action name="actionMoveRight1"> + <property name="text"> + <string>Move Right 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move right 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Right</string> + </property> + </action> + <action name="actionMoveDown1"> + <property name="text"> + <string>Move Down 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move down 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Down</string> + </property> + </action> + <action name="actionGoToPacket"> + <property name="text"> + <string>Go To Packet Under Cursor</string> + </property> + <property name="toolTip"> + <string>Go to packet currently under the cursor</string> + </property> + <property name="shortcut"> + <string>G</string> + </property> + </action> + <action name="actionFlowAny"> + <property name="text"> + <string>All Flows</string> + </property> + <property name="toolTip"> + <string>Show flows for all packets</string> + </property> + <property name="shortcut"> + <string>1</string> + </property> + </action> + <action name="actionFlowTcp"> + <property name="text"> + <string>TCP Flows</string> + </property> + <property name="toolTip"> + <string>Show only TCP flow information</string> + </property> + <property name="shortcut"> + <string>1</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>QCustomPlot</class> + <extends>QWidget</extends> + <header>qcustomplot.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>LBMUIMFlowDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>LBMUIMFlowDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 3cc5de5ec3..1ea43582dc 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -341,6 +341,21 @@ private slots: #endif void openStatisticsTreeDialog(const gchar *abbr); + void on_actionStatistics29WestTopics_Advertisements_by_Topic_triggered(); + void on_actionStatistics29WestTopics_Advertisements_by_Source_triggered(); + void on_actionStatistics29WestTopics_Advertisements_by_Transport_triggered(); + void on_actionStatistics29WestTopics_Queries_by_Topic_triggered(); + void on_actionStatistics29WestTopics_Queries_by_Receiver_triggered(); + void on_actionStatistics29WestTopics_Wildcard_Queries_by_Pattern_triggered(); + void on_actionStatistics29WestTopics_Wildcard_Queries_by_Receiver_triggered(); + void on_actionStatistics29WestQueues_Advertisements_by_Queue_triggered(); + void on_actionStatistics29WestQueues_Advertisements_by_Source_triggered(); + void on_actionStatistics29WestQueues_Queries_by_Queue_triggered(); + void on_actionStatistics29WestQueues_Queries_by_Receiver_triggered(); + void on_actionStatistics29WestUIM_Streams_triggered(); + void on_actionStatistics29WestUIM_Stream_Flow_Graph_triggered(); + void on_actionStatistics29WestLBTRM_triggered(); + void on_actionStatistics29WestLBTRU_triggered(); void on_actionStatisticsANCP_triggered(); void on_actionStatisticsBACappInstanceId_triggered(); void on_actionStatisticsBACappIP_triggered(); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 0d237c86d6..5407b7bf10 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -326,12 +326,51 @@ <addaction name="actionStatisticsHTTPRequests"/> <addaction name="actionStatisticsHTTPLoadDistribution"/> </widget> + <widget class="QMenu" name="menu29West"> + <property name="title"> + <string>29West</string> + </property> + <widget class="QMenu" name="menu29WestTopics"> + <property name="title"> + <string>Topics</string> + </property> + <addaction name="actionStatistics29WestTopics_Advertisements_by_Topic"/> + <addaction name="actionStatistics29WestTopics_Advertisements_by_Source"/> + <addaction name="actionStatistics29WestTopics_Advertisements_by_Transport"/> + <addaction name="actionStatistics29WestTopics_Queries_by_Topic"/> + <addaction name="actionStatistics29WestTopics_Queries_by_Receiver"/> + <addaction name="actionStatistics29WestTopics_Wildcard_Queries_by_Pattern"/> + <addaction name="actionStatistics29WestTopics_Wildcard_Queries_by_Receiver"/> + </widget> + <widget class="QMenu" name="menu29WestQueues"> + <property name="title"> + <string>Queues</string> + </property> + <addaction name="actionStatistics29WestQueues_Advertisements_by_Queue"/> + <addaction name="actionStatistics29WestQueues_Advertisements_by_Source"/> + <addaction name="actionStatistics29WestQueues_Queries_by_Queue"/> + <addaction name="actionStatistics29WestQueues_Queries_by_Receiver"/> + </widget> + <widget class="QMenu" name="menu29WestUIM"> + <property name="title"> + <string>UIM</string> + </property> + <addaction name="actionStatistics29WestUIM_Streams"/> + <addaction name="actionStatistics29WestUIM_Stream_Flow_Graph"/> + </widget> + <addaction name="menu29WestTopics"/> + <addaction name="menu29WestQueues"/> + <addaction name="menu29WestUIM"/> + <addaction name="actionStatistics29WestLBTRM"/> + <addaction name="actionStatistics29WestLBTRU"/> + </widget> <addaction name="actionSummary"/> <addaction name="actionProtocol_Hierarchy"/> <addaction name="actionStatisticsPacketLen"/> <addaction name="actionStatisticsIOGraph"/> <addaction name="separator"/> <addaction name="separator"/> + <addaction name="menu29West"/> <addaction name="actionStatisticsANCP"/> <addaction name="menuBACnet"/> <addaction name="actionStatisticsCollectd"/> @@ -1539,6 +1578,86 @@ <string>Change the way packets are dissected</string> </property> </action> + <action name="action29West"> + <property name="text"> + <string>29West</string> + </property> + </action> + <action name="actionStatistics29WestTopics_Advertisements_by_Topic"> + <property name="text"> + <string>Advertisements by Topic</string> + </property> + </action> + <action name="actionStatistics29WestTopics_Advertisements_by_Source"> + <property name="text"> + <string>Advertisements by Source</string> + </property> + </action> + <action name="actionStatistics29WestTopics_Advertisements_by_Transport"> + <property name="text"> + <string>Advertisements by Transport</string> + </property> + </action> + <action name="actionStatistics29WestTopics_Queries_by_Topic"> + <property name="text"> + <string>Queries by Topic</string> + </property> + </action> + <action name="actionStatistics29WestTopics_Queries_by_Receiver"> + <property name="text"> + <string>Queries by Receiver</string> + </property> + </action> + <action name="actionStatistics29WestTopics_Wildcard_Queries_by_Pattern"> + <property name="text"> + <string>Wildcard Queries by Pattern</string> + </property> + </action> + <action name="actionStatistics29WestTopics_Wildcard_Queries_by_Receiver"> + <property name="text"> + <string>Wildcard Queries by Receiver</string> + </property> + </action> + <action name="actionStatistics29WestQueues_Advertisements_by_Queue"> + <property name="text"> + <string>Advertisements by Queue</string> + </property> + </action> + <action name="actionStatistics29WestQueues_Advertisements_by_Source"> + <property name="text"> + <string>Advertisements by Source</string> + </property> + </action> + <action name="actionStatistics29WestQueues_Queries_by_Queue"> + <property name="text"> + <string>Queries by Queue</string> + </property> + </action> + <action name="actionStatistics29WestQueues_Queries_by_Receiver"> + <property name="text"> + <string>Queries by Receiver</string> + </property> + </action> + <action name="actionStatistics29WestUIM_Streams"> + <property name="text"> + <string>Streams</string> + </property> + </action> + <action name="actionStatistics29WestUIM_Stream_Flow_Graph"> + <property name="text"> + <string>Stream Flow Graph</string> + </property> + </action> + <action name="actionStatistics29WestLBTRM"> + <property name="text"> + <string>LBT-RM</string> + </property> + </action> + <action name="actionStatistics29WestLBTRU"> + <property name="text"> + <string>LBT-RU</string> + </property> + </action> <action name="actionSCTPFilterThisAssociation"> <property name="text"> <string>Filter this Association</string> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 4bc3fe2361..7bbb4486d9 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -72,6 +72,10 @@ #include "export_object_dialog.h" #include "export_pdu_dialog.h" #include "io_graph_dialog.h" +#include "lbm_stream_dialog.h" +#include "lbm_uimflow_dialog.h" +#include "lbm_lbtrm_transport_dialog.h" +#include "lbm_lbtru_transport_dialog.h" #include "packet_comment_dialog.h" #include "preferences_dialog.h" #include "print_dialog.h" @@ -419,7 +423,7 @@ void MainWindow::captureFileReadFinished(const capture_file *cf) { // add_menu_recent_capture_file(cf->filename); // /* Remember folder for next Open dialog and save it in recent */ -// dir_path = get_dirname(g_strdup(cf->filename)); +// dir_path = get_dirname(g_strdup(cf->filename)); // wsApp->setLastOpenDir(dir_path); // g_free(dir_path); // } @@ -1911,6 +1915,100 @@ void MainWindow::openStatisticsTreeDialog(const gchar *abbr) st_dialog->show(); } +void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Topic_triggered() +{ + openStatisticsTreeDialog("lbmr_topic_ads_topic"); +} + +void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Source_triggered() +{ + openStatisticsTreeDialog("lbmr_topic_ads_source"); +} + +void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Transport_triggered() +{ + openStatisticsTreeDialog("lbmr_topic_ads_transport"); +} + +void MainWindow::on_actionStatistics29WestTopics_Queries_by_Topic_triggered() +{ + openStatisticsTreeDialog("lbmr_topic_queries_topic"); +} + +void MainWindow::on_actionStatistics29WestTopics_Queries_by_Receiver_triggered() +{ + openStatisticsTreeDialog("lbmr_topic_queries_receiver"); +} + +void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Pattern_triggered() +{ + openStatisticsTreeDialog("lbmr_topic_queries_pattern"); +} + +void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Receiver_triggered() +{ + openStatisticsTreeDialog("lbmr_topic_queries_pattern_receiver"); +} + +void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Queue_triggered() +{ + openStatisticsTreeDialog("lbmr_queue_ads_queue"); +} + +void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Source_triggered() +{ + openStatisticsTreeDialog("lbmr_queue_ads_source"); +} + +void MainWindow::on_actionStatistics29WestQueues_Queries_by_Queue_triggered() +{ + openStatisticsTreeDialog("lbmr_queue_queries_queue"); +} + +void MainWindow::on_actionStatistics29WestQueues_Queries_by_Receiver_triggered() +{ + openStatisticsTreeDialog("lbmr_queue_queries_receiver"); +} + +void MainWindow::on_actionStatistics29WestUIM_Streams_triggered() +{ + LBMStreamDialog *stream_dialog = new LBMStreamDialog(this, cap_file_); +// connect(stream_dialog, SIGNAL(goToPacket(int)), +// packet_list_, SLOT(goToPacket(int))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + stream_dialog, SLOT(setCaptureFile(capture_file*))); + stream_dialog->show(); +} + +void MainWindow::on_actionStatistics29WestUIM_Stream_Flow_Graph_triggered() +{ + LBMUIMFlowDialog * uimflow_dialog = new LBMUIMFlowDialog(this, cap_file_); + connect(uimflow_dialog, SIGNAL(goToPacket(int)), + packet_list_, SLOT(goToPacket(int))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + uimflow_dialog, SLOT(setCaptureFile(capture_file*))); + uimflow_dialog->show(); +} + +void MainWindow::on_actionStatistics29WestLBTRM_triggered() +{ + LBMLBTRMTransportDialog * lbtrm_dialog = new LBMLBTRMTransportDialog(this, cap_file_); + connect(lbtrm_dialog, SIGNAL(goToPacket(int)), + packet_list_, SLOT(goToPacket(int))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + lbtrm_dialog, SLOT(setCaptureFile(capture_file*))); + lbtrm_dialog->show(); +} +void MainWindow::on_actionStatistics29WestLBTRU_triggered() +{ + LBMLBTRUTransportDialog * lbtru_dialog = new LBMLBTRUTransportDialog(this, cap_file_); + connect(lbtru_dialog, SIGNAL(goToPacket(int)), + packet_list_, SLOT(goToPacket(int))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + lbtru_dialog, SLOT(setCaptureFile(capture_file*))); + lbtru_dialog->show(); +} + void MainWindow::on_actionStatisticsANCP_triggered() { openStatisticsTreeDialog("ancp"); |