static void
gst_neonhttp_src_init (GstNeonhttpSrc * src)
{
    const gchar *str;

    src->neon_http_debug = DEFAULT_NEON_HTTP_DEBUG;
    src->user_agent = g_strdup (DEFAULT_USER_AGENT);
    src->automatic_redirect = DEFAULT_AUTOMATIC_REDIRECT;
    src->accept_self_signed = DEFAULT_ACCEPT_SELF_SIGNED;
    src->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
    src->read_timeout = DEFAULT_READ_TIMEOUT;
    src->iradio_mode = DEFAULT_IRADIO_MODE;

    src->cookies = NULL;
    src->session = NULL;
    src->request = NULL;
    memset (&src->uri, 0, sizeof (src->uri));
    memset (&src->proxy, 0, sizeof (src->proxy));
    src->content_size = -1;
    src->seekable = TRUE;

    gst_neonhttp_src_set_location (src, DEFAULT_LOCATION, NULL);

    /* configure proxy */
    str = g_getenv ("http_proxy");
    if (str && !gst_neonhttp_src_set_proxy (src, str)) {
        GST_WARNING_OBJECT (src,
                            "The proxy set on http_proxy env var ('%s') cannot be parsed.", str);
    }
}
static gboolean
gst_neonhttp_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
{
  GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler);

  return gst_neonhttp_src_set_location (src, uri);
}
/* Try to send the HTTP request to the Icecast server, and if possible deals with
 * all the probable redirections (HTTP status code == 3xx)
 */
static gint
gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
        ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir)
{
    ne_session *session = NULL;
    ne_request *request = NULL;
    gchar **c;
    gint res;
    gint http_status = 0;
    guint request_count = 0;

    do {
        if (src->proxy.host && src->proxy.port) {
            session =
                ne_session_create (src->uri.scheme, src->uri.host, src->uri.port);
            ne_session_proxy (session, src->proxy.host, src->proxy.port);
        } else if (src->proxy.host || src->proxy.port) {
            /* both proxy host and port must be specified or none */
            return HTTP_REQUEST_WRONG_PROXY;
        } else {
            session =
                ne_session_create (src->uri.scheme, src->uri.host, src->uri.port);
        }

        if (src->connect_timeout > 0) {
            ne_set_connect_timeout (session, src->connect_timeout);
        }

        if (src->read_timeout > 0) {
            ne_set_read_timeout (session, src->read_timeout);
        }

        ne_set_session_flag (session, NE_SESSFLAG_ICYPROTO, 1);
        ne_ssl_set_verify (session, ssl_verify_callback, src);

        request = ne_request_create (session, "GET", src->query_string);

        if (src->user_agent) {
            ne_add_request_header (request, "User-Agent", src->user_agent);
        }

        for (c = src->cookies; c != NULL && *c != NULL; ++c) {
            GST_INFO ("Adding header Cookie : %s", *c);
            ne_add_request_header (request, "Cookies", *c);
        }

        if (src->iradio_mode)
            ne_add_request_header (request, "icy-metadata", "1");

        if (offset > 0) {
            ne_print_request_header (request, "Range",
                                     "bytes=%" G_GINT64_FORMAT "-", offset);
        }

        res = ne_begin_request (request);

        if (res == NE_OK) {
            /* When the HTTP status code is 3xx, it is not the SHOUTcast streaming content yet;
             * Reload the HTTP request with a new URI value */
            http_status = ne_get_status (request)->code;
            if (STATUS_IS_REDIRECTION (http_status) && do_redir) {
                const gchar *redir;

                /* the new URI value to go when redirecting can be found on the 'Location' HTTP header */
                redir = ne_get_response_header (request, "Location");
                if (redir != NULL) {
                    ne_uri_free (&src->uri);
                    gst_neonhttp_src_set_location (src, redir, NULL);
                    GST_LOG_OBJECT (src, "Got HTTP Status Code %d", http_status);
                    GST_LOG_OBJECT (src, "Using 'Location' header [%s]", src->uri.host);
                }
            }
        }

        if ((res != NE_OK) ||
                (offset == 0 && http_status != 200) ||
                (offset > 0 && http_status != 206 &&
                 !STATUS_IS_REDIRECTION (http_status))) {
            ne_request_destroy (request);
            request = NULL;
            ne_close_connection (session);
            ne_session_destroy (session);
            session = NULL;
            if (offset > 0 && http_status != 206 &&
                    !STATUS_IS_REDIRECTION (http_status)) {
                src->seekable = FALSE;
            }
        }

        /* if - NE_OK */
        if (STATUS_IS_REDIRECTION (http_status) && do_redir) {
            ++request_count;
            GST_LOG_OBJECT (src, "redirect request_count is now %d", request_count);
            if (request_count < MAX_HTTP_REDIRECTS_NUMBER && do_redir) {
                GST_INFO_OBJECT (src, "Redirecting to %s", src->uri.host);
            } else {
                GST_WARNING_OBJECT (src, "Will not redirect, try again with a "
                                    "different URI or redirect location %s", src->uri.host);
            }
            /* FIXME: when not redirecting automatically, shouldn't we post a
             * redirect element message on the bus? */
        }
        /* do the redirect, go back to send another HTTP request now using the 'Location' */
    } while (do_redir && (request_count < MAX_HTTP_REDIRECTS_NUMBER)
             && STATUS_IS_REDIRECTION (http_status));

    if (session) {
        *ses = session;
        *req = request;
    }

    return res;
}
static void
gst_neonhttp_src_set_property (GObject * object, guint prop_id,
                               const GValue * value, GParamSpec * pspec)
{
    GstNeonhttpSrc *src = GST_NEONHTTP_SRC (object);

    switch (prop_id) {
    case PROP_PROXY:
    {
        const gchar *proxy;

        proxy = g_value_get_string (value);

        if (proxy == NULL) {
            GST_WARNING ("proxy property cannot be NULL");
            goto done;
        }
        if (!gst_neonhttp_src_set_proxy (src, proxy)) {
            GST_WARNING ("badly formated proxy");
            goto done;
        }
        break;
    }
    case PROP_LOCATION:
    {
        const gchar *location;

        location = g_value_get_string (value);

        if (location == NULL) {
            GST_WARNING ("location property cannot be NULL");
            goto done;
        }
        if (!gst_neonhttp_src_set_location (src, location, NULL)) {
            GST_WARNING ("badly formated location");
            goto done;
        }
        break;
    }
    case PROP_USER_AGENT:
        g_free (src->user_agent);
        src->user_agent = g_strdup (g_value_get_string (value));
        break;
    case PROP_COOKIES:
        if (src->cookies)
            g_strfreev (src->cookies);
        src->cookies = (gchar **) g_value_dup_boxed (value);
        break;
    case PROP_AUTOMATIC_REDIRECT:
        src->automatic_redirect = g_value_get_boolean (value);
        break;
    case PROP_ACCEPT_SELF_SIGNED:
        src->accept_self_signed = g_value_get_boolean (value);
        break;
    case PROP_CONNECT_TIMEOUT:
        src->connect_timeout = g_value_get_uint (value);
        break;
    case PROP_READ_TIMEOUT:
        src->read_timeout = g_value_get_uint (value);
        break;
#ifndef GST_DISABLE_GST_DEBUG
    case PROP_NEON_HTTP_DEBUG:
        src->neon_http_debug = g_value_get_boolean (value);
        break;
#endif
    case PROP_IRADIO_MODE:
        src->iradio_mode = g_value_get_boolean (value);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
done:
    return;
}