diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 26 | ||||
-rw-r--r-- | transmitters/Makefile.am | 3 | ||||
-rw-r--r-- | transmitters/rawudp/Makefile.am | 23 | ||||
-rw-r--r-- | transmitters/rawudp/fs-rawudp-stream-transmitter.c | 199 | ||||
-rw-r--r-- | transmitters/rawudp/fs-rawudp-stream-transmitter.h | 91 | ||||
-rw-r--r-- | transmitters/rawudp/fs-rawudp-transmitter.c | 195 | ||||
-rw-r--r-- | transmitters/rawudp/fs-rawudp-transmitter.h | 87 | ||||
-rw-r--r-- | transmitters/rawudp/stun.c | 343 | ||||
-rw-r--r-- | transmitters/rawudp/stun.h | 129 |
10 files changed, 1098 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 6a1e1f44..ba5bf09b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,7 @@ SUBDIRS_EXT = SUBDIRS = \ gst-libs \ gst $(SUBDIRS_EXT) \ + transmitters \ tests \ docs # @@ -15,6 +16,7 @@ SUBDIRS = \ DIST_SUBDIRS = \ gst-libs \ gst $(SUBDIRS_EXT) \ + transmitters \ tests \ docs # diff --git a/configure.ac b/configure.ac index 59dbd2ce..6f3ec556 100644 --- a/configure.ac +++ b/configure.ac @@ -133,6 +133,30 @@ AM_CONDITIONAL(BUILD_EXTERNAL, test "x$BUILD_EXTERNAL" = "xyes") dnl *** path for our local plugins *** + +dnl these are all the transmitter plug-ins +FS2_TRANSMITTER_PLUGINS_ALL=" \ + rawudp + " +AC_SUBST(FS2_TRANSMITTER_PLUGINS_ALL) + +FS2_TRANSMITTER_PLUGINS_SELECTED="" + +AC_ARG_WITH(transmitter-plugins, + AC_HELP_STRING([--with-transmitter-plugins], + [comma-separated list of plug-ins to compile]), + [for i in `echo $withval | tr , ' '`; do + if echo $FS2_TRANSMITTER_PLUGINS_ALL | grep $i > /dev/null + then + FS2_TRANSMITTER_PLUGINS_SELECTED="$FS2_TRANSMITTER_PLUGINS_SELECTED $i" + else + echo "plug-in $i not recognized, ignoring..." + fi + done], + [FS2_TRANSMITTER_PLUGINS_SELECTED=$FS2_TRANSMITTER_PLUGINS_ALL]) + +AC_SUBST(FS2_TRANSMITTER_PLUGINS_SELECTED) + dnl set the plugindir where plugins should be installed AS_AC_EXPAND(FS2_PLUGIN_PATH, ${libdir}/farsight-$FS2_MAJORMINOR) AC_SUBST(FS2_PLUGIN_PATH) @@ -308,6 +332,8 @@ gst/funnel/Makefile gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/farsight/Makefile +transmitters/Makefile +transmitters/rawudp/Makefile dnl pkgconfig/Makefile dnl pkgconfig/farsight2.pc dnl pkgconfig/farsight2-uninstalled.pc diff --git a/transmitters/Makefile.am b/transmitters/Makefile.am new file mode 100644 index 00000000..353b1f0a --- /dev/null +++ b/transmitters/Makefile.am @@ -0,0 +1,3 @@ + +SUBDIRS = $(FS2_TRANSMITTER_PLUGINS_SELECTED) +DIST_SUBDIRS = $(FS2_TRANMITTER_PLUGINS_ALL) diff --git a/transmitters/rawudp/Makefile.am b/transmitters/rawudp/Makefile.am new file mode 100644 index 00000000..b067ca2c --- /dev/null +++ b/transmitters/rawudp/Makefile.am @@ -0,0 +1,23 @@ + +plugindir = $(FS2_PLUGIN_PATH) + +plugin_LTLIBRARIES = librawudp-transmitter.la + +# sources used to compile this lib +librawudp_transmitter_la_SOURCES = \ + fs-rawudp-transmitter.c \ + fs-rawudp-stream-transmitter.c \ + stun.c + +# flags used to compile this plugin +librawudp_transmitter_la_CFLAGS = $(FS2_INTERNAL_CFLAGS) $(FS2_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +librawudp_transmitter_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +librawudp_transmitter_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/farsight/libgstfarsight-0.10.la \ + $(FS2_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) + +noinst_HEADERS = \ + fs-rawudp-transmitter.h \ + fs-rawudp-stream-transmitter.h \ + stun.h diff --git a/transmitters/rawudp/fs-rawudp-stream-transmitter.c b/transmitters/rawudp/fs-rawudp-stream-transmitter.c new file mode 100644 index 00000000..79fb7f7c --- /dev/null +++ b/transmitters/rawudp/fs-rawudp-stream-transmitter.c @@ -0,0 +1,199 @@ +/* + * Farsight2 - Farsight RAW UDP with STUN Transmitter + * + * Copyright 2007 Collabora Ltd. + * @author: Olivier Crete <olivier.crete@collabora.co.uk> + * Copyright 2007 Nokia Corp. + * + * fs-rawudp-transmitter.c - A Farsight UDP transmitter with STUN + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 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 Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/** + * SECTION:fs-stream-transmitter + * @short_description: A stream transmitter object for UDP with STUN + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "fs-rawudp-stream-transmitter.h" + +#include <gst/gst.h> + +/* Signals */ +enum +{ + LAST_SIGNAL +}; + +/* props */ +enum +{ + PROP_0, + PROP_SENDING, +}; + +struct _FsRawUdpStreamTransmitterPrivate +{ + gboolean disposed; +}; + +#define FS_RAWUDP_STREAM_TRANSMITTER_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_RAWUDP_STREAM_TRANSMITTER, \ + FsRawUdpStreamTransmitterPrivate)) + +static void fs_rawudp_stream_transmitter_class_init (FsRawUdpStreamTransmitterClass *klass); +static void fs_rawudp_stream_transmitter_init (FsRawUdpStreamTransmitter *self); +static void fs_rawudp_stream_transmitter_dispose (GObject *object); +static void fs_rawudp_stream_transmitter_finalize (GObject *object); + +static void fs_rawudp_stream_transmitter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void fs_rawudp_stream_transmitter_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static gboolean fs_rawudp_stream_transmitter_add_remote_candidate ( + FsStreamTransmitter *streamtransmitter, FsCandidate *candidate, + GError **error); + + +static GObjectClass *parent_class = NULL; +// static guint signals[LAST_SIGNAL] = { 0 }; + +GType +fs_rawudp_stream_transmitter_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof (FsRawUdpStreamTransmitterClass), + NULL, + NULL, + (GClassInitFunc) fs_rawudp_stream_transmitter_class_init, + NULL, + NULL, + sizeof (FsRawUdpStreamTransmitter), + 0, + (GInstanceInitFunc) fs_rawudp_stream_transmitter_init + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "FsRawUdpStreamTransmitter", &info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +static void +fs_rawudp_stream_transmitter_class_init (FsRawUdpStreamTransmitterClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + FsStreamTransmitterClass *streamtransmitterclass = + FS_STREAM_TRANSMITTER_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = fs_rawudp_stream_transmitter_set_property; + gobject_class->get_property = fs_rawudp_stream_transmitter_get_property; + + streamtransmitterclass->add_remote_candidate = + fs_rawudp_stream_transmitter_add_remote_candidate; + + g_object_class_override_property (gobject_class, PROP_SENDING, "sending"); + + gobject_class->dispose = fs_rawudp_stream_transmitter_dispose; + gobject_class->finalize = fs_rawudp_stream_transmitter_finalize; + + g_type_class_add_private (klass, sizeof (FsRawUdpStreamTransmitterPrivate)); +} + +static void +fs_rawudp_stream_transmitter_init (FsRawUdpStreamTransmitter *self) +{ + /* member init */ + self->priv = FS_RAWUDP_STREAM_TRANSMITTER_GET_PRIVATE (self); + self->priv->disposed = FALSE; +} + +static void +fs_rawudp_stream_transmitter_dispose (GObject *object) +{ + FsRawUdpStreamTransmitter *self = FS_RAWUDP_STREAM_TRANSMITTER (object); + + if (self->priv->disposed) { + /* If dispose did already run, return. */ + return; + } + + /* Make sure dispose does not run twice. */ + self->priv->disposed = TRUE; + + parent_class->dispose (object); +} + +static void +fs_rawudp_stream_transmitter_finalize (GObject *object) +{ + parent_class->finalize (object); +} + +static void +fs_rawudp_stream_transmitter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ +} + +static void +fs_rawudp_stream_transmitter_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ +} + + +/** + * fs_rawudp_stream_transmitter_add_remote_candidate + * @streamtransmitter: a #FsStreamTransmitter + * @candidate: a remote #FsCandidate to add + * @error: location of a #GError, or NULL if no error occured + * + * This function is used to add remote candidates to the transmitter + * + * Returns: TRUE of the candidate could be added, FALSE if it couldnt + * (and the #GError will be set) + */ + +static gboolean +fs_rawudp_stream_transmitter_add_remote_candidate ( + FsStreamTransmitter *streamtransmitter, FsCandidate *candidate, + GError **error) +{ + return FALSE; +} + diff --git a/transmitters/rawudp/fs-rawudp-stream-transmitter.h b/transmitters/rawudp/fs-rawudp-stream-transmitter.h new file mode 100644 index 00000000..9e3637fe --- /dev/null +++ b/transmitters/rawudp/fs-rawudp-stream-transmitter.h @@ -0,0 +1,91 @@ +/* + * Farsight2 - Farsight RAW UDP with STUN Stream Transmitter + * + * Copyright 2007 Collabora Ltd. + * @author: Olivier Crete <olivier.crete@collabora.co.uk> + * Copyright 2007 Nokia Corp. + * + * fs-stream-transmitter.h - A Farsight UDP stream transmitter with STUN + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 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 Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FS_RAWUDP_STREAM_TRANSMITTER_H__ +#define __FS_RAWUDP_STREAM_TRANSMITTER_H__ + +#include <glib.h> +#include <glib-object.h> + +#include <gst/farsight/fs-stream-transmitter.h> + +G_BEGIN_DECLS + +/* TYPE MACROS */ +#define FS_TYPE_RAWUDP_STREAM_TRANSMITTER \ + (fs_rawudp_stream_transmitter_get_type()) +#define FS_RAWUDP_STREAM_TRANSMITTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_RAWUDP_STREAM_TRANSMITTER, \ + FsRawUdpStreamTransmitter)) +#define FS_RAWUDP_STREAM_TRANSMITTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_RAWUDP_STREAM_TRANSMITTER, \ + FsRawUdpStreamTransmitterClass)) +#define FS_IS_RAWUDP_STREAM_TRANSMITTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_RAWUDP_STREAM_TRANSMITTER)) +#define FS_IS_RAWUDP_STREAM_TRANSMITTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_RAWUDP_STREAM_TRANSMITTER)) +#define FS_RAWUDP_STREAM_TRANSMITTER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_RAWUDP_STREAM_TRANSMITTER, \ + FsRawUdpStreamTransmitterClass)) +#define FS_RAWUDP_STREAM_TRANSMITTER_CAST(obj) ((FsRawUdpStreamTransmitter *) (obj)) + +typedef struct _FsRawUdpStreamTransmitter FsRawUdpStreamTransmitter; +typedef struct _FsRawUdpStreamTransmitterClass FsRawUdpStreamTransmitterClass; +typedef struct _FsRawUdpStreamTransmitterPrivate FsRawUdpStreamTransmitterPrivate; + +/** + * FsRawUdpStreamTransmitterClass: + * @parent_class: Our parent + * + * The Raw UDP stream transmitter class + */ + +struct _FsRawUdpStreamTransmitterClass +{ + FsStreamTransmitter parent_class; + + /*virtual functions */ + /*< private >*/ + gpointer _padding[8]; +}; + +/** + * FsRawUdpStreamTransmitter: + * + * All members are private, access them using methods and properties + */ +struct _FsRawUdpStreamTransmitter +{ + FsStreamTransmitterClass parent; + + /*< private >*/ + FsRawUdpStreamTransmitterPrivate *priv; + gpointer _padding[8]; +}; + +GType fs_rawudp_stream_transmitter_get_type (void); + +G_END_DECLS + +#endif /* __FS_RAWUDP_STREAM_TRANSMITTER_H__ */ diff --git a/transmitters/rawudp/fs-rawudp-transmitter.c b/transmitters/rawudp/fs-rawudp-transmitter.c new file mode 100644 index 00000000..e93981a7 --- /dev/null +++ b/transmitters/rawudp/fs-rawudp-transmitter.c @@ -0,0 +1,195 @@ +/* + * Farsight2 - Farsight RAW UDP with STUN Transmitter + * + * Copyright 2007 Collabora Ltd. + * @author: Olivier Crete <olivier.crete@collabora.co.uk> + * Copyright 2007 Nokia Corp. + * + * fs-rawudp-transmitter.h - A Farsight UDP transmitter with STUN + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 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 Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * SECTION:fs-rawudp-transmitter + * @short_description: A transmitter for raw udp (with STUN) + * + * This transmitter provides RAW udp (with stun) + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "fs-rawudp-transmitter.h" + +/* Signals */ +enum +{ + LAST_SIGNAL +}; + +/* props */ +enum +{ + PROP_0, + PROP_GST_SINK, + PROP_GST_SRC, +}; + +struct _FsRawUdpTransmitterPrivate +{ + gboolean disposed; +}; + +#define FS_RAWUDP_TRANSMITTER_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_RAWUDP_TRANSMITTER, FsRawUdpTransmitterPrivate)) + +static void fs_rawudp_transmitter_class_init (FsRawUdpTransmitterClass *klass); +static void fs_rawudp_transmitter_init (FsRawUdpTransmitter *self); +static void fs_rawudp_transmitter_dispose (GObject *object); +static void fs_rawudp_transmitter_finalize (GObject *object); + +static void fs_rawudp_transmitter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void fs_rawudp_transmitter_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static FsStreamTransmitter *fs_rawudp_transmitter_new_stream_transmitter ( + FsTransmitter *transmitter, FsParticipant *participant); + + +static GObjectClass *parent_class = NULL; +//static guint signals[LAST_SIGNAL] = { 0 }; + +GType +fs_rawudp_transmitter_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof (FsRawUdpTransmitterClass), + NULL, + NULL, + (GClassInitFunc) fs_rawudp_transmitter_class_init, + NULL, + NULL, + sizeof (FsRawUdpTransmitter), + 0, + (GInstanceInitFunc) fs_rawudp_transmitter_init + }; + + type = g_type_register_static (FS_TYPE_TRANSMITTER, + "FsRawUdpTransmitter", &info, 0); + } + + return type; +} + +static void +fs_rawudp_transmitter_class_init (FsRawUdpTransmitterClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + FsTransmitterClass *transmitter_class = FS_TRANSMITTER_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = fs_rawudp_transmitter_set_property; + gobject_class->get_property = fs_rawudp_transmitter_get_property; + + g_object_class_override_property (gobject_class, PROP_GST_SRC, "gst-src"); + g_object_class_override_property (gobject_class, PROP_GST_SINK, "gst-sink"); + + transmitter_class->new_stream_transmitter = + fs_rawudp_transmitter_new_stream_transmitter; + + gobject_class->dispose = fs_rawudp_transmitter_dispose; + gobject_class->finalize = fs_rawudp_transmitter_finalize; + + g_type_class_add_private (klass, sizeof (FsRawUdpTransmitterPrivate)); +} + +static void +fs_rawudp_transmitter_init (FsRawUdpTransmitter *self) +{ + /* member init */ + self->priv = FS_RAWUDP_TRANSMITTER_GET_PRIVATE (self); + self->priv->disposed = FALSE; +} + +static void +fs_rawudp_transmitter_dispose (GObject *object) +{ + FsRawUdpTransmitter *self = FS_RAWUDP_TRANSMITTER (object); + + if (self->priv->disposed) { + /* If dispose did already run, return. */ + return; + } + + /* Make sure dispose does not run twice. */ + self->priv->disposed = TRUE; + + parent_class->dispose (object); +} + +static void +fs_rawudp_transmitter_finalize (GObject *object) +{ + parent_class->finalize (object); +} + +static void +fs_rawudp_transmitter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ +} + +static void +fs_rawudp_transmitter_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ +} + + +/** + * fs_rawudp_transmitter_new_stream_rawudp_transmitter: + * @transmitter: a #FsTranmitter + * @participant: the #FsParticipant for which the #FsStream using this + * new #FsStreamTransmitter is created + * + * This function will create a new #FsStreamTransmitter element for a + * specific participant for this #FsRawUdpTransmitter + * + * Returns: a new #FsStreamTransmitter + */ + +static FsStreamTransmitter * +fs_rawudp_transmitter_new_stream_transmitter (FsTransmitter *transmitter, + FsParticipant *participant) +{ + + return NULL; +} diff --git a/transmitters/rawudp/fs-rawudp-transmitter.h b/transmitters/rawudp/fs-rawudp-transmitter.h new file mode 100644 index 00000000..7269b16d --- /dev/null +++ b/transmitters/rawudp/fs-rawudp-transmitter.h @@ -0,0 +1,87 @@ +/* + * Farsight2 - Farsight RAW UDP with STUN Transmitter + * + * Copyright 2007 Collabora Ltd. + * @author: Olivier Crete <olivier.crete@collabora.co.uk> + * Copyright 2007 Nokia Corp. + * + * fs-rawudp-transmitter.h - A Farsight UDP transmitter with STUN + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 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 Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FS_RAWUDP_TRANSMITTER_H__ +#define __FS_RAWUDP_TRANSMITTER_H__ + +#include <gst/farsight/fs-transmitter.h> + +G_BEGIN_DECLS + +/* TYPE MACROS */ +#define FS_TYPE_RAWUDP_TRANSMITTER \ + (fs_rawudp_transmitter_get_type()) +#define FS_RAWUDP_TRANSMITTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_RAWUDP_TRANSMITTER, \ + FsRawUdpTransmitter)) +#define FS_RAWUDP_TRANSMITTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_RAWUDP_TRANSMITTER, \ + FsRawUdpTransmitterClass)) +#define FS_IS_RAWUDP_TRANSMITTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_RAWUDP_TRANSMITTER)) +#define FS_IS_RAWUDP_TRANSMITTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_RAWUDP_TRANSMITTER)) +#define FS_RAWUDP_TRANSMITTER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_RAWUDP_TRANSMITTER, \ + FsRawUdpTransmitterClass)) +#define FS_RAWUDP_TRANSMITTER_CAST(obj) ((FsRawUdpTransmitter *) (obj)) + +typedef struct _FsRawUdpTransmitter FsRawUdpTransmitter; +typedef struct _FsRawUdpTransmitterClass FsRawUdpTransmitterClass; +typedef struct _FsRawUdpTransmitterPrivate FsRawUdpTransmitterPrivate; + +/** + * FsRawUdpTransmitterClass: + * @parent_class: Our parent + * + * The Raw UDP transmitter class + */ + +struct _FsRawUdpTransmitterClass +{ + FsTransmitterClass parent_class; + + /*< private >*/ + gpointer _padding[8]; +}; + +/** + * FsRawUdpTransmitter: + * + * All members are private, access them using methods and properties + */ +struct _FsRawUdpTransmitter +{ + FsTransmitter parent; + + /*< private >*/ + FsRawUdpTransmitterPrivate *priv; + gpointer _padding[8]; +}; + +GType fs_rawudp_transmitter_get_type (void); + +G_END_DECLS + +#endif /* __FS_RAWUDP_TRANSMITTER_H__ */ diff --git a/transmitters/rawudp/stun.c b/transmitters/rawudp/stun.c new file mode 100644 index 00000000..1157fd74 --- /dev/null +++ b/transmitters/rawudp/stun.c @@ -0,0 +1,343 @@ +#include "stun.h" + +#include <string.h> + +#ifndef G_OS_WIN32 +#include <arpa/inet.h> +#else +#include <winsock2.h> +#endif + +/* round up to multiple of 4 */ +G_GNUC_CONST +static guint +ceil4 (guint n) +{ + if (n % 4 == 0) + return n; + else + return n + 4 - (n % 4); +} + +G_GNUC_WARN_UNUSED_RESULT +static StunAttribute * +stun_attribute_new (guint type) +{ + StunAttribute *attr = g_slice_new0 (StunAttribute); + + attr->type = type; + return attr; +} + +StunAttribute * +stun_attribute_mapped_address_new (guint32 ip, guint16 port) +{ + StunAttribute *attr = stun_attribute_new (STUN_ATTRIBUTE_MAPPED_ADDRESS); + + attr->length = 8; + attr->address.padding = 0; + attr->address.af = 1; + attr->address.ip = ip; + attr->address.port = port; + return attr; +} + +StunAttribute * +stun_attribute_username_new (const gchar *username) +{ + StunAttribute *attr; + + attr = stun_attribute_new (STUN_ATTRIBUTE_USERNAME); + g_assert (strlen (username) < sizeof (attr->username)); + attr->length = strlen (username); + strcpy (attr->username, username); + return attr; +} + +void +stun_attribute_free (StunAttribute *attr) +{ + g_slice_free (StunAttribute, attr); +} + +G_GNUC_WARN_UNUSED_RESULT +static gboolean +_stun_attribute_unpack (StunAttribute *attr, guint length, const gchar *s) +{ + guint type; + + if (length < 4) + /* must start with 16 bit type, 16 bit length */ + return FALSE; + + type = ntohs (*(guint16 *) s); + + switch (type) + { + case STUN_ATTRIBUTE_MAPPED_ADDRESS: + if (length != 12) + return FALSE; + + attr->address.af = (guint8) s[5]; + g_assert (attr->address.af == 1); + attr->address.port = ntohs (*(guint16 *)(s + 6)); + attr->address.ip = ntohl (*(guint32 *)(s + 8)); + break; + + case STUN_ATTRIBUTE_USERNAME: + case STUN_ATTRIBUTE_PASSWORD: + if (length - 4 > sizeof (attr->username) / sizeof (gchar)) + return FALSE; + + attr->length = length - 4; + + if (type == STUN_ATTRIBUTE_USERNAME) + memcpy (attr->username, s + 4, attr->length); + else + memcpy (attr->password, s + 4, attr->length); + break; + + default: + /* unknown attribute; we can only unpack the type */ + break; + } + + attr->type = type; + return TRUE; +} + +StunAttribute * +stun_attribute_unpack (guint length, const gchar *s) +{ + StunAttribute *attr; + + attr = stun_attribute_new (0); + + if (_stun_attribute_unpack (attr, length, s)) + return attr; + + stun_attribute_free (attr); + return NULL; +} + +guint +stun_attribute_pack (StunAttribute *attr, gchar **packed) +{ + switch (attr->type) + { + case STUN_ATTRIBUTE_MAPPED_ADDRESS: + { + if (packed != NULL) + { + StunAttribute *ret = g_malloc0 (sizeof (StunAttribute)); + + ret->type = htons (attr->type); + ret->length = htons (8); + ret->address.af = attr->address.af; + ret->address.port = htons (attr->address.port); + ret->address.ip = htonl (attr->address.ip); + *packed = (gchar *) ret; + } + + return 12; + } + + case STUN_ATTRIBUTE_USERNAME: + { + if (packed != NULL) + { + StunAttribute *ret = g_malloc0 (sizeof (StunAttribute)); + + ret->type = htons (attr->type); + ret->length = htons (attr->length); + memcpy (ret->username, attr->username, attr->length); + *packed = (gchar *) ret; + } + + return ceil4 (4 + attr->length); + } + + default: + return 0; + } +} + +gchar * +stun_attribute_dump (StunAttribute *attr) +{ + switch (attr->type) + { + case STUN_ATTRIBUTE_MAPPED_ADDRESS: + return g_strdup_printf ( + "MAPPED-ADDRESS %d.%d.%d.%d:%d", + (attr->address.ip & 0xff000000) >> 24, + (attr->address.ip & 0x00ff0000) >> 16, + (attr->address.ip & 0x0000ff00) >> 8, + (attr->address.ip & 0x000000ff) >> 0, + attr->address.port); + case STUN_ATTRIBUTE_USERNAME: + return g_strdup_printf ( + "USERNAME \"%*s\"", attr->length, attr->username); + default: + return g_strdup_printf ("UNKNOWN (%d)", attr->type); + } +} + +void +stun_message_init (StunMessage *msg, guint type, const gchar *id) +{ + msg->type = type; + + if (id != NULL) + memcpy (msg->transaction_id, id, 16); +} + +StunMessage * +stun_message_new (guint type, const gchar *id, guint n_attributes) +{ + StunMessage *msg = g_slice_new0 (StunMessage); + + stun_message_init (msg, type, id); + + if (n_attributes != 0) + msg->attributes = g_malloc0 ( + (n_attributes + 1) * sizeof (StunAttribute *)); + + return msg; +} + +void +stun_message_free (StunMessage *msg) +{ + StunAttribute **attr; + + if (msg->attributes) + { + for (attr = msg->attributes; *attr; attr++) + stun_attribute_free (*attr); + + g_free (msg->attributes); + } + + g_slice_free (StunMessage, msg); +} + +StunMessage * +stun_message_unpack (guint length, const gchar *s) +{ + guint attr_length; + guint n_attributes = 0; + guint i; + guint offset; + StunAttribute *attr; + StunMessage *msg; + + /* message header is 20 bytes */ + + if (length < 20) + return NULL; + + /* count the number of attributes */ + + for (offset = 20; offset < length; offset += attr_length) + { + attr_length = ceil4 (4 + ntohs (*(guint16 *)(s + offset + 2))); + n_attributes++; + } + + /* create message structure */ + + msg = stun_message_new (ntohs (*(guint16 *) s), s + 4, n_attributes); + + /* unpack attributes */ + + for (i = 0, offset = 20; i < n_attributes; i++, offset += attr_length) + { + attr_length = 4 + ntohs (*(guint16 *)(s + offset + 2)); + attr = msg->attributes[i] = stun_attribute_unpack (attr_length, + s + offset); + attr_length = ceil4 (attr_length); + } + + return msg; +} + +guint +stun_message_pack (StunMessage *msg, gchar **packed) +{ + gchar *tmp; + guint length = 0; + + if (msg->attributes) + { + StunAttribute **attr; + + for (attr = msg->attributes; *attr; attr++) + length += stun_attribute_pack (*attr, NULL); + } + + g_assert (length % 4 == 0); + tmp = g_malloc0 (length + 20); + *(guint16 *) (tmp + 0) = htons (msg->type); + *(guint16 *) (tmp + 2) = htons (length); + memcpy (tmp + 4, msg->transaction_id, 16); + + if (msg->attributes) + { + StunAttribute **attr; + gchar *pos = tmp + 20; + + for (attr = msg->attributes; *attr; attr++) + { + gchar *attr_packed; + guint attr_length = stun_attribute_pack (*attr, &attr_packed); + memcpy (pos, attr_packed, attr_length); + g_free (attr_packed); + pos += attr_length; + } + } + + *packed = tmp; + return length + 20; +} + +gchar * +stun_message_dump (StunMessage *msg) +{ + StunAttribute **attr; + GString *tmp = g_string_new (""); + const gchar *name; + + switch (msg->type) { + case STUN_MESSAGE_BINDING_REQUEST: + name = "BINDING-REQUEST"; + break; + case STUN_MESSAGE_BINDING_RESPONSE: + name = "BINDING-RESPONSE"; + break; + case STUN_MESSAGE_BINDING_ERROR_RESPONSE: + name = "BINDING-ERROR-RESPONSE"; + break; + default: + name = "(UNKNOWN)"; + } + + g_string_printf (tmp, + "%s %08x:%08x:%08x:%08x\n", + name, + ntohl (*(guint32 *)(msg->transaction_id)), + ntohl (*(guint32 *)(msg->transaction_id + 4)), + ntohl (*(guint32 *)(msg->transaction_id + 8)), + ntohl (*(guint32 *)(msg->transaction_id + 12))); + + if (msg->attributes) + for (attr = msg->attributes; *attr; attr++) + { + gchar *dump = stun_attribute_dump (*attr); + g_string_append_printf (tmp, " %s\n", dump); + g_free (dump); + } + + return g_string_free (tmp, FALSE); +} + diff --git a/transmitters/rawudp/stun.h b/transmitters/rawudp/stun.h new file mode 100644 index 00000000..87f00f85 --- /dev/null +++ b/transmitters/rawudp/stun.h @@ -0,0 +1,129 @@ + +#ifndef __STUN_H__ +#define __STUN_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +typedef enum +{ + STUN_MESSAGE_BINDING_REQUEST = 0x001, + STUN_MESSAGE_BINDING_RESPONSE = 0x101, + STUN_MESSAGE_BINDING_ERROR_RESPONSE = 0x111, + STUN_MESSAGE_SHARED_SECRET_REQUEST = 0x002, + STUN_MESSAGE_SHARED_SECRET_RESPONSE = 0x102, + STUN_MESSAGE_SHARED_SECRET_ERROR_RESPONSE = 0x112 +} StunMessageType; + +/* a = defined by RFC 3489 + * b = defined by RFC 3489bis + * c = defined by draft-ietf-behave-turn-02 + */ + +typedef enum +{ + // mandatory parameters (<= 0x7fff) + STUN_ATTRIBUTE_MAPPED_ADDRESS = 0x0001, // ab + STUN_ATTRIBUTE_RESPONSE_ADDRESS = 0x0002, // a + STUN_ATTRIBUTE_CHANGE_REQUEST = 0x0003, // a + STUN_ATTRIBUTE_CHANGED_ADDRESS = 0x0004, // a + STUN_ATTRIBUTE_SOURCE_ADDRESS = 0x0005, // a + STUN_ATTRIBUTE_USERNAME = 0x0006, // ab + STUN_ATTRIBUTE_PASSWORD = 0x0007, // ab + STUN_ATTRIBUTE_MESSAGE_INTEGRITY = 0x0008, // ab + STUN_ATTRIBUTE_ERROR_CODE = 0x0009, // ab + STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES = 0x000a, // ab + STUN_ATTRIBUTE_REFLECTED_FROM = 0x000b, // a + STUN_ATTRIBUTE_REALM = 0x0014, // b + STUN_ATTRIBUTE_NONCE = 0x0015, // b + STUN_ATTRIBUTE_LIFETIME = 0x000D, // c + STUN_ATTRIBUTE_BANDWIDTH = 0x0010, // c + STUN_ATTRIBUTE_REMOTE_ADDRESS = 0x0012, // c + STUN_ATTRIBUTE_DATA = 0x0013, // c + STUN_ATTRIBUTE_RELAY_ADDRESS = 0x0016, // c + STUN_ATTRIBUTE_REQUESTED_PORT_PROPS = 0x0018, // c + STUN_ATTRIBUTE_REQUESTED_TRANSPORT = 0x0019, // c + STUN_ATTRIBUTE_REQUESTED_IP = 0x0022, // c + STUN_ATTRIBUTE_TIMER_VAL = 0x0021, // c + // optional parameters (> 0x7fff) + STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS = 0x8020, // b + STUN_ATTRIBUTE_FINGERPRINT = 0x8023, // b + STUN_ATTRIBUTE_SERVER = 0x8022, // b + SUTN_ATTRIBUTE_ALTERNATE_SERVER = 0x8023, // b + STUN_ATTRIBUTE_REFRESH_INTERVAL = 0x8024, // b +} StunAttributeType; + +typedef struct _StunAttribute StunAttribute; + +struct _StunAttribute { + guint16 type; + guint16 length; + union { + struct { + guint8 padding; + guint8 af; + guint16 port; + guint32 ip; + } address; + gchar username[128]; + gchar password[128]; + }; +}; + +typedef struct _StunMessage StunMessage; + +struct _StunMessage { + guint16 type; + gchar transaction_id[16]; + StunAttribute **attributes; +}; + +G_GNUC_WARN_UNUSED_RESULT +StunAttribute * +stun_attribute_mapped_address_new (guint32 ip_address, guint16 port); + +StunAttribute * +stun_attribute_username_new (const gchar *username); + +void +stun_attribute_free (StunAttribute *attr); + +G_GNUC_WARN_UNUSED_RESULT +guint +stun_attribute_pack (StunAttribute *attr, gchar **ret); + +G_GNUC_WARN_UNUSED_RESULT +gchar * +stun_attribute_dump (StunAttribute *attr); + +G_GNUC_WARN_UNUSED_RESULT +StunAttribute * +stun_attribute_unpack (guint length, const gchar *s); + +void +stun_message_init (StunMessage *msg, guint type, const gchar *id); + +G_GNUC_WARN_UNUSED_RESULT +StunMessage * +stun_message_new (guint type, const gchar *id, guint n_attributes); + +void +stun_message_free (StunMessage *msg); +G_GNUC_WARN_UNUSED_RESULT + +guint +stun_message_pack (StunMessage *msg, gchar **packed); +G_GNUC_WARN_UNUSED_RESULT + +gchar * +stun_message_dump (StunMessage *msg); +G_GNUC_WARN_UNUSED_RESULT + +StunMessage * +stun_message_unpack (guint length, const gchar *s); + +G_END_DECLS + +#endif /* __STUN_H__ */ + |