Commit 79cb147c authored by Philipp Schafft's avatar Philipp Schafft 🦁

Cleanup: unbreak 100-continue a bit.

This tries to unbreak the 100-continue thing a bit.
Proper headers are send in case of 100-continue. Also the 200 OK
was moved to the end of the stream.
The client may even be reused. But I'm not sure we only do
'End of stream' in cases we are not on an undefined state of the
client. Do we as of now support anything that give us EOS without
a fatal socket state (error or shutdown)?

At least this unbreaks 100-continue with active TLS that was broken
as hell as we sent the header in clear over the socket. Not checking
if it was transmitted completly or something. Using lowlevel socket
calls (in contrast to the connection level calls that would have
handled the TLS just fine).

While this seem sto be a huge improvement to the situation I kindly
ask you to do a lot testing on this. Both with SOURCE as well as
PUT clients.
parent d6908eb0
......@@ -251,12 +251,6 @@ void client_send_error(client_t *client, int status, int plain, const char *mess
fserve_add_client (client, NULL);
}
void client_send_100(client_t *client)
{
/* On demand inject a HTTP/1.1 100 Continue to make sure clients are happy */
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;
......
......@@ -106,7 +106,6 @@ typedef struct _client_tag
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);
......
......@@ -814,20 +814,6 @@ int connection_complete_source(source_t *source, int response)
return -1;
}
/* For PUT support we check for 100-continue and send back a 100 to stay in spec */
expectcontinue = httpp_getvar (source->parser, "expect");
if (expectcontinue != NULL) {
#ifdef HAVE_STRCASESTR
if (strcasestr (expectcontinue, "100-continue") != NULL)
#else
ICECAST_LOG_WARN("OS doesn't support case insenestive substring checks...");
if (strstr (expectcontinue, "100-continue") != NULL)
#endif
{
client_send_100 (source->client);
}
}
global.sources++;
stats_event_args(NULL, "sources", "%d", global.sources);
global_unlock();
......@@ -881,8 +867,26 @@ static inline void source_startup(client_t *client, const char *uri)
source_client_callback(client, source);
} else {
refbuf_t *ok = refbuf_new(PER_CLIENT_REFBUF_SIZE);
const char *expectcontinue;
int status_to_send = 200;
/* For PUT support we check for 100-continue and send back a 100 to stay in spec */
expectcontinue = httpp_getvar (source->parser, "expect");
if (expectcontinue != NULL) {
#ifdef HAVE_STRCASESTR
if (strcasestr (expectcontinue, "100-continue") != NULL)
#else
ICECAST_LOG_WARN("OS doesn't support case insenestive substring checks...");
if (strstr (expectcontinue, "100-continue") != NULL)
#endif
{
status_to_send = 100;
}
}
client->respcode = 200;
util_http_build_header(ok->data, PER_CLIENT_REFBUF_SIZE, 0, 0, 200, NULL, NULL, NULL, "", NULL, client);
util_http_build_header(ok->data, PER_CLIENT_REFBUF_SIZE, 0, 0, status_to_send, NULL, NULL, NULL, "", NULL, client);
ok->len = strlen(ok->data);
/* we may have unprocessed data read in, so don't overwrite it */
ok->associated = client->refbuf;
......
......@@ -887,6 +887,31 @@ static void source_shutdown (source_t *source)
/* delete this sources stats */
stats_event(source->mount, NULL, NULL);
if (source->client && source->parser) {
/* For PUT support we check for 100-continue and send back a final 200. */
const char *expectcontinue = httpp_getvar(source->parser, "expect");
if (expectcontinue != NULL) {
#ifdef HAVE_STRCASESTR
if (strcasestr (expectcontinue, "100-continue") != NULL)
#else
ICECAST_LOG_WARN("OS doesn't support case insenestive substring checks...");
if (strstr (expectcontinue, "100-continue") != NULL)
#endif
{
client_t *client = source->client;
source->client = NULL; /* detach client from source. */
util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0, 0, 200, NULL, NULL, NULL, "", NULL, source->client);
client->refbuf->len = strlen(client->refbuf->data);
refbuf_release(client->refbuf->next);
client->refbuf->next = NULL;
client->pos = 0;
fserve_add_client(client, NULL);
}
}
}
/* we don't remove the source from the tree here, it may be a relay and
therefore reserved */
source_clear_source(source);
......
......@@ -661,6 +661,7 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
{
switch (status)
{
case 100: statusmsg = "Continue"; http_version = "1.1"; break;
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;
......
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