mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
New plugin: pcapparse (#520899).
Original commit message from CVS: * configure.ac: * gst/pcapparse/Makefile.am: * gst/pcapparse/gstpcapparse.c: * gst/pcapparse/gstpcapparse.h: New plugin: pcapparse (#520899).
This commit is contained in:
parent
407b788242
commit
65062ed750
5 changed files with 579 additions and 0 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2008-08-24 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
|
||||||
|
|
||||||
|
* configure.ac:
|
||||||
|
* gst/pcapparse/Makefile.am:
|
||||||
|
* gst/pcapparse/gstpcapparse.c:
|
||||||
|
* gst/pcapparse/gstpcapparse.h:
|
||||||
|
New plugin: pcapparse (#520899).
|
||||||
|
|
||||||
2008-08-24 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
|
2008-08-24 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
|
||||||
|
|
||||||
patch by: Haakon Sporsheim <hakon.sporsheim@tandberg.com>
|
patch by: Haakon Sporsheim <hakon.sporsheim@tandberg.com>
|
||||||
|
|
|
@ -257,6 +257,7 @@ AG_GST_CHECK_PLUGIN(mpegvideoparse)
|
||||||
AG_GST_CHECK_PLUGIN(mve)
|
AG_GST_CHECK_PLUGIN(mve)
|
||||||
AG_GST_CHECK_PLUGIN(nsf)
|
AG_GST_CHECK_PLUGIN(nsf)
|
||||||
AG_GST_CHECK_PLUGIN(nuvdemux)
|
AG_GST_CHECK_PLUGIN(nuvdemux)
|
||||||
|
AG_GST_CHECK_PLUGIN(pcapparse)
|
||||||
AG_GST_CHECK_PLUGIN(rawparse)
|
AG_GST_CHECK_PLUGIN(rawparse)
|
||||||
AG_GST_CHECK_PLUGIN(real)
|
AG_GST_CHECK_PLUGIN(real)
|
||||||
AG_GST_CHECK_PLUGIN(rtpmanager)
|
AG_GST_CHECK_PLUGIN(rtpmanager)
|
||||||
|
@ -1268,6 +1269,7 @@ gst/mpegvideoparse/Makefile
|
||||||
gst/mve/Makefile
|
gst/mve/Makefile
|
||||||
gst/nsf/Makefile
|
gst/nsf/Makefile
|
||||||
gst/nuvdemux/Makefile
|
gst/nuvdemux/Makefile
|
||||||
|
gst/pcapparse/Makefile
|
||||||
gst/rawparse/Makefile
|
gst/rawparse/Makefile
|
||||||
gst/rtpmanager/Makefile
|
gst/rtpmanager/Makefile
|
||||||
gst/sdp/Makefile
|
gst/sdp/Makefile
|
||||||
|
|
11
gst/pcapparse/Makefile.am
Normal file
11
gst/pcapparse/Makefile.am
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
plugin_LTLIBRARIES = libgstpcapparse.la
|
||||||
|
|
||||||
|
libgstpcapparse_la_SOURCES = \
|
||||||
|
gstpcapparse.c
|
||||||
|
|
||||||
|
noinst_HEADERS = \
|
||||||
|
gstpcapparse.h
|
||||||
|
|
||||||
|
libgstpcapparse_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS)
|
||||||
|
libgstpcapparse_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
|
||||||
|
libgstpcapparse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
480
gst/pcapparse/gstpcapparse.c
Normal file
480
gst/pcapparse/gstpcapparse.c
Normal file
|
@ -0,0 +1,480 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2007 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-pcapparse
|
||||||
|
*
|
||||||
|
* <refsect2>
|
||||||
|
* <title>Example launch line</title>
|
||||||
|
* <para>
|
||||||
|
* <programlisting>
|
||||||
|
* gst-launch-0.10 -v filesrc location=h264crasher.pcap ! pcapparse ! rtph264depay ! ffdec_h264 ! fakesink
|
||||||
|
* </programlisting>
|
||||||
|
* </para>
|
||||||
|
* </refsect2>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* - React on state-change and update state accordingly.
|
||||||
|
* - Implement support for timestamping the buffers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gstpcapparse.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#else
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_SRC_IP,
|
||||||
|
PROP_DST_IP,
|
||||||
|
PROP_SRC_PORT,
|
||||||
|
PROP_DST_PORT,
|
||||||
|
};
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_pcap_parse_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_pcap_parse_debug
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("raw/x-pcap"));
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
|
static void gst_pcap_parse_dispose (GObject * object);
|
||||||
|
static void gst_pcap_parse_finalize (GObject * object);
|
||||||
|
static void gst_pcap_parse_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_pcap_parse_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static void gst_pcap_parse_reset (GstPcapParse * self);
|
||||||
|
|
||||||
|
static GstFlowReturn gst_pcap_parse_chain (GstPad * pad, GstBuffer * buffer);
|
||||||
|
|
||||||
|
GST_BOILERPLATE (GstPcapParse, gst_pcap_parse, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_base_init (gpointer gclass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
|
||||||
|
static GstElementDetails element_details = {
|
||||||
|
"PCapParse",
|
||||||
|
"Raw/Parser",
|
||||||
|
"Parses a raw pcap stream",
|
||||||
|
"Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>"
|
||||||
|
};
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_template));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&src_template));
|
||||||
|
|
||||||
|
gst_element_class_set_details (element_class, &element_details);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_class_init (GstPcapParseClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->dispose = gst_pcap_parse_dispose;
|
||||||
|
gobject_class->finalize = gst_pcap_parse_finalize;
|
||||||
|
gobject_class->get_property = gst_pcap_parse_get_property;
|
||||||
|
gobject_class->set_property = gst_pcap_parse_set_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_SRC_IP, g_param_spec_string ("src-ip", "Source IP",
|
||||||
|
"Source IP to restrict to", "", G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_DST_IP, g_param_spec_string ("dst-ip", "Destination IP",
|
||||||
|
"Destination IP to restrict to", "", G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_SRC_PORT, g_param_spec_int ("src-port", "Source port",
|
||||||
|
"Source port to restrict to", -1, G_MAXUINT16, -1,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_DST_PORT, g_param_spec_int ("dst-port", "Destination port",
|
||||||
|
"Destination port to restrict to", -1, G_MAXUINT16, -1,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_pcap_parse_debug, "pcapparse", 0, "pcap parser");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_init (GstPcapParse * self, GstPcapParseClass * gclass)
|
||||||
|
{
|
||||||
|
self->sink_pad = gst_pad_new_from_static_template (&sink_template, "sink");
|
||||||
|
gst_pad_set_chain_function (self->sink_pad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_pcap_parse_chain));
|
||||||
|
gst_pad_use_fixed_caps (self->sink_pad);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (self), self->sink_pad);
|
||||||
|
|
||||||
|
self->src_pad = gst_pad_new_from_static_template (&src_template, "src");
|
||||||
|
gst_pad_use_fixed_caps (self->src_pad);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (self), self->src_pad);
|
||||||
|
|
||||||
|
self->src_ip = -1;
|
||||||
|
self->dst_ip = -1;
|
||||||
|
self->src_port = -1;
|
||||||
|
self->dst_port = -1;
|
||||||
|
|
||||||
|
self->adapter = gst_adapter_new ();
|
||||||
|
|
||||||
|
gst_pcap_parse_reset (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
GstPcapParse *self = GST_PCAP_PARSE (object);
|
||||||
|
|
||||||
|
g_object_unref (self->adapter);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstPcapParse *self = GST_PCAP_PARSE (object);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *
|
||||||
|
get_ip_address_as_string (gint64 ip_addr)
|
||||||
|
{
|
||||||
|
if (ip_addr >= 0) {
|
||||||
|
struct in_addr addr;
|
||||||
|
addr.s_addr = ip_addr;
|
||||||
|
return inet_ntoa (addr);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_ip_address_from_string (gint64 * ip_addr, const gchar * ip_str)
|
||||||
|
{
|
||||||
|
if (ip_str[0] != '\0') {
|
||||||
|
gulong addr = inet_addr (ip_str);
|
||||||
|
if (addr != INADDR_NONE)
|
||||||
|
*ip_addr = addr;
|
||||||
|
} else {
|
||||||
|
*ip_addr = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstPcapParse *self = GST_PCAP_PARSE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_SRC_IP:
|
||||||
|
g_value_set_string (value, get_ip_address_as_string (self->src_ip));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DST_IP:
|
||||||
|
g_value_set_string (value, get_ip_address_as_string (self->dst_ip));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SRC_PORT:
|
||||||
|
g_value_set_int (value, self->src_port);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DST_PORT:
|
||||||
|
g_value_set_int (value, self->dst_port);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstPcapParse *self = GST_PCAP_PARSE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_SRC_IP:
|
||||||
|
set_ip_address_from_string (&self->src_ip, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DST_IP:
|
||||||
|
set_ip_address_from_string (&self->dst_ip, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SRC_PORT:
|
||||||
|
self->src_port = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DST_PORT:
|
||||||
|
self->dst_port = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_pcap_parse_reset (GstPcapParse * self)
|
||||||
|
{
|
||||||
|
self->initialized = FALSE;
|
||||||
|
self->swap_endian = FALSE;
|
||||||
|
self->cur_packet_size = -1;
|
||||||
|
self->buffer_offset = 0;
|
||||||
|
|
||||||
|
gst_adapter_clear (self->adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
gst_pcap_parse_read_uint32 (GstPcapParse * self, const guint8 * p)
|
||||||
|
{
|
||||||
|
guint32 val = *((guint32 *) p);
|
||||||
|
|
||||||
|
if (self->swap_endian) {
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
return GUINT32_FROM_BE (val);
|
||||||
|
#else
|
||||||
|
return GUINT32_FROM_LE (val);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ETH_HEADER_LEN 14
|
||||||
|
#define IP_HEADER_MIN_LEN 20
|
||||||
|
#define UDP_HEADER_LEN 8
|
||||||
|
|
||||||
|
#define IP_PROTO_UDP 17
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_pcap_parse_scan_frame (GstPcapParse * self,
|
||||||
|
const guint8 * buf,
|
||||||
|
gint buf_size, const guint8 ** payload, gint * payload_size)
|
||||||
|
{
|
||||||
|
const guint8 *buf_ip;
|
||||||
|
const guint8 *buf_udp;
|
||||||
|
guint16 eth_type;
|
||||||
|
guint8 b;
|
||||||
|
guint8 ip_header_size;
|
||||||
|
guint8 ip_protocol;
|
||||||
|
guint32 ip_src_addr;
|
||||||
|
guint32 ip_dst_addr;
|
||||||
|
guint16 udp_src_port;
|
||||||
|
guint16 udp_dst_port;
|
||||||
|
guint16 udp_len;
|
||||||
|
|
||||||
|
if (buf_size < ETH_HEADER_LEN + IP_HEADER_MIN_LEN + UDP_HEADER_LEN)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
eth_type = GUINT16_FROM_BE (*((guint16 *) (buf + 12)));
|
||||||
|
if (eth_type != 0x800)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
buf_ip = buf + ETH_HEADER_LEN;
|
||||||
|
|
||||||
|
b = *buf_ip;
|
||||||
|
if (((b >> 4) & 0x0f) != 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ip_header_size = (b & 0x0f) * 4;
|
||||||
|
if (buf_ip + ip_header_size > buf + buf_size)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ip_protocol = *(buf_ip + 9);
|
||||||
|
if (ip_protocol != IP_PROTO_UDP)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ip_src_addr = *((guint32 *) (buf_ip + 12));
|
||||||
|
if (self->src_ip >= 0 && ip_src_addr != self->src_ip)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ip_dst_addr = *((guint32 *) (buf_ip + 16));
|
||||||
|
if (self->dst_ip >= 0 && ip_dst_addr != self->dst_ip)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
buf_udp = buf_ip + ip_header_size;
|
||||||
|
|
||||||
|
udp_src_port = GUINT16_FROM_BE (*((guint16 *) (buf_udp + 0)));
|
||||||
|
if (self->src_port >= 0 && udp_src_port != self->src_port)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
udp_dst_port = GUINT16_FROM_BE (*((guint16 *) (buf_udp + 2)));
|
||||||
|
if (self->dst_port >= 0 && udp_dst_port != self->dst_port)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
udp_len = GUINT16_FROM_BE (*((guint16 *) (buf_udp + 4)));
|
||||||
|
if (udp_len < UDP_HEADER_LEN || buf_udp + udp_len > buf + buf_size)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*payload = buf_udp + UDP_HEADER_LEN;
|
||||||
|
*payload_size = udp_len - UDP_HEADER_LEN;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_pcap_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstPcapParse *self = GST_PCAP_PARSE (GST_PAD_PARENT (pad));
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
if (GST_PAD_CAPS (self->src_pad) == NULL) {
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
caps = gst_pad_peer_get_caps (self->src_pad);
|
||||||
|
if (caps == NULL)
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
|
||||||
|
if (!gst_caps_is_fixed (caps) || !gst_pad_set_caps (self->src_pad, caps)) {
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_adapter_push (self->adapter, buffer);
|
||||||
|
|
||||||
|
while (ret == GST_FLOW_OK) {
|
||||||
|
gint avail;
|
||||||
|
const guint8 *data;
|
||||||
|
|
||||||
|
avail = gst_adapter_available (self->adapter);
|
||||||
|
|
||||||
|
if (self->initialized) {
|
||||||
|
if (self->cur_packet_size >= 0) {
|
||||||
|
if (avail < self->cur_packet_size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (self->cur_packet_size > 0) {
|
||||||
|
const guint8 *payload_data;
|
||||||
|
gint payload_size;
|
||||||
|
|
||||||
|
data = gst_adapter_peek (self->adapter, self->cur_packet_size);
|
||||||
|
|
||||||
|
if (gst_pcap_parse_scan_frame (self, data, self->cur_packet_size,
|
||||||
|
&payload_data, &payload_size)) {
|
||||||
|
GstBuffer *out_buf;
|
||||||
|
|
||||||
|
ret = gst_pad_alloc_buffer_and_set_caps (self->src_pad,
|
||||||
|
self->buffer_offset, payload_size,
|
||||||
|
GST_PAD_CAPS (self->src_pad), &out_buf);
|
||||||
|
|
||||||
|
if (ret == GST_FLOW_OK) {
|
||||||
|
memcpy (GST_BUFFER_DATA (out_buf), payload_data, payload_size);
|
||||||
|
|
||||||
|
ret = gst_pad_push (self->src_pad, out_buf);
|
||||||
|
|
||||||
|
self->buffer_offset += payload_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_adapter_flush (self->adapter, self->cur_packet_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->cur_packet_size = -1;
|
||||||
|
} else {
|
||||||
|
guint32 ts_sec;
|
||||||
|
guint32 ts_usec;
|
||||||
|
guint32 incl_len;
|
||||||
|
guint32 orig_len;
|
||||||
|
|
||||||
|
if (avail < 16)
|
||||||
|
break;
|
||||||
|
|
||||||
|
data = gst_adapter_peek (self->adapter, 16);
|
||||||
|
|
||||||
|
ts_sec = gst_pcap_parse_read_uint32 (self, data + 0);
|
||||||
|
ts_usec = gst_pcap_parse_read_uint32 (self, data + 4);
|
||||||
|
incl_len = gst_pcap_parse_read_uint32 (self, data + 8);
|
||||||
|
orig_len = gst_pcap_parse_read_uint32 (self, data + 12);
|
||||||
|
|
||||||
|
gst_adapter_flush (self->adapter, 16);
|
||||||
|
|
||||||
|
self->cur_packet_size = incl_len;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
guint magic;
|
||||||
|
|
||||||
|
if (avail < 24)
|
||||||
|
break;
|
||||||
|
|
||||||
|
data = gst_adapter_peek (self->adapter, 24);
|
||||||
|
|
||||||
|
magic = *((guint32 *) data);
|
||||||
|
|
||||||
|
gst_adapter_flush (self->adapter, 24);
|
||||||
|
|
||||||
|
if (magic == 0xa1b2c3d4)
|
||||||
|
self->swap_endian = FALSE;
|
||||||
|
else if (magic == 0xd4c3b2a1)
|
||||||
|
self->swap_endian = TRUE;
|
||||||
|
else
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
if (ret == GST_FLOW_OK)
|
||||||
|
self->initialized = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
gst_pcap_parse_reset (self);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
plugin_init (GstPlugin * plugin)
|
||||||
|
{
|
||||||
|
return gst_element_register (plugin, "pcapparse",
|
||||||
|
GST_RANK_NONE, GST_TYPE_PCAP_PARSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||||
|
GST_VERSION_MINOR,
|
||||||
|
"pcapparse",
|
||||||
|
"Element parsing raw pcap streams",
|
||||||
|
plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")
|
78
gst/pcapparse/gstpcapparse.h
Normal file
78
gst/pcapparse/gstpcapparse.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2007 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_PCAP_PARSE_H__
|
||||||
|
#define __GST_PCAP_PARSE_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/base/gstadapter.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_PCAP_PARSE \
|
||||||
|
(gst_pcap_parse_get_type ())
|
||||||
|
#define GST_PCAP_PARSE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PCAP_PARSE, GstPcapParse))
|
||||||
|
#define GST_PCAP_PARSE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PCAP_PARSE, GstPcapParseClass))
|
||||||
|
#define GST_IS_PCAP_PARSE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PCAP_PARSE))
|
||||||
|
#define GST_IS_PCAP_PARSE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PCAP_PARSE))
|
||||||
|
|
||||||
|
typedef struct _GstPcapParse GstPcapParse;
|
||||||
|
typedef struct _GstPcapParseClass GstPcapParseClass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PCAP_PARSE_STATE_CREATED,
|
||||||
|
PCAP_PARSE_STATE_PARSING,
|
||||||
|
} GstPcapParseState;
|
||||||
|
|
||||||
|
struct _GstPcapParse
|
||||||
|
{
|
||||||
|
GstElement element;
|
||||||
|
|
||||||
|
GstPad * sink_pad;
|
||||||
|
GstPad * src_pad;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
gint64 src_ip;
|
||||||
|
gint64 dst_ip;
|
||||||
|
gint32 src_port;
|
||||||
|
gint32 dst_port;
|
||||||
|
|
||||||
|
/* state */
|
||||||
|
GstAdapter * adapter;
|
||||||
|
gboolean initialized;
|
||||||
|
gboolean swap_endian;
|
||||||
|
gint64 cur_packet_size;
|
||||||
|
gint64 buffer_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstPcapParseClass
|
||||||
|
{
|
||||||
|
GstElementClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_pcap_parse_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_PCAP_PARSE_H__ */
|
Loading…
Reference in a new issue