forked from Mirrors/sngrep
cf: Add a keybinding to only display active RTP streams
We consider an active RTP stream those that have received a RTP packet in the last STREAM_INACTIVE_SECS seconds (which defaults to 3). This is a bit adhoc display that requires testing.
This commit is contained in:
parent
b7fb904b40
commit
4aacd31211
@ -650,7 +650,8 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||||||
if (address_equals(msg->packet->src, stream->dst)) {
|
if (address_equals(msg->packet->src, stream->dst)) {
|
||||||
// Reuse the msg arrow columns as destination column
|
// Reuse the msg arrow columns as destination column
|
||||||
if ((msgarrow = call_flow_arrow_find(ui, msg))) {
|
if ((msgarrow = call_flow_arrow_find(ui, msg))) {
|
||||||
arrow->dcolumn = msgarrow->scolumn;
|
// Get origin and destination column
|
||||||
|
arrow->dcolumn = call_flow_column_get(ui, msg->call->callid, msg->packet->src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +675,20 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||||||
if (msg && address_equals(msg->packet->src, stream->src)) {
|
if (msg && address_equals(msg->packet->src, stream->src)) {
|
||||||
// Reuse the msg arrow columns as destination column
|
// Reuse the msg arrow columns as destination column
|
||||||
if ((msgarrow = call_flow_arrow_find(ui, msg))) {
|
if ((msgarrow = call_flow_arrow_find(ui, msg))) {
|
||||||
arrow->scolumn = msgarrow->scolumn;
|
// Get origin and destination column
|
||||||
|
arrow->scolumn = call_flow_column_get(ui, msg->call->callid, msg->packet->src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefer message that configured this stream rather than any column
|
||||||
|
if (!arrow->scolumn) {
|
||||||
|
msg = stream->media->msg;
|
||||||
|
// If message and stream share the same IP address
|
||||||
|
if (address_equals(msg->packet->dst, stream->src)) {
|
||||||
|
// Reuse the msg arrow columns as destination column
|
||||||
|
if ((msgarrow = call_flow_arrow_find(ui, msg))) {
|
||||||
|
arrow->scolumn = call_flow_column_get(ui, msg->call->callid, msg->packet->dst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,16 +748,23 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if displayed stream is active
|
||||||
|
int active = stream_is_active(stream);
|
||||||
|
|
||||||
// Clear the line
|
// Clear the line
|
||||||
mvwprintw(win, cline, startpos + 2, "%*s", distance, "");
|
mvwprintw(win, cline, startpos + 2, "%*s", distance, "");
|
||||||
// Draw method
|
// Draw RTP arrow text
|
||||||
mvwprintw(win, cline, startpos + (distance) / 2 - strlen(text) / 2 + 2, "%s", text);
|
mvwprintw(win, cline, startpos + (distance) / 2 - strlen(text) / 2 + 2, "%s", text);
|
||||||
|
|
||||||
if (!setting_has_value(SETTING_CF_SDP_INFO, "compressed"))
|
if (!setting_has_value(SETTING_CF_SDP_INFO, "compressed"))
|
||||||
cline++;
|
cline++;
|
||||||
|
|
||||||
// Draw line between columns
|
// Draw line between columns
|
||||||
mvwhline(win, cline, startpos + 2, ACS_HLINE, distance);
|
if (active)
|
||||||
|
mvwhline(win, cline, startpos + 2, '-', distance);
|
||||||
|
else
|
||||||
|
mvwhline(win, cline, startpos + 2, ACS_HLINE, distance);
|
||||||
|
|
||||||
// Write the arrow at the end of the message (two arrows if this is a retrans)
|
// Write the arrow at the end of the message (two arrows if this is a retrans)
|
||||||
if (arrow_dir == CF_ARROW_RIGHT) {
|
if (arrow_dir == CF_ARROW_RIGHT) {
|
||||||
if (!setting_has_value(SETTING_CF_SDP_INFO, "compressed")) {
|
if (!setting_has_value(SETTING_CF_SDP_INFO, "compressed")) {
|
||||||
@ -751,7 +772,7 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||||||
mvwprintw(win, cline, endpos, "%d", stream->dst.port);
|
mvwprintw(win, cline, endpos, "%d", stream->dst.port);
|
||||||
}
|
}
|
||||||
mvwaddch(win, cline, endpos - 2, '>');
|
mvwaddch(win, cline, endpos - 2, '>');
|
||||||
if (arrow->rtp_count != stream_get_count(stream)) {
|
if (active) {
|
||||||
arrow->rtp_count = stream_get_count(stream);
|
arrow->rtp_count = stream_get_count(stream);
|
||||||
arrow->rtp_ind_pos = (arrow->rtp_ind_pos + 1) % distance;
|
arrow->rtp_ind_pos = (arrow->rtp_ind_pos + 1) % distance;
|
||||||
mvwaddch(win, cline, startpos + arrow->rtp_ind_pos + 2, '>');
|
mvwaddch(win, cline, startpos + arrow->rtp_ind_pos + 2, '>');
|
||||||
@ -762,7 +783,7 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||||||
mvwprintw(win, cline, startpos - 4, "%d", stream->dst.port);
|
mvwprintw(win, cline, startpos - 4, "%d", stream->dst.port);
|
||||||
}
|
}
|
||||||
mvwaddch(win, cline, startpos + 2, '<');
|
mvwaddch(win, cline, startpos + 2, '<');
|
||||||
if (arrow->rtp_count != stream_get_count(stream)) {
|
if (active) {
|
||||||
arrow->rtp_count = stream_get_count(stream);
|
arrow->rtp_count = stream_get_count(stream);
|
||||||
arrow->rtp_ind_pos = (arrow->rtp_ind_pos + 1) % distance;
|
arrow->rtp_ind_pos = (arrow->rtp_ind_pos + 1) % distance;
|
||||||
mvwaddch(win, cline, endpos - arrow->rtp_ind_pos - 2, '<');
|
mvwaddch(win, cline, endpos - arrow->rtp_ind_pos - 2, '<');
|
||||||
@ -814,6 +835,8 @@ int
|
|||||||
call_flow_arrow_height(ui_t *ui, const call_flow_arrow_t *arrow)
|
call_flow_arrow_height(ui_t *ui, const call_flow_arrow_t *arrow)
|
||||||
{
|
{
|
||||||
if (arrow->type == CF_ARROW_SIP) {
|
if (arrow->type == CF_ARROW_SIP) {
|
||||||
|
if (setting_enabled(SETTING_CF_ONLYMEDIA))
|
||||||
|
return 0;
|
||||||
if (setting_has_value(SETTING_CF_SDP_INFO, "compressed"))
|
if (setting_has_value(SETTING_CF_SDP_INFO, "compressed"))
|
||||||
return 1;
|
return 1;
|
||||||
if (!msg_has_sdp(arrow->item))
|
if (!msg_has_sdp(arrow->item))
|
||||||
@ -921,7 +944,7 @@ call_flow_draw_raw(ui_t *ui, sip_msg_t *msg)
|
|||||||
info->raw_win = raw_win = newwin(raw_height, raw_width, 0, 0);
|
info->raw_win = raw_win = newwin(raw_height, raw_width, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw raw box lines
|
// Draw raw box li
|
||||||
wattron(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF));
|
wattron(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF));
|
||||||
mvwvline(ui->win, 1, ui->width - raw_width - 2, ACS_VLINE, ui->height - 2);
|
mvwvline(ui->win, 1, ui->width - raw_width - 2, ACS_VLINE, ui->height - 2);
|
||||||
wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF));
|
wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF));
|
||||||
@ -939,6 +962,11 @@ call_flow_draw_raw(ui_t *ui, sip_msg_t *msg)
|
|||||||
int
|
int
|
||||||
call_flow_draw_raw_rtcp(ui_t *ui, rtp_stream_t *stream)
|
call_flow_draw_raw_rtcp(ui_t *ui, rtp_stream_t *stream)
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* TODO This is too experimental to even display it
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
|
||||||
call_flow_info_t *info;
|
call_flow_info_t *info;
|
||||||
WINDOW *raw_win;
|
WINDOW *raw_win;
|
||||||
int raw_width, raw_height;
|
int raw_width, raw_height;
|
||||||
@ -1094,6 +1122,10 @@ call_flow_handle_key(ui_t *ui, int key)
|
|||||||
case ACTION_SDP_INFO:
|
case ACTION_SDP_INFO:
|
||||||
setting_toggle(SETTING_CF_SDP_INFO);
|
setting_toggle(SETTING_CF_SDP_INFO);
|
||||||
break;
|
break;
|
||||||
|
case ACTION_ONLY_MEDIA:
|
||||||
|
setting_toggle(SETTING_CF_ONLYMEDIA);
|
||||||
|
call_flow_set_group(info->group);
|
||||||
|
break;
|
||||||
case ACTION_TOGGLE_MEDIA:
|
case ACTION_TOGGLE_MEDIA:
|
||||||
setting_toggle(SETTING_CF_MEDIA);
|
setting_toggle(SETTING_CF_MEDIA);
|
||||||
// Force reload arrows
|
// Force reload arrows
|
||||||
@ -1463,12 +1495,18 @@ call_flow_arrow_filter(void *item)
|
|||||||
call_flow_arrow_t *arrow = (call_flow_arrow_t *) item;
|
call_flow_arrow_t *arrow = (call_flow_arrow_t *) item;
|
||||||
|
|
||||||
// SIP arrows are never filtered
|
// SIP arrows are never filtered
|
||||||
if (arrow->type == CF_ARROW_SIP)
|
if (arrow->type == CF_ARROW_SIP && setting_disabled(SETTING_CF_ONLYMEDIA))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// RTP arrows are only displayed when requested
|
// RTP arrows are only displayed when requested
|
||||||
if (arrow->type == CF_ARROW_RTP && setting_enabled(SETTING_CF_MEDIA))
|
if (arrow->type == CF_ARROW_RTP) {
|
||||||
return 1;
|
// Display all streams
|
||||||
|
if (setting_enabled(SETTING_CF_MEDIA))
|
||||||
|
return 1;
|
||||||
|
// Otherwise only show active streams
|
||||||
|
if (setting_has_value(SETTING_CF_MEDIA, SETTING_ACTIVE))
|
||||||
|
return stream_is_active(arrow->item);
|
||||||
|
}
|
||||||
|
|
||||||
// Rest of the arrows are never displayed
|
// Rest of the arrows are never displayed
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -77,6 +77,7 @@ key_binding_t bindings[ACTION_SENTINEL] = {
|
|||||||
{ ACTION_SELECT, "select", { KEY_SPACE }, 1 },
|
{ ACTION_SELECT, "select", { KEY_SPACE }, 1 },
|
||||||
{ ACTION_CONFIRM, "confirm", { KEY_INTRO }, 1 },
|
{ ACTION_CONFIRM, "confirm", { KEY_INTRO }, 1 },
|
||||||
{ ACTION_TOGGLE_MEDIA, "togglemedia", { KEY_F(3), 'm' }, 2 },
|
{ ACTION_TOGGLE_MEDIA, "togglemedia", { KEY_F(3), 'm' }, 2 },
|
||||||
|
{ ACTION_ONLY_MEDIA, "onlymedia", { 'M' }, 1 },
|
||||||
{ ACTION_TOGGLE_RAW, "rawpreview", { 't' }, 1 },
|
{ ACTION_TOGGLE_RAW, "rawpreview", { 't' }, 1 },
|
||||||
{ ACTION_INCREASE_RAW, "morerawpreview", { '9' }, 1 },
|
{ ACTION_INCREASE_RAW, "morerawpreview", { '9' }, 1 },
|
||||||
{ ACTION_DECREASE_RAW, "lessrawpreview", { '0' }, 1 },
|
{ ACTION_DECREASE_RAW, "lessrawpreview", { '0' }, 1 },
|
||||||
|
@ -97,6 +97,7 @@ enum key_actions {
|
|||||||
ACTION_SELECT,
|
ACTION_SELECT,
|
||||||
ACTION_CONFIRM,
|
ACTION_CONFIRM,
|
||||||
ACTION_TOGGLE_MEDIA,
|
ACTION_TOGGLE_MEDIA,
|
||||||
|
ACTION_ONLY_MEDIA,
|
||||||
ACTION_TOGGLE_RAW,
|
ACTION_TOGGLE_RAW,
|
||||||
ACTION_INCREASE_RAW,
|
ACTION_INCREASE_RAW,
|
||||||
ACTION_DECREASE_RAW,
|
ACTION_DECREASE_RAW,
|
||||||
|
10
src/rtp.c
10
src/rtp.c
@ -29,6 +29,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <time.h>
|
||||||
#include "rtp.h"
|
#include "rtp.h"
|
||||||
#include "sip.h"
|
#include "sip.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
@ -100,6 +103,7 @@ stream_add_packet(rtp_stream_t *stream, packet_t *packet)
|
|||||||
if (stream->pktcnt == 0)
|
if (stream->pktcnt == 0)
|
||||||
stream->time = packet_time(packet);
|
stream->time = packet_time(packet);
|
||||||
|
|
||||||
|
stream->lasttm = (int) time(NULL);
|
||||||
stream->pktcnt++;
|
stream->pktcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,6 +476,12 @@ stream_is_complete(rtp_stream_t *stream)
|
|||||||
return (stream->pktcnt != 0);
|
return (stream->pktcnt != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
stream_is_active(rtp_stream_t *stream)
|
||||||
|
{
|
||||||
|
return ((int) time(NULL) - stream->lasttm <= STREAM_INACTIVE_SECS);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
data_is_rtp(u_char *data, uint32_t len)
|
data_is_rtp(u_char *data, uint32_t len)
|
||||||
{
|
{
|
||||||
|
17
src/rtp.h
17
src/rtp.h
@ -50,6 +50,9 @@
|
|||||||
// RTCP common header length
|
// RTCP common header length
|
||||||
#define RTCP_HDR_LENGTH 4
|
#define RTCP_HDR_LENGTH 4
|
||||||
|
|
||||||
|
// If stream does not receive a packet in this seconds, we consider it inactive
|
||||||
|
#define STREAM_INACTIVE_SECS 3
|
||||||
|
|
||||||
// RTCP header types
|
// RTCP header types
|
||||||
//! http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml
|
//! http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml
|
||||||
enum rtcp_header_types
|
enum rtcp_header_types
|
||||||
@ -108,6 +111,8 @@ struct rtp_stream {
|
|||||||
uint32_t pktcnt;
|
uint32_t pktcnt;
|
||||||
//! Time of first received packet of stream
|
//! Time of first received packet of stream
|
||||||
struct timeval time;
|
struct timeval time;
|
||||||
|
//! Unix timestamp of last received packet
|
||||||
|
int lasttm;
|
||||||
|
|
||||||
// Stream information (depending on type)
|
// Stream information (depending on type)
|
||||||
union {
|
union {
|
||||||
@ -321,6 +326,18 @@ stream_is_older(rtp_stream_t *one, rtp_stream_t *two);
|
|||||||
int
|
int
|
||||||
stream_is_complete(rtp_stream_t *stream);
|
stream_is_complete(rtp_stream_t *stream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if a stream is still active
|
||||||
|
*
|
||||||
|
* This simply checks the timestamp of the last received packet of the stream
|
||||||
|
* marking as inactive if it was before STREAM_INACTIVE_SECS ago
|
||||||
|
*
|
||||||
|
* @return 1 if stream is active
|
||||||
|
* @return 0 if stream is inactive
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
stream_is_active(rtp_stream_t *stream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the data is a RTP packet
|
* @brief Check if the data is a RTP packet
|
||||||
* RFC 5761 Section 4. Distinguishable RTP and RTCP Packets
|
* RFC 5761 Section 4. Distinguishable RTP and RTCP Packets
|
||||||
|
@ -67,7 +67,8 @@ setting_t settings[SETTING_COUNT] = {
|
|||||||
{ SETTING_CF_SCROLLSTEP, "cf.scrollstep", SETTING_FMT_NUMBER, "4", NULL },
|
{ SETTING_CF_SCROLLSTEP, "cf.scrollstep", SETTING_FMT_NUMBER, "4", NULL },
|
||||||
{ SETTING_CF_LOCALHIGHLIGHT, "cf.localhighlight", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
{ SETTING_CF_LOCALHIGHLIGHT, "cf.localhighlight", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||||
{ SETTING_CF_SDP_INFO, "cf.sdpinfo", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_SDP_INFO },
|
{ SETTING_CF_SDP_INFO, "cf.sdpinfo", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_SDP_INFO },
|
||||||
{ SETTING_CF_MEDIA, "cf.media", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
{ SETTING_CF_MEDIA, "cf.media", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_MEDIA },
|
||||||
|
{ SETTING_CF_ONLYMEDIA, "cf.onlymedia", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||||
{ SETTING_CF_DELTA, "cf.deltatime", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
{ SETTING_CF_DELTA, "cf.deltatime", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||||
{ SETTING_CR_SCROLLSTEP, "cr.scrollstep", SETTING_FMT_NUMBER, "10", NULL },
|
{ SETTING_CR_SCROLLSTEP, "cr.scrollstep", SETTING_FMT_NUMBER, "10", NULL },
|
||||||
{ SETTING_FILTER_PAYLOAD, "filter.payload", SETTING_FMT_STRING, "", NULL },
|
{ SETTING_FILTER_PAYLOAD, "filter.payload", SETTING_FMT_STRING, "", NULL },
|
||||||
|
@ -56,12 +56,14 @@ typedef struct setting_option setting_t;
|
|||||||
#define SETTING_ENUM_SDP_INFO (const char *[]){ "off", "first", "full", "compressed", NULL}
|
#define SETTING_ENUM_SDP_INFO (const char *[]){ "off", "first", "full", "compressed", NULL}
|
||||||
#define SETTING_ENUM_STORAGE (const char *[]){ "none", "memory", NULL }
|
#define SETTING_ENUM_STORAGE (const char *[]){ "none", "memory", NULL }
|
||||||
#define SETTING_ENUM_HEPVERSION (const char *[]){ "2", "3", NULL }
|
#define SETTING_ENUM_HEPVERSION (const char *[]){ "2", "3", NULL }
|
||||||
|
#define SETTING_ENUM_MEDIA (const char *[]){ "off", "on", "active", NULL }
|
||||||
|
|
||||||
//! Other useful defines
|
//! Other useful defines
|
||||||
#define SETTING_ON "on"
|
#define SETTING_ON "on"
|
||||||
#define SETTING_OFF "off"
|
#define SETTING_OFF "off"
|
||||||
#define SETTING_YES "yes"
|
#define SETTING_YES "yes"
|
||||||
#define SETTING_NO "no"
|
#define SETTING_NO "no"
|
||||||
|
#define SETTING_ACTIVE "active"
|
||||||
|
|
||||||
|
|
||||||
//! Available setting Options
|
//! Available setting Options
|
||||||
@ -98,6 +100,7 @@ enum setting_id {
|
|||||||
SETTING_CF_LOCALHIGHLIGHT,
|
SETTING_CF_LOCALHIGHLIGHT,
|
||||||
SETTING_CF_SDP_INFO,
|
SETTING_CF_SDP_INFO,
|
||||||
SETTING_CF_MEDIA,
|
SETTING_CF_MEDIA,
|
||||||
|
SETTING_CF_ONLYMEDIA,
|
||||||
SETTING_CF_DELTA,
|
SETTING_CF_DELTA,
|
||||||
SETTING_CR_SCROLLSTEP,
|
SETTING_CR_SCROLLSTEP,
|
||||||
SETTING_FILTER_PAYLOAD,
|
SETTING_FILTER_PAYLOAD,
|
||||||
|
Loading…
Reference in New Issue
Block a user