示例#1
0
文件: file.c 项目: Akilklk/vlc
static struct vlc_http_msg *vlc_http_file_open(struct vlc_http_file *file,
                                               uintmax_t offset)
{
    struct vlc_http_msg *resp;

    resp = vlc_http_res_open(&file->resource, vlc_http_file_req, &offset);
    if (resp == NULL)
        return NULL;

    int status = vlc_http_msg_get_status(resp);
    if (status == 206)
    {
        const char *str = vlc_http_msg_get_header(resp, "Content-Range");
        if (str == NULL)
            /* A multipart/byteranges response. This is not what we asked for
             * and we do not support it. */
            goto fail;

        uintmax_t start, end;
        if (sscanf(str, "bytes %ju-%ju", &start, &end) != 2
         || start != offset || start > end)
            /* A single range response is what we asked for, but not at that
             * start offset. */
            goto fail;
    }

    return resp;
fail:
    vlc_http_msg_destroy(resp);
    errno = EIO;
    return NULL;
}
示例#2
0
文件: file.c 项目: Akilklk/vlc
int vlc_http_file_seek(struct vlc_http_file *file, uintmax_t offset)
{
    struct vlc_http_msg *resp = vlc_http_file_open(file, offset);
    if (resp == NULL)
        return -1;

    int status = vlc_http_msg_get_status(resp);
    if (file->resp != NULL)
    {   /* Accept the new and ditch the old one if:
         * - requested succeeded and range was accepted (206),
         * - requested failed due to out-of-range (416),
         * - request succeeded and seek offset is zero (2xx).
         */
        if (status != 206 && status != 416 && (offset != 0 || status >= 300))
        {
            vlc_http_msg_destroy(resp);
            return -1;
        }
        vlc_http_msg_destroy(file->resp);
    }

    file->resp = resp;
    file->offset = offset;
    return 0;
}
示例#3
0
文件: file.c 项目: Akilklk/vlc
int vlc_http_file_get_status(struct vlc_http_file *file)
{
    if (file->resp == NULL)
    {
        file->resp = vlc_http_file_open(file, file->offset);
        if (file->resp == NULL)
            return -1;
    }
    return vlc_http_msg_get_status(file->resp);
}
示例#4
0
文件: resource.c 项目: rlugojr/vlc
int vlc_http_res_get_status(struct vlc_http_resource *res)
{
    if (res->response == NULL)
    {
        if (res->failure)
            return -1;

        res->response = vlc_http_res_open(res, res + 1);
        if (res->response == NULL)
        {
            res->failure = true;
            return -1;
        }
    }
    return vlc_http_msg_get_status(res->response);
}
示例#5
0
文件: resource.c 项目: rlugojr/vlc
struct vlc_http_msg *vlc_http_res_open(struct vlc_http_resource *res,
                                       void *opaque)
{
    struct vlc_http_msg *req;
retry:
    req = vlc_http_res_req(res, opaque);
    if (unlikely(req == NULL))
        return NULL;

    struct vlc_http_msg *resp = vlc_http_mgr_request(res->manager, res->secure,
                                res->host, res->port, req);
    vlc_http_msg_destroy(req);

    resp = vlc_http_msg_get_final(resp);
    if (resp == NULL)
        return NULL;

    vlc_http_msg_get_cookies(resp, vlc_http_mgr_get_jar(res->manager),
                             res->secure, res->host, res->path);

    int status = vlc_http_msg_get_status(resp);
    if (status < 200 || status >= 599)
        goto fail;

    if (status == 406 && res->negotiate)
    {   /* Not Acceptable: Content negotiation failed. Normally it means
         * one (or more) Accept or Accept-* header line does not match any
         * representation of the entity. So we set a flag to remove those
         * header lines (unless they accept everything), and retry.
         * In principles, it could be any header line, and the server can
         * pass Vary to clarify. It cannot be caused by If-*, Range, TE or the
         * other transfer- rather than representation-affecting header lines.
         */
        vlc_http_msg_destroy(resp);
        res->negotiate = false;
        goto retry;
    }

    if (res->cbs->response_validate(res, resp, opaque))
        goto fail;

    return resp;
fail:
    vlc_http_msg_destroy(resp);
    return NULL;
}
示例#6
0
static struct vlc_http_msg *vlc_http_tunnel_open(struct vlc_http_conn *conn,
                                                 const char *hostname,
                                                 unsigned port)
{
    char *authority = vlc_http_authority(hostname, port);
    if (authority == NULL)
        return NULL;

    struct vlc_http_msg *req = vlc_http_req_create("CONNECT", NULL, authority,
                                                   NULL);
    free(authority);
    if (unlikely(req == NULL))
        return NULL;

    vlc_http_msg_add_header(req, "ALPN", "h2, http%%2F1.1");
    vlc_http_msg_add_agent(req, PACKAGE_NAME "/" PACKAGE_VERSION);

    struct vlc_http_stream *stream = vlc_http_stream_open(conn, req);

    vlc_http_msg_destroy(req);
    if (stream == NULL)
        return NULL;

    struct vlc_http_msg *resp = vlc_http_msg_get_initial(stream);
    resp = vlc_http_msg_get_final(resp);
    if (resp == NULL)
        return NULL;

    int status = vlc_http_msg_get_status(resp);
    if ((status / 100) != 2)
    {
        vlc_http_msg_destroy(resp);
        resp = NULL;
    }
    return resp;
}
示例#7
0
文件: message.c 项目: 0xheart0/vlc
struct vlc_http_msg *vlc_http_msg_get_final(struct vlc_http_msg *m)
{
    while (m != NULL && (vlc_http_msg_get_status(m) / 100) == 1)
        m = vlc_http_msg_iterate(m);
    return m;
}
示例#8
0
int main(void)
{
    struct vlc_http_stream *s, *s2;
    struct vlc_http_msg *m;
    struct block_t *b;
    uint_fast32_t sid = -1; /* Second guessed stream IDs :-/ */

    conn_create();
    conn_destroy();

    conn_create();
    conn_send(vlc_h2_frame_ping(42));
    conn_expect(PING);

    /* Test rejected stream */
    sid += 2;
    s = stream_open();
    assert(s != NULL);
    conn_expect(HEADERS);
    conn_send(vlc_h2_frame_rst_stream(sid, VLC_H2_REFUSED_STREAM));
    m = vlc_http_stream_read_headers(s);
    assert(m == NULL);
    b = vlc_http_stream_read(s);
    assert(b == NULL);
    vlc_http_stream_close(s, false);
    conn_expect(RST_STREAM);

    /* Test accepted stream */
    sid += 2;
    s = stream_open();
    assert(s != NULL);
    stream_reply(sid, false);
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    vlc_http_msg_destroy(m);

    stream_data(3, "Hello ", false); /* late data */
    stream_data(3, "world!", true);

    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);

    /* Test continuation then accepted stream */
    sid += 2;
    s = stream_open();
    assert(s != NULL);
    stream_continuation(sid);
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    assert(vlc_http_msg_get_status(m) == 100);
    stream_reply(sid, false);
    m = vlc_http_msg_iterate(m);
    assert(m != NULL);
    stream_data(sid, "Hello ", false);
    stream_data(sid, "world!", true);
    stream_data(sid, "Stray message", false); /* data after EOS */
    b = vlc_http_msg_read(m);
    assert(b != NULL);
    block_Release(b);
    b = vlc_http_msg_read(m);
    assert(b != NULL);
    block_Release(b);
    b = vlc_http_msg_read(m);
    assert(b == NULL);
    vlc_http_msg_destroy(m);

    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);

    /* Test accepted stream after continuation */
    sid += 2;
    s = stream_open();
    assert(s != NULL);
    stream_continuation(sid);
    stream_reply(sid, true);
    sid += 2;
    s2 = stream_open(); /* second stream to enforce test timing/ordering */
    assert(s2 != NULL);
    stream_reply(sid, true);
    m = vlc_http_msg_get_initial(s2);
    assert(m != NULL);
    vlc_http_msg_destroy(m);
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    assert(vlc_http_msg_get_status(m) == 200);
    b = vlc_http_msg_read(m);
    assert(b == NULL);
    vlc_http_msg_destroy(m);

    conn_expect(HEADERS);
    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);

    /* Test nonexistent stream reset */
    conn_send(vlc_h2_frame_rst_stream(sid + 100, VLC_H2_REFUSED_STREAM));

    /* Test multiple streams in non-LIFO order */
    sid += 2;
    s = stream_open();
    assert(s != NULL);
    sid += 2;
    s2 = stream_open();
    assert(s2 != NULL);
    stream_reply(sid, false);
    stream_reply(sid - 2, true);
    stream_data(sid, "Discarded", false); /* not read data */
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    vlc_http_msg_destroy(m);
    m = vlc_http_msg_get_initial(s2);
    assert(m != NULL);
    vlc_http_msg_destroy(m);

    conn_expect(HEADERS);
    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);
    /* might or might not seen one or two extra RST_STREAM now */

    /* Test graceful connection termination */
    sid += 2;
    s = stream_open();
    assert(s != NULL);
    conn_send(vlc_h2_frame_goaway(sid - 2, VLC_H2_NO_ERROR));
    m = vlc_http_stream_read_headers(s);
    assert(m == NULL);

    /* Test stream after connection shut down */
    assert(stream_open() == NULL);

    /* Test releasing connection before stream */
    conn_destroy();
    vlc_http_stream_close(s, false);

    return 0;
}