int call_attr_compare(sip_call_t *one, sip_call_t *two, enum sip_attr_id id) { char onevalue[256], twovalue[256]; int oneintvalue, twointvalue; int comparetype; /* TODO 0 = string compare, 1 = int comprare */ switch (id) { case SIP_ATTR_CALLINDEX: oneintvalue = one->index; twointvalue = two->index; comparetype = 1; break; case SIP_ATTR_MSGCNT: oneintvalue = call_msg_count(one); twointvalue = call_msg_count(two); comparetype = 1; break; default: // Get attribute values memset(onevalue, 0, sizeof(onevalue)); memset(twovalue, 0, sizeof(twovalue)); call_get_attribute(one, id, onevalue); call_get_attribute(two, id, twovalue); comparetype = 0; break; } switch (comparetype) { case 0: if (strlen(twovalue) == 0 && strlen(onevalue) == 0) return 0; if (strlen(twovalue) == 0) return 1; if (strlen(onevalue) == 0) return -1; return strcmp(onevalue, twovalue); case 1: if (oneintvalue == twointvalue) return 0; if (oneintvalue > twointvalue) return 1; if (oneintvalue < twointvalue) return -1; /* no break */ default: return 0; } }
const char * call_get_attribute(sip_call_t *call, enum sip_attr_id id) { char value[80]; if (id == SIP_ATTR_MSGCNT) { // FIXME REALLY sprintf(value, "%d", call_msg_count(call)); return strdup(value); } if (id == SIP_ATTR_STARTING) { return msg_get_attribute(call_get_next_msg(call, NULL), SIP_ATTR_METHOD); } return msg_get_attribute(call_get_next_msg(call, NULL), id); }
sip_msg_t * sip_check_packet(packet_t *packet) { sip_msg_t *msg; sip_call_t *call; char callid[1024], xcallid[1024]; address_t src, dst; u_char payload[MAX_SIP_PAYLOAD]; bool newcall = false; // Max SIP payload allowed if (packet->payload_len > MAX_SIP_PAYLOAD) return NULL; // Get Addresses from packet src = packet->src; dst = packet->dst; // Initialize local variables memset(callid, 0, sizeof(callid)); memset(xcallid, 0, sizeof(xcallid)); // Get payload from packet(s) memset(payload, 0, MAX_SIP_PAYLOAD); memcpy(payload, packet_payload(packet), packet_payloadlen(packet)); // Get the Call-ID of this message if (!sip_get_callid((const char*) payload, callid)) return NULL; // Create a new message from this data if (!(msg = msg_create((const char*) payload))) return NULL; // Get Method and request for the following checks // There is no need to parse all payload at this point // If no response or request code is found, this is not a SIP message if (!sip_get_msg_reqresp(msg, payload)) { // Deallocate message memory msg_destroy(msg); return NULL; } // Find the call for this msg if (!(call = sip_find_by_callid(callid))) { // Check if payload matches expression if (!sip_check_match_expression((const char*) payload)) goto skip_message; // User requested only INVITE starting dialogs if (calls.only_calls && msg->reqresp != SIP_METHOD_INVITE) goto skip_message; // Only create a new call if the first msg // is a request message in the following gorup if (calls.ignore_incomplete && msg->reqresp > SIP_METHOD_MESSAGE) goto skip_message; // Get the Call-ID of this message sip_get_xcallid((const char*) payload, xcallid); // Rotate call list if limit has been reached if (calls.limit == sip_calls_count()) sip_calls_rotate(); // Create the call if not found if (!(call = call_create(callid, xcallid))) goto skip_message; // Add this Call-Id to hash table htable_insert(calls.callids, call->callid, call); // Set call index call->index = ++calls.last_index; // Mark this as a new call newcall = true; } // At this point we know we're handling an interesting SIP Packet msg->packet = packet; // Always parse first call message if (call_msg_count(call) == 0) { // Parse SIP payload sip_parse_msg_payload(msg, payload); // If this call has X-Call-Id, append it to the parent call if (strlen(call->xcallid)) { call_add_xcall(sip_find_by_callid(call->xcallid), call); } } // Add the message to the call call_add_message(call, msg); if (call_is_invite(call)) { // Parse media data sip_parse_msg_media(msg, payload); // Update Call State call_update_state(call, msg); // Check if this call should be in active call list if (call_is_active(call)) { if (sip_call_is_active(call)) { vector_append(calls.active, call); } } else { if (sip_call_is_active(call)) { vector_remove(calls.active, call); } } } if (newcall) { // Append this call to the call list vector_append(calls.list, call); } // Mark the list as changed calls.changed = true; // Return the loaded message return msg; skip_message: // Deallocate message memory msg_destroy(msg); return NULL; }
void call_list_draw_list(PANEL *panel) { WINDOW *win; int height, width, cline = 0; struct sip_call *call; int i, collen; char coltext[256]; int colid; int colpos; int color; // Get panel info call_list_info_t *info = call_list_info(panel); // Get window of call list panel win = info->list_win; getmaxyx(win, height, width); // If autoscroll is enabled, select the last dialog if (info->autoscroll) { call_list_handle_key(panel, key_action_key(ACTION_END)); } // If no active call, use the fist one (if exists) 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 while ((call = vector_iterator_next(&info->calls))) { // Stop if we have reached the bottom of the list if (cline == height) break; // We only print calls with messages (In fact, all call should have msgs) if (!call_msg_count(call)) continue; // Show bold selected rows if (call_group_exists(info->group, call)) wattron(win, A_BOLD | COLOR_PAIR(CP_DEFAULT)); // Highlight active call if (call->index == info->cur_call + 1) { wattron(win, COLOR_PAIR(CP_WHITE_ON_BLUE)); // Reverse colors on monochrome terminals if (!has_colors()) wattron(win, A_REVERSE); } // Set current line background clear_line(win, cline); // Set current line selection box mvwprintw(win, cline, 2, call_group_exists(info->group, call) ? "[*]" : "[ ]"); // Print requested columns colpos = 6; for (i = 0; i < info->columncnt; i++) { // Get current column id colid = info->columns[i].id; // Get current column width collen = info->columns[i].width; // Check if next column fits on window width if (colpos + collen >= width) break; // Initialize column text memset(coltext, 0, sizeof(coltext)); // Get call attribute for current column if (!call_get_attribute(call, colid, coltext)) { colpos += collen + 1; continue; } // Enable attribute color (if not current one) color = 0; if (call->index != info->cur_call + 1 && (color = sip_attr_get_color(colid, coltext)) > 0) wattron(win, color); // Add the column text to the existing columns mvwprintw(win, cline, colpos, "%.*s", collen, coltext); colpos += collen + 1; // Disable attribute color if (color > 0) wattroff(win, color); } cline++; wattroff(win, COLOR_PAIR(CP_DEFAULT)); wattroff(win, COLOR_PAIR(CP_DEF_ON_BLUE)); wattroff(win, A_BOLD | A_REVERSE); } // Draw scrollbar to the right draw_vscrollbar(win, info->first_line, info->dispcallcnt, 1); wnoutrefresh(info->list_win); }