Commit c1df2e66 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

https: factor common connection management code

parent 3dbc71f3
...@@ -9,8 +9,8 @@ libvlc_http_la_SOURCES = \ ...@@ -9,8 +9,8 @@ libvlc_http_la_SOURCES = \
access/http/hpack.c access/http/hpack.h access/http/hpackenc.c \ access/http/hpack.c access/http/hpack.h access/http/hpackenc.c \
access/http/h2frame.c access/http/h2frame.h \ access/http/h2frame.c access/http/h2frame.h \
access/http/h2output.c access/http/h2output.h \ access/http/h2output.c access/http/h2output.h \
access/http/h2conn.c access/http/h2conn.h \ access/http/h2conn.c access/http/h1conn.c \
access/http/h1conn.c access/http/h1conn.h access/http/chunked.c \ access/http/chunked.c access/http/conn.h \
access/http/connmgr.c access/http/connmgr.h access/http/connmgr.c access/http/connmgr.h
libvlc_http_la_CPPFLAGS = -Dneedsomethinghere libvlc_http_la_CPPFLAGS = -Dneedsomethinghere
libvlc_http_la_LIBADD = \ libvlc_http_la_LIBADD = \
......
...@@ -30,11 +30,10 @@ ...@@ -30,11 +30,10 @@
#include <string.h> #include <string.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_block.h> #include <vlc_block.h>
#include <vlc_tls.h> /* FIXME: remove this and test */ #include <vlc_tls.h> /* TODO: remove this */
#include "message.h" #include "message.h"
#include "transport.h" #include "conn.h"
#include "h1conn.h"
struct vlc_chunked_stream struct vlc_chunked_stream
{ {
......
...@@ -25,14 +25,13 @@ ...@@ -25,14 +25,13 @@
#undef NDEBUG #undef NDEBUG
#include <assert.h> #include <assert.h>
//#include <inttypes.h> #include <stddef.h>
//#include <stdlib.h>
#include <string.h> #include <string.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_tls.h> #include <vlc_tls.h>
#include <vlc_block.h> #include <vlc_block.h>
#include "h1conn.h" #include "conn.h"
#include "message.h" #include "message.h"
/* I/O callbacks */ /* I/O callbacks */
......
/***************************************************************************** /*****************************************************************************
* h2conn.h: HTTP/2 connection handling * conn.h: HTTP connections
***************************************************************************** *****************************************************************************
* Copyright (C) 2015 Rémi Denis-Courmont * Copyright (C) 2015 Rémi Denis-Courmont
* *
...@@ -19,12 +19,36 @@ ...@@ -19,12 +19,36 @@
*****************************************************************************/ *****************************************************************************/
struct vlc_tls; struct vlc_tls;
struct vlc_http_conn;
struct vlc_http_msg; struct vlc_http_msg;
struct vlc_http_stream;
struct vlc_h2_conn; struct vlc_http_conn_cbs
{
struct vlc_http_stream *(*stream_open)(struct vlc_http_conn *,
const struct vlc_http_msg *);
void (*release)(struct vlc_http_conn *);
};
struct vlc_h2_conn *vlc_h2_conn_create(struct vlc_tls *tls); struct vlc_http_conn
void vlc_h2_conn_release(struct vlc_h2_conn *conn); {
const struct vlc_http_conn_cbs *cbs;
struct vlc_tls *tls;
};
struct vlc_http_stream *vlc_h2_stream_open(struct vlc_h2_conn *conn, static inline struct vlc_http_stream *
const struct vlc_http_msg *msg); vlc_http_stream_open(struct vlc_http_conn *conn, const struct vlc_http_msg *m)
{
return conn->cbs->stream_open(conn, m);
}
static inline void vlc_http_conn_release(struct vlc_http_conn *conn)
{
conn->cbs->release(conn);
}
struct vlc_http_conn *vlc_h1_conn_create(struct vlc_tls *);
struct vlc_http_conn *vlc_h2_conn_create(struct vlc_tls *);
struct vlc_http_stream *vlc_chunked_open(struct vlc_http_stream *,
struct vlc_tls *);
...@@ -27,8 +27,7 @@ ...@@ -27,8 +27,7 @@
#include <vlc_tls.h> #include <vlc_tls.h>
#include <vlc_interrupt.h> #include <vlc_interrupt.h>
#include "transport.h" #include "transport.h"
#include "h1conn.h" #include "conn.h"
#include "h2conn.h"
#include "connmgr.h" #include "connmgr.h"
#include "message.h" #include "message.h"
...@@ -88,64 +87,48 @@ static vlc_tls_t *vlc_https_connect_i11e(vlc_tls_creds_t *creds, ...@@ -88,64 +87,48 @@ static vlc_tls_t *vlc_https_connect_i11e(vlc_tls_creds_t *creds,
struct vlc_http_mgr struct vlc_http_mgr
{ {
vlc_tls_creds_t *creds; vlc_tls_creds_t *creds;
struct vlc_h1_conn *conn1; struct vlc_http_conn *conn;
struct vlc_h2_conn *conn2;
}; };
static struct vlc_h1_conn *vlc_h1_conn_find(struct vlc_http_mgr *mgr, static struct vlc_http_conn *vlc_http_mgr_find(struct vlc_http_mgr *mgr,
const char *host, unsigned port) const char *host, unsigned port)
{ {
(void) host; (void) port; (void) host; (void) port;
return mgr->conn1; return mgr->conn;
} }
static struct vlc_h2_conn *vlc_h2_conn_find(struct vlc_http_mgr *mgr, static void vlc_http_mgr_release(struct vlc_http_mgr *mgr,
const char *host, unsigned port) struct vlc_http_conn *conn)
{ {
(void) host; (void) port; assert(mgr->conn == conn);
return mgr->conn2; mgr->conn = NULL;
vlc_http_conn_release(conn);
} }
static static
struct vlc_http_msg *vlc_https_request_reuse(struct vlc_http_mgr *mgr, struct vlc_http_msg *vlc_http_mgr_reuse(struct vlc_http_mgr *mgr,
const char *host, unsigned port, const char *host, unsigned port,
const struct vlc_http_msg *req) const struct vlc_http_msg *req)
{ {
struct vlc_h2_conn *conn2 = vlc_h2_conn_find(mgr, host, port); struct vlc_http_conn *conn = vlc_http_mgr_find(mgr, host, port);
if (conn2 != NULL) if (conn == NULL)
{ return NULL;
struct vlc_http_stream *s = vlc_h2_stream_open(conn2, req);
if (s != NULL)
{
struct vlc_http_msg *m = vlc_http_stream_read_headers(s);
if (m != NULL)
return m;
vlc_http_stream_close(s, false);
/* NOTE: If the request were not idempotent, NULL should be
* returned here. POST is not used/supported so far, and CONNECT is
* treated as if it were idempotent (which turns out OK here). */
}
/* Get rid of closing or reset connection */
vlc_h2_conn_release(conn2);
mgr->conn2 = NULL;
}
struct vlc_h1_conn *conn1 = vlc_h1_conn_find(mgr, host, port); struct vlc_http_stream *stream = vlc_http_stream_open(conn, req);
if (conn1 != NULL) if (stream != NULL)
{ {
struct vlc_http_stream *s = vlc_h1_stream_open(conn1, req); struct vlc_http_msg *m = vlc_http_stream_read_headers(stream);
if (s != NULL)
{
struct vlc_http_msg *m = vlc_http_stream_read_headers(s);
if (m != NULL) if (m != NULL)
return m; return m;
vlc_http_stream_close(s, false); vlc_http_stream_close(stream, false);
} /* NOTE: If the request were not idempotent, we do not know if it was
vlc_h1_conn_release(conn1); * process by the other end. So POST is not used/supported so far, and
mgr->conn1 = NULL; * CONNECT is treated as if it were idempotent (which is OK here). */
} }
/* Get rid of closing or reset connection */
vlc_http_mgr_release(mgr, conn);
return NULL; return NULL;
} }
...@@ -154,34 +137,31 @@ struct vlc_http_msg *vlc_https_request(struct vlc_http_mgr *mgr, ...@@ -154,34 +137,31 @@ struct vlc_http_msg *vlc_https_request(struct vlc_http_mgr *mgr,
const struct vlc_http_msg *req) const struct vlc_http_msg *req)
{ {
/* TODO? non-idempotent request support */ /* TODO? non-idempotent request support */
struct vlc_http_msg *resp = vlc_https_request_reuse(mgr, host, port, req); struct vlc_http_msg *resp = vlc_http_mgr_reuse(mgr, host, port, req);
if (resp != NULL) if (resp != NULL)
return resp; return resp;
bool http2; bool http2;
vlc_tls_t *tls = vlc_https_connect_i11e(mgr->creds, host, port, &http2); vlc_tls_t *tls = vlc_https_connect_i11e(mgr->creds, host, port, &http2);
if (tls == NULL) if (tls == NULL)
return NULL; return NULL;
struct vlc_http_conn *conn;
if (http2) if (http2)
{ conn = vlc_h2_conn_create(tls);
struct vlc_h2_conn *conn2 = vlc_h2_conn_create(tls);
if (likely(conn2 != NULL))
mgr->conn2 = conn2;
else else
vlc_tls_Close(tls); conn = vlc_h1_conn_create(tls);
}
else /* TODO: HTTP/1.x support */ if (unlikely(conn == NULL))
{ {
struct vlc_h1_conn *conn1 = vlc_h1_conn_create(tls);
if (likely(conn1 != NULL))
mgr->conn1 = conn1;
else
vlc_tls_Close(tls); vlc_tls_Close(tls);
return NULL;
} }
return vlc_https_request_reuse(mgr, host, port, req); mgr->conn = conn;
return vlc_http_mgr_reuse(mgr, host, port, req);
} }
struct vlc_http_mgr *vlc_http_mgr_create(vlc_object_t *obj) struct vlc_http_mgr *vlc_http_mgr_create(vlc_object_t *obj)
...@@ -197,17 +177,14 @@ struct vlc_http_mgr *vlc_http_mgr_create(vlc_object_t *obj) ...@@ -197,17 +177,14 @@ struct vlc_http_mgr *vlc_http_mgr_create(vlc_object_t *obj)
return NULL; return NULL;
} }
mgr->conn1 = NULL; mgr->conn = NULL;
mgr->conn2 = NULL;
return mgr; return mgr;
} }
void vlc_http_mgr_destroy(struct vlc_http_mgr *mgr) void vlc_http_mgr_destroy(struct vlc_http_mgr *mgr)
{ {
if (mgr->conn2 != NULL) if (mgr->conn != NULL)
vlc_h2_conn_release(mgr->conn2); vlc_http_mgr_release(mgr, mgr->conn);
if (mgr->conn1 != NULL)
vlc_h1_conn_release(mgr->conn1);
vlc_tls_Delete(mgr->creds); vlc_tls_Delete(mgr->creds);
free(mgr); free(mgr);
} }
...@@ -32,9 +32,8 @@ ...@@ -32,9 +32,8 @@
#include <vlc_tls.h> #include <vlc_tls.h>
#include <vlc_block.h> #include <vlc_block.h>
#include "h1conn.h" #include "conn.h"
#include "message.h" #include "message.h"
#include "transport.h"
static unsigned vlc_http_can_read(const char *buf, size_t len) static unsigned vlc_http_can_read(const char *buf, size_t len)
{ {
...@@ -109,35 +108,41 @@ static int vlc_http_minor(const char *msg) ...@@ -109,35 +108,41 @@ static int vlc_http_minor(const char *msg)
struct vlc_h1_conn struct vlc_h1_conn
{ {
struct vlc_http_conn conn;
struct vlc_http_stream stream; struct vlc_http_stream stream;
struct vlc_tls *tls;
uintmax_t content_length; uintmax_t content_length;
bool connection_close; bool connection_close;
bool active; bool active;
bool released; bool released;
}; };
#define CO(conn) ((conn)->tls->obj) #define CO(conn) ((conn)->conn.tls->obj)
static void vlc_h1_conn_destroy(struct vlc_h1_conn *conn); static void vlc_h1_conn_destroy(struct vlc_h1_conn *conn);
static void *vlc_h1_stream_fatal(struct vlc_h1_conn *conn) static void *vlc_h1_stream_fatal(struct vlc_h1_conn *conn)
{ {
msg_Dbg(CO(conn), "connection failed"); msg_Dbg(CO(conn), "connection failed");
vlc_tls_Close(conn->tls); vlc_tls_Close(conn->conn.tls);
conn->tls = NULL; conn->conn.tls = NULL;
return NULL; return NULL;
} }
static_assert(offsetof(struct vlc_h1_conn, stream) == 0, "Cast error"); static_assert(offsetof(struct vlc_h1_conn, conn) == 0, "Cast error");
struct vlc_http_stream *vlc_h1_stream_open(struct vlc_h1_conn *conn, static struct vlc_h1_conn *vlc_h1_stream_conn(struct vlc_http_stream *stream)
{
return (void *)(((char *)stream) - offsetof(struct vlc_h1_conn, stream));
}
static struct vlc_http_stream *vlc_h1_stream_open(struct vlc_http_conn *c,
const struct vlc_http_msg *req) const struct vlc_http_msg *req)
{ {
struct vlc_h1_conn *conn = (struct vlc_h1_conn *)c;
size_t len; size_t len;
ssize_t val; ssize_t val;
if (conn->active || conn->tls == NULL) if (conn->active || conn->conn.tls == NULL)
return NULL; return NULL;
char *payload = vlc_http_msg_format(req, &len); char *payload = vlc_http_msg_format(req, &len);
...@@ -145,7 +150,7 @@ struct vlc_http_stream *vlc_h1_stream_open(struct vlc_h1_conn *conn, ...@@ -145,7 +150,7 @@ struct vlc_http_stream *vlc_h1_stream_open(struct vlc_h1_conn *conn,
return NULL; return NULL;
msg_Dbg(CO(conn), "outgoing request:\n%.*s", (int)len, payload); msg_Dbg(CO(conn), "outgoing request:\n%.*s", (int)len, payload);
val = vlc_tls_Write(conn->tls, payload, len); val = vlc_tls_Write(conn->conn.tls, payload, len);
free(payload); free(payload);
if (val < (ssize_t)len) if (val < (ssize_t)len)
...@@ -159,12 +164,12 @@ struct vlc_http_stream *vlc_h1_stream_open(struct vlc_h1_conn *conn, ...@@ -159,12 +164,12 @@ struct vlc_http_stream *vlc_h1_stream_open(struct vlc_h1_conn *conn,
static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream) static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream)
{ {
struct vlc_h1_conn *conn = (struct vlc_h1_conn *)stream; struct vlc_h1_conn *conn = vlc_h1_stream_conn(stream);
struct vlc_http_msg *resp; struct vlc_http_msg *resp;
size_t len; size_t len;
int minor; int minor;
char *payload = vlc_https_headers_recv(conn->tls, &len); char *payload = vlc_https_headers_recv(conn->conn.tls, &len);
if (payload == NULL) if (payload == NULL)
return vlc_h1_stream_fatal(conn); return vlc_h1_stream_fatal(conn);
...@@ -193,7 +198,7 @@ static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream) ...@@ -193,7 +198,7 @@ static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream)
if ((str != NULL) && strcasestr(str, "chunked")) if ((str != NULL) && strcasestr(str, "chunked"))
{ {
assert(conn->content_length == UINTMAX_MAX); assert(conn->content_length == UINTMAX_MAX);
stream = vlc_chunked_open(stream, conn->tls); stream = vlc_chunked_open(stream, conn->conn.tls);
if (unlikely(stream == NULL)) if (unlikely(stream == NULL))
return NULL; return NULL;
} }
...@@ -207,7 +212,7 @@ static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream) ...@@ -207,7 +212,7 @@ static struct vlc_http_msg *vlc_h1_stream_wait(struct vlc_http_stream *stream)
static block_t *vlc_h1_stream_read(struct vlc_http_stream *stream) static block_t *vlc_h1_stream_read(struct vlc_http_stream *stream)
{ {
struct vlc_h1_conn *conn = (struct vlc_h1_conn *)stream; struct vlc_h1_conn *conn = vlc_h1_stream_conn(stream);
size_t size = 2048; size_t size = 2048;
if (size > conn->content_length) if (size > conn->content_length)
...@@ -219,7 +224,7 @@ static block_t *vlc_h1_stream_read(struct vlc_http_stream *stream) ...@@ -219,7 +224,7 @@ static block_t *vlc_h1_stream_read(struct vlc_http_stream *stream)
if (unlikely(block == NULL)) if (unlikely(block == NULL))
return NULL; return NULL;
ssize_t val = vlc_tls_Read(conn->tls, block->p_buffer, size, false); ssize_t val = vlc_tls_Read(conn->conn.tls, block->p_buffer, size, false);
if (val <= 0) if (val <= 0)
{ {
block_Release(block); block_Release(block);
...@@ -235,57 +240,66 @@ static block_t *vlc_h1_stream_read(struct vlc_http_stream *stream) ...@@ -235,57 +240,66 @@ static block_t *vlc_h1_stream_read(struct vlc_http_stream *stream)
static void vlc_h1_stream_close(struct vlc_http_stream *stream, bool abort) static void vlc_h1_stream_close(struct vlc_http_stream *stream, bool abort)
{ {
struct vlc_h1_conn *conn = (struct vlc_h1_conn *)stream; struct vlc_h1_conn *conn = vlc_h1_stream_conn(stream);
assert(conn->active); assert(conn->active);
conn->active = false; conn->active = false;
if (abort) if (abort)
{ {
vlc_tls_Close(conn->tls); vlc_tls_Close(conn->conn.tls);
conn->tls = NULL; conn->conn.tls = NULL;
} }
if (conn->released) if (conn->released)
vlc_h1_conn_destroy(conn); vlc_h1_conn_destroy(conn);
} }
static struct vlc_http_stream_cbs vlc_h1_stream_callbacks = static const struct vlc_http_stream_cbs vlc_h1_stream_callbacks =
{ {
vlc_h1_stream_wait, vlc_h1_stream_wait,
vlc_h1_stream_read, vlc_h1_stream_read,
vlc_h1_stream_close, vlc_h1_stream_close,
}; };
struct vlc_h1_conn *vlc_h1_conn_create(vlc_tls_t *tls)
{
struct vlc_h1_conn *conn = malloc(sizeof (*conn));
if (unlikely(conn == NULL))
return NULL;
conn->stream.cbs = &vlc_h1_stream_callbacks;
conn->tls = tls;
conn->active = false;
conn->released = false;
return conn;
}
static void vlc_h1_conn_destroy(struct vlc_h1_conn *conn) static void vlc_h1_conn_destroy(struct vlc_h1_conn *conn)
{ {
assert(!conn->active); assert(!conn->active);
assert(conn->released); assert(conn->released);
if (conn->tls != NULL) if (conn->conn.tls != NULL)
vlc_tls_Close(conn->tls); vlc_tls_Close(conn->conn.tls);
free(conn); free(conn);
} }
void vlc_h1_conn_release(struct vlc_h1_conn *conn) static void vlc_h1_conn_release(struct vlc_http_conn *c)
{ {
struct vlc_h1_conn *conn = (struct vlc_h1_conn *)c;
assert(!conn->released); assert(!conn->released);
conn->released = true; conn->released = true;
if (!conn->active) if (!conn->active)
vlc_h1_conn_destroy(conn); vlc_h1_conn_destroy(conn);
} }
static const struct vlc_http_conn_cbs vlc_h1_conn_callbacks =
{
vlc_h1_stream_open,
vlc_h1_conn_release,
};
struct vlc_http_conn *vlc_h1_conn_create(vlc_tls_t *tls)
{
struct vlc_h1_conn *conn = malloc(sizeof (*conn));
if (unlikely(conn == NULL))
return NULL;
conn->conn.cbs = &vlc_h1_conn_callbacks;
conn->conn.tls = tls;
conn->stream.cbs = &vlc_h1_stream_callbacks;
conn->active = false;
conn->released = false;
return &conn->conn;
}
/*****************************************************************************
* h1conn.h: HTTP 1.x connection handling
*****************************************************************************
* Copyright © 2015 Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
struct vlc_h1_conn;
struct vlc_http_msg;
struct vlc_http_stream;
struct vlc_tls;
struct vlc_h1_conn *vlc_h1_conn_create(struct vlc_tls *);
void vlc_h1_conn_release(struct vlc_h1_conn *);
struct vlc_http_stream *vlc_h1_stream_open(struct vlc_h1_conn *conn,
const struct vlc_http_msg *req);
struct vlc_http_stream *vlc_chunked_open(struct vlc_http_stream *,
struct vlc_tls *);
...@@ -36,17 +36,16 @@ ...@@ -36,17 +36,16 @@
#include "h2frame.h" #include "h2frame.h"
#include "h2output.h" #include "h2output.h"
#include "h2conn.h" #include "conn.h"
#include "transport.h"
#include "message.h" #include "message.h"
#define CO(c) ((c)->tls->obj) #define CO(c) ((c)->conn.tls->obj)
#define SO(s) CO((s)->conn) #define SO(s) CO((s)->conn)
/** HTTP/2 connection */ /** HTTP/2 connection */
struct vlc_h2_conn struct vlc_h2_conn
{ {
struct vlc_tls *tls; /**< Underlying TLS session */ struct vlc_http_conn conn;
struct vlc_h2_output *out; /**< Send thread */ struct vlc_h2_output *out; /**< Send thread */
struct vlc_h2_stream *streams; /**< List of open streams */ struct vlc_h2_stream *streams; /**< List of open streams */
...@@ -57,6 +56,8 @@ struct vlc_h2_conn ...@@ -57,6 +56,8 @@ struct vlc_h2_conn
vlc_thread_t thread; /**< Receive thread */ vlc_thread_t thread; /**< Receive thread */
}; };
static_assert(offsetof(struct vlc_h2_conn, conn) == 0, "Cast error");
static void vlc_h2_conn_destroy(struct vlc_h2_conn *conn); static void vlc_h2_conn_destroy(struct vlc_h2_conn *conn);
/** HTTP/2 stream */ /** HTTP/2 stream */
...@@ -370,9 +371,10 @@ static const struct vlc_http_stream_cbs vlc_h2_stream_callbacks = ...@@ -370,9 +371,10 @@ static const struct vlc_http_stream_cbs vlc_h2_stream_callbacks =
* \param msg HTTP message headers (including response status or request) * \param msg HTTP message headers (including response status or request)
* \return an HTTP stream, or NULL on error * \return an HTTP stream, or NULL on error
*/ */
struct vlc_http_stream *vlc_h2_stream_open(struct vlc_h2_conn *conn, static struct vlc_http_stream *vlc_h2_stream_open(struct vlc_http_conn *c,
const struct vlc_http_msg *msg) const struct vlc_http_msg *msg)
{ {
struct vlc_h2_conn *conn = (struct vlc_h2_conn *)c;
struct vlc_h2_stream *s = malloc(sizeof (*s)); struct vlc_h2_stream *s = malloc(sizeof (*s));
if (unlikely(s == NULL)) if (unlikely(s == NULL))
return NULL; return NULL;
...@@ -497,7 +499,7 @@ static void vlc_h2_window_status(void *ctx, uint32_t *restrict rcwd) ...@@ -497,7 +499,7 @@ static void vlc_h2_window_status(void *ctx, uint32_t *restrict rcwd)
} }
/** HTTP/2 frames parser callbacks table */ /** HTTP/2 frames parser callbacks table */
static const struct vlc_h2_parser_cbs vlc_h2_conn_callbacks = static const struct vlc_h2_parser_cbs vlc_h2_parser_callbacks =
{ {
vlc_h2_setting, vlc_h2_setting,
vlc_h2_settings_done, vlc_h2_settings_done,
...@@ -610,7 +612,7 @@ static void *vlc_h2_recv_thread(void *data) ...@@ -610,7 +612,7 @@ static void *vlc_h2_recv_thread(void *data)
int canc, val; int canc, val;
canc = vlc_savecancel(); canc = vlc_savecancel();
parser = vlc_h2_parse_init(conn, &vlc_h2_conn_callbacks); parser = vlc_h2_parse_init(conn, &vlc_h2_parser_callbacks);
if (unlikely(parser == NULL)) if (unlikely(parser == NULL))
goto fail; goto fail;
...@@ -618,7 +620,7 @@ static void *vlc_h2_recv_thread(void *data) ...@@ -618,7 +620,7 @@ static void *vlc_h2_recv_thread(void *data)
do do
{ {
vlc_restorecancel(canc); vlc_restorecancel(canc);
frame = vlc_h2_frame_recv(conn->tls); frame = vlc_h2_frame_recv(conn->conn.tls);
canc = vlc_savecancel(); canc = vlc_savecancel();
if (frame == NULL) if (frame == NULL)
...@@ -643,37 +645,6 @@ fail: ...@@ -643,37 +645,6 @@ fail:
return NULL; return NULL;
} }
struct vlc_h2_conn *vlc_h2_conn_create(struct vlc_tls *tls)
{
struct vlc_h2_conn *conn = malloc(sizeof (*conn));
if (unlikely(conn == NULL))
return NULL;
conn->tls = tls;
conn->out = vlc_h2_output_create(tls, true);
conn->streams = NULL;
conn->next_id = 1; /* TODO: server side */
conn->released = false;
if (unlikely(conn->out == NULL))
goto error;
vlc_mutex_init(&conn->lock);
if (vlc_h2_output_send(conn->out, vlc_h2_frame_settings())
|| vlc_clone(&conn->thread, vlc_h2_recv_thread, conn,
VLC_THREAD_PRIORITY_INPUT))
{
vlc_mutex_destroy(&conn->lock);
vlc_h2_output_destroy(conn->out);
goto error;
}
return conn;
error:
free(conn);
return NULL;
}
static void vlc_h2_conn_destroy(struct vlc_h2_conn *conn) static void vlc_h2_conn_destroy(struct vlc_h2_conn *conn)
{ {
assert(conn->streams == NULL); assert(conn->streams == NULL);
...@@ -686,12 +657,13 @@ static void vlc_h2_conn_destroy(struct vlc_h2_conn *conn) ...@@ -686,12 +657,13 @@ static void vlc_h2_conn_destroy(struct vlc_h2_conn *conn)
vlc_mutex_destroy(&conn->lock); vlc_mutex_destroy(&conn->lock);
vlc_h2_output_destroy(conn->out); vlc_h2_output_destroy(conn->out);
vlc_tls_Close(conn->tls); vlc_tls_Close(conn->conn.tls);
free(conn); free(conn);
} }
void vlc_h2_conn_release(struct vlc_h2_conn *conn) static void vlc_h2_conn_release(struct vlc_http_conn *c)
{ {
struct vlc_h2_conn *conn = (struct vlc_h2_conn *)c;
bool destroy; bool destroy;
vlc_mutex_lock(&conn->lock); vlc_mutex_lock(&conn->lock);
...@@ -704,3 +676,41 @@ void vlc_h2_conn_release(struct vlc_h2_conn *conn) ...@@ -704,3 +676,41 @@ void vlc_h2_conn_release(struct vlc_h2_conn *conn)
if (destroy) if (destroy)
vlc_h2_conn_destroy(conn); vlc_h2_conn_destroy(conn);
} }
static const struct vlc_http_conn_cbs vlc_h2_conn_callbacks =
{
vlc_h2_stream_open,
vlc_h2_conn_release,
};
struct vlc_http_conn *vlc_h2_conn_create(struct vlc_tls *tls)
{
struct vlc_h2_conn *conn = malloc(sizeof (*conn));
if (unlikely(conn == NULL))
return NULL;
conn->conn.cbs = &vlc_h2_conn_callbacks;
conn->conn.tls = tls;
conn->out = vlc_h2_output_create(tls, true);
conn->streams = NULL;
conn->next_id = 1; /* TODO: server side */
conn->released = false;
if (unlikely(conn->out == NULL))
goto error;
vlc_mutex_init(&conn->lock);
if (vlc_h2_output_send(conn->out, vlc_h2_frame_settings())
|| vlc_clone(&conn->thread, vlc_h2_recv_thread, conn,
VLC_THREAD_PRIORITY_INPUT))
{
vlc_mutex_destroy(&conn->lock);
vlc_h2_output_destroy(conn->out);
goto error;
}
return &conn->conn;
error:
free(conn);
return NULL;
}
...@@ -38,11 +38,10 @@ ...@@ -38,11 +38,10 @@
#include <vlc_block.h> #include <vlc_block.h>
#include <vlc_tls.h> #include <vlc_tls.h>
#include "h2frame.h" #include "h2frame.h"
#include "h2conn.h" #include "conn.h"
#include "message.h" #include "message.h"
#include "transport.h"
static struct vlc_h2_conn *conn; static struct vlc_http_conn *conn;
static int external_fd; static int external_fd;
static void conn_send(struct vlc_h2_frame *f) static void conn_send(struct vlc_h2_frame *f)
...@@ -116,7 +115,7 @@ static void conn_create(void) ...@@ -116,7 +115,7 @@ static void conn_create(void)
static void conn_destroy(void) static void conn_destroy(void)
{ {
shutdown(external_fd, SHUT_WR); shutdown(external_fd, SHUT_WR);
vlc_h2_conn_release(conn); vlc_http_conn_release(conn);
close(external_fd); close(external_fd);
} }
...@@ -126,7 +125,7 @@ static struct vlc_http_stream *stream_open(void) ...@@ -126,7 +125,7 @@ static struct vlc_http_stream *stream_open(void)
"www.example.com", "/"); "www.example.com", "/");
assert(m != NULL); assert(m != NULL);
struct vlc_http_stream *s = vlc_h2_stream_open(conn, m); struct vlc_http_stream *s = vlc_http_stream_open(conn, m);
vlc_http_msg_destroy(m); vlc_http_msg_destroy(m);
return s; return s;
} }
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <vlc_tls.h> #include <vlc_tls.h>
#include "h2frame.h" #include "h2frame.h"
#include "h2output.h" #include "h2output.h"
#include "transport.h"
#define VLC_H2_MAX_QUEUE (1u << 24) #define VLC_H2_MAX_QUEUE (1u << 24)
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <vlc_tls.h> #include <vlc_tls.h>
#include "h2frame.h" #include "h2frame.h"
#include "h2output.h" #include "h2output.h"
#include "transport.h"
#undef msleep #undef msleep
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment