1 diff -urN gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.c gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.c
2 --- gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.c 1969-12-31 19:00:00.000000000 -0500
3 +++ gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.c 2005-03-02 11:08:24.546323513 -0500
6 + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
7 + * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
9 + * This library is free software; you can redistribute it and/or
10 + * modify it under the terms of the GNU Library General Public
11 + * License as published by the Free Software Foundation; either
12 + * version 2 of the License, or (at your option) any later version.
14 + * This library is distributed in the hope that it will be useful,
15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 + * Library General Public License for more details.
19 + * You should have received a copy of the GNU Library General Public
20 + * License along with this library; if not, write to the
21 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 + * Boston, MA 02111-1307, USA.
30 +#include <gst/gst-i18n-plugin.h>
32 +#include "gsthttpclientsrc.h"
33 +#include <string.h> /* memset */
35 +#include <sys/types.h>
36 +#include <sys/socket.h>
37 +#include <netinet/in.h>
38 +#include <arpa/inet.h>
39 +#include <sys/ioctl.h>
42 +#ifdef HAVE_FIONREAD_IN_SYS_FILIO
43 +#include <sys/filio.h>
46 +GST_DEBUG_CATEGORY (httpclientsrc_debug);
47 +#define GST_CAT_DEFAULT httpclientsrc_debug
49 +#define MAX_READ_SIZE 4 * 1024
51 +/* elementfactory information */
52 +static GstElementDetails gst_httpclientsrc_details =
53 +GST_ELEMENT_DETAILS ("HTTP Client source",
55 + "Receive data as a client over the network via HTTP",
56 + "Jamey Hicks <jamey dot hicks at hp dot com> based on tcpclientsrc by Thomas Vander Stichele <thomas at apestaart dot org>");
58 +/* HttpclientSrc signals and args */
72 +#define HTTP_DEFAULT_METHOD "GET"
74 +static void gst_httpclientsrc_base_init (gpointer g_class);
75 +static void gst_httpclientsrc_class_init (GstHttpclientSrc * klass);
76 +static void gst_httpclientsrc_init (GstHttpclientSrc * httpclientsrc);
78 +static GstCaps *gst_httpclientsrc_getcaps (GstPad * pad);
80 +static GstData *gst_httpclientsrc_get (GstPad * pad);
81 +static GstElementStateReturn gst_httpclientsrc_change_state (GstElement *
84 +static void gst_httpclientsrc_set_property (GObject * object, guint prop_id,
85 + const GValue * value, GParamSpec * pspec);
86 +static void gst_httpclientsrc_get_property (GObject * object, guint prop_id,
87 + GValue * value, GParamSpec * pspec);
88 +static void gst_httpclientsrc_set_clock (GstElement * element, GstClock * clock);
90 +static GstElementClass *parent_class = NULL;
92 +/*static guint gst_httpclientsrc_signals[LAST_SIGNAL] = { 0 }; */
95 +gst_httpclientsrc_get_type (void)
97 + static GType httpclientsrc_type = 0;
100 + if (!httpclientsrc_type) {
101 + static const GTypeInfo httpclientsrc_info = {
102 + sizeof (GstHttpclientSrcClass),
103 + gst_httpclientsrc_base_init,
105 + (GClassInitFunc) gst_httpclientsrc_class_init,
108 + sizeof (GstHttpclientSrc),
110 + (GInstanceInitFunc) gst_httpclientsrc_init,
114 + httpclientsrc_type =
115 + g_type_register_static (GST_TYPE_ELEMENT, "GstHttpclientSrc",
116 + &httpclientsrc_info, 0);
118 + return httpclientsrc_type;
122 +gst_httpclientsrc_base_init (gpointer g_class)
124 + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
126 + gst_element_class_set_details (element_class, &gst_httpclientsrc_details);
130 +gst_httpclientsrc_class_init (GstHttpclientSrc * klass)
132 + GObjectClass *gobject_class;
133 + GstElementClass *gstelement_class;
135 + gobject_class = (GObjectClass *) klass;
136 + gstelement_class = (GstElementClass *) klass;
138 + parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
140 + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
141 + g_param_spec_string ("location", "Source Location (URL)",
142 + "URL of the data to read", NULL, G_PARAM_READWRITE));
143 + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_METHOD,
144 + g_param_spec_string ("method", "HTTP METHOD, defaults to GET",
145 + "Method of the read request", NULL, G_PARAM_READWRITE));
146 + g_object_class_install_property (gobject_class, ARG_PROTOCOL,
147 + g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in",
148 + GST_TYPE_TCP_PROTOCOL_TYPE, GST_TCP_PROTOCOL_TYPE_NONE,
149 + G_PARAM_READWRITE));
151 + gobject_class->set_property = gst_httpclientsrc_set_property;
152 + gobject_class->get_property = gst_httpclientsrc_get_property;
154 + gstelement_class->change_state = gst_httpclientsrc_change_state;
155 + gstelement_class->set_clock = gst_httpclientsrc_set_clock;
157 + GST_DEBUG_CATEGORY_INIT (httpclientsrc_debug, "httpclientsrc", 0,
158 + "HTTP Client Source");
162 +gst_httpclientsrc_set_clock (GstElement * element, GstClock * clock)
164 + GstHttpclientSrc *httpclientsrc;
166 + httpclientsrc = GST_HTTPCLIENTSRC (element);
168 + httpclientsrc->clock = clock;
172 +gst_httpclientsrc_init (GstHttpclientSrc * this)
174 + /* create the src pad */
175 + this->srcpad = gst_pad_new ("src", GST_PAD_SRC);
176 + gst_element_add_pad (GST_ELEMENT (this), this->srcpad);
177 + gst_pad_set_get_function (this->srcpad, gst_httpclientsrc_get);
178 + gst_pad_set_getcaps_function (this->srcpad, gst_httpclientsrc_getcaps);
180 + this->port = TCP_DEFAULT_PORT;
181 + this->method = g_strdup(HTTP_DEFAULT_METHOD);
182 + this->location = NULL;
184 + this->clock = NULL;
185 + this->sock_fd = -1;
186 + this->protocol = GST_TCP_PROTOCOL_TYPE_NONE;
187 + this->curoffset = 0;
190 + GST_FLAG_UNSET (this, GST_HTTPCLIENTSRC_OPEN);
194 +gst_httpclientsrc_getcaps (GstPad * pad)
196 + GstHttpclientSrc *src;
197 + GstCaps *caps = NULL;
199 + src = GST_HTTPCLIENTSRC (GST_OBJECT_PARENT (pad));
201 + if (!GST_FLAG_IS_SET (src, GST_HTTPCLIENTSRC_OPEN))
202 + caps = gst_caps_new_any ();
203 + else if (src->caps)
204 + caps = gst_caps_copy (src->caps);
206 + caps = gst_caps_new_any ();
207 + GST_DEBUG_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
208 + g_assert (GST_IS_CAPS (caps));
213 +gst_httpclientsrc_get (GstPad * pad)
215 + GstHttpclientSrc *src;
219 + GstData *data = NULL;
220 + GstBuffer *buf = NULL;
222 + g_return_val_if_fail (pad != NULL, NULL);
223 + g_return_val_if_fail (GST_IS_PAD (pad), NULL);
224 + src = GST_HTTPCLIENTSRC (GST_OBJECT_PARENT (pad));
225 + g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_HTTPCLIENTSRC_OPEN), NULL);
227 + /* try to negotiate here */
228 + if (!gst_pad_is_negotiated (pad)) {
229 + if (GST_PAD_LINK_FAILED (gst_pad_renegotiate (pad))) {
230 + GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), GST_ERROR_SYSTEM);
231 + gst_buffer_unref (buf);
232 + return GST_DATA (gst_event_new (GST_EVENT_EOS));
236 + /* if we have a left over buffer after a discont, return that */
237 + if (src->buffer_after_discont) {
238 + buf = src->buffer_after_discont;
239 + GST_LOG_OBJECT (src,
240 + "Returning buffer after discont of size %d, ts %"
241 + GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT
242 + ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
243 + GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
244 + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
245 + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));
246 + src->buffer_after_discont = NULL;
247 + return GST_DATA (buf);
250 + /* read the buffer header if we're using a protocol */
251 + switch (src->protocol) {
254 + case GST_TCP_PROTOCOL_TYPE_NONE:
255 + /* do a blocking select on the socket */
256 + FD_ZERO (&testfds);
257 + FD_SET (src->sock_fd, &testfds);
258 + ret = select (src->sock_fd + 1, &testfds, (fd_set *) 0, (fd_set *) 0, 0);
259 + /* no action (0) is an error too in our case */
261 + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
262 + ("select failed: %s", g_strerror (errno)));
263 + return GST_DATA (gst_event_new (GST_EVENT_EOS));
266 + /* ask how much is available for reading on the socket */
267 + ret = ioctl (src->sock_fd, FIONREAD, &readsize);
269 + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
270 + ("ioctl failed: %s", g_strerror (errno)));
271 + return GST_DATA (gst_event_new (GST_EVENT_EOS));
273 + GST_LOG_OBJECT (src, "ioctl says %d bytes available", readsize);
274 + buf = gst_buffer_new_and_alloc (readsize);
276 + case GST_TCP_PROTOCOL_TYPE_GDP:
277 + if (!(data = gst_tcp_gdp_read_header (GST_ELEMENT (src), src->sock_fd))) {
278 + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
279 + ("Could not read data header through GDP"));
280 + return GST_DATA (gst_event_new (GST_EVENT_EOS));
282 + if (GST_IS_EVENT (data))
284 + buf = GST_BUFFER (data);
286 + GST_LOG_OBJECT (src, "Going to read data from socket into buffer %p",
288 + /* use this new buffer to read data into */
289 + readsize = GST_BUFFER_SIZE (buf);
292 + g_warning ("Unhandled protocol type");
296 + GST_LOG_OBJECT (src, "Reading %d bytes", readsize);
297 + ret = gst_tcp_socket_read (src->sock_fd, GST_BUFFER_DATA (buf), readsize);
299 + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
300 + gst_buffer_unref (buf);
301 + return GST_DATA (gst_event_new (GST_EVENT_EOS));
304 + /* if we read 0 bytes, and we're blocking, we hit eos */
306 + GST_DEBUG ("blocking read returns 0, EOS");
307 + gst_buffer_unref (buf);
308 + gst_element_set_eos (GST_ELEMENT (src));
309 + return GST_DATA (gst_event_new (GST_EVENT_EOS));
313 + GST_BUFFER_SIZE (buf) = readsize;
314 + GST_BUFFER_MAXSIZE (buf) = readsize;
316 + /* FIXME: we could decide to set OFFSET and OFFSET_END for non-protocol
317 + * streams to mean the bytes processed */
319 + /* if this is our first buffer, we need to send a discont with the
320 + * given timestamp or the current offset, and store the buffer for
321 + * the next iteration through the get loop */
322 + if (src->send_discont) {
323 + GstClockTime timestamp;
326 + src->send_discont = FALSE;
327 + src->buffer_after_discont = buf;
328 + /* if the timestamp is valid, send a timed discont
329 + * taking into account the incoming buffer's timestamps */
330 + timestamp = GST_BUFFER_TIMESTAMP (buf);
331 + if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
332 + GST_DEBUG_OBJECT (src,
333 + "sending discontinuous with timestamp %" GST_TIME_FORMAT,
334 + GST_TIME_ARGS (timestamp));
336 + gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, timestamp, NULL);
337 + return GST_DATA (event);
339 + /* otherwise, send an offset discont */
340 + GST_DEBUG_OBJECT (src, "sending discontinuous with offset %d",
343 + gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset,
345 + return GST_DATA (event);
348 + src->curoffset += readsize;
349 + GST_LOG_OBJECT (src,
350 + "Returning buffer from _get of size %d, ts %"
351 + GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT
352 + ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
353 + GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
354 + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
355 + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));
356 + return GST_DATA (buf);
360 +gst_httpclientsrc_set_property (GObject * object, guint prop_id,
361 + const GValue * value, GParamSpec * pspec)
363 + GstHttpclientSrc *httpclientsrc;
366 + /* it's not null if we got it, but it might not be ours */
367 + g_return_if_fail (GST_IS_HTTPCLIENTSRC (object));
368 + httpclientsrc = GST_HTTPCLIENTSRC (object);
370 + GST_DEBUG_OBJECT (httpclientsrc, "setting property %d", prop_id);
373 + case ARG_LOCATION: {
374 + gchar *pathstart = NULL;
375 + gchar *location = NULL;
376 + gchar *hostport = NULL;
377 + gchar *portstart = NULL;
379 + g_free (httpclientsrc->location);
380 + g_free (httpclientsrc->host);
381 + g_free (httpclientsrc->path);
382 + httpclientsrc->location = location = g_strdup (g_value_get_string (value));
383 + GST_DEBUG_OBJECT (httpclientsrc, "setting location=%s", location);
385 + if (strncmp(location, "http://", 7) != 0)
387 + locationlen = strlen(location);
388 + hostport = location + 7;
389 + GST_DEBUG_OBJECT (httpclientsrc, " hostport=%s", hostport);
391 + pathstart = strchr(hostport, '/');
392 + GST_DEBUG_OBJECT (httpclientsrc, " pathstart=%s", pathstart);
395 + httpclientsrc->path = g_strdup(pathstart);
397 + httpclientsrc->path = g_strdup("/");
398 + pathstart = location+locationlen;
400 + hostport = g_strndup(hostport, pathstart - hostport);
401 + portstart = strrchr(hostport, ':');
402 + GST_DEBUG_OBJECT (httpclientsrc, " hostport=%s portstart=%s", hostport, portstart);
403 + if (portstart != NULL) {
404 + httpclientsrc->host = g_strndup(hostport, portstart - hostport);
405 + httpclientsrc->port = strtoul(portstart+1, NULL, 0);
408 + httpclientsrc->host = hostport;
409 + httpclientsrc->port = 80;
411 + GST_DEBUG_OBJECT (httpclientsrc, " host=%s port=%d path=%s", httpclientsrc->host, httpclientsrc->port, httpclientsrc->path);
414 + g_free (httpclientsrc->method);
415 + httpclientsrc->method = g_strdup (g_value_get_string (value));
418 + httpclientsrc->protocol = g_value_get_enum (value);
422 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
428 +gst_httpclientsrc_get_property (GObject * object, guint prop_id, GValue * value,
429 + GParamSpec * pspec)
431 + GstHttpclientSrc *httpclientsrc;
433 + g_return_if_fail (GST_IS_HTTPCLIENTSRC (object));
434 + httpclientsrc = GST_HTTPCLIENTSRC (object);
438 + g_value_set_string (value, httpclientsrc->location);
441 + g_value_set_string (value, httpclientsrc->method);
444 + g_value_set_enum (value, httpclientsrc->protocol);
448 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
453 +/* create a socket for connecting to remote server */
455 +gst_httpclientsrc_init_receive (GstHttpclientSrc * this)
459 + struct addrinfo *addrinfo, *top_addrinfo;
461 + gchar *request = NULL;
463 + GST_DEBUG_OBJECT (this, "getaddrinfo %s", this->host);
464 + ret = getaddrinfo(this->host, "http", NULL, &addrinfo);
465 + top_addrinfo = addrinfo;
468 + this->addr_family = addr_family = addrinfo->ai_family;
469 + this->server_addrlen = addrinfo->ai_addrlen;
470 + memset(&this->server_sockaddr, 0, sizeof(this->server_sockaddr));
471 + memcpy(&this->server_sockaddr, addrinfo->ai_addr, addrinfo->ai_addrlen);
473 + /* create receiving client socket */
474 + GST_DEBUG_OBJECT (this, "opening receiving client socket to %s:%d\n",
475 + this->host, this->port);
476 + if ((this->sock_fd = socket (this->addr_family, SOCK_STREAM, 0)) == -1) {
477 + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM);
480 + GST_DEBUG_OBJECT (this, "opened receiving client socket with fd %d",
483 + /* look up name if we need to */
484 + GST_DEBUG_OBJECT (this, "IP address for host %s is %s", this->host, ip);
487 + switch (this->addr_family) {
489 + ((struct sockaddr_in *)&this->server_sockaddr)->sin_port = htons(this->port);
490 + inet_ntop(this->addr_family, &(((struct sockaddr_in *)&this->server_sockaddr)->sin_addr), ip, sizeof(ip));
493 + ((struct sockaddr_in6 *)&this->server_sockaddr)->sin6_port = htons(this->port);
494 + inet_ntop(this->addr_family, &(((struct sockaddr_in6 *)&this->server_sockaddr)->sin6_addr), ip, sizeof(ip));
497 + if (this->addr_family == AF_INET6) {
500 + struct in6_addr *in6_addr = &(((struct sockaddr_in6 *)&this->server_sockaddr)->sin6_addr);
501 + for (i = 0; i < sizeof(struct in6_addr); i++) {
502 + int b = in6_addr->s6_addr[i];
503 + offset += sprintf(ip+offset, ":%02x", b);
507 + /* connect to server */
508 + GST_DEBUG_OBJECT (this, "connecting to server family=%d ip=%s port=%d sockaddrlen=%d",
509 + this->addr_family, ip, this->port, this->server_addrlen);
510 + ret = connect (this->sock_fd, (struct sockaddr *) &this->server_sockaddr, this->server_addrlen);
515 + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ,
516 + (_("Connection to %s:%d refused."), this->host, this->port),
518 + if (addrinfo->ai_next == NULL)
522 + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
523 + ("connect to %s:%d failed: %s", this->host, this->port,
524 + g_strerror (errno)));
525 + if (addrinfo->ai_next == NULL)
529 + addrinfo = addrinfo->ai_next;
531 + GST_DEBUG_OBJECT(this, "retrying with addrinfo %p", addrinfo);
536 + /* send request and headers */
537 + request = g_strdup_printf("%s %s HTTP/1.0\r\nHost: %s\r\n\r\n",
538 + this->method, this->path, this->host);
539 + GST_DEBUG_OBJECT(this, "sending request %s", request);
540 + if (gst_tcp_socket_write(this->sock_fd, request, strlen(request)) < 0) {
541 + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
542 + ("sending HTTP request to %s failed: %s", this->location,
543 + g_strerror (errno)));
549 + /* receive and discard headers */
551 + char responseline[12];
553 + /* receive response line (HTTP/1.x NNN) */
554 + if ((rc = gst_tcp_socket_read(this->sock_fd, responseline, sizeof(responseline))) < 0) {
555 + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
556 + ("reading HTTP response from %s failed: %s", this->location,
557 + g_strerror (errno)));
560 + GST_DEBUG_OBJECT(this, "got %d byte response %s", rc, responseline);
562 + enum response_state {
567 + RESPONSE_END_OF_HEADERS /* saw crlfcrlf */
568 + } response_state = RESPONSE_CHAR;
569 + while (response_state != RESPONSE_END_OF_HEADERS) {
571 + if (gst_tcp_socket_read(this->sock_fd, &ch, sizeof(ch)) < 0) {
572 + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
573 + ("reading HTTP response from %s failed: %s", this->location,
574 + g_strerror (errno)));
579 + switch (response_state) {
580 + case RESPONSE_CR: response_state = RESPONSE_CRLF; break;
581 + case RESPONSE_CRLFCR: response_state = RESPONSE_END_OF_HEADERS; break;
582 + default: response_state = RESPONSE_CHAR;
585 + switch (response_state) {
586 + case RESPONSE_CRLF: response_state = RESPONSE_CRLFCR; break;
587 + default: response_state = RESPONSE_CR;
590 + response_state = RESPONSE_CHAR;
595 + this->send_discont = TRUE;
596 + this->buffer_after_discont = NULL;
597 + GST_FLAG_SET (this, GST_HTTPCLIENTSRC_OPEN);
599 + /* get the caps if we're using GDP */
600 + if (this->protocol == GST_TCP_PROTOCOL_TYPE_GDP) {
601 + /* if we haven't received caps yet, we should get them first */
602 + if (!this->caps_received) {
605 + GST_DEBUG_OBJECT (this, "getting caps through GDP");
606 + if (!(caps = gst_tcp_gdp_read_caps (GST_ELEMENT (this), this->sock_fd))) {
607 + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
608 + ("Could not read caps through GDP"));
611 + if (!GST_IS_CAPS (caps)) {
612 + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
613 + ("Could not read caps through GDP"));
616 + GST_DEBUG_OBJECT (this, "Received caps through GDP: %" GST_PTR_FORMAT,
618 + this->caps_received = TRUE;
626 +gst_httpclientsrc_close (GstHttpclientSrc * this)
628 + if (this->sock_fd != -1) {
629 + close (this->sock_fd);
630 + this->sock_fd = -1;
632 + this->caps_received = FALSE;
634 + gst_caps_free (this->caps);
637 + GST_FLAG_UNSET (this, GST_HTTPCLIENTSRC_OPEN);
640 +static GstElementStateReturn
641 +gst_httpclientsrc_change_state (GstElement * element)
643 + g_return_val_if_fail (GST_IS_HTTPCLIENTSRC (element), GST_STATE_FAILURE);
645 + if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
646 + if (GST_FLAG_IS_SET (element, GST_HTTPCLIENTSRC_OPEN))
647 + gst_httpclientsrc_close (GST_HTTPCLIENTSRC (element));
649 + if (!GST_FLAG_IS_SET (element, GST_HTTPCLIENTSRC_OPEN)) {
650 + if (!gst_httpclientsrc_init_receive (GST_HTTPCLIENTSRC (element)))
651 + return GST_STATE_FAILURE;
655 + if (GST_ELEMENT_CLASS (parent_class)->change_state)
656 + return GST_ELEMENT_CLASS (parent_class)->change_state (element);
658 + return GST_STATE_SUCCESS;
660 diff -urN gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.h gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.h
661 --- gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.h 1969-12-31 19:00:00.000000000 -0500
662 +++ gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.h 2005-03-02 09:47:01.640623151 -0500
665 + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
666 + * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
668 + * This library is free software; you can redistribute it and/or
669 + * modify it under the terms of the GNU Library General Public
670 + * License as published by the Free Software Foundation; either
671 + * version 2 of the License, or (at your option) any later version.
673 + * This library is distributed in the hope that it will be useful,
674 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
675 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
676 + * Library General Public License for more details.
678 + * You should have received a copy of the GNU Library General Public
679 + * License along with this library; if not, write to the
680 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
681 + * Boston, MA 02111-1307, USA.
685 +#ifndef __GST_HTTPCLIENTSRC_H__
686 +#define __GST_HTTPCLIENTSRC_H__
688 +#include <gst/gst.h>
692 +#endif /* __cplusplus */
694 +#include <netdb.h> /* sockaddr_in */
695 +#include <netinet/in.h> /* sockaddr_in */
699 +#define GST_TYPE_HTTPCLIENTSRC \
700 + (gst_httpclientsrc_get_type())
701 +#define GST_HTTPCLIENTSRC(obj) \
702 + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_HTTPCLIENTSRC,GstHttpclientSrc))
703 +#define GST_HTTPCLIENTSRC_CLASS(klass) \
704 + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_HTTPCLIENTSRC,GstHttpclientSrc))
705 +#define GST_IS_HTTPCLIENTSRC(obj) \
706 + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_HTTPCLIENTSRC))
707 +#define GST_IS_HTTPCLIENTSRC_CLASS(obj) \
708 + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_HTTPCLIENTSRC))
710 +typedef struct _GstHttpclientSrc GstHttpclientSrc;
711 +typedef struct _GstHttpclientSrcClass GstHttpclientSrcClass;
713 +typedef enum GstHttpclientSrcFlags {
714 + GST_HTTPCLIENTSRC_OPEN = GST_ELEMENT_FLAG_LAST,
716 + GST_HTTPCLIENTSRC_FLAG_LAST,
717 +} GstHttpclientSrcFlags;
719 +struct _GstHttpclientSrc {
720 + GstElement element;
725 + /* server information */
731 + gchar *location; /* url */
732 + struct sockaddr_storage server_sockaddr;
733 + int server_addrlen;
738 + /* number of bytes we've gotten */
741 + GstTCPProtocolType protocol; /* protocol used for reading data */
742 + gboolean caps_received; /* if we have received caps yet */
746 + gboolean send_discont; /* TRUE when we need to send a discont */
747 + GstBuffer *buffer_after_discont; /* temporary storage for buffer */
750 +struct _GstHttpclientSrcClass {
751 + GstElementClass parent_class;
754 +GType gst_httpclientsrc_get_type (void);
759 +#endif /* __cplusplus */
761 +#endif /* __GST_HTTPCLIENTSRC_H__ */
762 diff -urN gst-plugins-0.8.7/gst/tcp/gsttcpplugin.c gst-plugins-0.8.7-httpsrc1/gst/tcp/gsttcpplugin.c
763 --- gst-plugins-0.8.7/gst/tcp/gsttcpplugin.c 2004-11-05 12:15:10.000000000 -0500
764 +++ gst-plugins-0.8.7-httpsrc1/gst/tcp/gsttcpplugin.c 2005-03-02 09:59:33.003801791 -0500
767 #include "gsttcpsrc.h"
768 #include "gsttcpsink.h"
769 +#include "gsthttpclientsrc.h"
770 #include "gsttcpclientsrc.h"
771 #include "gsttcpclientsink.h"
772 #include "gsttcpserversrc.h"
774 if (!gst_element_register (plugin, "multifdsink", GST_RANK_NONE,
775 GST_TYPE_MULTIFDSINK))
777 + if (!gst_element_register (plugin, "httpclientsrc", GST_RANK_NONE,
778 + GST_TYPE_HTTPCLIENTSRC))
781 GST_DEBUG_CATEGORY_INIT (tcp_debug, "tcp", 0, "TCP calls");
783 diff -urN gst-plugins-0.8.7/gst/tcp/Makefile.am gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.am
784 --- gst-plugins-0.8.7/gst/tcp/Makefile.am 2004-11-02 02:41:44.000000000 -0500
785 +++ gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.am 2005-03-02 09:29:30.125528594 -0500
790 + gsthttpclientsrc.c \
791 gsttcpclientsrc.c gsttcpclientsink.c \
792 gsttcpserversrc.c gsttcpserversink.c
798 + gsthttpclientsrc.h \
799 gsttcpclientsrc.h gsttcpclientsink.h \
800 gsttcpserversrc.h gsttcpserversink.h
802 diff -urN gst-plugins-0.8.7/gst/tcp/Makefile.in gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.in
803 --- gst-plugins-0.8.7/gst/tcp/Makefile.in 2005-01-05 05:47:55.000000000 -0500
804 +++ gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.in 2005-03-02 09:33:30.515512648 -0500
806 am_libgsttcp_la_OBJECTS = libgsttcp_la-gsttcpplugin.lo \
807 libgsttcp_la-gsttcpsrc.lo libgsttcp_la-gsttcpsink.lo \
808 libgsttcp_la-gsttcp.lo libgsttcp_la-gstfdset.lo \
809 - libgsttcp_la-gstmultifdsink.lo libgsttcp_la-gsttcpclientsrc.lo \
810 + libgsttcp_la-gstmultifdsink.lo libgsttcp_la-gsthttpclientsrc.lo \
811 + libgsttcp_la-gsttcpclientsrc.lo \
812 libgsttcp_la-gsttcpclientsink.lo \
813 libgsttcp_la-gsttcpserversrc.lo \
814 libgsttcp_la-gsttcpserversink.lo
819 + gsthttpclientsrc.c \
820 gsttcpclientsrc.c gsttcpclientsink.c \
821 gsttcpserversrc.c gsttcpserversink.c
827 - gsttcpclientsrc.h gsttcpclientsink.h \
828 + gsthttpclientsrc.h gsttcpclientsrc.h gsttcpclientsink.h \
829 gsttcpserversrc.h gsttcpserversink.h
831 CLEANFILES = $(BUILT_SOURCES)
833 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcp.Plo@am__quote@
834 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpclientsink.Plo@am__quote@
835 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Plo@am__quote@
836 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Plo@am__quote@
837 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpplugin.Plo@am__quote@
838 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpserversink.Plo@am__quote@
839 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpserversrc.Plo@am__quote@
841 @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
842 @am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -c -o libgsttcp_la-gstmultifdsink.lo `test -f 'gstmultifdsink.c' || echo '$(srcdir)/'`gstmultifdsink.c
844 +libgsttcp_la-gsthttpclientsrc.lo: gsthttpclientsrc.c
845 +@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -MT libgsttcp_la-gsthttpclientsrc.lo -MD -MP -MF "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Tpo" -c -o libgsttcp_la-gsthttpclientsrc.lo `test -f 'gsthttpclientsrc.c' || echo '$(srcdir)/'`gsthttpclientsrc.c; \
846 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Tpo" "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Plo"; else rm -f "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Tpo"; exit 1; fi
847 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsthttpclientsrc.c' object='libgsttcp_la-gsthttpclientsrc.lo' libtool=yes @AMDEPBACKSLASH@
848 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
849 +@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -c -o libgsttcp_la-gsthttpclientsrc.lo `test -f 'gsthttpclientsrc.c' || echo '$(srcdir)/'`gsthttpclientsrc.c
851 libgsttcp_la-gsttcpclientsrc.lo: gsttcpclientsrc.c
852 @am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -MT libgsttcp_la-gsttcpclientsrc.lo -MD -MP -MF "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Tpo" -c -o libgsttcp_la-gsttcpclientsrc.lo `test -f 'gsttcpclientsrc.c' || echo '$(srcdir)/'`gsttcpclientsrc.c; \
853 @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Tpo" "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Plo"; else rm -f "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Tpo"; exit 1; fi