forked from Mirrors/sngrep
sdp: move SDP parsing to packet_sdp dissector
This commit is contained in:
parent
0db67ad858
commit
4d4ff634d0
|
@ -23,6 +23,7 @@ set(SOURCES
|
|||
src/packet/dissectors/packet_tcp.c
|
||||
src/packet/dissectors/packet_udp.c
|
||||
src/packet/dissectors/packet_sip.c
|
||||
src/packet/dissectors/packet_sdp.c
|
||||
src/packet/dissectors/packet_rtp.c
|
||||
src/packet/dissectors/packet_rtcp.c
|
||||
src/capture/capture.c
|
||||
|
@ -43,7 +44,6 @@ set(SOURCES
|
|||
src/group.c
|
||||
src/keybinding.c
|
||||
src/main.c
|
||||
src/packet/media.c
|
||||
src/option.c
|
||||
src/packet/old_packet.c
|
||||
src/packet/rtp.c
|
||||
|
|
|
@ -423,7 +423,7 @@ call_flow_draw_message(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||
{
|
||||
call_flow_info_t *info;
|
||||
WINDOW *flow_win;
|
||||
sdp_media_t *media;
|
||||
PacketSdpMedia *media;
|
||||
const char *callid;
|
||||
char msg_method[SIP_ATTR_MAXLEN];
|
||||
char msg_time[80];
|
||||
|
@ -486,12 +486,12 @@ call_flow_draw_message(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||
if (msg_has_sdp(msg) && setting_has_value(SETTING_CF_SDP_INFO, "first")) {
|
||||
sprintf(method, "%.3s (%s:%u)",
|
||||
msg_method,
|
||||
media->address.ip,
|
||||
media->address.port);
|
||||
media->sconn->address,
|
||||
media->rtpport);
|
||||
}
|
||||
|
||||
if (msg_has_sdp(msg) && setting_has_value(SETTING_CF_SDP_INFO, "full")) {
|
||||
sprintf(method, "%.3s (%s)", msg_method, media->address.ip);
|
||||
sprintf(method, "%.3s (%s)", msg_method, media->sconn->address);
|
||||
}
|
||||
|
||||
// Draw message type or status and line
|
||||
|
@ -568,16 +568,10 @@ call_flow_draw_message(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||
for (;!g_sequence_iter_is_end(it); it = g_sequence_iter_next(it)) {
|
||||
media = g_sequence_get(it);
|
||||
sprintf(mediastr, "%s %d (%s)",
|
||||
media->type,
|
||||
media->address.port,
|
||||
media_get_prefered_format(media));
|
||||
if (arrow->dir == CF_ARROW_SPIRAL) {
|
||||
mvwprintw(flow_win, cline + 1, startpos + 5, mediastr);
|
||||
} else {
|
||||
mvwprintw(flow_win, cline + 1, startpos + distance / 2 - strlen(mediastr) / 2 + 2, mediastr);
|
||||
}
|
||||
cline++;
|
||||
aline++;
|
||||
packet_sdp_media_type_str(media->type),
|
||||
media->rtpport,
|
||||
msg_get_preferred_codec_alias(msg));
|
||||
mvwprintw(flow_win, cline++, startpos + distance / 2 - strlen(mediastr) / 2 + 2, mediastr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,7 +695,7 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||
sprintf(text, "RTP (%s) %d", stream_get_format(stream), stream_get_count(stream));
|
||||
|
||||
// Get message data
|
||||
call = stream->media->msg->call;
|
||||
call = stream->msg->call;
|
||||
|
||||
/**
|
||||
* This logic will try to use the same columns for the stream representation
|
||||
|
@ -709,7 +703,7 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||
* if they share the same IP addresses.
|
||||
*/
|
||||
// Message with Stream destination configured in SDP content
|
||||
msg = stream->media->msg;
|
||||
msg = stream->msg;
|
||||
|
||||
// If message and stream share the same IP address
|
||||
if (address_equals(msg->packet->src, stream->dst)) {
|
||||
|
@ -747,7 +741,7 @@ call_flow_draw_rtp_stream(ui_t *ui, call_flow_arrow_t *arrow, int cline)
|
|||
|
||||
// Prefer message that configured this stream rather than any column
|
||||
if (!arrow->scolumn) {
|
||||
msg = stream->media->msg;
|
||||
msg = stream->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
|
||||
|
@ -954,7 +948,7 @@ call_flow_arrow_message(const call_flow_arrow_t *arrow)
|
|||
|
||||
if (arrow->type == CF_ARROW_RTP) {
|
||||
rtp_stream_t *stream = arrow->item;
|
||||
return stream->media->msg;
|
||||
return stream->msg;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
#include "config.h"
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include "packet_sdp.h"
|
||||
|
||||
/**
|
||||
|
@ -40,7 +41,7 @@
|
|||
* preferrence and may or may not match reality.
|
||||
*
|
||||
*/
|
||||
SDPFormat formats[] = {
|
||||
PacketSdpFormat formats[] = {
|
||||
{ 0, "PCMU/8000", "g711u" },
|
||||
{ 3, "GSM/8000", "gsm" },
|
||||
{ 4, "G723/8000", "g723" },
|
||||
|
@ -65,12 +66,170 @@ SDPFormat formats[] = {
|
|||
{ 32, "MPV/90000", "mpv" },
|
||||
{ 33, "MP2T/90000", "mp2t" },
|
||||
{ 34, "H263/90000", "h263" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
void
|
||||
packet_parse_sdp(PacketDissector *handler, Packet *packet, GByteArray *data)
|
||||
{
|
||||
const struct {
|
||||
const gchar *str;
|
||||
enum PacketSdpMediaType type;
|
||||
} media_types[] = {
|
||||
{ "audio", SDP_MEDIA_AUDIO },
|
||||
{ "video", SDP_MEDIA_VIDEO },
|
||||
{ "text", SDP_MEDIA_TEXT },
|
||||
{ "application", SDP_MEDIA_APPLICATION },
|
||||
{ "message", SDP_MEDIA_MESSAGE },
|
||||
{ "image", SDP_MEDIA_IMAGE }
|
||||
};
|
||||
|
||||
const gchar*
|
||||
packet_sdp_media_type_str(enum PacketSdpMediaType type)
|
||||
{
|
||||
for (guint i = 0; i < G_N_ELEMENTS(media_types); i++) {
|
||||
if (media_types[i].type == type) {
|
||||
return media_types[i].str;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
packet_sdp_dissect_connection(PacketSdpData *sdp, PacketSdpMedia *media, gchar *line)
|
||||
{
|
||||
// c=<nettype> <addrtype> <connection-address>
|
||||
gchar **conn_data = g_strsplit(line, " ", 3);
|
||||
|
||||
// Get connection address
|
||||
PacketSdpConnection *conn = g_malloc(sizeof(PacketSdpConnection));
|
||||
g_utf8_strncpy(conn->address, conn_data[SDP_CONN_ADDRESS], ADDRESSLEN);
|
||||
|
||||
// Set media/session connection data
|
||||
if (media == NULL) {
|
||||
sdp->sconn = conn;
|
||||
} else {
|
||||
media->sconn = conn;
|
||||
}
|
||||
}
|
||||
|
||||
static enum PacketSdpMediaType
|
||||
packet_sdp_media_type(const gchar *media)
|
||||
{
|
||||
g_return_val_if_fail(media != NULL, 0);
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS(media_types); i++) {
|
||||
if (g_ascii_strcasecmp(media, media_types[i].str) == 0) {
|
||||
return media_types[i].type;
|
||||
}
|
||||
}
|
||||
|
||||
return SDP_MEDIA_UNKNOWN;
|
||||
}
|
||||
|
||||
static PacketSdpFormat *
|
||||
packet_sdp_standard_format(guint32 code)
|
||||
{
|
||||
for (guint i = 0;i < G_N_ELEMENTS(formats); i++) {
|
||||
if (formats[i].id == code) {
|
||||
return &formats[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PacketSdpMedia *
|
||||
packet_sdp_dissect_media(PacketSdpData *sdp, gchar *line)
|
||||
{
|
||||
// m=<media> <port> <proto> <fmt>
|
||||
gchar **media_data = g_strsplit(line, " ", 4);
|
||||
|
||||
// Create a new media container
|
||||
PacketSdpMedia *media = g_malloc0(sizeof(PacketSdpMedia));
|
||||
media->sconn = sdp->sconn;
|
||||
media->rtpport = (guint16)strtoul(media_data[SDP_MEDIA_PORT], NULL, 10);
|
||||
media->type = packet_sdp_media_type(media_data[SDP_MEDIA_MEDIA]);
|
||||
|
||||
// Parse SDP preferred codec order
|
||||
gchar **formats = g_strsplit(media_data[SDP_MEDIA_FORMAT], " ", -1);
|
||||
for (guint i = 0; i < g_strv_length(formats); i++ ) {
|
||||
// Check if format code is standard
|
||||
guint32 code = (guint32)strtoul(formats[i], NULL, 10);
|
||||
|
||||
PacketSdpFormat *format = packet_sdp_standard_format(code);
|
||||
if (format == NULL) {
|
||||
// Unknown media format for this code
|
||||
format = g_malloc0(sizeof(PacketSdpFormat));
|
||||
format->id = code;
|
||||
}
|
||||
|
||||
// Add new format for this media
|
||||
media->formats = g_list_append(media->formats, format);
|
||||
}
|
||||
|
||||
return media;
|
||||
}
|
||||
|
||||
static void
|
||||
packet_sdp_dissect_attribute(PacketSdpData *sdp G_GNUC_UNUSED, PacketSdpMedia *media, gchar *line)
|
||||
{
|
||||
// a=<attribute>
|
||||
// a=<attribute>:<value>
|
||||
gchar **rtpattr = g_strsplit_set(line, " :", -1);
|
||||
|
||||
if (g_ascii_strncasecmp(rtpattr[SDP_ATTR_NAME], "rtpmap", 6) == 0) {
|
||||
// Check if format code is standard
|
||||
guint32 code = (guint32)strtoul(rtpattr[2], NULL, 10);
|
||||
PacketSdpFormat *format = packet_sdp_standard_format(code);
|
||||
|
||||
if (format == NULL) {
|
||||
for (guint i = 0; i < g_list_length(media->formats); i++) {
|
||||
format = g_list_nth_data(media->formats, i);
|
||||
if (format->id == code) {
|
||||
format->name = format->alias = rtpattr[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (g_ascii_strncasecmp(rtpattr[SDP_ATTR_NAME], "rtcp", 4) == 0) {
|
||||
media->rtcpport = (guint16)strtoul(rtpattr[SDP_ATTR_VALUE], NULL, 10);
|
||||
}
|
||||
}
|
||||
|
||||
static GByteArray *
|
||||
packet_sdp_dissect(PacketParser *parser G_GNUC_UNUSED, Packet *packet, GByteArray *data)
|
||||
{
|
||||
GString *payload = g_string_new_len((const gchar *) data->data, data->len);
|
||||
|
||||
PacketSdpData *sdp = g_malloc0(sizeof(PacketSdpData));
|
||||
PacketSdpMedia *media = NULL;
|
||||
|
||||
gchar **lines = g_strsplit(payload->str, "\r\n", -1);
|
||||
for (guint i = 0; i < g_strv_length(lines); i++ ) {
|
||||
gchar *line = lines[i] + 2;
|
||||
switch (lines[i][0]) {
|
||||
case 'c':
|
||||
packet_sdp_dissect_connection(sdp, media, line);
|
||||
break;
|
||||
case 'm':
|
||||
media = packet_sdp_dissect_media(sdp, line);
|
||||
sdp->medias = g_list_append(sdp->medias, media);
|
||||
break;
|
||||
case 'a':
|
||||
packet_sdp_dissect_attribute(sdp, media, line);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set packet SDP data
|
||||
g_ptr_array_insert(packet->proto, PACKET_SDP, sdp);
|
||||
}
|
||||
|
||||
PacketDissector *
|
||||
packet_sdp_new()
|
||||
{
|
||||
PacketDissector *proto = g_malloc0(sizeof(PacketDissector));
|
||||
proto->id = PACKET_SDP;
|
||||
proto->dissect = packet_sdp_dissect;
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,21 +34,39 @@
|
|||
#include "packet/dissector.h"
|
||||
|
||||
|
||||
//! Connection Data fields
|
||||
#define SDP_CONN_NETTYPE 0
|
||||
#define SDP_CONN_ADDRTYPE 1
|
||||
#define SDP_CONN_ADDRESS 2
|
||||
|
||||
//! Media Description fields
|
||||
#define SDP_MEDIA_MEDIA 0
|
||||
#define SDP_MEDIA_PORT 1
|
||||
#define SDP_MEDIA_PROTO 2
|
||||
#define SDP_MEDIA_FORMAT 3
|
||||
|
||||
//! Attribute fields
|
||||
#define SDP_ATTR_NAME 0
|
||||
#define SDP_ATTR_VALUE 1
|
||||
|
||||
|
||||
//! SDP handled media types
|
||||
enum sdp_media_type
|
||||
enum PacketSdpMediaType
|
||||
{
|
||||
SDP_MEDIA_AUDIO = 0,
|
||||
SDP_MEDIA_VIDEO,
|
||||
SDP_MEDIA_TEXT,
|
||||
SDP_MEDIA_APPLICATION,
|
||||
SDP_MEDIA_MESSAGE,
|
||||
SDP_MEDIA_IMAGE,
|
||||
SDP_MEDIA_UNKNOWN = -1,
|
||||
SDP_MEDIA_AUDIO = 0,
|
||||
SDP_MEDIA_VIDEO = 1,
|
||||
SDP_MEDIA_TEXT = 2,
|
||||
SDP_MEDIA_APPLICATION = 3,
|
||||
SDP_MEDIA_MESSAGE = 4,
|
||||
SDP_MEDIA_IMAGE = 5,
|
||||
};
|
||||
|
||||
//! Shorter declaration of SDP structures
|
||||
typedef struct _SDPConnection SDPConnection;
|
||||
typedef struct _SDPMedia SDPMedia;
|
||||
typedef struct _SDPFormat SDPFormat;
|
||||
typedef struct _PacketSdpConnection PacketSdpConnection;
|
||||
typedef struct _PacketSdpMedia PacketSdpMedia;
|
||||
typedef struct _PacketSdpFormat PacketSdpFormat;
|
||||
typedef struct _PacketSdpData PacketSdpData;
|
||||
|
||||
/**
|
||||
* @brief SDP ConnectionData (c=) information
|
||||
|
@ -67,9 +85,10 @@ typedef struct _SDPFormat SDPFormat;
|
|||
* We only support one connection data per media description. If multicast
|
||||
* connection strings are provided, only one will be parsed.
|
||||
*/
|
||||
struct _SDPConnection {
|
||||
struct _PacketSdpConnection
|
||||
{
|
||||
//! Connection Address
|
||||
Address addr;
|
||||
gchar address[ADDRESSLEN];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -82,11 +101,18 @@ struct _SDPConnection {
|
|||
* present in one of the media formats description lines.
|
||||
*
|
||||
*/
|
||||
struct SDPMedia {
|
||||
struct _PacketSdpMedia
|
||||
{
|
||||
//! Media type
|
||||
enum sdp_media_type type;
|
||||
//! Transport port + connection data Address
|
||||
Address port;
|
||||
enum PacketSdpMediaType type;
|
||||
//! Session connection address (if not global)
|
||||
PacketSdpConnection *sconn;
|
||||
//! RTP Transport port
|
||||
guint16 rtpport;
|
||||
//! RTCP Transport port
|
||||
guint16 rtcpport;
|
||||
//! RTP Address (Connection IP + RTP port)
|
||||
Address address;
|
||||
//! Media formats list (SDPFormat)
|
||||
GList *formats;
|
||||
};
|
||||
|
@ -100,7 +126,8 @@ struct SDPMedia {
|
|||
* Note that sngrep only supports RTP transport protocol so all SDP format
|
||||
* ids are actually RTP Payload type numbers.
|
||||
*/
|
||||
struct _SDPFormat {
|
||||
struct _PacketSdpFormat
|
||||
{
|
||||
//! RTP payload
|
||||
guint32 id;
|
||||
//! RTP Encoding name from RFC3551 or SDP fmt attribute
|
||||
|
@ -109,16 +136,18 @@ struct _SDPFormat {
|
|||
const gchar *alias;
|
||||
};
|
||||
|
||||
|
||||
struct sdp_pvt {
|
||||
struct _PacketSdpData
|
||||
{
|
||||
//! Session connection address (optional)
|
||||
SDPConnection sconn;
|
||||
PacketSdpConnection *sconn;
|
||||
//! SDP Media description list (SDPMedia)
|
||||
GList *medias;
|
||||
};
|
||||
|
||||
void
|
||||
packet_parse_sdp(PacketDissector *handler, Packet *packet, GByteArray *data);
|
||||
const gchar*
|
||||
packet_sdp_media_type_str(enum PacketSdpMediaType type);
|
||||
|
||||
PacketDissector *
|
||||
packet_sdp_new();
|
||||
|
||||
#endif /* PACKET_PACKET_SDP_H_ */
|
||||
|
|
|
@ -29,11 +29,10 @@
|
|||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <packet/old_packet.h>
|
||||
#include "packet_sip.h"
|
||||
#include "packet_ip.h"
|
||||
#include "packet_tcp.h"
|
||||
#include "packet_udp.h"
|
||||
#include "packet_sdp.h"
|
||||
#include "sip.h"
|
||||
#include "packet_sip.h"
|
||||
#include "packet/old_packet.h"
|
||||
|
||||
/* @brief list of methods and responses */
|
||||
|
@ -156,12 +155,15 @@ static GByteArray *
|
|||
packet_sip_parse(PacketParser *parser, Packet *packet, GByteArray *data)
|
||||
{
|
||||
GMatchInfo *pmatch;
|
||||
DissectorSipData *sip = g_ptr_array_index(parser->dissectors, PACKET_SIP);
|
||||
gint start, end;
|
||||
|
||||
// Only handle UTF-8 SIP payloads
|
||||
if (!g_utf8_validate(data->data, data->len, NULL)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
DissectorSipData *sip = g_ptr_array_index(parser->dissectors, PACKET_SIP);
|
||||
|
||||
// Convert payload to something we can parse with regular expressions
|
||||
GString *payload = g_string_new_len(data->data, data->len);
|
||||
|
||||
|
@ -185,7 +187,6 @@ packet_sip_parse(PacketParser *parser, Packet *packet, GByteArray *data)
|
|||
// Not a SIP message or not complete
|
||||
return data;
|
||||
}
|
||||
gint start, end;
|
||||
g_match_info_fetch_pos(pmatch, 1, &start, &end);
|
||||
|
||||
// The SDP body of the SIP message ends in another packet
|
||||
|
@ -216,6 +217,10 @@ packet_sip_parse(PacketParser *parser, Packet *packet, GByteArray *data)
|
|||
}
|
||||
g_match_info_free(pmatch);
|
||||
|
||||
// Check we have a valid SIP packet
|
||||
if (sip_data->callid == NULL)
|
||||
return data;
|
||||
|
||||
// Method
|
||||
if (g_regex_match(sip->reg_method, payload->str, 0, &pmatch)) {
|
||||
sip_data->reqresp = sip_method_from_str(g_match_info_fetch_named(pmatch, "method"));
|
||||
|
@ -269,13 +274,21 @@ packet_sip_parse(PacketParser *parser, Packet *packet, GByteArray *data)
|
|||
}
|
||||
g_match_info_free(pmatch);
|
||||
|
||||
|
||||
// Add SIP information to the packet
|
||||
g_ptr_array_insert(packet->proto, PACKET_SIP, sip_data);
|
||||
|
||||
if (sip_data->callid != NULL) {
|
||||
sip_check_packet(packet);
|
||||
return NULL;
|
||||
}
|
||||
// Check if we have Body separator field
|
||||
g_regex_match(sip->reg_body, payload->str, 0, &pmatch);
|
||||
g_match_info_fetch_pos(pmatch, 0, &start, &end);
|
||||
|
||||
// Remove SIP headers from data
|
||||
data = g_byte_array_remove_range(data, 0, end);
|
||||
|
||||
// Pass data to subdissectors
|
||||
packet_parser_next_dissector(parser, packet, data);
|
||||
|
||||
// Add data to storage
|
||||
sip_check_packet(packet);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -327,7 +340,7 @@ packet_sip_init(PacketParser *parser)
|
|||
cflags, mflags, NULL);
|
||||
|
||||
sip->reg_body = g_regex_new(
|
||||
"\r\n\r\n(.*)",
|
||||
"\r\n\r\n",
|
||||
cflags & ~G_REGEX_MULTILINE, mflags, NULL);
|
||||
|
||||
sip->reg_reason = g_regex_new(
|
||||
|
@ -374,5 +387,6 @@ packet_sip_new()
|
|||
proto->init = packet_sip_init;
|
||||
proto->dissect = packet_sip_parse;
|
||||
proto->deinit = packet_sip_deinit;
|
||||
proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_SDP));
|
||||
return proto;
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** sngrep - SIP Messages flow viewer
|
||||
**
|
||||
** Copyright (C) 2013-2018 Ivan Alonso (Kaian)
|
||||
** Copyright (C) 2013-2018 Irontec SL. All rights reserved.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file media.c
|
||||
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
|
||||
*
|
||||
* @brief Source of functions defined in media.h
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "glib-utils.h"
|
||||
#include "media.h"
|
||||
#include "packet/rtp.h"
|
||||
#include "util.h"
|
||||
|
||||
sdp_media_t *
|
||||
media_create(struct sip_msg *msg)
|
||||
{
|
||||
sdp_media_t *media;;
|
||||
|
||||
// Allocate memory for this media structure
|
||||
if (!(media = sng_malloc(sizeof(sdp_media_t))))
|
||||
return NULL;
|
||||
|
||||
// Initialize all fields
|
||||
media->msg = msg;
|
||||
media->formats = g_sequence_new(sng_free);
|
||||
return media;
|
||||
}
|
||||
|
||||
void
|
||||
media_destroy(void *item)
|
||||
{
|
||||
sdp_media_t *media = (sdp_media_t *) item;
|
||||
if (!item)
|
||||
return;
|
||||
g_sequence_free(media->formats);
|
||||
sng_free(media);
|
||||
}
|
||||
|
||||
void
|
||||
media_set_type(sdp_media_t *media, const char *type)
|
||||
{
|
||||
strcpy(media->type, type);
|
||||
}
|
||||
|
||||
void
|
||||
media_set_address(sdp_media_t *media, Address addr)
|
||||
{
|
||||
media->address = addr;
|
||||
}
|
||||
|
||||
void
|
||||
media_set_prefered_format(sdp_media_t *media, uint32_t code)
|
||||
{
|
||||
media->fmtcode = code;
|
||||
}
|
||||
|
||||
void
|
||||
media_add_format(sdp_media_t *media, uint32_t code, const char *format)
|
||||
{
|
||||
sdp_media_fmt_t *fmt;
|
||||
|
||||
if (!(fmt = sng_malloc(sizeof(sdp_media_fmt_t))))
|
||||
return;
|
||||
|
||||
fmt->id = code;
|
||||
strcpy(fmt->format, format);
|
||||
g_sequence_append(media->formats, fmt);
|
||||
}
|
||||
|
||||
const char *
|
||||
media_get_format(sdp_media_t *media, uint32_t code)
|
||||
{
|
||||
sdp_media_fmt_t *format;
|
||||
GSequenceIter *it = g_sequence_get_begin_iter(media->formats);
|
||||
for (;!g_sequence_iter_is_end(it); it = g_sequence_iter_next(it)) {
|
||||
format = g_sequence_get(it);
|
||||
if (format->id == code)
|
||||
return format->format;
|
||||
}
|
||||
|
||||
return "Unassigned";
|
||||
}
|
||||
|
||||
const char *
|
||||
media_get_prefered_format(sdp_media_t *media)
|
||||
{
|
||||
const char *format;
|
||||
|
||||
// Check if format is standard
|
||||
if ((format = rtp_get_standard_format(media->fmtcode))) {
|
||||
return format;
|
||||
}
|
||||
// Try to get format form SDP payload
|
||||
return media_get_format(media, media->fmtcode);
|
||||
}
|
||||
|
||||
int
|
||||
media_get_format_code(sdp_media_t *media)
|
||||
{
|
||||
return media->fmtcode;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** sngrep - SIP Messages flow viewer
|
||||
**
|
||||
** Copyright (C) 2013-2018 Ivan Alonso (Kaian)
|
||||
** Copyright (C) 2013-2018 Irontec SL. All rights reserved.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file media.h
|
||||
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
|
||||
*
|
||||
* @brief Functions to manage call media
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SNGREP_MEDIA_H_
|
||||
#define __SNGREP_MEDIA_H_
|
||||
|
||||
#include "config.h"
|
||||
#include <sys/types.h>
|
||||
#include <glib.h>
|
||||
#include "capture/capture_pcap.h"
|
||||
|
||||
#define MEDIATYPELEN 15
|
||||
|
||||
//! Shorter declaration of sdp_media structure
|
||||
typedef struct sdp_media sdp_media_t;
|
||||
//! Shorter declaration of sdp_media_fmt structure
|
||||
typedef struct sdp_media_fmt sdp_media_fmt_t;
|
||||
|
||||
struct sip_msg;
|
||||
struct sip_call;
|
||||
|
||||
struct sdp_media_fmt {
|
||||
uint32_t id;
|
||||
char format[50];
|
||||
};
|
||||
|
||||
|
||||
struct sdp_media {
|
||||
//! SDP Addresses information
|
||||
Address address;
|
||||
char type[MEDIATYPELEN];
|
||||
uint32_t fmtcode;
|
||||
//! List of described formats in this media
|
||||
GSequence *formats;
|
||||
//! Message with this SDP content
|
||||
struct sip_msg *msg;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocate memory for a new media structure
|
||||
*
|
||||
* Create a structure for a new message sdp connection data.
|
||||
*
|
||||
* @param msg SIP Message pointer owner of this media
|
||||
* @return new allocated structure
|
||||
*/
|
||||
sdp_media_t *
|
||||
media_create(struct sip_msg *msg);
|
||||
|
||||
void
|
||||
media_destroy(void *item);
|
||||
|
||||
void
|
||||
media_set_type(sdp_media_t *media, const char *type);
|
||||
|
||||
void
|
||||
media_set_address(sdp_media_t *media, Address addr);
|
||||
|
||||
void
|
||||
media_set_prefered_format(sdp_media_t *media, uint32_t code);
|
||||
|
||||
void
|
||||
media_add_format(sdp_media_t *media, uint32_t code, const char *format);
|
||||
|
||||
const char *
|
||||
media_get_type(sdp_media_t *media);
|
||||
|
||||
const char *
|
||||
media_get_format(sdp_media_t *media, uint32_t code);
|
||||
|
||||
const char *
|
||||
media_get_prefered_format(sdp_media_t *media);
|
||||
|
||||
int
|
||||
media_get_format_code(sdp_media_t *media);
|
||||
|
||||
#endif /* __SNGREP_MEDIA_H_ */
|
|
@ -57,6 +57,8 @@ enum packet_oldtype {
|
|||
typedef struct old_packet packet_t;
|
||||
//! Shorter declaration of frame structure
|
||||
typedef struct frame frame_t;
|
||||
//! Forward declaration Packet structure
|
||||
typedef struct _Packet Packet;
|
||||
|
||||
/**
|
||||
* @brief Packet capture data.
|
||||
|
@ -66,6 +68,7 @@ typedef struct frame frame_t;
|
|||
* packet can only contain one SIP message.
|
||||
*/
|
||||
struct old_packet {
|
||||
Packet *newpacket;
|
||||
//! IP protocol
|
||||
uint8_t ip_version;
|
||||
//! Transport protocol
|
||||
|
|
|
@ -56,7 +56,6 @@ packet_free(Packet *packet)
|
|||
gboolean
|
||||
packet_has_type(Packet *packet, enum packet_proto type)
|
||||
{
|
||||
// return (packet->types & ( 1 << type)) != 0;
|
||||
return g_ptr_array_index(packet->proto, type) != NULL;
|
||||
}
|
||||
|
||||
|
@ -81,6 +80,7 @@ packet_to_oldpkt(Packet *packet)
|
|||
packet_t *oldpkt = g_malloc0(sizeof(packet_t));
|
||||
|
||||
PacketIpData *ipdata = g_ptr_array_index(packet->proto, PACKET_IP);
|
||||
oldpkt->newpacket = packet;
|
||||
oldpkt->src = ipdata->saddr;
|
||||
oldpkt->dst = ipdata->daddr;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "packet/dissectors/packet_tcp.h"
|
||||
#include "packet/dissectors/packet_tls.h"
|
||||
#include "packet/dissectors/packet_sip.h"
|
||||
#include "packet/dissectors/packet_sdp.h"
|
||||
#include "packet/dissectors/packet_rtp.h"
|
||||
#include "packet/dissectors/packet_rtcp.h"
|
||||
#include "parser.h"
|
||||
|
@ -80,6 +81,9 @@ packet_parser_add_proto(PacketParser *parser, GNode *parent, enum packet_proto i
|
|||
case PACKET_SIP:
|
||||
dissector = packet_sip_new();
|
||||
break;
|
||||
case PACKET_SDP:
|
||||
dissector = packet_sdp_new();
|
||||
break;
|
||||
case PACKET_RTP:
|
||||
dissector = packet_rtp_new();
|
||||
break;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include "sip.h"
|
||||
|
||||
rtp_stream_t *
|
||||
stream_create(sdp_media_t *media, Address dst, int type)
|
||||
stream_create(Packet *packet, PacketSdpMedia *media)
|
||||
{
|
||||
rtp_stream_t *stream;
|
||||
|
||||
|
@ -47,9 +47,9 @@ stream_create(sdp_media_t *media, Address dst, int type)
|
|||
return NULL;
|
||||
|
||||
// Initialize all fields
|
||||
stream->type = type;
|
||||
stream->type = media->type;
|
||||
stream->media = media;
|
||||
stream->dst = dst;
|
||||
stream->dst = media->address;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ stream_get_count(rtp_stream_t *stream)
|
|||
|
||||
struct sip_call *
|
||||
stream_get_call(rtp_stream_t *stream) {
|
||||
if (stream && stream->media && stream->media->msg)
|
||||
return stream->media->msg->call;
|
||||
if (stream && stream->media && stream->msg)
|
||||
return stream->msg->call;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,12 @@ stream_get_format(rtp_stream_t *stream)
|
|||
return fmt;
|
||||
|
||||
// Try to get format form SDP payload
|
||||
if ((fmt = media_get_format(stream->media, stream->rtpinfo.fmtcode)))
|
||||
return fmt;
|
||||
for (guint i = 0; i < g_list_length(stream->media->formats); i++) {
|
||||
PacketSdpFormat *format = g_list_nth_data(stream->media->formats, i);
|
||||
if (format->id == stream->rtpinfo.fmtcode) {
|
||||
return format->alias;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found format for this code
|
||||
return NULL;
|
||||
|
@ -153,10 +157,10 @@ rtp_check_packet(packet_t *packet)
|
|||
// We have found a stream, but with different format
|
||||
if (stream_is_complete(stream) && stream->rtpinfo.fmtcode != format) {
|
||||
// Create a new stream for this new format
|
||||
stream = stream_create(stream->media, dst, PACKET_RTP);
|
||||
stream = stream_create(packet->newpacket, stream->media);
|
||||
stream_complete(stream, src);
|
||||
stream_set_format(stream, format);
|
||||
call_add_stream(msg_get_call(stream->media->msg), stream);
|
||||
call_add_stream(msg_get_call(stream->msg), stream);
|
||||
}
|
||||
|
||||
// First packet for this stream, set source data
|
||||
|
@ -184,20 +188,20 @@ rtp_check_packet(packet_t *packet)
|
|||
*/
|
||||
|
||||
// Check if an stream in the opposite direction exists
|
||||
if (!(reverse = rtp_find_call_stream(stream->media->msg->call, stream->dst, stream->src))) {
|
||||
reverse = stream_create(stream->media, stream->src, PACKET_RTP);
|
||||
if (!(reverse = rtp_find_call_stream(stream->msg->call, stream->dst, stream->src))) {
|
||||
reverse = stream_create(packet->newpacket, stream->media);
|
||||
stream_complete(reverse, stream->dst);
|
||||
stream_set_format(reverse, format);
|
||||
call_add_stream(msg_get_call(stream->media->msg), reverse);
|
||||
call_add_stream(msg_get_call(stream->msg), reverse);
|
||||
} else {
|
||||
// If the reverse stream has other source configured
|
||||
if (reverse->src.port && !addressport_equals(stream->src, reverse->src)) {
|
||||
if (!(reverse = rtp_find_call_exact_stream(stream->media->msg->call, stream->dst, stream->src))) {
|
||||
if (!(reverse = rtp_find_call_exact_stream(stream->msg->call, stream->dst, stream->src))) {
|
||||
// Create a new reverse stream
|
||||
reverse = stream_create(stream->media, stream->src, PACKET_RTP);
|
||||
reverse = stream_create(packet->newpacket, stream->media);
|
||||
stream_complete(reverse, stream->dst);
|
||||
stream_set_format(reverse, format);
|
||||
call_add_stream(msg_get_call(stream->media->msg), reverse);
|
||||
call_add_stream(msg_get_call(stream->msg), reverse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,9 @@
|
|||
#define __SNGREP_RTP_H
|
||||
|
||||
#include "config.h"
|
||||
#include "sip_msg.h"
|
||||
#include "capture/capture_pcap.h"
|
||||
#include "media.h"
|
||||
#include "packet/dissectors/packet_sdp.h"
|
||||
#include "packet/dissectors/packet_rtp.h"
|
||||
#include "packet/dissectors/packet_rtcp.h"
|
||||
|
||||
|
@ -49,7 +50,9 @@ struct rtp_stream {
|
|||
//! Destination address
|
||||
Address dst;
|
||||
//! SDP media that setup this stream
|
||||
sdp_media_t *media;
|
||||
PacketSdpMedia *media;
|
||||
//! SIP message that setup this stream
|
||||
sip_msg_t *msg;
|
||||
//! Packet count for this stream
|
||||
uint32_t pktcnt;
|
||||
//! Time of first received packet of stream
|
||||
|
@ -79,7 +82,7 @@ struct rtp_stream {
|
|||
};
|
||||
|
||||
rtp_stream_t *
|
||||
stream_create(sdp_media_t *media, Address dst, int type);
|
||||
stream_create(Packet *packet, PacketSdpMedia *media);
|
||||
|
||||
rtp_stream_t *
|
||||
stream_complete(rtp_stream_t *stream, Address src);
|
||||
|
|
129
src/sip.c
129
src/sip.c
|
@ -188,7 +188,7 @@ sip_check_packet(Packet *packet)
|
|||
|
||||
if (call_is_invite(call)) {
|
||||
// Parse media data
|
||||
sip_parse_msg_media(msg, sip_data->payload);
|
||||
sip_parse_msg_media(msg);
|
||||
// Update Call State
|
||||
call_update_state(call, msg);
|
||||
// Check if this call should be in active call list
|
||||
|
@ -305,106 +305,43 @@ sip_get_msg_reqresp_str(sip_msg_t *msg)
|
|||
}
|
||||
|
||||
void
|
||||
sip_parse_msg_media(sip_msg_t *msg, const u_char *payload)
|
||||
sip_parse_msg_media(sip_msg_t *msg)
|
||||
{
|
||||
Packet *packet = msg->packet->newpacket;
|
||||
Address emptyaddr = {};
|
||||
|
||||
#define ADD_STREAM(stream) \
|
||||
if (stream) { \
|
||||
if (!rtp_find_call_stream(call, src, stream->dst)) { \
|
||||
call_add_stream(call, stream); \
|
||||
} else { \
|
||||
sng_free(stream); \
|
||||
stream = NULL; \
|
||||
} \
|
||||
PacketSdpData *sdp = g_ptr_array_index(packet->proto, PACKET_SDP);
|
||||
if (sdp == NULL) return;
|
||||
|
||||
for (guint i = 0; i < g_list_length(sdp->medias); i++) {
|
||||
PacketSdpMedia *media = g_list_nth_data(sdp->medias, i);
|
||||
|
||||
// Add to the message
|
||||
g_sequence_append(msg->medias, media);
|
||||
|
||||
// Create RTP stream for this media
|
||||
if (rtp_find_call_stream(msg->call, emptyaddr, media->address) == NULL) {
|
||||
rtp_stream_t *stream = stream_create(packet, media);
|
||||
call_add_stream(msg->call, stream);
|
||||
}
|
||||
|
||||
// Create RTCP stream for this media
|
||||
if (rtp_find_call_stream(msg->call, emptyaddr, media->address) == NULL) {
|
||||
rtp_stream_t *stream = stream_create(packet, media);
|
||||
stream->dst.port = (media->rtcpport) ? media->rtcpport : (guint16) (media->rtpport + 1);
|
||||
call_add_stream(msg->call, stream);
|
||||
}
|
||||
|
||||
// Create RTP stream with source of message as destination address
|
||||
if (rtp_find_call_stream(msg->call, msg->packet->src, media->address) == NULL) {
|
||||
rtp_stream_t *stream = stream_create(packet, media);
|
||||
stream->dst = msg->packet->src;
|
||||
stream->dst.port = media->rtpport;
|
||||
call_add_stream(msg->call, stream);
|
||||
}
|
||||
}
|
||||
|
||||
Address dst, src = { };
|
||||
rtp_stream_t *rtp_stream = NULL, *rtcp_stream = NULL, *msg_rtp_stream = NULL;
|
||||
char media_type[MEDIATYPELEN] = { };
|
||||
char media_format[30] = { };
|
||||
uint32_t media_fmt_pref;
|
||||
uint32_t media_fmt_code;
|
||||
sdp_media_t *media = NULL;
|
||||
char *payload2, *tofree, *line;
|
||||
sip_call_t *call = msg_get_call(msg);
|
||||
|
||||
// Parse each line of payload looking for sdp information
|
||||
tofree = payload2 = strdup((char*)payload);
|
||||
while ((line = strsep(&payload2, "\r\n")) != NULL) {
|
||||
// Check if we have a media string
|
||||
if (!strncmp(line, "m=", 2)) {
|
||||
if (sscanf(line, "m=%s %hu RTP/%*s %u", media_type, &dst.port, &media_fmt_pref) == 3) {
|
||||
|
||||
// Add streams from previous 'm=' line to the call
|
||||
ADD_STREAM(msg_rtp_stream);
|
||||
ADD_STREAM(rtp_stream);
|
||||
ADD_STREAM(rtcp_stream);
|
||||
|
||||
// Create a new media structure for this message
|
||||
if ((media = media_create(msg))) {
|
||||
media_set_type(media, media_type);
|
||||
media_set_address(media, dst);
|
||||
media_set_prefered_format(media, media_fmt_pref);
|
||||
msg_add_media(msg, media);
|
||||
|
||||
/**
|
||||
* From SDP we can only guess destination address port. RTP Capture proccess
|
||||
* will determine when the stream has been completed, getting source address
|
||||
* and port of the stream.
|
||||
*/
|
||||
// Create a new stream with this destination address:port
|
||||
|
||||
// Create RTP stream with source of message as destination address
|
||||
msg_rtp_stream = stream_create(media, dst, PACKET_RTP);
|
||||
msg_rtp_stream->dst = msg->packet->src;
|
||||
msg_rtp_stream->dst.port = dst.port;
|
||||
|
||||
// Create RTP stream
|
||||
rtp_stream = stream_create(media, dst, PACKET_RTP);
|
||||
|
||||
// Create RTCP stream
|
||||
rtcp_stream = stream_create(media, dst, PACKET_RTCP);
|
||||
rtcp_stream->dst.port++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have a connection string
|
||||
if (!strncmp(line, "c=", 2)) {
|
||||
if (sscanf(line, "c=IN IP4 %s", dst.ip) && media) {
|
||||
media_set_address(media, dst);
|
||||
strcpy(rtp_stream->dst.ip, dst.ip);
|
||||
strcpy(rtcp_stream->dst.ip, dst.ip);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have attribute format string
|
||||
if (!strncmp(line, "a=rtpmap:", 9)) {
|
||||
if (media && sscanf(line, "a=rtpmap:%u %[^ ]", &media_fmt_code, media_format)) {
|
||||
media_add_format(media, media_fmt_code, media_format);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have attribute format RTCP port
|
||||
if (!strncmp(line, "a=rtcp:", 7) && rtcp_stream) {
|
||||
sscanf(line, "a=rtcp:%hu", &rtcp_stream->dst.port);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Add streams from last 'm=' line to the call
|
||||
ADD_STREAM(msg_rtp_stream);
|
||||
ADD_STREAM(rtp_stream);
|
||||
ADD_STREAM(rtcp_stream);
|
||||
|
||||
sng_free(tofree);
|
||||
|
||||
#undef ADD_STREAM
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
sip_calls_clear()
|
||||
{
|
||||
|
|
|
@ -306,7 +306,7 @@ sip_get_msg_reqresp_str(sip_msg_t *msg);
|
|||
* @return 0 in all cases
|
||||
*/
|
||||
void
|
||||
sip_parse_msg_media(sip_msg_t *msg, const u_char *payload);
|
||||
sip_parse_msg_media(sip_msg_t *msg);
|
||||
|
||||
/**
|
||||
* @brief Get Capture Matching expression
|
||||
|
|
|
@ -177,7 +177,7 @@ sip_msg_t *
|
|||
call_msg_with_media(sip_call_t *call, Address dst)
|
||||
{
|
||||
sip_msg_t *msg;
|
||||
sdp_media_t *media;
|
||||
PacketSdpMedia *media;
|
||||
GSequenceIter *itmsg;
|
||||
GSequenceIter *itmedia;
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "glib-utils.h"
|
||||
#include "sip_msg.h"
|
||||
#include "packet/dissectors/packet_sip.h"
|
||||
#include "packet/media.h"
|
||||
#include "packet/dissectors/packet_sdp.h"
|
||||
#include "sip.h"
|
||||
|
||||
sip_msg_t *
|
||||
|
@ -42,7 +42,7 @@ msg_create()
|
|||
sip_msg_t *msg;
|
||||
if (!(msg = sng_malloc(sizeof(sip_msg_t))))
|
||||
return NULL;
|
||||
msg->medias = g_sequence_new(media_destroy);
|
||||
msg->medias = g_sequence_new(NULL);
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -87,12 +87,6 @@ msg_is_request(sip_msg_t *msg)
|
|||
return msg->reqresp < 100;
|
||||
}
|
||||
|
||||
void
|
||||
msg_add_media(sip_msg_t *msg, sdp_media_t *media)
|
||||
{
|
||||
g_sequence_append(msg->medias, media);
|
||||
}
|
||||
|
||||
const char *
|
||||
msg_get_payload(sip_msg_t *msg)
|
||||
{
|
||||
|
@ -169,3 +163,15 @@ msg_is_older(sip_msg_t *one, sip_msg_t *two)
|
|||
// Otherwise
|
||||
return timeval_is_older(msg_get_time(one), msg_get_time(two));
|
||||
}
|
||||
|
||||
const gchar *
|
||||
msg_get_preferred_codec_alias(sip_msg_t *msg)
|
||||
{
|
||||
PacketSdpMedia *media = g_sequence_first(msg->medias);
|
||||
g_return_val_if_fail(media != NULL, NULL);
|
||||
|
||||
PacketSdpFormat *format = g_list_nth_data(media->formats, 0);
|
||||
g_return_val_if_fail(format != NULL, NULL);
|
||||
|
||||
return format->alias;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
#include <glib.h>
|
||||
#include "packet/media.h"
|
||||
#include "sip_attr.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -121,15 +120,6 @@ msg_media_count(sip_msg_t *msg);
|
|||
int
|
||||
msg_has_sdp(void *item);
|
||||
|
||||
/**
|
||||
* @brief Add a media structure to a msg
|
||||
*
|
||||
* @param cmsg SIP Message to be updated
|
||||
* @param media Media structure to be added
|
||||
*/
|
||||
void
|
||||
msg_add_media(sip_msg_t *msg, sdp_media_t *media);
|
||||
|
||||
/**
|
||||
* @brief Check if a message is a Request or response
|
||||
*
|
||||
|
@ -139,18 +129,6 @@ msg_add_media(sip_msg_t *msg, sdp_media_t *media);
|
|||
int
|
||||
msg_is_request(sip_msg_t *msg);
|
||||
|
||||
/**
|
||||
* @brief Add a new media for given message
|
||||
*
|
||||
* A SIP message can have multiple media description in
|
||||
* the SIP payload content
|
||||
*
|
||||
* @param msg SIP message that will store this packet
|
||||
* @param media parsed media structure from payload
|
||||
*/
|
||||
void
|
||||
msg_add_media(sip_msg_t *msg, sdp_media_t *media);
|
||||
|
||||
/**
|
||||
* @brief Get SIP Message payload
|
||||
*/
|
||||
|
@ -192,4 +170,8 @@ int
|
|||
msg_is_older(sip_msg_t *one, sip_msg_t *two);
|
||||
|
||||
|
||||
const gchar *
|
||||
msg_get_preferred_codec_alias(sip_msg_t *msg);
|
||||
|
||||
|
||||
#endif /* __SNGREP_SIP_MSG_H */
|
||||
|
|
Loading…
Reference in New Issue