Commit 71408e62 authored by Philipp Schafft's avatar Philipp Schafft 🦁

Feature: Allow RFC 2817 style Upgrade command.

This allows the usage of RFC 2817 style upgrade commands.
This is not correctly announced yet.
Can hardly be tested as most clients do not support this.
Will be helpful with TLS support in libshout.
See: #2159, #2152
parent c806e47a
......@@ -107,6 +107,8 @@ static inline void client_reuseconnection(client_t *client) {
client_destroy(client);
if (reuse == ICECAST_REUSE_UPGRADETLS)
connection_uses_ssl(con);
connection_queue(con);
}
......@@ -239,6 +241,62 @@ void client_send_100(client_t *client)
sock_write (client->con->sock, "HTTP/1.1 100 Continue\r\n\r\n");
}
void client_send_101(client_t *client, reuse_t reuse)
{
ssize_t ret;
if (!client)
return;
if (reuse != ICECAST_REUSE_UPGRADETLS) {
client_send_500(client, "Bad reuse parameter");
return;
}
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
0, 101, NULL,
"text/plain", "utf-8",
NULL, NULL, client);
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"Content-Length: 0\r\nUpgrade: TLS/1.0, HTTP/1.0\r\nConnection: Upgrade\r\n\r\n");
client->respcode = 101;
client->refbuf->len = strlen(client->refbuf->data);
client->reuse = reuse;
fserve_add_client(client, NULL);
}
void client_send_426(client_t *client, reuse_t reuse)
{
ssize_t ret;
if (!client)
return;
if (reuse != ICECAST_REUSE_UPGRADETLS) {
client_send_500(client, "Bad reuse parameter");
return;
}
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
0, 426, NULL,
"text/plain", "utf-8",
NULL, NULL, client);
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"Content-Length: 0\r\nUpgrade: TLS/1.0, HTTP/1.0\r\nConnection: Upgrade\r\n\r\n");
client->respcode = 426;
client->refbuf->len = strlen(client->refbuf->data);
client->reuse = ICECAST_REUSE_KEEPALIVE;
fserve_add_client(client, NULL);
}
/* this function is designed to work even if client is in bad state */
static inline void client_send_500(client_t *client, const char *message)
{
......
......@@ -34,7 +34,9 @@ typedef enum _reuse_tag {
/* do not reuse */
ICECAST_REUSE_CLOSE = 0,
/* reuse */
ICECAST_REUSE_KEEPALIVE
ICECAST_REUSE_KEEPALIVE,
/* Upgrade to TLS */
ICECAST_REUSE_UPGRADETLS
} reuse_t;
typedef struct _client_tag
......@@ -105,6 +107,8 @@ int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser);
void client_destroy(client_t *client);
void client_send_error(client_t *client, int status, int plain, const char *message);
void client_send_100(client_t *client);
void client_send_101(client_t *client, reuse_t reuse);
void client_send_426(client_t *client, reuse_t reuse);
int client_send_bytes (client_t *client, const void *buf, unsigned len);
int client_read_bytes (client_t *client, void *buf, unsigned len);
void client_set_queue (client_t *client, refbuf_t *refbuf);
......
......@@ -1423,6 +1423,7 @@ static void _handle_connection(void)
}
if (already_parsed || httpp_parse (parser, client->refbuf->data, node->offset)) {
char *uri;
const char *upgrade;
/* we may have more than just headers, so prepare for it */
if (node->stream_offset == node->offset) {
......@@ -1449,6 +1450,12 @@ static void _handle_connection(void)
continue;
}
upgrade = httpp_getvar(parser, "upgrade");
if (upgrade && strstr(upgrade, "TLS/1.0") != NULL) {
client_send_101(client, ICECAST_REUSE_UPGRADETLS);
continue;
}
uri = util_normalise_uri(rawuri);
if (!uri) {
......
......@@ -61,6 +61,7 @@ void connection_close(connection_t *con);
connection_t *connection_create(sock_t sock, sock_t serversock, char *ip);
int connection_complete_source(struct source_tag *source, int response);
void connection_queue(connection_t *con);
void connection_uses_ssl(connection_t *con);
extern rwlock_t _source_shutdown_rwlock;
......
......@@ -652,6 +652,7 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
{
switch (status)
{
case 101: statusmsg = "Switching Protocols"; http_version = "1.1"; break;
case 200: statusmsg = "OK"; break;
case 206: statusmsg = "Partial Content"; http_version = "1.1"; break;
case 400: statusmsg = "Bad Request"; break;
......@@ -659,6 +660,7 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
case 403: statusmsg = "Forbidden"; break;
case 404: statusmsg = "File Not Found"; break;
case 416: statusmsg = "Request Range Not Satisfiable"; break;
case 426: statusmsg = "Upgrade Required"; http_version = "1.1"; break;
default: statusmsg = "(unknown status code)"; break;
}
}
......
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