const QString ConversationHashTablesDialog::hashTableToHtmlTable(const QString table_name, struct _GHashTable *hash_table)
{
    GList *conversation_keys = NULL;
    if (hash_table) conversation_keys = g_hash_table_get_keys(hash_table);
    int num_keys = g_list_length(conversation_keys);

    QString html_table = QString("<p>%1, %2 entries</p>").arg(table_name).arg(num_keys);
    if (num_keys < 1) return html_table;

    int one_em = fontMetrics().height();
    html_table += QString("<table cellpadding=\"%1\">\n").arg(one_em / 4);

    html_table += "<tr><th align=\"left\">Address 1</th><th align=\"left\">Port 1</th><th align=\"left\">Address 2</th><th align=\"left\">Port 2</th></tr>\n";

    // XXX Add a column for the hash value.
    for (GList *ck_entry = conversation_keys; ck_entry; ck_entry = g_list_next(ck_entry)) {
        const conversation_key *conv_key = (conversation_key *) ck_entry->data;
        html_table += QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td></tr>\n")
                .arg(address_to_qstring(&conv_key->addr1))
                .arg(conv_key->port1)
                .arg(address_to_qstring(&conv_key->addr2))
                .arg(conv_key->port2);
    }
    html_table += "</table>\n";
    return html_table;
}
 QList<QVariant> rowData() {
     return QList<QVariant>()
             << address_to_qstring(&src_addr_) << src_port_
             << address_to_qstring(&dst_addr_) << dst_port_
             << num_packets_ << avg_pps_
             << avg_bw_ << max_bw_
             << top_burst_size_ << num_bursts_
             << top_buff_usage_ << num_buff_alarms_;
 }
QString TCPStreamDialog::streamDescription()
{
    QString description(tr(" for %1:%2 %3 %4:%5")
            .arg(address_to_qstring(&graph_.src_address))
            .arg(graph_.src_port)
            .arg(UTF8_RIGHTWARDS_ARROW)
            .arg(address_to_qstring(&graph_.dst_address))
            .arg(graph_.dst_port));
    return description;
}
    const QString filterExpression() {
        QString ip_version;

        if (src_addr_.type == AT_IPv6) ip_version = "v6";

        const QString filter_expr = QString("(ip%1.src==%2 && udp.srcport==%3 && ip%1.dst==%4 && udp.dstport==%5)")
                .arg(ip_version)
                .arg(address_to_qstring(&src_addr_))
                .arg(src_port_)
                .arg(address_to_qstring(&dst_addr_))
                .arg(dst_port_);
        return filter_expr;
    }
 void draw() {
     setText(col_src_addr_, address_to_qstring(&src_addr_));
     setText(col_src_port_, QString::number(src_port_));
     setText(col_dst_addr_, address_to_qstring(&dst_addr_));
     setText(col_dst_port_, QString::number(dst_port_));
     setText(col_packets_, QString::number(num_packets_));
     setText(col_packets_s_, QString::number(avg_pps_, 'f', 2));
     setText(col_avg_bw_, bits_s_to_qstring(avg_bw_));
     setText(col_max_bw_, bits_s_to_qstring(max_bw_));
     setText(col_max_burst_, QString("%1 / %2ms").arg(top_burst_size_).arg(mcast_stream_burstint));
     setText(col_burst_alarms_, QString::number(num_bursts_));
     setText(col_max_buffers_, bits_s_to_qstring(top_buff_usage_));
     setText(col_buffer_alarms_, QString::number(num_buff_alarms_));
 }
 QList<QVariant> rowData() {
     return QList<QVariant>()
             << address_to_qstring(&addr_)
             << data(col_pct_packets_, Qt::UserRole).toDouble()
             << sent_ << received_ << probe_req_ << probe_resp_
             << auth_ << deauth_ << other_ << text(col_protection_);
 }
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_qstring(source_address))
        .arg(source_port);
    m_endpoint_b = QString("%1:%2")
        .arg(address_to_qstring(destination_address))
        .arg(destination_port);
}
void RtpPlayerDialog::addRtpStream(struct _rtp_stream_info *rtp_stream)
{
    if (!rtp_stream) return;

    // Find the RTP streams associated with this conversation.
    // gtk/rtp_player.c:mark_rtp_stream_to_play does this differently.

    RtpAudioStream *audio_stream = NULL;
    int tli_count = ui->streamTreeWidget->topLevelItemCount();
    for (int row = 0; row < tli_count; row++) {
        QTreeWidgetItem *ti = ui->streamTreeWidget->topLevelItem(row);
        RtpAudioStream *row_stream = ti->data(stream_data_col_, Qt::UserRole).value<RtpAudioStream*>();
        if (row_stream->isMatch(rtp_stream)) {
            audio_stream = row_stream;
            break;
        }
    }

    if (!audio_stream) {
        audio_stream = new RtpAudioStream(this, rtp_stream);
        audio_stream->setColor(ColorUtils::graph_colors_[tli_count % ColorUtils::graph_colors_.length()]);

        QTreeWidgetItem *ti = new QTreeWidgetItem(ui->streamTreeWidget);
        ti->setText(src_addr_col_, address_to_qstring(&rtp_stream->src_addr));
        ti->setText(src_port_col_, QString::number(rtp_stream->src_port));
        ti->setText(dst_addr_col_, address_to_qstring(&rtp_stream->dest_addr));
        ti->setText(dst_port_col_, QString::number(rtp_stream->dest_port));
        ti->setText(ssrc_col_, int_to_qstring(rtp_stream->ssrc, 8, 16));
        ti->setText(first_pkt_col_, QString::number(rtp_stream->setup_frame_number));
        ti->setText(num_pkts_col_, QString::number(rtp_stream->packet_count));

        ti->setData(stream_data_col_, Qt::UserRole, QVariant::fromValue(audio_stream));

        for (int col = 0; col < ui->streamTreeWidget->columnCount(); col++) {
            ti->setTextColor(col, audio_stream->color());
        }

        connect(ui->playButton, SIGNAL(clicked(bool)), audio_stream, SLOT(startPlaying()));
        connect(ui->stopButton, SIGNAL(clicked(bool)), audio_stream, SLOT(stopPlaying()));

        connect(audio_stream, SIGNAL(startedPlaying()), this, SLOT(updateWidgets()));
        connect(audio_stream, SIGNAL(finishedPlaying()), this, SLOT(updateWidgets()));
        connect(audio_stream, SIGNAL(processedSecs(double)), this, SLOT(setPlayPosition(double)));
    }
 WlanStationTreeWidgetItem(address *addr) :
     QTreeWidgetItem (wlan_station_row_type_),
     packets_(0),
     sent_(0),
     received_(0),
     probe_req_(0),
     probe_resp_(0),
     auth_(0),
     deauth_(0),
     other_(0)
 {
     copy_address(&addr_, addr);
     setText(col_bssid_, address_to_qstring(&addr_));
 }
 const QString filterExpression() {
     QString filter_expr = QString("wlan.addr==%1")
             .arg(address_to_qstring(&addr_));
     return filter_expr;
 }
Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) :
    WiresharkDialog(parent, cf),
    ui(new Ui::Iax2AnalysisDialog),
    port_src_fwd_(0),
    port_dst_fwd_(0),
    port_src_rev_(0),
    port_dst_rev_(0)
{
    ui->setupUi(this);
    setWindowSubtitle(tr("IAX2 Stream Analysis"));

    // XXX Use recent settings instead
    resize(parent.width() * 4 / 5, parent.height() * 4 / 5);
    ui->progressFrame->hide();

    stream_ctx_menu_.addAction(ui->actionGoToPacket);
    stream_ctx_menu_.addAction(ui->actionNextProblem);
    stream_ctx_menu_.addSeparator();
    stream_ctx_menu_.addAction(ui->actionSaveAudio);
    stream_ctx_menu_.addAction(ui->actionSaveForwardAudio);
    stream_ctx_menu_.addAction(ui->actionSaveReverseAudio);
    stream_ctx_menu_.addSeparator();
    stream_ctx_menu_.addAction(ui->actionSaveCsv);
    stream_ctx_menu_.addAction(ui->actionSaveForwardCsv);
    stream_ctx_menu_.addAction(ui->actionSaveReverseCsv);
    stream_ctx_menu_.addSeparator();
    stream_ctx_menu_.addAction(ui->actionSaveGraph);
    ui->forwardTreeWidget->installEventFilter(this);
    ui->forwardTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->forwardTreeWidget, SIGNAL(customContextMenuRequested(QPoint)),
                SLOT(showStreamMenu(QPoint)));
    ui->reverseTreeWidget->installEventFilter(this);
    ui->reverseTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->reverseTreeWidget, SIGNAL(customContextMenuRequested(QPoint)),
                SLOT(showStreamMenu(QPoint)));
    connect(ui->streamGraph, SIGNAL(mousePress(QMouseEvent*)),
            this, SLOT(graphClicked(QMouseEvent*)));

    graph_ctx_menu_.addAction(ui->actionSaveGraph);

    QStringList header_labels;
    for (int i = 0; i < ui->forwardTreeWidget->columnCount(); i++) {
        header_labels << ui->forwardTreeWidget->headerItem()->text(i);
    }
    ui->reverseTreeWidget->setHeaderLabels(header_labels);

    memset(&src_fwd_, 0, sizeof(address));
    memset(&dst_fwd_, 0, sizeof(address));
    memset(&src_rev_, 0, sizeof(address));
    memset(&dst_rev_, 0, sizeof(address));

    QList<QCheckBox *> graph_cbs = QList<QCheckBox *>()
            << ui->fJitterCheckBox << ui->fDiffCheckBox
            << ui->rJitterCheckBox << ui->rDiffCheckBox;

    for (int i = 0; i < num_graphs_; i++) {
        QCPGraph *graph = ui->streamGraph->addGraph();
        graph->setPen(QPen(ColorUtils::graph_colors_[i]));
        graph->setName(graph_cbs[i]->text());
        graphs_ << graph;
        graph_cbs[i]->setChecked(true);
        graph_cbs[i]->setIcon(StockIcon::colorIcon(ColorUtils::graph_colors_[i], QPalette::Text));
    }
    ui->streamGraph->xAxis->setLabel("Arrival Time");
    ui->streamGraph->yAxis->setLabel("Value (ms)");

    // We keep our temp files open for the lifetime of the dialog. The GTK+
    // UI opens and closes at various points.
    QString tempname = QString("%1/wireshark_iax2_f").arg(QDir::tempPath());
    fwd_tempfile_ = new QTemporaryFile(tempname, this);
    fwd_tempfile_->open();
    tempname = QString("%1/wireshark_iax2_r").arg(QDir::tempPath());
    rev_tempfile_ = new QTemporaryFile(tempname, this);
    rev_tempfile_->open();

    if (fwd_tempfile_->error() != QFile::NoError || rev_tempfile_->error() != QFile::NoError) {
        err_str_ = tr("Unable to save RTP data.");
        ui->actionSaveAudio->setEnabled(false);
        ui->actionSaveForwardAudio->setEnabled(false);
        ui->actionSaveReverseAudio->setEnabled(false);
    }

    QMenu *save_menu = new QMenu();
    save_menu->addAction(ui->actionSaveAudio);
    save_menu->addAction(ui->actionSaveForwardAudio);
    save_menu->addAction(ui->actionSaveReverseAudio);
    save_menu->addSeparator();
    save_menu->addAction(ui->actionSaveCsv);
    save_menu->addAction(ui->actionSaveForwardCsv);
    save_menu->addAction(ui->actionSaveReverseCsv);
    save_menu->addSeparator();
    save_menu->addAction(ui->actionSaveGraph);
    ui->buttonBox->button(QDialogButtonBox::Save)->setMenu(save_menu);

    const gchar *filter_text = "iax2 && (ip || ipv6)";
    dfilter_t *sfcode;
    gchar *err_msg;

    if (!dfilter_compile(filter_text, &sfcode, &err_msg)) {
        QMessageBox::warning(this, tr("No IAX2 packets found"), QString("%1").arg(err_msg));
        g_free(err_msg);
        close();
    }

    if (!cap_file_.capFile() || !cap_file_.capFile()->current_frame) close();

    frame_data *fdata = cap_file_.capFile()->current_frame;

    if (!cf_read_record(cap_file_.capFile(), fdata)) close();

    epan_dissect_t edt;

    epan_dissect_init(&edt, cap_file_.capFile()->epan, TRUE, FALSE);
    epan_dissect_prime_dfilter(&edt, sfcode);
    epan_dissect_run(&edt, cap_file_.capFile()->cd_t, &cap_file_.capFile()->phdr,
                     frame_tvbuff_new_buffer(fdata, &cap_file_.capFile()->buf), fdata, NULL);

    // This shouldn't happen (the menu item should be disabled) but check anyway
    if (!dfilter_apply_edt(sfcode, &edt)) {
        epan_dissect_cleanup(&edt);
        dfilter_free(sfcode);
        err_str_ = tr("Please select an IAX2 packet");
        updateWidgets();
        return;
    }

    dfilter_free(sfcode);

    /* ok, it is a IAX2 frame, so let's get the ip and port values */
    COPY_ADDRESS(&(src_fwd_), &(edt.pi.src));
    COPY_ADDRESS(&(dst_fwd_), &(edt.pi.dst));
    port_src_fwd_ = edt.pi.srcport;
    port_dst_fwd_ = edt.pi.destport;

    /* assume the inverse ip/port combination for the reverse direction */
    COPY_ADDRESS(&(src_rev_), &(edt.pi.dst));
    COPY_ADDRESS(&(dst_rev_), &(edt.pi.src));
    port_src_rev_ = edt.pi.destport;
    port_dst_rev_ = edt.pi.srcport;

#if 0
    /* check if it is Voice or MiniPacket */
    bool ok;
    getIntFromProtoTree(edt.tree, "iax2", "iax2.call", &ok);
    if (!ok) {
        err_str_ = tr("Please select an IAX2 packet.");
        updateWidgets();
        return;
    }
#endif

#ifdef IAX2_RTP_STREAM_CHECK
    rtpstream_tapinfot tapinfo;

    /* Register the tap listener */
    memset(&tapinfo, 0, sizeof(rtpstream_tapinfot));
    tapinfo.tap_data = this;
    tapinfo.mode = TAP_ANALYSE;

//    register_tap_listener_rtp_stream(&tapinfo, NULL);
    /* Scan for RTP streams (redissect all packets) */
    rtpstream_scan(&tapinfo, cap_file_.capFile(), NULL);

    int num_streams = 0;
    GList *filtered_list = NULL;
    for (GList *strinfo_list = g_list_first(tapinfo.strinfo_list); strinfo_list; strinfo_list = g_list_next(strinfo_list)) {
        rtp_stream_info_t * strinfo = (rtp_stream_info_t*)(strinfo_list->data);
                 << address_to_qstring(&strinfo->dest_addr) << address_to_qstring(&src_rev_) << address_to_qstring(&dst_rev_);
        if (ADDRESSES_EQUAL(&(strinfo->src_addr), &(src_fwd_))
            && (strinfo->src_port == port_src_fwd_)
            && (ADDRESSES_EQUAL(&(strinfo->dest_addr), &(dst_fwd_)))
            && (strinfo->dest_port == port_dst_fwd_))
        {
            ++num_streams;
            filtered_list = g_list_prepend(filtered_list, strinfo);
        }

        if (ADDRESSES_EQUAL(&(strinfo->src_addr), &(src_rev_))
            && (strinfo->src_port == port_src_rev_)
            && (ADDRESSES_EQUAL(&(strinfo->dest_addr), &(dst_rev_)))
            && (strinfo->dest_port == port_dst_rev_))
        {
            ++num_streams;
            filtered_list = g_list_append(filtered_list, strinfo);
        }
    }