More vector refactoring

This commit is contained in:
Kaian 2015-06-22 17:20:14 +02:00
parent b4b434a04d
commit 6f4b8d9e58
14 changed files with 341 additions and 410 deletions

View File

@ -182,8 +182,6 @@ parse_packet(u_char *mode, const struct pcap_pkthdr *header, const u_char *packe
int transport; /* 0 UDP, 1 TCP, 2 TLS */
// Source and Destination Ports
u_short sport, dport;
// Media structure for RTP packets
//rtp_stream_t *stream;
// Ignore packets while capture is paused
if (capture_is_paused())
@ -337,10 +335,14 @@ parse_packet(u_char *mode, const struct pcap_pkthdr *header, const u_char *packe
// Store this packets in output file
dump_packet(capinfo.pd, header, packet);
} else {
#if 0
// Check if this is a RTP packet from active calls
sip_call_t *call;
for (call = call_get_next_active(NULL); call; call = call_get_next_active(call)) {
// Media structure for RTP packets
rtp_stream_t *stream;
vector_iter_t calls = sip_calls_iterator();
vector_iterator_set_filter(&calls, call_is_active);
while ((call = vector_iterator_next(&calls))) {
// Check if this call has an RTP stream for current packet data
if ((stream = call_find_stream(call, ip_src, sport, ip_dst, dport))) {
//! Add packet to found stream
@ -350,7 +352,6 @@ parse_packet(u_char *mode, const struct pcap_pkthdr *header, const u_char *packe
break;
}
}
#endif
}
// Deallocate packet duplicated payload

View File

@ -91,29 +91,6 @@ filter_get(int type)
return filters[type].expr;
}
void
filter_stats(int *total, int *displayed)
{
// TODO
// sip_call_t *call = NULL;
//
// // Initialize stats
// *total = 0;
// *displayed = 0;
//
// while ((call = call_get_next(call))) {
// (*total)++;
// if (filter_check_call(call) == 0)
// (*displayed)++;
// }
vector_iter_t it = sip_calls_iterator();
*total = vector_iterator_count(&it);
vector_iterator_set_filter(&it, filter_check_call);
*displayed = vector_iterator_count(&it);
}
int
filter_check_call(void *item)
{
@ -124,7 +101,7 @@ filter_check_call(void *item)
// Filter for this call has already be processed
if (call->filtered != -1)
return call->filtered;
return (call->filtered == 0);
// By default, call matches all filters
call->filtered = 0;
@ -179,15 +156,16 @@ filter_check_call(void *item)
}
// Return the final filter status
return call->filtered;
return (call->filtered == 0);
}
void
filter_reset_calls()
{
sip_call_t *call = NULL;
sip_call_t *call;
vector_iter_t calls = sip_calls_iterator();
// Force filter evaluation
while ((call = call_get_next(call)))
while ((call = vector_iterator_next(&calls)))
call->filtered = -1;
}

View File

@ -109,15 +109,6 @@ filter_set(int type, const char *expr);
const char *
filter_get(int type);
/**
* @brief Get Filtered calls
*
* @param total Total calls processed
* @param displayed number of calls matching filters
*/
void
filter_stats(int *total, int *displayed);
/**
* @brief Check if a call if filtered
*

View File

@ -38,6 +38,7 @@ call_group_create()
return NULL;
}
memset(group, 0, sizeof(sip_call_group_t));
group->calls = vector_create(5, 2);
return group;
}
@ -50,54 +51,32 @@ call_group_destroy(sip_call_group_t *group)
void
call_group_add(sip_call_group_t *group, sip_call_t *call)
{
if (!group || !call || call_group_exists(group, call))
return;
group->calls[group->callcnt++] = call;
vector_append(group->calls, call);
}
void
call_group_del(sip_call_group_t *group, sip_call_t *call)
{
int i;
if (!group || !call || !call_group_exists(group, call))
return;
for (i = 0; i < group->callcnt; i++) {
if (call == group->calls[i]) {
group->calls[i] = group->calls[i + 1];
call = group->calls[i + 1];
}
}
group->callcnt--;
vector_remove(group->calls, call);
}
int
call_group_exists(sip_call_group_t *group, sip_call_t *call)
{
int i;
for (i = 0; i < group->callcnt; i++) {
if (call == group->calls[i])
return 1;
}
return 0;
return (vector_index(group->calls, call) >= 0) ? 1 : 0;
}
int
call_group_color(sip_call_group_t *group, sip_call_t *call)
{
int i;
for (i = 0; i < group->callcnt; i++) {
if (call == group->calls[i]) {
return (i % 7) + 1;
}
}
return -1;
return (vector_index(group->calls, call) % 7) + 1;
}
sip_call_t *
call_group_get_next(sip_call_group_t *group, sip_call_t *call)
{
sip_msg_t *next, *first;
sip_call_t *c;
int i;
if (!group)
@ -115,15 +94,16 @@ call_group_get_next(sip_call_group_t *group, sip_call_t *call)
next = NULL;
// Get the call with the next chronological message
for (i = 0; i < group->callcnt; i++) {
if (group->calls[i] == call)
for (i = 0; i < vector_count(group->calls); i++) {
if ((c = vector_item(group->calls, i)) == call)
continue;
// Get first message
first = call_get_next_msg(group->calls[i], NULL);
first = vector_first(c->msgs);
// Is first message of this call older?
if (sip_msg_is_older(first, call->msgs) && (!next || !sip_msg_is_older(first, next))) {
if (sip_msg_is_older(first, vector_first(call->msgs))
&& (!next || !sip_msg_is_older(first, next))) {
next = first;
break;
}
@ -135,25 +115,23 @@ call_group_get_next(sip_call_group_t *group, sip_call_t *call)
int
call_group_count(sip_call_group_t *group)
{
return group->callcnt;
return vector_count(group->calls);
}
int
call_group_msg_count(sip_call_group_t *group)
{
sip_msg_t *msg = NULL;
sip_call_t *call;
vector_iter_t msgs;
int msgcnt = 0, i;
for (i = 0; i < group->callcnt; i++) {
for (i = 0; i < vector_count(group->calls); i++) {
call = vector_item(group->calls, i);
msgs = vector_iterator(call->msgs);
if (group->sdp_only) {
while ((msg = call_get_next_msg(group->calls[i], msg))) {
if (!msg->sdp)
continue;
msgcnt++;
}
} else {
msgcnt += call_msg_count(group->calls[i]);
vector_iterator_set_filter(&msgs, msg_has_sdp);
}
msgcnt += vector_iterator_count(&msgs);
}
return msgcnt;
}
@ -179,24 +157,30 @@ call_group_get_next_msg(sip_call_group_t *group, sip_msg_t *msg)
{
sip_msg_t *next = NULL;
sip_msg_t *cand;
vector_iter_t msgs;
sip_call_t *call;
int i;
// FIXME Performance hack for huge dialogs
if (group->callcnt == 1) {
cand = msg;
while ((cand = call_get_next_msg(group->calls[0], cand))) {
if (group->sdp_only && !cand->sdp)
continue;
break;
}
return cand;
if (vector_count(group->calls) == 1) {
call = vector_first(group->calls);
msgs = vector_iterator(call->msgs);
vector_iterator_set_current(&msgs, vector_index(call->msgs, msg));
if (group->sdp_only)
vector_iterator_set_filter(&msgs, msg_has_sdp);
return vector_iterator_next(&msgs);
}
for (i = 0; i < group->callcnt; i++) {
for (i = 0; i < vector_count(group->calls); i++) {
call = vector_item(group->calls, i);
msgs = vector_iterator(call->msgs);
if (group->sdp_only)
vector_iterator_set_filter(&msgs, msg_has_sdp);
cand = NULL;
while ((cand = call_get_next_msg(group->calls[i], cand))) {
if (group->sdp_only && !cand->sdp)
continue;
while ((cand = vector_iterator_next(&msgs))) {
// candidate must be between msg and next
if (sip_msg_is_older(cand, msg) && (!next || !sip_msg_is_older(cand, next))) {
next = cand;
@ -228,10 +212,12 @@ call_group_get_next_stream(sip_call_group_t *group, rtp_stream_t *stream)
{
rtp_stream_t *next = NULL;
rtp_stream_t *cand;
sip_call_t *call;
int i;
for (i = 0; i < group->callcnt; i++) {
for (cand = group->calls[i]->streams; cand; cand = cand->next) {
for (i = 0; i < vector_count(group->calls); i++) {
call = vector_item(group->calls, i);
for (cand = call ->streams; cand; cand = cand->next) {
if (!stream_get_count(cand))
continue;

View File

@ -50,9 +50,7 @@ typedef struct sip_call_group sip_call_group_t;
*/
struct sip_call_group {
//! Calls array in the group
sip_call_t *calls[1024];
//! Calls counter
int callcnt;
vector_t *calls;
//! Color of the last printed call in mode Color-by-Call
int color;
//! Only consider SDP messages from Calls

View File

@ -64,7 +64,7 @@ setting_t settings[SETTING_COUNT] =
{ SETTING_CF_SCROLLSTEP, "cf.scrollstep", SETTING_FMT_NUMBER, "4", NULL },
{ SETTING_CF_LOCALHIGHLIGHT, "cf.localhighlight", SETTING_FMT_ENUM, "on", SETTING_ENUM_ONOFF },
{ SETTING_CF_SDP_INFO, "cf.sdpinfo", SETTING_FMT_ENUM, "off", SETTING_ENUM_SDP_INFO },
{ SETTING_CF_MEDIA, "cf.media", SETTING_FMT_ENUM, "off", SETTING_ENUM_ONOFF },
{ SETTING_CF_MEDIA, "cf.media", SETTING_FMT_ENUM, "on", SETTING_ENUM_ONOFF },
{ SETTING_CF_DELTA, "cf.deltatime", SETTING_FMT_ENUM, "on", SETTING_ENUM_ONOFF },
{ SETTING_CR_SCROLLSTEP, "cr.scrollstep", SETTING_FMT_NUMBER, "10", NULL },
{ SETTING_FILTER_METHODS, "filter.methods", SETTING_FMT_STRING, NULL, NULL },

208
src/sip.c
View File

@ -108,24 +108,10 @@ sip_msg_create(const char *payload)
void
sip_msg_destroy(sip_msg_t *msg)
{
sip_msg_t *prev = NULL;
if (!msg)
return;
// If the message belongs to a call, remove it from
// its message list
if (msg->call) {
if ((prev = call_get_prev_msg(msg->call, msg))) {
prev->next = msg->next;
} else {
msg->call->msgs = msg->next;
}
if (msg->next) {
msg->next->prev = msg->prev;
}
}
// Free message attribute list
sip_attr_list_destroy(msg->attrs);
@ -154,13 +140,18 @@ sip_call_create(char *callid)
memset(call, 0, sizeof(sip_call_t));
// Add this call to the call list
pthread_mutex_lock(&calls.lock);
index = vector_append(calls.list, call);
pthread_mutex_unlock(&calls.lock);
// Store this call in hash table
entry.key = strdup(callid);
entry.data = (void *) call;
hsearch(entry, ENTER);
// Create a vector to store call messages
call->msgs = vector_create(10, 5);
// Initialize call filter status
call->filtered = -1;
@ -173,6 +164,9 @@ sip_call_create(char *callid)
void
sip_call_destroy(sip_call_t *call)
{
sip_msg_t *msg;
vector_iter_t msgs;
// No call to destroy
if (!call)
return;
@ -181,8 +175,12 @@ sip_call_destroy(sip_call_t *call)
vector_remove(calls.list, call);
// Remove all call messages
while (call->msgs)
sip_msg_destroy(call->msgs);
msgs = vector_iterator(call->msgs);
while ((msg = vector_iterator_next(&msgs))) {
sip_msg_destroy(msg);
vector_remove(call->msgs, msg);
}
// Remove all call attributes
sip_attr_list_destroy(call->attrs);
@ -342,28 +340,29 @@ sip_calls_iterator()
return vector_iterator(calls.list);
}
void
sip_calls_stats(int *total, int *displayed)
{
vector_iter_t it = vector_iterator(calls.list);
pthread_mutex_lock(&calls.lock);
// Total number of calls without filtering
*total = vector_iterator_count(&it);
// Total number of calls after filtering
vector_iterator_set_filter(&it, filter_check_call);
*displayed = vector_iterator_count(&it);
pthread_mutex_unlock(&calls.lock);
}
void
call_add_message(sip_call_t *call, sip_msg_t *msg)
{
// Set the message owner
msg->call = call;
// Put this msg at the end of the msg list
if (!call->msgs) {
call->msgs = msg;
msg->prev = NULL;
} else {
call->last_msg->next = msg;
msg->prev = call->last_msg;
}
call->last_msg = msg;
// Increase message count
call->msgcnt++;
vector_append(call->msgs, msg);
// Store message count
call_set_attribute(call, SIP_ATTR_MSGCNT, "%d", call->msgcnt);
call_set_attribute(call, SIP_ATTR_MSGCNT, "%d", vector_count(call->msgs));
}
sip_call_t *
@ -398,7 +397,7 @@ call_find_by_xcallid(const char *xcallid)
int
call_msg_count(sip_call_t *call)
{
return call->msgcnt;
return vector_count(call->msgs);
}
int
@ -432,9 +431,9 @@ call_get_next_msg(sip_call_t *call, sip_msg_t *msg)
sip_msg_t *ret;
pthread_mutex_lock(&calls.lock);
if (msg == NULL) {
ret = call->msgs;
ret = vector_first(call->msgs);
} else {
ret = msg->next;
ret = vector_item(call->msgs, vector_index(call->msgs, msg) + 1);
}
// Parse message if not parsed
@ -450,13 +449,7 @@ call_get_prev_msg(sip_call_t *call, sip_msg_t *msg)
{
sip_msg_t *ret = NULL;
pthread_mutex_lock(&calls.lock);
if (msg == NULL) {
// No message, no previous
ret = NULL;
} else {
// Get previous message
ret = msg->prev;
}
ret = vector_item(call->msgs, vector_index(call->msgs, msg) - 1);
// Parse message if not parsed
if (ret && !ret->parsed)
@ -466,66 +459,22 @@ call_get_prev_msg(sip_call_t *call, sip_msg_t *msg)
return ret;
}
sip_call_t *
call_get_next(sip_call_t *cur)
int
call_is_active(void *item)
{
sip_call_t * next;
pthread_mutex_lock(&calls.lock);
next = vector_item(calls.list, vector_index(calls.list, cur) + 1);
pthread_mutex_unlock(&calls.lock);
return next;
// TODO
sip_call_t *call = (sip_call_t *)item;
return call->active;
}
sip_call_t *
call_get_prev(sip_call_t *cur)
int
msg_has_sdp(void *item)
{
sip_call_t *prev;
pthread_mutex_lock(&calls.lock);
prev = vector_item(calls.list, vector_index(calls.list, cur) - 1);
pthread_mutex_unlock(&calls.lock);
return prev;
// TODO
sip_msg_t *msg = (sip_msg_t *)item;
return msg->sdp;
}
sip_call_t *
call_get_next_filtered(sip_call_t *cur)
{
sip_call_t *next = call_get_next(cur);
pthread_mutex_lock(&calls.lock);
// Return next not filtered call
if (next && filter_check_call(next))
next = call_get_next_filtered(next);
pthread_mutex_unlock(&calls.lock);
return next;
}
sip_call_t *
call_get_prev_filtered(sip_call_t *cur)
{
sip_call_t *prev = call_get_prev(cur);
pthread_mutex_lock(&calls.lock);
// Return previous call if this one is filtered
if (prev && filter_check_call(prev))
prev = call_get_prev_filtered(prev);
pthread_mutex_unlock(&calls.lock);
return prev;
}
sip_call_t *
call_get_next_active(sip_call_t *cur)
{
sip_call_t *next;
for (next = call_get_next(cur); next; next = call_get_next(next))
if (next && next->active)
break;
return next;
}
void
call_update_state(sip_call_t *call, sip_msg_t *msg)
@ -533,13 +482,17 @@ call_update_state(sip_call_t *call, sip_msg_t *msg)
const char *callstate;
char dur[20];
int reqresp;
sip_msg_t *first;
// Sanity check
if (!call || !call->msgs || !msg)
return;
// Get the first message in the call
first = vector_first(call->msgs);
// Check First message of Call has INVITE method
if (call->msgs->reqresp != SIP_METHOD_INVITE) {
if (first->reqresp != SIP_METHOD_INVITE) {
return;
}
@ -559,15 +512,13 @@ call_update_state(sip_call_t *call, sip_msg_t *msg)
// Alice is not in the mood
call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CANCELLED);
// Store total call duration
call_set_attribute(call, SIP_ATTR_TOTALDUR,
sip_calculate_duration(call->msgs, msg, dur));
call_set_attribute(call, SIP_ATTR_TOTALDUR, sip_calculate_duration(first, msg, dur));
call->active = 0;
} else if (reqresp > 400) {
// Bob is not in the mood
call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_REJECTED);
// Store total call duration
call_set_attribute(call, SIP_ATTR_TOTALDUR,
sip_calculate_duration(call->msgs, msg, dur));
call_set_attribute(call, SIP_ATTR_TOTALDUR, sip_calculate_duration(first, msg, dur));
call->active = 0;
}
} else if (!strcmp(callstate, SIP_CALLSTATE_INCALL)) {
@ -585,8 +536,7 @@ call_update_state(sip_call_t *call, sip_msg_t *msg)
call->active = 1;
} else {
// Store total call duration
call_set_attribute(call, SIP_ATTR_TOTALDUR,
sip_calculate_duration(call->msgs, msg, dur));
call_set_attribute(call, SIP_ATTR_TOTALDUR, sip_calculate_duration(first, msg, dur));
}
} else {
// This is actually a call
@ -595,8 +545,6 @@ call_update_state(sip_call_t *call, sip_msg_t *msg)
call->active = 1;
}
}
}
void
@ -869,23 +817,18 @@ int
msg_is_retrans(sip_msg_t *msg)
{
sip_msg_t *prev = NULL;
vector_iter_t it;
// Sanity check
if (!msg || !msg->call || !msg->payload)
return 0;
// Start on previous message
prev = msg;
// Get previous message in call
it = vector_iterator(msg->call->msgs);
vector_iterator_set_current(&it, vector_index(msg->call->msgs, msg));
prev = vector_iterator_prev(&it);
// Check previous messages in same call
while ((prev = call_get_prev_msg(msg->call, prev))) {
// Check if the payload is exactly the same
if (!strcasecmp(msg->payload, prev->payload)) {
return 1;
}
}
return 0;
return (prev && !strcasecmp(msg->payload, prev->payload));
}
int
@ -894,41 +837,6 @@ msg_is_request(sip_msg_t *msg)
return msg->reqresp < SIP_METHOD_SENTINEL;
}
sip_msg_t *
msg_get_request(sip_msg_t *msg)
{
sip_msg_t *tmp = msg;
if (!msg)
return NULL;
if (!msg_is_request(msg))
return NULL;
for (tmp = call_get_prev_msg(msg->call, tmp); tmp; tmp = call_get_prev_msg(msg->call, tmp)) {
if (msg_is_request(tmp))
continue;
if (!strcmp(tmp->src, msg->dst) && tmp->sport == msg->dport)
return tmp;
}
return NULL;
}
sip_msg_t *
msg_get_request_sdp(sip_msg_t *msg)
{
sip_msg_t *tmp = msg;
while (tmp) {
if ((tmp = msg_get_request(tmp)) && tmp->sdp)
return tmp;
}
return NULL;
}
char *
msg_get_header(sip_msg_t *msg, char *out)
{
@ -1072,7 +980,7 @@ call_get_attribute(sip_call_t *call, enum sip_attr_id id)
case SIP_ATTR_TOTALDUR:
return sip_attr_get(call->attrs, id);
default:
return msg_get_attribute(call_get_next_msg(call, NULL), id);
return msg_get_attribute(vector_first(call->msgs), id);
}
return NULL;

108
src/sip.h
View File

@ -90,11 +90,11 @@ struct sip_msg {
//! Message attribute list
char *attrs[SIP_ATTR_COUNT];
//! Source address
char src[50];
char src[ADDRESSLEN];
//! Source port
u_short sport;
//! Destination address
char dst[50];
char dst[ADDRESSLEN];
//! Destination port
u_short dport;
//! Temporal payload data before being parsed
@ -118,10 +118,6 @@ struct sip_msg {
u_char *pcap_packet;
//! Message owner
sip_call_t *call;
//! Messages Double linked list
sip_msg_t *prev;
sip_msg_t *next;
};
/**
@ -138,12 +134,8 @@ struct sip_call {
int filtered;
//! For call dialogs, mark if call has not yet finished
int active;
//! List of messages of this call
sip_msg_t *msgs;
//! Pointer to the last added message
sip_msg_t *last_msg;
//! How many messages has this call
int msgcnt;
//! List of messages of this call (sip_msg_t*)
vector_t *msgs;
//! Message when conversation started
sip_msg_t *cstart_msg;
//! RTP streams for this call
@ -294,6 +286,15 @@ sip_calls_count();
vector_iter_t
sip_calls_iterator();
/**
* @brief Return stats from call list
*
* @param total Total calls processed
* @param displayed number of calls matching filters
*/
void
sip_calls_stats(int *total, int *displayed);
/**
* @brief Append message to the call's message list
*
@ -366,79 +367,12 @@ msg_media_count(sip_msg_t *msg);
sip_call_t *
call_get_xcall(sip_call_t *call);
/**
* @brief Finds the next msg in a call.
*
* If the passed msg is NULL it returns the first message
* in the call
*
* @param call SIP call structure
* @param msg Actual SIP msg from the call (can be NULL)
* @return Next chronological message in the call
*/
sip_msg_t *
call_get_next_msg(sip_call_t *call, sip_msg_t *msg);
/**
* @brief Finds the prev msg in a call.
*
* If the passed msg is the first message in the call
* this function will return NULL
*
* @param call SIP call structure
* @param msg Actual SIP msg from the call
* @return Previous chronological message in the call
*/
sip_msg_t *
call_get_prev_msg(sip_call_t *call, sip_msg_t *msg);
int
call_is_active(void *item);
/**
* @brief Get next call
*
* General getter for call list. Never access calls list
* directly, use this instead.
*
* @param cur Current call. Pass NULL to get the first call.
* @return Next call in the list or NULL if there is no next call
*/
sip_call_t *
call_get_next(sip_call_t *cur);
/**
* @brief Get previous call
*
* General getter for call list. Never access calls list
* directly, use this instead.
*
* @param cur Current call
* @return Prev call in the list or NULL if there is no previous call
*/
sip_call_t *
call_get_prev(sip_call_t *cur);
/**
* @brief Get next call after applying filters and ignores
*
* @param cur Current call. Pass NULL to get the first call.
* @return Next call in the list or NULL if there is no next call
*/
sip_call_t *
call_get_next_filtered(sip_call_t *cur);
/**
* @brief Get previous call applying filters and ignores
*
* General getter for call list. Never access calls list
* directly, use this instead.
*
* @param cur Current call
* @return Prev call in the list or NULL if there is no previous call
*/
sip_call_t *
call_get_prev_filtered(sip_call_t *cur);
sip_call_t *
call_get_next_active(sip_call_t *cur);
int
msg_has_sdp(void *item);
/**
* @brief Update Call State attribute with its last parsed message
@ -520,13 +454,6 @@ msg_is_retrans(sip_msg_t *msg);
int
msg_is_request(sip_msg_t *msg);
sip_msg_t *
msg_get_request(sip_msg_t *msg);
sip_msg_t *
msg_get_request_sdp(sip_msg_t *msg);
/**
* @brief Get summary of message header data
*
@ -676,7 +603,6 @@ sip_method_from_str(const char *method);
const char *
sip_address_format(const char *address);
/**
* @brief Return address:port formatted depending on active settings
*

View File

@ -145,11 +145,11 @@ call_flow_draw(PANEL *panel)
werase(win);
// Set title
if (info->group->callcnt == 1) {
if (call_group_count(info->group) == 1) {
sprintf(title, "Call flow for %s",
call_get_attribute(*info->group->calls, SIP_ATTR_CALLID));
call_get_attribute(vector_first(info->group->calls), SIP_ATTR_CALLID));
} else {
sprintf(title, "Call flow for %d dialogs", info->group->callcnt);
sprintf(title, "Call flow for %d dialogs", call_group_count(info->group));
}
// Print color mode in title
@ -840,16 +840,12 @@ call_flow_handle_key(PANEL *panel, int key)
case ACTION_SHOW_FLOW_EX:
werase(panel_window(panel));
// KEY_X , Display current call flow
if (info->group->callcnt == 1) {
group = call_group_create();
call_group_add(group, info->group->calls[0]);
call_group_add(group, call_get_xcall(info->group->calls[0]));
call_flow_set_group(group);
} else {
group = call_group_create();
call_group_add(group, info->group->calls[0]);
call_flow_set_group(group);
if (call_group_count(info->group) == 1) {
call_group_add(group, call_get_xcall(vector_first(info->group->calls)));
}
call_group_add(group, vector_first(info->group->calls));
call_flow_set_group(group);
break;
case ACTION_SHOW_RAW:
// KEY_R, display current call in raw mode

View File

@ -40,6 +40,7 @@
#include "ui_call_flow.h"
#include "ui_call_raw.h"
#include "ui_save.h"
#include "sip.h"
/**
* Ui Structure definition for Call List panel
@ -111,6 +112,11 @@ call_list_create()
info->list_win = subwin(win, height - 5, width, 4, 0);
info->group = call_group_create();
// Get current call list
info->calls = sip_calls_iterator();
vector_iterator_set_filter(&info->calls, filter_check_call);
info->cur_call = info->first_call = -1;
// Set defualt filter text if configured
if (setting_get_value(SETTING_CL_FILTER)) {
set_field_buffer(info->fields[FLD_LIST_FILTER], 0, setting_get_value(SETTING_CL_FILTER));
@ -217,7 +223,7 @@ call_list_draw_header(PANEL *panel)
wattroff(win, A_BOLD | A_REVERSE | COLOR_PAIR(CP_DEF_ON_CYAN));
// Get filter call counters
//filter_stats(&info->callcnt, &info->dispcallcnt);
sip_calls_stats(&info->callcnt, &info->dispcallcnt);
// Print calls count (also filtered)
mvwprintw(win, 1, 35, "%*s", 35, "");
@ -265,16 +271,21 @@ call_list_draw_list(PANEL *panel)
getmaxyx(win, height, width);
// If no active call, use the fist one (if exists)
if (!info->first_call && call_get_next_filtered(NULL)) {
info->cur_call = info->first_call = call_get_next_filtered(NULL);
if (info->first_call == -1 && vector_iterator_count(&info->calls)) {
vector_iterator_reset(&info->calls);
call = vector_iterator_next(&info->calls);
info->cur_call = info->first_call = vector_index(vector_iterator_vector(&info->calls), call);
info->cur_line = info->first_line = 1;
}
// Clear call list before redrawing
werase(win);
// Set the iterator position to the first call
vector_iterator_set_current(&info->calls, info->first_call - 1 );
// Fill the call list
for (call = info->first_call; call; call = call_get_next_filtered(call)) {
while ((call = vector_iterator_next(&info->calls))) {
// Stop if we have reached the bottom of the list
if (cline == height)
break;
@ -288,7 +299,7 @@ call_list_draw_list(PANEL *panel)
wattron(win, A_BOLD | COLOR_PAIR(CP_DEFAULT));
// Highlight active call
if (call == info->cur_call) {
if (call == vector_item(vector_iterator_vector(&info->calls), info->cur_call)) {
// Reverse colors on monochrome terminals
if (!has_colors())
wattron(win, A_REVERSE);
@ -417,6 +428,7 @@ call_list_handle_key(PANEL *panel, int key)
ui_t *next_panel;
sip_call_group_t *group;
int action = -1;
sip_call_t *call;
// Sanity check, this should not happen
if (!(info = call_list_info(panel)))
@ -430,29 +442,34 @@ call_list_handle_key(PANEL *panel, int key)
WINDOW *win = info->list_win;
getmaxyx(win, height, width);
// Reset iterator position to current call
vector_iterator_set_current(&info->calls, info->cur_call);
// Check actions for this key
while ((action = key_find_action(key, action)) != ERR) {
// Check if we handle this action
switch (action) {
case ACTION_DOWN:
// Check if there is a call below us
if (!info->cur_call || !call_get_next_filtered(info->cur_call))
if (!vector_iterator_next(&info->calls))
break;
info->cur_call = call_get_next_filtered(info->cur_call);
info->cur_call = vector_iterator_current(&info->calls);
info->cur_line++;
// If we are out of the bottom of the displayed list
// refresh it starting in the next call
if (info->cur_line > height) {
info->first_call = call_get_next_filtered(info->first_call);
vector_iterator_set_current(&info->calls, info->first_call);
vector_iterator_next(&info->calls);
info->first_call = vector_iterator_current(&info->calls);
info->first_line++;
info->cur_line = height;
}
break;
case ACTION_UP:
// Check if there is a call above us
if (!info->cur_call || !call_get_prev_filtered(info->cur_call))
if (!vector_iterator_prev(&info->calls))
break;
info->cur_call = call_get_prev_filtered(info->cur_call);
info->cur_call = vector_iterator_current(&info->calls);
info->cur_line--;
// If we are out of the top of the displayed list
// refresh it starting in the previous (in fact current) call
@ -484,48 +501,45 @@ call_list_handle_key(PANEL *panel, int key)
break;
case ACTION_SHOW_FLOW:
// Check we have calls in the list
if (!info->cur_call)
if (info->cur_call == -1)
break;
next_panel = ui_create_panel(PANEL_CALL_FLOW);
if (info->group->callcnt) {
ui_create_panel(PANEL_CALL_FLOW);
if (call_group_count(info->group)) {
group = info->group;
} else {
if (!info->cur_call)
break;
group = call_group_create();
call_group_add(group, info->cur_call);
call = vector_item(vector_iterator_vector(&info->calls), info->cur_call);
call_group_add(group, call);
}
call_flow_set_group(group);
break;
case ACTION_SHOW_FLOW_EX:
// Check we have calls in the list
if (!info->cur_call)
if (info->cur_call == -1)
break;
// Display current call flow (extended)
ui_create_panel(PANEL_CALL_FLOW);
if (info->group->callcnt) {
if (call_group_count(info->group)) {
group = info->group;
} else {
if (!info->cur_call)
break;
group = call_group_create();
call_group_add(group, info->cur_call);
call_group_add(group, call_get_xcall(info->cur_call));
call = vector_item(vector_iterator_vector(&info->calls), info->cur_call);
call_group_add(group, call);
call_group_add(group, call_get_xcall(call));
}
call_flow_set_group(group);
break;
case ACTION_SHOW_RAW:
// Check we have calls in the list
if (!info->cur_call)
if (info->cur_call == -1)
break;
ui_create_panel(PANEL_CALL_RAW);
if (info->group->callcnt) {
if (call_group_count(info->group)) {
group = info->group;
} else {
if (!info->cur_call)
break;
group = call_group_create();
call_group_add(group, info->cur_call);
call = vector_item(vector_iterator_vector(&info->calls), info->cur_call);
call_group_add(group, call);
}
call_raw_set_group(group);
break;
@ -556,12 +570,11 @@ call_list_handle_key(PANEL *panel, int key)
ui_create_panel(PANEL_SETTINGS);
break;
case ACTION_SELECT:
if (!info->cur_call)
break;
if (call_group_exists(info->group, info->cur_call)) {
call_group_del(info->group, info->cur_call);
call = vector_item(vector_iterator_vector(&info->calls), info->cur_call);
if (call_group_exists(info->group, call)) {
call_group_del(info->group, call);
} else {
call_group_add(info->group, info->cur_call);
call_group_add(info->group, call);
}
break;
case ACTION_PREV_SCREEN:
@ -825,9 +838,9 @@ call_list_clear(PANEL *panel)
return;
// Initialize structures
info->first_call = info->cur_call = NULL;
info->first_call = info->cur_call = -1;
info->first_line = info->cur_line = 0;
info->group->callcnt = 0;
vector_clear(info->group->calls);
// Clear Displayed lines
werase(info->list_win);

View File

@ -73,12 +73,14 @@ struct call_list_column {
* panel pointer.
*/
struct call_list_info {
//! Displayed calls iterator
vector_iter_t calls;
//! First displayed call, for drawing faster
sip_call_t *first_call;
int first_call;
//! First displayed call counter, for drawing scroll arrow faster
int first_line;
//! Selected call in the list
sip_call_t *cur_call;
int cur_call;
//! Selected calls with space
sip_call_group_t *group;
//! Displayed column list, make it configurable in the future

View File

@ -193,7 +193,7 @@ save_draw(PANEL *panel)
WINDOW *win = panel_window(panel);
// Get filter stats
filter_stats(&total, &displayed);
sip_calls_stats(&total, &displayed);
mvwprintw(win, 7, 3, "( ) all dialogs ");
mvwprintw(win, 8, 3, "( ) selected dialogs [%d]", call_group_count(info->group));
@ -359,6 +359,7 @@ save_to_file(PANEL *panel)
pcap_dumper_t *pd = NULL;
FILE *f = NULL;
int i;
vector_iter_t calls, msgs;
// Get panel information
save_info_t *info = save_info(panel);
@ -418,24 +419,38 @@ save_to_file(PANEL *panel)
}
}
// Get calls iterator
calls = sip_calls_iterator();
switch(info->savemode) {
case SAVE_ALL:
// Save all packets to the file
while ((call = call_get_next(call)))
while ((msg = call_get_next_msg(call, msg)))
while ((call = vector_iterator_next(&calls))) {
msgs = vector_iterator(call->msgs);
while ((msg = vector_iterator_next(&msgs))) {
(info->saveformat == SAVE_PCAP) ? save_msg_pcap(pd, msg) : save_msg_txt(f, msg);
}
}
break;
case SAVE_SELECTED:
// Save selected packets to file
while ((call = call_group_get_next(info->group, call)))
while ((msg = call_get_next_msg(call, msg)))
while ((call = call_group_get_next(info->group, call))) {
msgs = vector_iterator(call->msgs);
while ((msg = vector_iterator_next(&msgs))) {
(info->saveformat == SAVE_PCAP) ? save_msg_pcap(pd, msg) : save_msg_txt(f, msg);
}
}
break;
case SAVE_DISPLAYED:
// Set filtering for this iterator
vector_iterator_set_filter(&calls, filter_check_call);
// Save selected packets to file
while ((call = call_get_next_filtered(call)))
while ((msg = call_get_next_msg(call, msg)))
while ((call = vector_iterator_next(&calls))) {
msgs = vector_iterator(call->msgs);
while ((msg = vector_iterator_next(&msgs))) {
(info->saveformat == SAVE_PCAP) ? save_msg_pcap(pd, msg) : save_msg_txt(f, msg);
}
}
break;
}

View File

@ -29,6 +29,7 @@
#include "vector.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
vector_t *
vector_create(int limit, int step)
@ -61,6 +62,10 @@ vector_clear(vector_t *vector)
int
vector_append(vector_t *vector, void *item)
{
// Sanity check
if (!item)
return vector->count;
// Check if we need to increase vector size
if (vector->count == vector->limit) {
// Increase vector size
@ -76,23 +81,34 @@ vector_append(vector_t *vector, void *item)
void
vector_remove(vector_t *vector, void *item)
{
// Get item position
int idx = vector_index(vector, item);
// Decrease item counter
vector->count--;
// Move the rest of the elements one position up
memcpy(vector->list + idx, vector->list + idx + 1, sizeof(void *) * (vector->count - idx));
}
void *
vector_item(vector_t *vector, int index)
{
if (vector->count <= index || index < 0)
if (index >= vector->count || index < 0)
return NULL;
return vector->list[index];
}
void *
vector_first(vector_t *vector)
{
return vector_item(vector, 0);
}
int
vector_index(vector_t *vector, void *item)
{
// FIXME Bad perfomance
int i;
for (i=0; i < vector->count; i++) {
for (i = 0; i < vector->count; i++) {
if (vector->list[i] == item)
return i;
}
@ -115,16 +131,29 @@ vector_iterator(vector_t *vector)
return it;
}
vector_t *
vector_iterator_vector(vector_iter_t *it)
{
return it->vector;
}
int
vector_iterator_count(vector_iter_t *it)
{
int count = 0;
int pos = it->current;
if (!it->filter)
return vector_count(it->vector);
vector_iterator_reset(it);
while(vector_iterator_next(it))
if (!it->filter) {
count = vector_count(it->vector);
} else {
while (vector_iterator_next(it)) {
count++;
}
}
vector_iterator_set_current(it, pos);
return count;
}
@ -132,13 +161,65 @@ vector_iterator_count(vector_iter_t *it)
void *
vector_iterator_next(vector_iter_t *it)
{
// TODO Filter results
it->current++;
return vector_item(it->vector, it->current);
void *item;
if (it->current >= vector_count(it->vector))
return NULL;
while ((item = vector_item(it->vector, ++it->current))) {
if (it->filter) {
if (it->filter(item)) {
return item;
}
} else {
return item;
}
}
return NULL;
}
void *
vector_iterator_prev(vector_iter_t *it)
{
void *item;
if (it->current == -1)
return NULL;
while ((item = vector_item(it->vector, --it->current))) {
if (it->filter) {
if (it->filter(item)) {
return item;
}
} else {
return item;
}
}
return NULL;
}
void
vector_iterator_set_filter(vector_iter_t *it, int (*filter) (void *item))
vector_iterator_set_filter(vector_iter_t *it, int
(*filter)(void *item))
{
it->filter = filter;
}
void
vector_iterator_set_current(vector_iter_t *it, int current)
{
it->current = current;
}
int
vector_iterator_current(vector_iter_t *it)
{
return it->current;
}
void
vector_iterator_reset(vector_iter_t *it)
{
vector_iterator_set_current(it, -1);
}

View File

@ -106,6 +106,12 @@ vector_remove(vector_t *vector, void *item);
void *
vector_item(vector_t *vector, int index);
/**
* @brief Return first item of the vector
*/
void *
vector_first(vector_t *vector);
/**
* @brief Get the index of an item
*
@ -128,6 +134,12 @@ vector_count(vector_t *vector);
vector_iter_t
vector_iterator(vector_t *vector);
/**
* @brief Return the vector of this iterator
*/
vector_t *
vector_iterator_vector(vector_iter_t *it);
/**
* @brief Return the number of items of iterator
*/
@ -135,11 +147,17 @@ int
vector_iterator_count(vector_iter_t *it);
/**
* @brief Return next element of the iterator
* @brief Return next element of iterator
*/
void *
vector_iterator_next(vector_iter_t *it);
/**
* @brief Return prev element of iterator
*/
void *
vector_iterator_prev(vector_iter_t *it);
/**
* @brief Set iterator filter funcion
*
@ -148,4 +166,22 @@ vector_iterator_next(vector_iter_t *it);
void
vector_iterator_set_filter(vector_iter_t *it, int (*filter) (void *item));
/**
* @brief Set current iterator position
*/
void
vector_iterator_set_current(vector_iter_t *it, int current);
/**
* @brief Return current iterator position
*/
int
vector_iterator_current(vector_iter_t *it);
/**
* @brief Reset iterator position to initial
*/
void
vector_iterator_reset(vector_iter_t *it);
#endif /* __SNGREP_VECTOR_H_ */