Exemple #1
0
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
{
    HTTPContext *s = h->priv_data;
    int err, new_location, read_ret, seek_ret;

    if (!s->hd)
        return AVERROR_EOF;

    if (s->end_chunked_post && !s->end_header) {
        err = http_read_header(h, &new_location);
        if (err < 0)
            return err;
    }

    if (s->chunksize >= 0) {
        if (!s->chunksize) {
            char line[32];

                do {
                    if ((err = http_get_line(s, line, sizeof(line))) < 0)
                        return err;
                } while (!*line);    /* skip CR LF from last chunk */

                s->chunksize = strtoll(line, NULL, 16);

                av_log(NULL, AV_LOG_TRACE, "Chunked encoding data size: %"PRId64"'\n",
                        s->chunksize);

                if (!s->chunksize)
                    return 0;
        }
        size = FFMIN(size, s->chunksize);
    }
#if CONFIG_ZLIB
    if (s->compressed)
        return http_buf_read_compressed(h, buf, size);
#endif /* CONFIG_ZLIB */
    read_ret = http_buf_read(h, buf, size);
    if (read_ret < 0 && s->reconnect && !h->is_streamed && s->filesize > 0 && s->off < s->filesize) {
        av_log(h, AV_LOG_INFO, "Will reconnect at %"PRId64".\n", s->off);
        seek_ret = http_seek_internal(h, s->off, SEEK_SET, 1);
        if (seek_ret != s->off) {
            av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRId64".\n", s->off);
            return read_ret;
        }

        read_ret = http_buf_read(h, buf, size);
    }

    return read_ret;
}
Exemple #2
0
static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size)
{
    HTTPContext *s = h->priv_data;
    int ret;

    if (!s->inflate_buffer) {
        s->inflate_buffer = av_malloc(DECOMPRESS_BUF_SIZE);
        if (!s->inflate_buffer)
            return AVERROR(ENOMEM);
    }

    if (s->inflate_stream.avail_in == 0) {
        int read = http_buf_read(h, s->inflate_buffer, DECOMPRESS_BUF_SIZE);
        if (read <= 0)
            return read;
        s->inflate_stream.next_in  = s->inflate_buffer;
        s->inflate_stream.avail_in = read;
    }

    s->inflate_stream.avail_out = size;
    s->inflate_stream.next_out  = buf;

    ret = inflate(&s->inflate_stream, Z_SYNC_FLUSH);
    if (ret != Z_OK && ret != Z_STREAM_END)
        av_log(h, AV_LOG_WARNING, "inflate return value: %d, %s\n",
               ret, s->inflate_stream.msg);

    return size - s->inflate_stream.avail_out;
}
Exemple #3
0
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
{
    HTTPContext *s = h->priv_data;
    int err, new_location;

    if (!s->hd)
        return AVERROR_EOF;

    if (s->end_chunked_post && !s->end_header) {
        err = http_read_header(h, &new_location);
        if (err < 0)
            return err;
    }

    if (s->chunksize >= 0) {
        if (!s->chunksize) {
            char line[32];

            for (;;) {
                do {
                    if ((err = http_get_line(s, line, sizeof(line))) < 0)
                        return err;
                } while (!*line);    /* skip CR LF from last chunk */

                s->chunksize = strtoll(line, NULL, 16);

                av_log(NULL, AV_LOG_TRACE, "Chunked encoding data size: %"PRId64"'\n",
                        s->chunksize);

                if (!s->chunksize)
                    return 0;
                break;
            }
        }
        size = FFMIN(size, s->chunksize);
    }
#if CONFIG_ZLIB
    if (s->compressed)
        return http_buf_read_compressed(h, buf, size);
#endif /* CONFIG_ZLIB */
    return http_buf_read(h, buf, size);
}
Exemple #4
0
struct http_request *http_parse_request(struct http_channel *c,
                                        struct http_buf **queue,
                                        int len)
{
    struct http_request *r = nmem_malloc(c->nmem, sizeof(*r));
    char *p, *p2;
    char *start = nmem_malloc(c->nmem, len+1);
    char *buf = start;

    if (http_buf_read(c->http_server, queue, buf, len) < len)
    {
        yaz_log(YLOG_WARN, "http_buf_read < len (%d)", len);
        return 0;
    }
    r->search = "";
    r->channel = c;
    r->arguments = 0;
    r->headers = 0;
    r->content_buf = 0;
    r->content_len = 0;
    // Parse first line
    for (p = buf, p2 = r->method; *p && *p != ' ' && p - buf < 19; p++)
        *(p2++) = *p;
    if (*p != ' ')
    {
        yaz_log(YLOG_WARN, "Unexpected HTTP method in request");
        return 0;
    }
    *p2 = '\0';

    if (!(buf = strchr(buf, ' ')))
    {
        yaz_log(YLOG_WARN, "Missing Request-URI in HTTP request");
        return 0;
    }
    buf++;
    if (!(p = strchr(buf, ' ')))
    {
        yaz_log(YLOG_WARN, "HTTP Request-URI not terminated (too long?)");
        return 0;
    }
    *(p++) = '\0';
    if ((p2 = strchr(buf, '?'))) // Do we have arguments?
        *(p2++) = '\0';
    r->path = nmem_strdup(c->nmem, buf);
    if (p2)
    {
        r->search = nmem_strdup(c->nmem, p2);
        // Parse Arguments
        http_parse_arguments(r, c->nmem, p2);
    }
    buf = p;

    if (strncmp(buf, "HTTP/", 5))
        strcpy(r->http_version, "1.0");
    else
    {
        size_t skipped;
        buf += 5; // strlen("HTTP/")

        p = (char*) next_crlf(buf, &skipped);
        if (!p || skipped < 3 || skipped > 5)
            return 0;

        memcpy(r->http_version, buf, skipped);
        r->http_version[skipped] = '\0';
        buf = p;
    }
    strcpy(c->version, r->http_version);

    r->headers = 0;
    while (*buf)
    {
        size_t skipped;

        p = (char *) next_crlf(buf, &skipped);
        if (!p)
        {
            return 0;
        }
        else if (skipped == 0)
        {
            buf = p;
            break;
        }
        else
        {
            char *cp;
            char *n_v = nmem_malloc(c->nmem, skipped+1);
            struct http_header *h = nmem_malloc(c->nmem, sizeof(*h));

            memcpy(n_v, buf, skipped);
            n_v[skipped] = '\0';

            if (!(cp = strchr(n_v, ':')))
                return 0;
            h->name = nmem_strdupn(c->nmem, n_v, cp - n_v);
            cp++;
            while (isspace(*cp))
                cp++;
            h->value = nmem_strdup(c->nmem, cp);
            h->next = r->headers;
            r->headers = h;
            buf = p;
        }
    }

    // determine if we do keep alive
    if (!strcmp(c->version, "1.0"))
    {
        const char *v = http_lookup_header(r->headers, "Connection");
        if (v && !strcmp(v, "Keep-Alive"))
            c->keep_alive = 1;
        else
            c->keep_alive = 0;
    }
    else
    {
        const char *v = http_lookup_header(r->headers, "Connection");
        if (v && !strcmp(v, "close"))
            c->keep_alive = 0;
        else
            c->keep_alive = 1;
    }
    if (buf < start + len)
    {
        const char *content_type = http_lookup_header(r->headers,
                                                      "Content-Type");
        r->content_len = start + len - buf;
        r->content_buf = buf;

        if (!yaz_strcmp_del("application/x-www-form-urlencoded",
                            content_type, "; "))
        {
            http_parse_arguments(r, c->nmem, r->content_buf);
        }
    }
    return r;
}