LCOV - code coverage report
Current view: top level - gst-plugins-bad/ext/neon - gstneonhttpsrc.c (source / functions) Hit Total Coverage
Test: GStreamer Lines: 143 495 28.9 %
Date: 2011-03-25 Functions: 13 30 43.3 %
Branches: 34 389 8.7 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  * Copyright (C) <2005> Edgard Lima <edgard.lima@indt.org.br>
       3                 :            :  * Copyright (C) <2006> Rosfran Borges <rosfran.borges@indt.org.br>
       4                 :            :  * Copyright (C) <2006> Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
       5                 :            :  *
       6                 :            :  * This library is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU Library General Public
       8                 :            :  * License as published by the Free Software Foundation; either
       9                 :            :  * version 2 of the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This library is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Library General Public License for more 
      15                 :            :  */
      16                 :            : 
      17                 :            : #ifdef HAVE_CONFIG_H
      18                 :            : #include "config.h"
      19                 :            : #endif
      20                 :            : 
      21                 :            : #include "gstneonhttpsrc.h"
      22                 :            : #include <stdlib.h>
      23                 :            : #include <string.h>
      24                 :            : #ifdef _HAVE_UNISTD_H
      25                 :            : #include <unistd.h>
      26                 :            : #endif /* _HAVE_UNISTD_H */
      27                 :            : 
      28                 :            : #include <ne_redirect.h>
      29                 :            : 
      30                 :            : #define STATUS_IS_REDIRECTION(status)     ((status) >= 300 && (status) < 400)
      31                 :            : 
      32                 :            : GST_DEBUG_CATEGORY_STATIC (neonhttpsrc_debug);
      33                 :            : #define GST_CAT_DEFAULT neonhttpsrc_debug
      34                 :            : 
      35                 :            : #define MAX_READ_SIZE (4 * 1024)
      36                 :            : 
      37                 :            : /* max number of HTTP redirects, when iterating over a sequence of HTTP 3xx status code */
      38                 :            : #define MAX_HTTP_REDIRECTS_NUMBER 5
      39                 :            : 
      40                 :            : static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
      41                 :            :     GST_PAD_SRC,
      42                 :            :     GST_PAD_ALWAYS,
      43                 :            :     GST_STATIC_CAPS_ANY);
      44                 :            : 
      45                 :            : #define HTTP_SOCKET_ERROR        -2
      46                 :            : #define HTTP_REQUEST_WRONG_PROXY -1
      47                 :            : #define HTTP_DEFAULT_PORT        80
      48                 :            : #define HTTPS_DEFAULT_PORT       443
      49                 :            : #define HTTP_DEFAULT_HOST        "localhost"
      50                 :            : 
      51                 :            : /* default properties */
      52                 :            : #define DEFAULT_LOCATION             "http://"HTTP_DEFAULT_HOST":"G_STRINGIFY(HTTP_DEFAULT_PORT)
      53                 :            : #define DEFAULT_PROXY                ""
      54                 :            : #define DEFAULT_USER_AGENT           "GStreamer neonhttpsrc"
      55                 :            : #define DEFAULT_IRADIO_MODE          FALSE
      56                 :            : #define DEFAULT_IRADIO_NAME          NULL
      57                 :            : #define DEFAULT_IRADIO_GENRE         NULL
      58                 :            : #define DEFAULT_IRADIO_URL           NULL
      59                 :            : #define DEFAULT_AUTOMATIC_REDIRECT   TRUE
      60                 :            : #define DEFAULT_ACCEPT_SELF_SIGNED   FALSE
      61                 :            : #define DEFAULT_NEON_HTTP_DEBUG      FALSE
      62                 :            : #define DEFAULT_CONNECT_TIMEOUT      0
      63                 :            : #define DEFAULT_READ_TIMEOUT         0
      64                 :            : 
      65                 :            : enum
      66                 :            : {
      67                 :            :   PROP_0,
      68                 :            :   PROP_LOCATION,
      69                 :            :   PROP_PROXY,
      70                 :            :   PROP_USER_AGENT,
      71                 :            :   PROP_COOKIES,
      72                 :            :   PROP_IRADIO_MODE,
      73                 :            :   PROP_IRADIO_NAME,
      74                 :            :   PROP_IRADIO_GENRE,
      75                 :            :   PROP_IRADIO_URL,
      76                 :            :   PROP_AUTOMATIC_REDIRECT,
      77                 :            :   PROP_ACCEPT_SELF_SIGNED,
      78                 :            :   PROP_CONNECT_TIMEOUT,
      79                 :            :   PROP_READ_TIMEOUT,
      80                 :            : #ifndef GST_DISABLE_GST_DEBUG
      81                 :            :   PROP_NEON_HTTP_DEBUG
      82                 :            : #endif
      83                 :            : };
      84                 :            : 
      85                 :            : static void gst_neonhttp_src_uri_handler_init (gpointer g_iface,
      86                 :            :     gpointer iface_data);
      87                 :            : static void gst_neonhttp_src_dispose (GObject * gobject);
      88                 :            : static void gst_neonhttp_src_set_property (GObject * object, guint prop_id,
      89                 :            :     const GValue * value, GParamSpec * pspec);
      90                 :            : static void gst_neonhttp_src_get_property (GObject * object, guint prop_id,
      91                 :            :     GValue * value, GParamSpec * pspec);
      92                 :            : 
      93                 :            : static GstFlowReturn gst_neonhttp_src_create (GstPushSrc * psrc,
      94                 :            :     GstBuffer ** outbuf);
      95                 :            : static gboolean gst_neonhttp_src_start (GstBaseSrc * bsrc);
      96                 :            : static gboolean gst_neonhttp_src_stop (GstBaseSrc * bsrc);
      97                 :            : static gboolean gst_neonhttp_src_get_size (GstBaseSrc * bsrc, guint64 * size);
      98                 :            : static gboolean gst_neonhttp_src_is_seekable (GstBaseSrc * bsrc);
      99                 :            : static gboolean gst_neonhttp_src_do_seek (GstBaseSrc * bsrc,
     100                 :            :     GstSegment * segment);
     101                 :            : 
     102                 :            : static gboolean gst_neonhttp_src_set_proxy (GstNeonhttpSrc * src,
     103                 :            :     const gchar * uri);
     104                 :            : static gboolean gst_neonhttp_src_set_location (GstNeonhttpSrc * src,
     105                 :            :     const gchar * uri);
     106                 :            : static gint gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
     107                 :            :     ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir);
     108                 :            : static gint gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src,
     109                 :            :     GstBuffer * outbuf);
     110                 :            : static void gst_neonhttp_src_close_session (GstNeonhttpSrc * src);
     111                 :            : static gchar *gst_neonhttp_src_unicodify (const gchar * str);
     112                 :            : static void oom_callback (void);
     113                 :            : 
     114                 :            : static void
     115                 :          3 : _urihandler_init (GType type)
     116                 :            : {
     117                 :            :   static const GInterfaceInfo urihandler_info = {
     118                 :            :     gst_neonhttp_src_uri_handler_init,
     119                 :            :     NULL,
     120                 :            :     NULL
     121                 :            :   };
     122                 :            : 
     123                 :          3 :   g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
     124                 :            : 
     125         [ +  - ]:          3 :   GST_DEBUG_CATEGORY_INIT (neonhttpsrc_debug, "neonhttpsrc", 0,
     126                 :            :       "NEON HTTP src");
     127                 :          3 : }
     128                 :            : 
     129         [ +  + ]:         20 : GST_BOILERPLATE_FULL (GstNeonhttpSrc, gst_neonhttp_src, GstPushSrc,
     130                 :         20 :     GST_TYPE_PUSH_SRC, _urihandler_init);
     131                 :            : 
     132                 :            : static void
     133                 :          3 : gst_neonhttp_src_base_init (gpointer g_class)
     134                 :            : {
     135                 :          3 :   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
     136                 :            : 
     137                 :          3 :   gst_element_class_add_pad_template (element_class,
     138                 :            :       gst_static_pad_template_get (&srctemplate));
     139                 :            : 
     140                 :          3 :   gst_element_class_set_details_simple (element_class, "HTTP client source",
     141                 :            :       "Source/Network",
     142                 :            :       "Receive data as a client over the network via HTTP using NEON",
     143                 :            :       "Edgard Lima <edgard.lima@indt.org.br>, "
     144                 :            :       "Rosfran Borges <rosfran.borges@indt.org.br>, "
     145                 :            :       "Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>");
     146                 :          3 : }
     147                 :            : 
     148                 :            : static void
     149                 :          3 : gst_neonhttp_src_class_init (GstNeonhttpSrcClass * klass)
     150                 :            : {
     151                 :            :   GObjectClass *gobject_class;
     152                 :            :   GstBaseSrcClass *gstbasesrc_class;
     153                 :            :   GstPushSrcClass *gstpushsrc_class;
     154                 :            : 
     155                 :          3 :   gobject_class = (GObjectClass *) klass;
     156                 :          3 :   gstbasesrc_class = (GstBaseSrcClass *) klass;
     157                 :          3 :   gstpushsrc_class = (GstPushSrcClass *) klass;
     158                 :            : 
     159                 :          3 :   gobject_class->set_property = gst_neonhttp_src_set_property;
     160                 :          3 :   gobject_class->get_property = gst_neonhttp_src_get_property;
     161                 :          3 :   gobject_class->dispose = gst_neonhttp_src_dispose;
     162                 :            : 
     163                 :            :   g_object_class_install_property
     164                 :          3 :       (gobject_class, PROP_LOCATION,
     165                 :            :       g_param_spec_string ("location", "Location",
     166                 :            :           "Location to read from", "",
     167                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     168                 :            : 
     169                 :            :   g_object_class_install_property
     170                 :          3 :       (gobject_class, PROP_PROXY,
     171                 :            :       g_param_spec_string ("proxy", "Proxy",
     172                 :            :           "Proxy server to use, in the form HOSTNAME:PORT. "
     173                 :            :           "Defaults to the http_proxy environment variable",
     174                 :            :           "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     175                 :            : 
     176                 :            :   g_object_class_install_property
     177                 :          3 :       (gobject_class, PROP_USER_AGENT,
     178                 :            :       g_param_spec_string ("user-agent", "User-Agent",
     179                 :            :           "Value of the User-Agent HTTP request header field",
     180                 :            :           "GStreamer neonhttpsrc", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     181                 :            : 
     182                 :            :   /**
     183                 :            :    * GstNeonhttpSrc:cookies
     184                 :            :    *
     185                 :            :    * HTTP request cookies
     186                 :            :    *
     187                 :            :    * Since: 0.10.20
     188                 :            :    */
     189                 :          3 :   g_object_class_install_property (gobject_class, PROP_COOKIES,
     190                 :            :       g_param_spec_boxed ("cookies", "Cookies", "HTTP request cookies",
     191                 :            :           G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     192                 :            : 
     193                 :            :   g_object_class_install_property
     194                 :          3 :       (gobject_class, PROP_IRADIO_MODE,
     195                 :            :       g_param_spec_boolean ("iradio-mode", "iradio-mode",
     196                 :            :           "Enable internet radio mode (extraction of shoutcast/icecast metadata)",
     197                 :            :           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     198                 :            : 
     199                 :          3 :   g_object_class_install_property (gobject_class,
     200                 :            :       PROP_IRADIO_NAME,
     201                 :            :       g_param_spec_string ("iradio-name",
     202                 :            :           "iradio-name", "Name of the stream", NULL,
     203                 :            :           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
     204                 :            : 
     205                 :          3 :   g_object_class_install_property (gobject_class,
     206                 :            :       PROP_IRADIO_GENRE,
     207                 :            :       g_param_spec_string ("iradio-genre",
     208                 :            :           "iradio-genre", "Genre of the stream", NULL,
     209                 :            :           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
     210                 :            : 
     211                 :          3 :   g_object_class_install_property (gobject_class,
     212                 :            :       PROP_IRADIO_URL,
     213                 :            :       g_param_spec_string ("iradio-url",
     214                 :            :           "iradio-url",
     215                 :            :           "Homepage URL for radio stream", NULL,
     216                 :            :           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
     217                 :            : 
     218                 :            :   g_object_class_install_property
     219                 :          3 :       (gobject_class, PROP_AUTOMATIC_REDIRECT,
     220                 :            :       g_param_spec_boolean ("automatic-redirect", "automatic-redirect",
     221                 :            :           "Automatically follow HTTP redirects (HTTP Status Code 3xx)",
     222                 :            :           TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     223                 :            : 
     224                 :            :   g_object_class_install_property
     225                 :          3 :       (gobject_class, PROP_ACCEPT_SELF_SIGNED,
     226                 :            :       g_param_spec_boolean ("accept-self-signed", "accept-self-signed",
     227                 :            :           "Accept self-signed SSL/TLS certificates",
     228                 :            :           DEFAULT_ACCEPT_SELF_SIGNED,
     229                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     230                 :            : 
     231                 :            :   /**
     232                 :            :    * GstNeonhttpSrc:connect-timeout
     233                 :            :    *
     234                 :            :    * After how many seconds to timeout a connect attempt (0 = default)
     235                 :            :    *
     236                 :            :    * Since: 0.10.20
     237                 :            :    */
     238                 :          3 :   g_object_class_install_property (gobject_class, PROP_CONNECT_TIMEOUT,
     239                 :            :       g_param_spec_uint ("connect-timeout", "connect-timeout",
     240                 :            :           "Value in seconds to timeout a blocking connection (0 = default).", 0,
     241                 :            :           3600, DEFAULT_CONNECT_TIMEOUT,
     242                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     243                 :            : 
     244                 :            :   /**
     245                 :            :    * GstNeonhttpSrc:read-timeout
     246                 :            :    *
     247                 :            :    * After how many seconds to timeout a blocking read (0 = default)
     248                 :            :    *
     249                 :            :    * Since: 0.10.20
     250                 :            :    */
     251                 :          3 :   g_object_class_install_property (gobject_class, PROP_READ_TIMEOUT,
     252                 :            :       g_param_spec_uint ("read-timeout", "read-timeout",
     253                 :            :           "Value in seconds to timeout a blocking read (0 = default).", 0,
     254                 :            :           3600, DEFAULT_READ_TIMEOUT,
     255                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     256                 :            : 
     257                 :            : #ifndef GST_DISABLE_GST_DEBUG
     258                 :            :   g_object_class_install_property
     259                 :          3 :       (gobject_class, PROP_NEON_HTTP_DEBUG,
     260                 :            :       g_param_spec_boolean ("neon-http-debug", "neon-http-debug",
     261                 :            :           "Enable Neon HTTP debug messages",
     262                 :            :           DEFAULT_NEON_HTTP_DEBUG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     263                 :            : #endif
     264                 :            : 
     265                 :          3 :   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_neonhttp_src_start);
     266                 :          3 :   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_neonhttp_src_stop);
     267                 :          3 :   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_neonhttp_src_get_size);
     268                 :          3 :   gstbasesrc_class->is_seekable =
     269                 :          3 :       GST_DEBUG_FUNCPTR (gst_neonhttp_src_is_seekable);
     270                 :          3 :   gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_neonhttp_src_do_seek);
     271                 :            : 
     272                 :          3 :   gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_neonhttp_src_create);
     273                 :            : 
     274         [ -  + ]:          3 :   GST_DEBUG_CATEGORY_INIT (neonhttpsrc_debug, "neonhttpsrc", 0,
     275                 :            :       "NEON HTTP Client Source");
     276                 :          3 : }
     277                 :            : 
     278                 :            : static void
     279                 :          1 : gst_neonhttp_src_init (GstNeonhttpSrc * src, GstNeonhttpSrcClass * g_class)
     280                 :            : {
     281                 :            :   const gchar *str;
     282                 :            : 
     283                 :          1 :   src->neon_http_debug = DEFAULT_NEON_HTTP_DEBUG;
     284                 :          1 :   src->iradio_mode = DEFAULT_IRADIO_MODE;
     285                 :          1 :   src->iradio_name = DEFAULT_IRADIO_NAME;
     286                 :          1 :   src->iradio_genre = DEFAULT_IRADIO_GENRE;
     287                 :          1 :   src->iradio_url = DEFAULT_IRADIO_URL;
     288                 :          1 :   src->user_agent = g_strdup (DEFAULT_USER_AGENT);
     289                 :          1 :   src->automatic_redirect = DEFAULT_AUTOMATIC_REDIRECT;
     290                 :          1 :   src->accept_self_signed = DEFAULT_ACCEPT_SELF_SIGNED;
     291                 :          1 :   src->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
     292                 :          1 :   src->read_timeout = DEFAULT_READ_TIMEOUT;
     293                 :            : 
     294                 :          1 :   src->cookies = NULL;
     295                 :          1 :   src->session = NULL;
     296                 :          1 :   src->request = NULL;
     297                 :          1 :   memset (&src->uri, 0, sizeof (src->uri));
     298                 :          1 :   memset (&src->proxy, 0, sizeof (src->proxy));
     299                 :          1 :   src->content_size = -1;
     300                 :          1 :   src->icy_caps = NULL;
     301                 :          1 :   src->icy_metaint = 0;
     302                 :          1 :   src->seekable = TRUE;
     303                 :            : 
     304                 :          1 :   gst_neonhttp_src_set_location (src, DEFAULT_LOCATION);
     305                 :            : 
     306                 :            :   /* configure proxy */
     307                 :          1 :   str = g_getenv ("http_proxy");
     308 [ -  + ][ #  # ]:          1 :   if (str && !gst_neonhttp_src_set_proxy (src, str)) {
     309         [ #  # ]:          0 :     GST_WARNING_OBJECT (src,
     310                 :            :         "The proxy set on http_proxy env var ('%s') cannot be parsed.", str);
     311                 :            :   }
     312                 :          1 : }
     313                 :            : 
     314                 :            : static void
     315                 :          1 : gst_neonhttp_src_dispose (GObject * gobject)
     316                 :            : {
     317                 :          1 :   GstNeonhttpSrc *src = GST_NEONHTTP_SRC (gobject);
     318                 :            : 
     319                 :          1 :   ne_uri_free (&src->uri);
     320                 :          1 :   ne_uri_free (&src->proxy);
     321                 :            : 
     322                 :          1 :   g_free (src->user_agent);
     323                 :          1 :   g_free (src->iradio_name);
     324                 :          1 :   g_free (src->iradio_genre);
     325                 :          1 :   g_free (src->iradio_url);
     326                 :            : 
     327         [ -  + ]:          1 :   if (src->cookies) {
     328                 :          0 :     g_strfreev (src->cookies);
     329                 :          0 :     src->cookies = NULL;
     330                 :            :   }
     331                 :            : 
     332         [ -  + ]:          1 :   if (src->icy_caps) {
     333                 :          0 :     gst_caps_unref (src->icy_caps);
     334                 :          0 :     src->icy_caps = NULL;
     335                 :            :   }
     336                 :            : 
     337         [ -  + ]:          1 :   if (src->request) {
     338                 :          0 :     ne_request_destroy (src->request);
     339                 :          0 :     src->request = NULL;
     340                 :            :   }
     341                 :            : 
     342         [ -  + ]:          1 :   if (src->session) {
     343                 :          0 :     ne_close_connection (src->session);
     344                 :          0 :     ne_session_destroy (src->session);
     345                 :          0 :     src->session = NULL;
     346                 :            :   }
     347                 :            : 
     348         [ +  - ]:          1 :   if (src->location) {
     349                 :          1 :     ne_free (src->location);
     350                 :            :   }
     351         [ +  - ]:          1 :   if (src->query_string) {
     352                 :          1 :     ne_free (src->query_string);
     353                 :            :   }
     354                 :            : 
     355                 :          1 :   G_OBJECT_CLASS (parent_class)->dispose (gobject);
     356                 :          1 : }
     357                 :            : 
     358                 :            : static void
     359                 :          0 : gst_neonhttp_src_set_property (GObject * object, guint prop_id,
     360                 :            :     const GValue * value, GParamSpec * pspec)
     361                 :            : {
     362                 :          0 :   GstNeonhttpSrc *src = GST_NEONHTTP_SRC (object);
     363                 :            : 
     364   [ #  #  #  #  :          0 :   switch (prop_id) {
          #  #  #  #  #  
                   #  # ]
     365                 :            :     case PROP_PROXY:
     366                 :            :     {
     367                 :            :       const gchar *proxy;
     368                 :            : 
     369                 :          0 :       proxy = g_value_get_string (value);
     370                 :            : 
     371         [ #  # ]:          0 :       if (proxy == NULL) {
     372         [ #  # ]:          0 :         GST_WARNING ("proxy property cannot be NULL");
     373                 :          0 :         goto done;
     374                 :            :       }
     375         [ #  # ]:          0 :       if (!gst_neonhttp_src_set_proxy (src, proxy)) {
     376         [ #  # ]:          0 :         GST_WARNING ("badly formated proxy");
     377                 :          0 :         goto done;
     378                 :            :       }
     379                 :          0 :       break;
     380                 :            :     }
     381                 :            :     case PROP_LOCATION:
     382                 :            :     {
     383                 :            :       const gchar *location;
     384                 :            : 
     385                 :          0 :       location = g_value_get_string (value);
     386                 :            : 
     387         [ #  # ]:          0 :       if (location == NULL) {
     388         [ #  # ]:          0 :         GST_WARNING ("location property cannot be NULL");
     389                 :          0 :         goto done;
     390                 :            :       }
     391         [ #  # ]:          0 :       if (!gst_neonhttp_src_set_location (src, location)) {
     392         [ #  # ]:          0 :         GST_WARNING ("badly formated location");
     393                 :          0 :         goto done;
     394                 :            :       }
     395                 :          0 :       break;
     396                 :            :     }
     397                 :            :     case PROP_USER_AGENT:
     398         [ #  # ]:          0 :       if (src->user_agent)
     399                 :          0 :         g_free (src->user_agent);
     400                 :          0 :       src->user_agent = g_strdup (g_value_get_string (value));
     401                 :          0 :       break;
     402                 :            :     case PROP_COOKIES:
     403         [ #  # ]:          0 :       if (src->cookies)
     404                 :          0 :         g_strfreev (src->cookies);
     405                 :          0 :       src->cookies = (gchar **) g_value_dup_boxed (value);
     406                 :          0 :       break;
     407                 :            :     case PROP_IRADIO_MODE:
     408                 :          0 :       src->iradio_mode = g_value_get_boolean (value);
     409                 :          0 :       break;
     410                 :            :     case PROP_AUTOMATIC_REDIRECT:
     411                 :          0 :       src->automatic_redirect = g_value_get_boolean (value);
     412                 :          0 :       break;
     413                 :            :     case PROP_ACCEPT_SELF_SIGNED:
     414                 :          0 :       src->accept_self_signed = g_value_get_boolean (value);
     415                 :          0 :       break;
     416                 :            :     case PROP_CONNECT_TIMEOUT:
     417                 :          0 :       src->connect_timeout = g_value_get_uint (value);
     418                 :          0 :       break;
     419                 :            :     case PROP_READ_TIMEOUT:
     420                 :          0 :       src->read_timeout = g_value_get_uint (value);
     421                 :          0 :       break;
     422                 :            : #ifndef GST_DISABLE_GST_DEBUG
     423                 :            :     case PROP_NEON_HTTP_DEBUG:
     424                 :          0 :       src->neon_http_debug = g_value_get_boolean (value);
     425                 :          0 :       break;
     426                 :            : #endif
     427                 :            :     default:
     428                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     429                 :          0 :       break;
     430                 :            :   }
     431                 :            : done:
     432                 :          0 :   return;
     433                 :            : }
     434                 :            : 
     435                 :            : static void
     436                 :         13 : gst_neonhttp_src_get_property (GObject * object, guint prop_id,
     437                 :            :     GValue * value, GParamSpec * pspec)
     438                 :            : {
     439                 :         13 :   GstNeonhttpSrc *neonhttpsrc = GST_NEONHTTP_SRC (object);
     440                 :            : 
     441   [ +  +  +  +  :         13 :   switch (prop_id) {
          +  +  +  +  +  
             +  +  +  +  
                      - ]
     442                 :            :     case PROP_PROXY:
     443                 :            :     {
     444                 :            :       gchar *str;
     445                 :            : 
     446         [ -  + ]:          1 :       if (neonhttpsrc->proxy.host) {
     447                 :          0 :         str = ne_uri_unparse (&neonhttpsrc->proxy);
     448         [ #  # ]:          0 :         if (!str)
     449                 :          0 :           break;
     450                 :          0 :         g_value_set_string (value, str);
     451                 :          0 :         ne_free (str);
     452                 :            :       } else {
     453                 :          1 :         g_value_set_static_string (value, "");
     454                 :            :       }
     455                 :          1 :       break;
     456                 :            :     }
     457                 :            :     case PROP_LOCATION:
     458                 :            :     {
     459                 :            :       gchar *str;
     460                 :            : 
     461         [ +  - ]:          1 :       if (neonhttpsrc->uri.host) {
     462                 :          1 :         str = ne_uri_unparse (&neonhttpsrc->uri);
     463         [ -  + ]:          1 :         if (!str)
     464                 :          0 :           break;
     465                 :          1 :         g_value_set_string (value, str);
     466                 :          1 :         ne_free (str);
     467                 :            :       } else {
     468                 :          0 :         g_value_set_static_string (value, "");
     469                 :            :       }
     470                 :          1 :       break;
     471                 :            :     }
     472                 :            :     case PROP_USER_AGENT:
     473                 :          1 :       g_value_set_string (value, neonhttpsrc->user_agent);
     474                 :          1 :       break;
     475                 :            :     case PROP_COOKIES:
     476                 :          1 :       g_value_set_boxed (value, neonhttpsrc->cookies);
     477                 :          1 :       break;
     478                 :            :     case PROP_IRADIO_MODE:
     479                 :          1 :       g_value_set_boolean (value, neonhttpsrc->iradio_mode);
     480                 :          1 :       break;
     481                 :            :     case PROP_IRADIO_NAME:
     482                 :          1 :       g_value_set_string (value, neonhttpsrc->iradio_name);
     483                 :          1 :       break;
     484                 :            :     case PROP_IRADIO_GENRE:
     485                 :          1 :       g_value_set_string (value, neonhttpsrc->iradio_genre);
     486                 :          1 :       break;
     487                 :            :     case PROP_IRADIO_URL:
     488                 :          1 :       g_value_set_string (value, neonhttpsrc->iradio_url);
     489                 :          1 :       break;
     490                 :            :     case PROP_AUTOMATIC_REDIRECT:
     491                 :          1 :       g_value_set_boolean (value, neonhttpsrc->automatic_redirect);
     492                 :          1 :       break;
     493                 :            :     case PROP_ACCEPT_SELF_SIGNED:
     494                 :          1 :       g_value_set_boolean (value, neonhttpsrc->accept_self_signed);
     495                 :          1 :       break;
     496                 :            :     case PROP_CONNECT_TIMEOUT:
     497                 :          1 :       g_value_set_uint (value, neonhttpsrc->connect_timeout);
     498                 :          1 :       break;
     499                 :            :     case PROP_READ_TIMEOUT:
     500                 :          1 :       g_value_set_uint (value, neonhttpsrc->read_timeout);
     501                 :          1 :       break;
     502                 :            : #ifndef GST_DISABLE_GST_DEBUG
     503                 :            :     case PROP_NEON_HTTP_DEBUG:
     504                 :          1 :       g_value_set_boolean (value, neonhttpsrc->neon_http_debug);
     505                 :          1 :       break;
     506                 :            : #endif
     507                 :            :     default:
     508                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     509                 :          0 :       break;
     510                 :            :   }
     511                 :         13 : }
     512                 :            : 
     513                 :            : /* NEON CALLBACK */
     514                 :            : static void
     515                 :          0 : oom_callback (void)
     516                 :            : {
     517         [ #  # ]:          0 :   GST_ERROR ("memory exeception in neon");
     518                 :          0 : }
     519                 :            : 
     520                 :            : static GstFlowReturn
     521                 :          0 : gst_neonhttp_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
     522                 :            : {
     523                 :            :   GstNeonhttpSrc *src;
     524                 :            :   GstBaseSrc *basesrc;
     525                 :            :   GstFlowReturn ret;
     526                 :            :   gint read;
     527                 :            : 
     528                 :          0 :   src = GST_NEONHTTP_SRC (psrc);
     529                 :          0 :   basesrc = GST_BASE_SRC_CAST (psrc);
     530                 :            : 
     531                 :            :   /* The caller should know the number of bytes and not read beyond EOS. */
     532         [ #  # ]:          0 :   if (G_UNLIKELY (src->eos))
     533                 :          0 :     goto eos;
     534                 :            : 
     535                 :            :   /* Create the buffer. */
     536         [ #  # ]:          0 :   ret = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (basesrc),
     537                 :          0 :       basesrc->segment.last_stop, basesrc->blocksize,
     538                 :          0 :       src->icy_caps ? src->icy_caps :
     539                 :          0 :       GST_PAD_CAPS (GST_BASE_SRC_PAD (basesrc)), outbuf);
     540                 :            : 
     541         [ #  # ]:          0 :   if (G_UNLIKELY (ret != GST_FLOW_OK))
     542                 :          0 :     goto done;
     543                 :            : 
     544                 :          0 :   read = gst_neonhttp_src_request_dispatch (src, *outbuf);
     545         [ #  # ]:          0 :   if (G_UNLIKELY (read < 0))
     546                 :          0 :     goto read_error;
     547                 :            : 
     548         [ #  # ]:          0 :   GST_LOG_OBJECT (src, "returning %u bytes", GST_BUFFER_SIZE (*outbuf));
     549                 :            : 
     550                 :            : done:
     551                 :          0 :   return ret;
     552                 :            : 
     553                 :            :   /* ERRORS */
     554                 :            : eos:
     555                 :            :   {
     556         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "EOS reached");
     557                 :          0 :     return GST_FLOW_UNEXPECTED;
     558                 :            :   }
     559                 :            : read_error:
     560                 :            :   {
     561 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, READ,
         [ #  # ][ #  # ]
     562                 :            :         (NULL), ("Could not read any bytes (%i, %s)", read,
     563                 :            :             ne_get_error (src->session)));
     564                 :          0 :     gst_buffer_unref (*outbuf);
     565                 :          0 :     *outbuf = NULL;
     566                 :          0 :     return GST_FLOW_ERROR;
     567                 :            :   }
     568                 :            : }
     569                 :            : 
     570                 :            : /* create a socket for connecting to remote server */
     571                 :            : static gboolean
     572                 :          0 : gst_neonhttp_src_start (GstBaseSrc * bsrc)
     573                 :            : {
     574                 :          0 :   GstNeonhttpSrc *src = GST_NEONHTTP_SRC (bsrc);
     575                 :            :   const gchar *content_length;
     576                 :            :   gint res;
     577                 :            : 
     578                 :            : #ifndef GST_DISABLE_GST_DEBUG
     579         [ #  # ]:          0 :   if (src->neon_http_debug)
     580                 :          0 :     ne_debug_init (stderr, NE_DBG_HTTP);
     581                 :            : #endif
     582                 :            : 
     583                 :          0 :   ne_oom_callback (oom_callback);
     584                 :            : 
     585                 :          0 :   res = ne_sock_init ();
     586         [ #  # ]:          0 :   if (res != 0)
     587                 :          0 :     goto init_failed;
     588                 :            : 
     589                 :          0 :   res = gst_neonhttp_src_send_request_and_redirect (src,
     590                 :            :       &src->session, &src->request, 0, src->automatic_redirect);
     591                 :            : 
     592 [ #  # ][ #  # ]:          0 :   if (res != NE_OK || !src->session) {
     593         [ #  # ]:          0 :     if (res == HTTP_SOCKET_ERROR) {
     594                 :          0 :       goto socket_error;
     595         [ #  # ]:          0 :     } else if (res == HTTP_REQUEST_WRONG_PROXY) {
     596                 :          0 :       goto wrong_proxy;
     597                 :            :     } else {
     598                 :          0 :       goto begin_req_failed;
     599                 :            :     }
     600                 :            :   }
     601                 :            : 
     602                 :          0 :   content_length = ne_get_response_header (src->request, "Content-Length");
     603                 :            : 
     604         [ #  # ]:          0 :   if (content_length)
     605                 :          0 :     src->content_size = g_ascii_strtoull (content_length, NULL, 10);
     606                 :            :   else
     607                 :          0 :     src->content_size = -1;
     608                 :            : 
     609         [ #  # ]:          0 :   if (src->iradio_mode) {
     610                 :            :     /* Icecast stuff */
     611                 :            :     const gchar *str_value;
     612                 :            :     gint gint_value;
     613                 :            : 
     614                 :          0 :     str_value = ne_get_response_header (src->request, "icy-metaint");
     615         [ #  # ]:          0 :     if (str_value) {
     616         [ #  # ]:          0 :       if (sscanf (str_value, "%d", &gint_value) == 1) {
     617         [ #  # ]:          0 :         if (src->icy_caps) {
     618                 :          0 :           gst_caps_unref (src->icy_caps);
     619                 :          0 :           src->icy_caps = NULL;
     620                 :            :         }
     621                 :          0 :         src->icy_metaint = gint_value;
     622                 :          0 :         src->icy_caps = gst_caps_new_simple ("application/x-icy",
     623                 :            :             "metadata-interval", G_TYPE_INT, src->icy_metaint, NULL);
     624                 :            :       }
     625                 :            :     }
     626                 :            : 
     627                 :          0 :     str_value = ne_get_response_header (src->request, "icy-name");
     628         [ #  # ]:          0 :     if (str_value) {
     629         [ #  # ]:          0 :       if (src->iradio_name) {
     630                 :          0 :         g_free (src->iradio_name);
     631                 :          0 :         src->iradio_name = NULL;
     632                 :            :       }
     633                 :          0 :       src->iradio_name = gst_neonhttp_src_unicodify (str_value);
     634                 :            :     }
     635                 :          0 :     str_value = ne_get_response_header (src->request, "icy-genre");
     636         [ #  # ]:          0 :     if (str_value) {
     637         [ #  # ]:          0 :       if (src->iradio_genre) {
     638                 :          0 :         g_free (src->iradio_genre);
     639                 :          0 :         src->iradio_genre = NULL;
     640                 :            :       }
     641                 :          0 :       src->iradio_genre = gst_neonhttp_src_unicodify (str_value);
     642                 :            :     }
     643                 :          0 :     str_value = ne_get_response_header (src->request, "icy-url");
     644         [ #  # ]:          0 :     if (str_value) {
     645         [ #  # ]:          0 :       if (src->iradio_url) {
     646                 :          0 :         g_free (src->iradio_url);
     647                 :          0 :         src->iradio_url = NULL;
     648                 :            :       }
     649                 :          0 :       src->iradio_url = gst_neonhttp_src_unicodify (str_value);
     650                 :            :     }
     651                 :            :   }
     652                 :            : 
     653                 :          0 :   return TRUE;
     654                 :            : 
     655                 :            :   /* ERRORS */
     656                 :            : init_failed:
     657                 :            :   {
     658 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
         [ #  # ][ #  # ]
     659                 :            :         ("ne_sock_init() failed: %d", res));
     660                 :          0 :     return FALSE;
     661                 :            :   }
     662                 :            : socket_error:
     663                 :            :   {
     664 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
         [ #  # ][ #  # ]
     665                 :            :         ("HTTP Request failed when opening socket: %d", res));
     666                 :          0 :     return FALSE;
     667                 :            :   }
     668                 :            : wrong_proxy:
     669                 :            :   {
     670 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
         [ #  # ][ #  # ]
     671                 :            :         ("Proxy Server URI is invalid - make sure that either both proxy host "
     672                 :            :             "and port are specified or neither."));
     673                 :          0 :     return FALSE;
     674                 :            :   }
     675                 :            : begin_req_failed:
     676                 :            :   {
     677 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
         [ #  # ][ #  # ]
     678                 :            :         ("Could not begin request: %d", res));
     679                 :          0 :     return FALSE;
     680                 :            :   }
     681                 :            : }
     682                 :            : 
     683                 :            : /* close the socket and associated resources
     684                 :            :  * used both to recover from errors and go to NULL state */
     685                 :            : static gboolean
     686                 :          0 : gst_neonhttp_src_stop (GstBaseSrc * bsrc)
     687                 :            : {
     688                 :            :   GstNeonhttpSrc *src;
     689                 :            : 
     690                 :          0 :   src = GST_NEONHTTP_SRC (bsrc);
     691                 :            : 
     692         [ #  # ]:          0 :   if (src->iradio_name) {
     693                 :          0 :     g_free (src->iradio_name);
     694                 :          0 :     src->iradio_name = NULL;
     695                 :            :   }
     696                 :            : 
     697         [ #  # ]:          0 :   if (src->iradio_genre) {
     698                 :          0 :     g_free (src->iradio_genre);
     699                 :          0 :     src->iradio_genre = NULL;
     700                 :            :   }
     701                 :            : 
     702         [ #  # ]:          0 :   if (src->iradio_url) {
     703                 :          0 :     g_free (src->iradio_url);
     704                 :          0 :     src->iradio_url = NULL;
     705                 :            :   }
     706                 :            : 
     707         [ #  # ]:          0 :   if (src->icy_caps) {
     708                 :          0 :     gst_caps_unref (src->icy_caps);
     709                 :          0 :     src->icy_caps = NULL;
     710                 :            :   }
     711                 :            : 
     712                 :          0 :   src->eos = FALSE;
     713                 :          0 :   src->content_size = -1;
     714                 :          0 :   src->read_position = 0;
     715                 :          0 :   src->seekable = TRUE;
     716                 :            : 
     717                 :          0 :   gst_neonhttp_src_close_session (src);
     718                 :            : 
     719                 :            : #ifndef GST_DISABLE_GST_DEBUG
     720                 :          0 :   ne_debug_init (NULL, 0);
     721                 :            : #endif
     722                 :          0 :   ne_oom_callback (NULL);
     723                 :          0 :   ne_sock_exit ();
     724                 :            : 
     725                 :          0 :   return TRUE;
     726                 :            : }
     727                 :            : 
     728                 :            : static gboolean
     729                 :          0 : gst_neonhttp_src_get_size (GstBaseSrc * bsrc, guint64 * size)
     730                 :            : {
     731                 :            :   GstNeonhttpSrc *src;
     732                 :            : 
     733                 :          0 :   src = GST_NEONHTTP_SRC (bsrc);
     734                 :            : 
     735         [ #  # ]:          0 :   if (src->content_size == -1)
     736                 :          0 :     return FALSE;
     737                 :            : 
     738                 :          0 :   *size = src->content_size;
     739                 :            : 
     740                 :          0 :   return TRUE;
     741                 :            : }
     742                 :            : 
     743                 :            : static gboolean
     744                 :          0 : gst_neonhttp_src_is_seekable (GstBaseSrc * bsrc)
     745                 :            : {
     746                 :          0 :   return TRUE;
     747                 :            : }
     748                 :            : 
     749                 :            : static gboolean
     750                 :          0 : gst_neonhttp_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
     751                 :            : {
     752                 :            :   GstNeonhttpSrc *src;
     753                 :            :   gint res;
     754                 :          0 :   ne_session *session = NULL;
     755                 :          0 :   ne_request *request = NULL;
     756                 :            : 
     757                 :          0 :   src = GST_NEONHTTP_SRC (bsrc);
     758                 :            : 
     759         [ #  # ]:          0 :   if (!src->seekable)
     760                 :          0 :     return FALSE;
     761                 :            : 
     762         [ #  # ]:          0 :   if (src->read_position == segment->start)
     763                 :          0 :     return TRUE;
     764                 :            : 
     765                 :          0 :   res = gst_neonhttp_src_send_request_and_redirect (src,
     766                 :            :       &session, &request, segment->start, src->automatic_redirect);
     767                 :            : 
     768                 :            :   /* if we are able to seek, replace the session */
     769 [ #  # ][ #  # ]:          0 :   if (res == NE_OK && session) {
     770                 :          0 :     gst_neonhttp_src_close_session (src);
     771                 :          0 :     src->session = session;
     772                 :          0 :     src->request = request;
     773                 :          0 :     src->read_position = segment->start;
     774                 :          0 :     return TRUE;
     775                 :            :   }
     776                 :            : 
     777                 :          0 :   return FALSE;
     778                 :            : }
     779                 :            : 
     780                 :            : static gboolean
     781                 :          1 : gst_neonhttp_src_set_location (GstNeonhttpSrc * src, const gchar * uri)
     782                 :            : {
     783                 :          1 :   ne_uri_free (&src->uri);
     784         [ -  + ]:          1 :   if (src->location) {
     785                 :          0 :     ne_free (src->location);
     786                 :          0 :     src->location = NULL;
     787                 :            :   }
     788         [ -  + ]:          1 :   if (src->query_string) {
     789                 :          0 :     ne_free (src->query_string);
     790                 :          0 :     src->query_string = NULL;
     791                 :            :   }
     792                 :            : 
     793         [ -  + ]:          1 :   if (ne_uri_parse (uri, &src->uri) != 0)
     794                 :          0 :     goto parse_error;
     795                 :            : 
     796         [ -  + ]:          1 :   if (src->uri.scheme == NULL)
     797                 :          0 :     src->uri.scheme = g_strdup ("http");
     798                 :            : 
     799         [ -  + ]:          1 :   if (src->uri.host == NULL)
     800                 :          0 :     src->uri.host = g_strdup (DEFAULT_LOCATION);
     801                 :            : 
     802         [ -  + ]:          1 :   if (src->uri.port == 0) {
     803         [ #  # ]:          0 :     if (!strcmp (src->uri.scheme, "https"))
     804                 :          0 :       src->uri.port = HTTPS_DEFAULT_PORT;
     805                 :            :     else
     806                 :          0 :       src->uri.port = HTTP_DEFAULT_PORT;
     807                 :            :   }
     808                 :            : 
     809         [ -  + ]:          1 :   if (!src->uri.path)
     810                 :          0 :     src->uri.path = g_strdup ("");
     811                 :            : 
     812                 :          1 :   src->query_string = g_strjoin ("?", src->uri.path, src->uri.query, NULL);
     813                 :            : 
     814                 :          1 :   src->location = ne_uri_unparse (&src->uri);
     815                 :            : 
     816                 :          1 :   return TRUE;
     817                 :            : 
     818                 :            :   /* ERRORS */
     819                 :            : parse_error:
     820                 :            :   {
     821         [ #  # ]:          0 :     if (src->location) {
     822                 :          0 :       ne_free (src->location);
     823                 :          0 :       src->location = NULL;
     824                 :            :     }
     825         [ #  # ]:          0 :     if (src->query_string) {
     826                 :          0 :       ne_free (src->query_string);
     827                 :          0 :       src->query_string = NULL;
     828                 :            :     }
     829                 :          0 :     ne_uri_free (&src->uri);
     830                 :          1 :     return FALSE;
     831                 :            :   }
     832                 :            : }
     833                 :            : 
     834                 :            : static gboolean
     835                 :          0 : gst_neonhttp_src_set_proxy (GstNeonhttpSrc * src, const char *uri)
     836                 :            : {
     837                 :          0 :   ne_uri_free (&src->proxy);
     838                 :            : 
     839         [ #  # ]:          0 :   if (ne_uri_parse (uri, &src->proxy) != 0)
     840                 :          0 :     goto error;
     841                 :            : 
     842         [ #  # ]:          0 :   if (src->proxy.scheme)
     843         [ #  # ]:          0 :     GST_WARNING ("The proxy schema shouldn't be defined (schema is '%s')",
     844                 :            :         src->proxy.scheme);
     845                 :            : 
     846 [ #  # ][ #  # ]:          0 :   if (src->proxy.host && !src->proxy.port)
     847                 :          0 :     goto error;
     848                 :            : 
     849 [ #  # ][ #  # ]:          0 :   if (!src->proxy.path || src->proxy.userinfo)
     850                 :            :     goto error;
     851                 :          0 :   return TRUE;
     852                 :            : 
     853                 :            :   /* ERRORS */
     854                 :            : error:
     855                 :            :   {
     856                 :          0 :     ne_uri_free (&src->proxy);
     857                 :          0 :     return FALSE;
     858                 :            :   }
     859                 :            : }
     860                 :            : 
     861                 :            : static int
     862                 :          0 : ssl_verify_callback (void *data, int failures, const ne_ssl_certificate * cert)
     863                 :            : {
     864                 :          0 :   GstNeonhttpSrc *src = GST_NEONHTTP_SRC (data);
     865                 :            : 
     866 [ #  # ][ #  # ]:          0 :   if ((failures & NE_SSL_UNTRUSTED) &&
     867         [ #  # ]:          0 :       src->accept_self_signed && !ne_ssl_cert_signedby (cert)) {
     868 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_INFO (src, RESOURCE, READ,
         [ #  # ][ #  # ]
     869                 :            :         (NULL), ("Accepting self-signed server certificate"));
     870                 :            : 
     871                 :          0 :     failures &= ~NE_SSL_UNTRUSTED;
     872                 :            :   }
     873                 :            : 
     874         [ #  # ]:          0 :   if (failures & NE_SSL_NOTYETVALID)
     875 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, READ,
         [ #  # ][ #  # ]
     876                 :            :         (NULL), ("Server certificate not valid yet"));
     877         [ #  # ]:          0 :   if (failures & NE_SSL_EXPIRED)
     878 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, READ,
         [ #  # ][ #  # ]
     879                 :            :         (NULL), ("Server certificate has expired"));
     880         [ #  # ]:          0 :   if (failures & NE_SSL_IDMISMATCH)
     881 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, READ,
         [ #  # ][ #  # ]
     882                 :            :         (NULL), ("Server certificate doesn't match hostname"));
     883         [ #  # ]:          0 :   if (failures & NE_SSL_UNTRUSTED)
     884 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, RESOURCE, READ,
         [ #  # ][ #  # ]
     885                 :            :         (NULL), ("Server certificate signer not trusted"));
     886                 :            : 
     887         [ #  # ]:          0 :   GST_DEBUG_OBJECT (src, "failures: %d\n", failures);
     888                 :            : 
     889                 :          0 :   return failures;
     890                 :            : }
     891                 :            : 
     892                 :            : /* Try to send the HTTP request to the Icecast server, and if possible deals with
     893                 :            :  * all the probable redirections (HTTP status code == 3xx)
     894                 :            :  */
     895                 :            : static gint
     896                 :          0 : gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
     897                 :            :     ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir)
     898                 :            : {
     899                 :          0 :   ne_session *session = NULL;
     900                 :          0 :   ne_request *request = NULL;
     901                 :            :   gchar **c;
     902                 :            :   gint res;
     903                 :          0 :   gint http_status = 0;
     904                 :          0 :   guint request_count = 0;
     905                 :            : 
     906                 :            :   do {
     907 [ #  # ][ #  # ]:          0 :     if (src->proxy.host && src->proxy.port) {
     908                 :          0 :       session =
     909                 :          0 :           ne_session_create (src->uri.scheme, src->uri.host, src->uri.port);
     910                 :          0 :       ne_session_proxy (session, src->proxy.host, src->proxy.port);
     911 [ #  # ][ #  # ]:          0 :     } else if (src->proxy.host || src->proxy.port) {
     912                 :            :       /* both proxy host and port must be specified or none */
     913                 :          0 :       return HTTP_REQUEST_WRONG_PROXY;
     914                 :            :     } else {
     915                 :          0 :       session =
     916                 :          0 :           ne_session_create (src->uri.scheme, src->uri.host, src->uri.port);
     917                 :            :     }
     918                 :            : 
     919         [ #  # ]:          0 :     if (src->connect_timeout > 0) {
     920                 :          0 :       ne_set_connect_timeout (session, src->connect_timeout);
     921                 :            :     }
     922                 :            : 
     923         [ #  # ]:          0 :     if (src->read_timeout > 0) {
     924                 :          0 :       ne_set_read_timeout (session, src->read_timeout);
     925                 :            :     }
     926                 :            : 
     927                 :          0 :     ne_set_session_flag (session, NE_SESSFLAG_ICYPROTO, 1);
     928                 :          0 :     ne_ssl_set_verify (session, ssl_verify_callback, src);
     929                 :            : 
     930                 :          0 :     request = ne_request_create (session, "GET", src->query_string);
     931                 :            : 
     932         [ #  # ]:          0 :     if (src->user_agent) {
     933                 :          0 :       ne_add_request_header (request, "User-Agent", src->user_agent);
     934                 :            :     }
     935                 :            : 
     936 [ #  # ][ #  # ]:          0 :     for (c = src->cookies; c != NULL && *c != NULL; ++c) {
     937         [ #  # ]:          0 :       GST_INFO ("Adding header Cookie : %s", *c);
     938                 :          0 :       ne_add_request_header (request, "Cookies", *c);
     939                 :            :     }
     940                 :            : 
     941         [ #  # ]:          0 :     if (src->iradio_mode) {
     942                 :          0 :       ne_add_request_header (request, "icy-metadata", "1");
     943                 :            :     }
     944                 :            : 
     945         [ #  # ]:          0 :     if (offset > 0) {
     946                 :          0 :       ne_print_request_header (request, "Range",
     947                 :            :           "bytes=%" G_GINT64_FORMAT "-", offset);
     948                 :            :     }
     949                 :            : 
     950                 :          0 :     res = ne_begin_request (request);
     951                 :            : 
     952         [ #  # ]:          0 :     if (res == NE_OK) {
     953                 :            :       /* When the HTTP status code is 3xx, it is not the SHOUTcast streaming content yet;
     954                 :            :        * Reload the HTTP request with a new URI value */
     955                 :          0 :       http_status = ne_get_status (request)->code;
     956 [ #  # ][ #  # ]:          0 :       if (STATUS_IS_REDIRECTION (http_status) && do_redir) {
                 [ #  # ]
     957                 :            :         const gchar *redir;
     958                 :            : 
     959                 :            :         /* the new URI value to go when redirecting can be found on the 'Location' HTTP header */
     960                 :          0 :         redir = ne_get_response_header (request, "Location");
     961         [ #  # ]:          0 :         if (redir != NULL) {
     962                 :          0 :           ne_uri_free (&src->uri);
     963                 :          0 :           gst_neonhttp_src_set_location (src, redir);
     964         [ #  # ]:          0 :           GST_LOG_OBJECT (src, "Got HTTP Status Code %d", http_status);
     965         [ #  # ]:          0 :           GST_LOG_OBJECT (src, "Using 'Location' header [%s]", src->uri.host);
     966                 :            :         }
     967                 :            :       }
     968                 :            :     }
     969                 :            : 
     970 [ #  # ][ #  # ]:          0 :     if ((res != NE_OK) ||
     971 [ #  # ][ #  # ]:          0 :         (offset == 0 && http_status != 200) ||
     972 [ #  # ][ #  # ]:          0 :         (offset > 0 && http_status != 206 &&
     973         [ #  # ]:          0 :             !STATUS_IS_REDIRECTION (http_status))) {
     974                 :          0 :       ne_request_destroy (request);
     975                 :          0 :       request = NULL;
     976                 :          0 :       ne_close_connection (session);
     977                 :          0 :       ne_session_destroy (session);
     978                 :          0 :       session = NULL;
     979 [ #  # ][ #  # ]:          0 :       if (offset > 0 && http_status != 206 &&
                 [ #  # ]
     980         [ #  # ]:          0 :           !STATUS_IS_REDIRECTION (http_status)) {
     981                 :          0 :         src->seekable = FALSE;
     982                 :            :       }
     983                 :            :     }
     984                 :            : 
     985                 :            :     /* if - NE_OK */
     986 [ #  # ][ #  # ]:          0 :     if (STATUS_IS_REDIRECTION (http_status) && do_redir) {
                 [ #  # ]
     987                 :          0 :       ++request_count;
     988         [ #  # ]:          0 :       GST_LOG_OBJECT (src, "redirect request_count is now %d", request_count);
     989 [ #  # ][ #  # ]:          0 :       if (request_count < MAX_HTTP_REDIRECTS_NUMBER && do_redir) {
     990         [ #  # ]:          0 :         GST_INFO_OBJECT (src, "Redirecting to %s", src->uri.host);
     991                 :            :       } else {
     992         [ #  # ]:          0 :         GST_WARNING_OBJECT (src, "Will not redirect, try again with a "
     993                 :            :             "different URI or redirect location %s", src->uri.host);
     994                 :            :       }
     995                 :            :       /* FIXME: when not redirecting automatically, shouldn't we post a 
     996                 :            :        * redirect element message on the bus? */
     997                 :            :     }
     998                 :            :     /* do the redirect, go back to send another HTTP request now using the 'Location' */
     999         [ #  # ]:          0 :   } while (do_redir && (request_count < MAX_HTTP_REDIRECTS_NUMBER)
    1000 [ #  # ][ #  # ]:          0 :       && STATUS_IS_REDIRECTION (http_status));
                 [ #  # ]
    1001                 :            : 
    1002         [ #  # ]:          0 :   if (session) {
    1003                 :          0 :     *ses = session;
    1004                 :          0 :     *req = request;
    1005                 :            :   }
    1006                 :            : 
    1007                 :          0 :   return res;
    1008                 :            : }
    1009                 :            : 
    1010                 :            : static gint
    1011                 :          0 : gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, GstBuffer * outbuf)
    1012                 :            : {
    1013                 :            :   gint ret;
    1014                 :          0 :   gint read = 0;
    1015                 :          0 :   gint sizetoread = GST_BUFFER_SIZE (outbuf);
    1016                 :            : 
    1017                 :            :   /* Loop sending the request:
    1018                 :            :    * Retry whilst authentication fails and we supply it. */
    1019                 :            : 
    1020                 :          0 :   ssize_t len = 0;
    1021                 :            : 
    1022         [ #  # ]:          0 :   while (sizetoread > 0) {
    1023                 :          0 :     len = ne_read_response_block (src->request,
    1024                 :          0 :         (gchar *) GST_BUFFER_DATA (outbuf) + read, sizetoread);
    1025         [ #  # ]:          0 :     if (len > 0) {
    1026                 :          0 :       read += len;
    1027                 :          0 :       sizetoread -= len;
    1028                 :            :     } else {
    1029                 :          0 :       break;
    1030                 :            :     }
    1031                 :            : 
    1032                 :            :   }
    1033                 :            : 
    1034                 :          0 :   GST_BUFFER_SIZE (outbuf) = read;
    1035                 :            : 
    1036         [ #  # ]:          0 :   if (len < 0) {
    1037                 :          0 :     read = -2;
    1038                 :          0 :     goto done;
    1039         [ #  # ]:          0 :   } else if (len == 0) {
    1040                 :          0 :     ret = ne_end_request (src->request);
    1041         [ #  # ]:          0 :     if (ret != NE_RETRY) {
    1042         [ #  # ]:          0 :       if (ret == NE_OK) {
    1043                 :          0 :         src->eos = TRUE;
    1044                 :            :       } else {
    1045                 :          0 :         read = -3;
    1046                 :            :       }
    1047                 :            :     }
    1048                 :          0 :     goto done;
    1049                 :            :   }
    1050                 :            : 
    1051         [ #  # ]:          0 :   if (read > 0)
    1052                 :          0 :     src->read_position += read;
    1053                 :            : 
    1054                 :            : done:
    1055                 :          0 :   return read;
    1056                 :            : }
    1057                 :            : 
    1058                 :            : static void
    1059                 :          0 : gst_neonhttp_src_close_session (GstNeonhttpSrc * src)
    1060                 :            : {
    1061         [ #  # ]:          0 :   if (src->request) {
    1062                 :          0 :     ne_request_destroy (src->request);
    1063                 :          0 :     src->request = NULL;
    1064                 :            :   }
    1065                 :            : 
    1066         [ #  # ]:          0 :   if (src->session) {
    1067                 :          0 :     ne_close_connection (src->session);
    1068                 :          0 :     ne_session_destroy (src->session);
    1069                 :          0 :     src->session = NULL;
    1070                 :            :   }
    1071                 :          0 : }
    1072                 :            : 
    1073                 :            : /* The following two charset mangling functions were copied from gnomevfssrc.
    1074                 :            :  * Preserve them under the unverified assumption that they do something vaguely
    1075                 :            :  * worthwhile.
    1076                 :            :  */
    1077                 :            : static gchar *
    1078                 :          0 : unicodify (const gchar * str, gint len, ...)
    1079                 :            : {
    1080                 :          0 :   gchar *ret = NULL, *cset;
    1081                 :            :   va_list args;
    1082                 :            :   gsize bytes_read, bytes_written;
    1083                 :            : 
    1084         [ #  # ]:          0 :   if (g_utf8_validate (str, len, NULL))
    1085         [ #  # ]:          0 :     return g_strndup (str, len >= 0 ? len : strlen (str));
    1086                 :            : 
    1087                 :          0 :   va_start (args, len);
    1088 [ #  # ][ #  # ]:          0 :   while ((cset = va_arg (args, gchar *)) != NULL) {
    1089         [ #  # ]:          0 :     if (!strcmp (cset, "locale"))
    1090                 :          0 :       ret = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
    1091                 :            :     else
    1092                 :          0 :       ret = g_convert (str, len, "UTF-8", cset,
    1093                 :            :           &bytes_read, &bytes_written, NULL);
    1094         [ #  # ]:          0 :     if (ret)
    1095                 :          0 :       break;
    1096                 :            :   }
    1097                 :          0 :   va_end (args);
    1098                 :            : 
    1099                 :          0 :   return ret;
    1100                 :            : }
    1101                 :            : 
    1102                 :            : static gchar *
    1103                 :          0 : gst_neonhttp_src_unicodify (const gchar * str)
    1104                 :            : {
    1105                 :          0 :   return unicodify (str, -1, "locale", "ISO-8859-1", NULL);
    1106                 :            : }
    1107                 :            : 
    1108                 :            : /* GstURIHandler Interface */
    1109                 :            : static guint
    1110                 :          3 : gst_neonhttp_src_uri_get_type (void)
    1111                 :            : {
    1112                 :          3 :   return GST_URI_SRC;
    1113                 :            : }
    1114                 :            : 
    1115                 :            : static gchar **
    1116                 :          3 : gst_neonhttp_src_uri_get_protocols (void)
    1117                 :            : {
    1118                 :            :   static const gchar *protocols[] = { "http", "https", NULL };
    1119                 :          3 :   return (gchar **) protocols;
    1120                 :            : }
    1121                 :            : 
    1122                 :            : static const gchar *
    1123                 :          0 : gst_neonhttp_src_uri_get_uri (GstURIHandler * handler)
    1124                 :            : {
    1125                 :          0 :   GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler);
    1126                 :            : 
    1127                 :          0 :   return src->location;
    1128                 :            : }
    1129                 :            : 
    1130                 :            : static gboolean
    1131                 :          0 : gst_neonhttp_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
    1132                 :            : {
    1133                 :          0 :   GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler);
    1134                 :            : 
    1135                 :          0 :   return gst_neonhttp_src_set_location (src, uri);
    1136                 :            : }
    1137                 :            : 
    1138                 :            : static void
    1139                 :          3 : gst_neonhttp_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
    1140                 :            : {
    1141                 :          3 :   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
    1142                 :            : 
    1143                 :          3 :   iface->get_type = gst_neonhttp_src_uri_get_type;
    1144                 :          3 :   iface->get_protocols = gst_neonhttp_src_uri_get_protocols;
    1145                 :          3 :   iface->get_uri = gst_neonhttp_src_uri_get_uri;
    1146                 :          3 :   iface->set_uri = gst_neonhttp_src_uri_set_uri;
    1147                 :          3 : }
    1148                 :            : 
    1149                 :            : /* entry point to initialize the plug-in
    1150                 :            :  * initialize the plug-in itself
    1151                 :            :  * register the element factories and pad templates
    1152                 :            :  * register the features
    1153                 :            :  */
    1154                 :            : static gboolean
    1155                 :          3 : plugin_init (GstPlugin * plugin)
    1156                 :            : {
    1157                 :          3 :   return gst_element_register (plugin, "neonhttpsrc", GST_RANK_NONE,
    1158                 :            :       GST_TYPE_NEONHTTP_SRC);
    1159                 :            : }
    1160                 :            : 
    1161                 :            : /* this is the structure that gst-register looks for
    1162                 :            :  * so keep the name plugin_desc, or you cannot get your plug-in registered */
    1163                 :            : GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    1164                 :            :     GST_VERSION_MINOR,
    1165                 :            :     "neon",
    1166                 :            :     "lib neon http client src",
    1167                 :            :     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

Generated by: LCOV version 1.9