add new tcp elements

Original commit message from CVS:
add new tcp elements
parent 12be7d62
2004-05-20 Thomas Vander Stichele <thomas at apestaart dot org>
* gst/tcp/.cvsignore:
ignore enums
* gst/tcp/Makefile.am:
* gst/tcp/README:
* gst/tcp/gsttcp.c:
* gst/tcp/gsttcp.h:
* gst/tcp/gsttcpclientsink.c:
* gst/tcp/gsttcpclientsink.h:
* gst/tcp/gsttcpclientsrc.c:
* gst/tcp/gsttcpclientsrc.h:
* gst/tcp/gsttcpplugin.c:
* gst/tcp/gsttcpserversink.c:
* gst/tcp/gsttcpserversink.h:
* gst/tcp/gsttcpserversrc.c:
* gst/tcp/gsttcpserversrc.h:
add new tcp elements
2004-05-19 Wim Taymans <wim@fluendo.com>
* gst/law/mulaw-conversion.c: (mulaw_encode):
......
gsttcp-enumtypes.c
gsttcp-enumtypes.h
plugin_LTLIBRARIES = libgsttcp.la
libgsttcp_la_SOURCES = gsttcpplugin.c gsttcpsrc.c gsttcpsink.c
# variables used for enum/marshal generation
glib_enum_headers = gsttcp.h
glib_enum_define = GST_TCP_PROTOCOL
glib_enum_prefix = gst_tcp_protocol
include $(top_srcdir)/common/glib-gen.mak
built_sources = gsttcp-enumtypes.c
built_headers = gsttcp-enumtypes.h
BUILT_SOURCES = $(built_sources) $(built_headers)
libgsttcp_la_SOURCES = \
gsttcpplugin.c \
gsttcpsrc.c gsttcpsink.c \
$(built_sources) \
gsttcp.c \
gsttcpclientsrc.c gsttcpclientsink.c \
gsttcpserversrc.c gsttcpserversink.c
libgsttcp_la_CFLAGS = $(GST_CFLAGS)
libgsttcp_la_LIBADD =
libgsttcp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gsttcpsink.h gsttcpsrc.h gsttcpplugin.h
noinst_HEADERS = \
$(built_headers) \
gsttcpplugin.h \
gsttcpsrc.h gsttcpsink.h \
gsttcp.h \
gsttcpclientsrc.h gsttcpclientsink.h \
gsttcpserversrc.h gsttcpserversink.h
EXTRA_DIST = README
CLEANFILES = $(BUILT_SOURCES)
This part of the documentation is for the new tcp elements:
- tcpclientsrc
- tcpclientsink
- tcpserversrc
- tcpserversink
which are created to replace the old tcpsrc/tcpsink
TESTS
-----
Use these tests to test functionality of the various tcp plugins
* server: nc -l -p 3000
client: nc localhost 3000
everything you type in the server is shown on the client
everything you type in the client is shown on the server
* server: nc -l -p 3000
client: gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2
everything you type in the server is shown on the client
* server: nc -l -p 3000
client: gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000
everything you type in the client is shown on the server
* server: gst-launch tcpserversrc protocol=none port=3000 ! fdsink fd=2
client: gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000
TODO
----
- implement DNS resolution
--------
This is the old documentation for the original tcpsrc/tcpsink elements.
* What is TCP src/sink?
solution, like icecast or realaudio or whatever. But the future RTP plugins shall not do the actual transmission/reception of packets on the network themselve but the Application developer would be encouraged to use either the TCP or the UDP plugins for that. UDP would be used mostly but there could be situations where TCP would be the only available choice. For example streaming accross firewalls that do not allow UDP.
solution, like icecast or realaudio or whatever.
But the future RTP plugins shall not do the actual transmission/reception
of packets on the network themselve but the Application developer would be
encouraged to use either the TCP or the UDP plugins for that. UDP would be
used mostly but there could be situations where TCP would be the only
available choice. For example streaming accross firewalls that do not
allow UDP.
* Shortcomings
......
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
*
* gsttcp.c: TCP functions
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <glib.h>
#include <gst/gst.h>
#include <gst/gst-i18n-plugin.h>
#include <gst/dataprotocol/dataprotocol.h>
/* resolve host to IP address, throwing errors if it fails */
/* host can already be an IP address */
/* returns a newly allocated gchar * with the dotted ip address */
gchar *
gst_tcp_host_to_ip (GstElement * element, const gchar * host)
{
struct hostent *hostinfo;
char **addrs;
gchar *ip;
struct in_addr addr;
/* first check if it already is an IP address */
if (inet_aton (host, &addr)) {
return g_strdup (host);
}
/* FIXME: could do a localhost check here */
/* perform a name lookup */
hostinfo = gethostbyname (host);
if (!hostinfo) {
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL),
("Could not find IP address for host \"%s\".", host));
return NULL;
}
if (hostinfo->h_addrtype != AF_INET) {
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL),
("host \"%s\" is not an IP host", host));
return NULL;
}
addrs = hostinfo->h_addr_list;
/* There could be more than one IP address, but we just return the first */
ip = g_strdup (inet_ntoa (*(struct in_addr *) *addrs));
return ip;
}
/* write buffer to given socket incrementally.
* Returns number of bytes written.
*/
gint
gst_tcp_socket_write (int socket, const void *buf, size_t count)
{
size_t bytes_written = 0;
while (bytes_written < count) {
size_t wrote = write (socket, buf + bytes_written,
count - bytes_written);
if (wrote <= 0) {
return bytes_written;
}
bytes_written += wrote;
}
if (bytes_written < 0)
GST_DEBUG ("error while writing");
else
GST_DEBUG ("wrote %d bytes succesfully", bytes_written);
return bytes_written;
}
/* read number of bytes from a socket into a given buffer incrementally.
* Returns number of bytes read.
*/
gint
gst_tcp_socket_read (int socket, void *buf, size_t count)
{
size_t bytes_read = 0;
while (bytes_read < count) {
size_t ret = read (socket, buf + bytes_read,
count - bytes_read);
if (ret <= 0) {
return bytes_read;
}
bytes_read += ret;
}
if (bytes_read < 0)
GST_DEBUG ("error while reading");
else
GST_DEBUG ("read %d bytes succesfully", bytes_read);
return bytes_read;
}
/* read the gdp buffer header from the given socket
* returns a GstData,
* representing the new GstBuffer to read data into, or an EOS event
*/
GstData *
gst_tcp_gdp_read_header (GstElement * this, int socket)
{
size_t header_length = GST_DP_HEADER_LENGTH;
size_t readsize;
guint8 *header = NULL;
size_t ret;
GstBuffer *buffer;
header = g_malloc (header_length);
readsize = header_length;
GST_DEBUG_OBJECT (this, "Reading %d bytes for buffer packet header",
readsize);
ret = read (socket, header, readsize);
/* if we read 0 bytes, and we're blocking, we hit eos */
if (ret == 0) {
GST_DEBUG ("blocking read returns 0, EOS");
gst_element_set_eos (GST_ELEMENT (this));
return GST_DATA (gst_event_new (GST_EVENT_EOS));
}
if (ret < 0) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
return NULL;
}
if (ret != readsize) {
g_warning ("Wanted %d bytes, got %d bytes", readsize, ret);
}
g_assert (ret == readsize);
if (!gst_dp_validate_header (header_length, header)) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
("GDP buffer packet header does not validate"));
g_free (header);
return NULL;
}
GST_DEBUG_OBJECT (this, "validated buffer packet header");
buffer = gst_dp_buffer_from_header (header_length, header);
GST_DEBUG_OBJECT (this, "created new buffer %p from packet header", buffer);
return GST_DATA (buffer);
}
/* read the GDP caps packet from the given socket
* returns the caps, or NULL in case of an error */
GstCaps *
gst_tcp_gdp_read_caps (GstElement * this, int socket)
{
size_t header_length = GST_DP_HEADER_LENGTH;
size_t readsize;
guint8 *header = NULL;
guint8 *payload = NULL;
size_t ret;
GstCaps *caps;
gchar *string;
header = g_malloc (header_length);
readsize = header_length;
GST_LOG_OBJECT (this, "Reading %d bytes for caps packet header", readsize);
ret = read (socket, header, readsize);
if (ret < 0) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
return NULL;
}
g_assert (ret == readsize);
if (!gst_dp_validate_header (header_length, header)) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
("GDP caps packet header does not validate"));
g_free (header);
return NULL;
}
readsize = gst_dp_header_payload_length (header);
payload = g_malloc (readsize);
GST_LOG_OBJECT (this, "Reading %d bytes for caps packet payload", readsize);
ret = read (socket, payload, readsize);
if (ret < 0) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
g_free (header);
g_free (payload);
return NULL;
}
if (gst_dp_header_payload_type (header) != GST_DP_PAYLOAD_CAPS) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
("Header read doesn't describe CAPS payload"));
g_free (header);
g_free (payload);
return NULL;
}
g_assert (ret == readsize);
if (!gst_dp_validate_payload (readsize, header, payload)) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
("GDP caps packet payload does not validate"));
g_free (header);
g_free (payload);
return NULL;
}
caps = gst_dp_caps_from_packet (header_length, header, payload);
string = gst_caps_to_string (caps);
GST_DEBUG_OBJECT (this, "retrieved GDP caps from packet payload: %s", string);
g_free (header);
g_free (payload);
g_free (string);
return caps;
}
/* write a GDP header to the socket. Return false if fails. */
gboolean
gst_tcp_gdp_write_header (GstElement * this, int socket, GstBuffer * buffer,
gboolean fatal, const gchar * host, int port)
{
guint length;
guint8 *header;
size_t wrote;
if (!gst_dp_header_from_buffer (buffer, 0, &length, &header)) {
if (fatal)
GST_ELEMENT_ERROR (this, CORE, TOO_LAZY, (NULL),
("Could not create GDP header from buffer"));
return FALSE;
}
GST_LOG_OBJECT (this, "writing %d bytes for GDP buffer header", length);
wrote = gst_tcp_socket_write (socket, header, length);
if (wrote != length) {
if (fatal)
GST_ELEMENT_ERROR (this, RESOURCE, WRITE,
(_("Error while sending data to \"%s:%d\"."), host, port),
("Only %d of %d bytes written: %s",
wrote, GST_BUFFER_SIZE (buffer), g_strerror (errno)));
return FALSE;
}
return TRUE;
}
/* write GDP header and payload to the given socket for the given caps.
* Return false if fails. */
gboolean
gst_tcp_gdp_write_caps (GstElement * this, int socket, const GstCaps * caps,
gboolean fatal, const char *host, int port)
{
guint length;
guint8 *header;
guint8 *payload;
size_t wrote;
if (!gst_dp_packet_from_caps (caps, 0, &length, &header, &payload)) {
if (fatal)
GST_ELEMENT_ERROR (this, CORE, TOO_LAZY, (NULL),
("Could not create GDP packet from caps"));
return FALSE;
}
GST_LOG_OBJECT (this, "writing %d bytes for GDP caps header", length);
wrote = gst_tcp_socket_write (socket, header, length);
if (wrote != length) {
if (fatal)
GST_ELEMENT_ERROR (this, RESOURCE, WRITE,
(_("Error while sending gdp header data to \"%s:%d\"."), host, port),
("Only %d of %d bytes written: %s",
wrote, length, g_strerror (errno)));
return FALSE;
}
length = gst_dp_header_payload_length (header);
GST_LOG_OBJECT (this, "writing %d bytes for GDP caps payload", length);
wrote = gst_tcp_socket_write (socket, payload, length);
if (wrote != length) {
if (fatal)
GST_ELEMENT_ERROR (this, RESOURCE, WRITE,
(_("Error while sending gdp payload data to \"%s:%d\"."), host, port),
("Only %d of %d bytes written: %s",
wrote, length, g_strerror (errno)));
return FALSE;
}
return TRUE;
}
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
*
* gsttcp.h: helper functions
*
* 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_TCP_HELP_H__
#define __GST_TCP_HELP_H__
#include "gsttcp-enumtypes.h"
#include <gst/gst.h>
#include <gst/dataprotocol/dataprotocol.h>
G_BEGIN_DECLS
typedef enum
{
GST_TCP_PROTOCOL_TYPE_NONE,
GST_TCP_PROTOCOL_TYPE_GDP
} GstTCPProtocolType;
gchar * gst_tcp_host_to_ip (GstElement *element, const gchar *host);
gint gst_tcp_socket_write (int socket, const void *buf, size_t count);
gint gst_tcp_socket_read (int socket, void *buf, size_t count);
GstData * gst_tcp_gdp_read_header (GstElement *this, int socket);
GstCaps * gst_tcp_gdp_read_caps (GstElement *this, int socket);
gboolean gst_tcp_gdp_write_header (GstElement *this, int socket, GstBuffer *buffer, gboolean fatal, const gchar *host, int port);
gboolean gst_tcp_gdp_write_caps (GstElement *this, int socket, const GstCaps *caps, gboolean fatal, const gchar *host, int port);
G_END_DECLS
#endif /* __GST_TCP_HELP_H__ */
This diff is collapsed.
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* 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_TCPCLIENTSINK_H__
#define __GST_TCPCLIENTSINK_H__
#include <gst/gst.h>
#include "gsttcp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include "gsttcp.h"
#define GST_TYPE_TCPCLIENTSINK \
(gst_tcpclientsink_get_type())
#define GST_TCPCLIENTSINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TCPCLIENTSINK,GstTCPClientSink))
#define GST_TCPCLIENTSINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TCPCLIENTSINK,GstTCPClientSink))
#define GST_IS_TCPCLIENTSINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TCPCLIENTSINK))
#define GST_IS_TCPCLIENTSINK_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TCPCLIENTSINK))
typedef struct _GstTCPClientSink GstTCPClientSink;
typedef struct _GstTCPClientSinkClass GstTCPClientSinkClass;
typedef enum {
GST_TCPCLIENTSINK_OPEN = GST_ELEMENT_FLAG_LAST,
GST_TCPCLIENTSINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2,
} GstTCPClientSinkFlags;
struct _GstTCPClientSink {
GstElement element;
/* pad */
GstPad *sinkpad;
/* server information */
int port;
gchar *host;
struct sockaddr_in server_sin;
/* socket */
int sock_fd;
size_t data_written; /* how much bytes have we written ? */
GstTCPProtocolType protocol; /* used with the protocol enum */
gboolean caps_sent; /* whether or not we sent caps already */
guint mtu;
GstClock *clock;
};
struct _GstTCPClientSinkClass {
GstElementClass parent_class;
};
GType gst_tcpclientsink_get_type(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_TCPCLIENTSINK_H__ */
This diff is collapsed.
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
*
* 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_TCPCLIENTSRC_H__
#define __GST_TCPCLIENTSRC_H__
#include <gst/gst.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <netdb.h> /* sockaddr_in */
#include "gsttcp.h"
#define GST_TYPE_TCPCLIENTSRC \
(gst_tcpclientsrc_get_type())
#define GST_TCPCLIENTSRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TCPCLIENTSRC,GstTCPClientSrc))
#define GST_TCPCLIENTSRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TCPCLIENTSRC,GstTCPClientSrc))
#define GST_IS_TCPCLIENTSRC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TCPCLIENTSRC))
#define GST_IS_TCPCLIENTSRC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TCPCLIENTSRC))
typedef struct _GstTCPClientSrc GstTCPClientSrc;
typedef struct _GstTCPClientSrcClass GstTCPClientSrcClass;
typedef enum {
GST_TCPCLIENTSRC_OPEN = GST_ELEMENT_FLAG_LAST,
GST_TCPCLIENTSRC_FLAG_LAST,
} GstTCPClientSrcFlags;
struct _GstTCPClientSrc {
GstElement element;
/* pad */
GstPad *srcpad;
/* server information */
int port;
gchar *host;
struct sockaddr_in server_sin;
/* socket */
int sock_fd;
/* number of bytes we've gotten */
off_t curoffset;
GstTCPProtocolType protocol; /* protocol used for reading data */
gboolean caps_received; /* if we have received caps yet */
GstClock *clock;
gboolean send_discont; /* TRUE when we need to send a discont */
GstBuffer *buffer_after_discont; /* temporary storage for buffer */
};
struct _GstTCPClientSrcClass {
GstElementClass parent_class;
};
GType gst_tcpclientsrc_get_type (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_TCPCLIENTSRC_H__ */
......@@ -23,10 +23,17 @@
#include "gsttcpsrc.h"
#include "gsttcpsink.h"
#include "gsttcpclientsrc.h"
#include "gsttcpclientsink.h"
#include "gsttcpserversrc.h"
#include "gsttcpserversink.h"
static gboolean
plugin_init (GstPlugin * plugin)
{
if (!gst_library_load ("gstdataprotocol"))
return FALSE;
if (!gst_element_register (plugin, "tcpsink", GST_RANK_NONE,
GST_TYPE_TCPSINK))
return FALSE;
......@@ -34,6 +41,19 @@ plugin_init (GstPlugin * plugin)
if (!gst_element_register (plugin, "tcpsrc", GST_RANK_NONE, GST_TYPE_TCPSRC))
return FALSE;
if (!gst_element_register (plugin, "tcpclientsink", GST_RANK_NONE,
GST_TYPE_TCPCLIENTSINK))
return FALSE;
if (!gst_element_register (plugin, "tcpclientsrc", GST_RANK_NONE,
GST_TYPE_TCPCLIENTSRC))
return FALSE;
if (!gst_element_register (plugin, "tcpserversink", GST_RANK_NONE,
GST_TYPE_TCPSERVERSINK))
return FALSE;
if (!gst_element_register (plugin, "tcpserversrc", GST_RANK_NONE,
GST_TYPE_TCPSERVERSRC))
return FALSE;
return TRUE;
}
......
This diff is collapsed.
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
*
* 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.