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

http: add vlc_h1_request() for TCP Fast Open

...with insecure HTTP.
parent 2ddbc57e
...@@ -66,6 +66,42 @@ struct vlc_http_conn *vlc_h1_conn_create(void *ctx, struct vlc_tls *, ...@@ -66,6 +66,42 @@ struct vlc_http_conn *vlc_h1_conn_create(void *ctx, struct vlc_tls *,
struct vlc_http_stream *vlc_chunked_open(struct vlc_http_stream *, struct vlc_http_stream *vlc_chunked_open(struct vlc_http_stream *,
struct vlc_tls *); struct vlc_tls *);
/**
* Sends an HTTP/1.x request through a new connection.
*
* This function resolves a the specified HTTP server hostname, establishes a
* connection to specified TCP port of the server, then sends an HTTP request.
* The connection is not protected with TLS.
*
* All those operations are combined in a single function call in order to
* support TCP Fast Open. That can save one round-trip when establishing a new
* HTTP connection.
* \note In the case of TLS, TCP Fast Open would convey the TLS Client Hello
* message rather than the HTTP request header. The HTTP request header can
* however be sent with the TLS False Start. This is handled by the TLS stack
* and does not require a combined function call.
*
* \param ctx opaque context pointer for the HTTP connection
* \param hostname HTTP server or proxy hostname to connect to
* \param port TCP port number to connect to
* \param proxy true of the hostname and port correspond to an HTTP proxy,
* or false if they correspond to an HTTP origin server
* \param req HTTP request message
* \param idempotent whether the HTTP request is idempotent (e.g. GET),
* or not (e.g. POST)
* \param connp pointer to storage space for the established HTTP connection
* (or NULL if the connection is not to be reused) [OUT]
* can be NULL if the connection is not meant to be reused
* \return an HTTP stream on success, NULL on error
* \note *connp is undefined on error.
*/
struct vlc_http_stream *vlc_h1_request(void *ctx, const char *hostname,
unsigned port, bool proxy,
const struct vlc_http_msg *req,
bool idempotent,
struct vlc_http_conn **restrict connp);
/** @} */ /** @} */
/** /**
......
...@@ -338,3 +338,66 @@ struct vlc_http_conn *vlc_h1_conn_create(void *ctx, vlc_tls_t *tls, bool proxy) ...@@ -338,3 +338,66 @@ struct vlc_http_conn *vlc_h1_conn_create(void *ctx, vlc_tls_t *tls, bool proxy)
return &conn->conn; return &conn->conn;
} }
struct vlc_http_stream *vlc_h1_request(void *ctx, const char *hostname,
unsigned port, bool proxy,
const struct vlc_http_msg *req,
bool idempotent,
struct vlc_http_conn **restrict connp)
{
struct addrinfo hints =
{
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
}, *res;
vlc_http_dbg(ctx, "resolving %s ...", hostname);
int val = vlc_getaddrinfo_i11e(hostname, port, &hints, &res);
if (val != 0)
{ /* TODO: C locale for gai_strerror() */
vlc_http_err(ctx, "cannot resolve %s: %s", hostname,
gai_strerror(val));
return NULL;
}
for (const struct addrinfo *p = res; p != NULL; p = p->ai_next)
{
vlc_tls_t *tcp = vlc_tls_SocketOpenAddrInfo(p, idempotent);
if (tcp == NULL)
{
vlc_http_err(ctx, "socket error: %s", vlc_strerror_c(errno));
continue;
}
struct vlc_http_conn *conn = vlc_h1_conn_create(ctx, tcp, proxy);
if (unlikely(conn == NULL))
{
vlc_tls_SessionDelete(tcp);
continue;
}
/* Send the HTTP request */
struct vlc_http_stream *stream = vlc_http_stream_open(conn, req);
if (stream != NULL)
{
if (connp != NULL)
*connp = conn;
else
vlc_http_conn_release(conn);
freeaddrinfo(res);
return stream;
}
vlc_http_conn_release(conn);
if (!idempotent)
break; /* If the request is nonidempotent, it cannot be resent. */
}
/* All address info failed. */
freeaddrinfo(res);
return NULL;
}
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