Commit 36d10121 authored by Philipp Schafft's avatar Philipp Schafft 🦁

Feature: Support PUT with chunked transfer encoding.

This adds the Transfer-Encoding chunked to PUT support.

Please test carefully. Will add PUT to Allow: header after testing.

Have fun.

Closes: #2088
parent 79cb147c
......@@ -158,6 +158,8 @@ void client_destroy(client_t *client)
connection_close(client->con);
if (client->parser)
httpp_destroy(client->parser);
if (client->encoding)
httpp_encoding_release(client->encoding);
global_lock();
global.clients--;
......@@ -177,23 +179,36 @@ void client_destroy(client_t *client)
}
/* helper function for reading data from a client */
static ssize_t __client_read_bytes_real(client_t *client, void *buf, size_t len)
{
/* we have data to read from a refbuf first */
if (client->refbuf->len < len)
len = client->refbuf->len;
memcpy (buf, client->refbuf->data, len);
if (len < client->refbuf->len) {
char *ptr = client->refbuf->data;
memmove (ptr, ptr+len, client->refbuf->len - len);
}
client->refbuf->len -= len;
return len;
}
int client_read_bytes(client_t *client, void *buf, unsigned len)
{
ssize_t (*reader)(void*, void*, size_t) = (ssize_t(*)(void*,void*,size_t))__client_read_bytes_real;
void *userdata = client;
int bytes;
if (client->refbuf && client->refbuf->len) {
/* we have data to read from a refbuf first */
if (client->refbuf->len < len)
len = client->refbuf->len;
memcpy (buf, client->refbuf->data, len);
if (len < client->refbuf->len) {
char *ptr = client->refbuf->data;
memmove (ptr, ptr+len, client->refbuf->len - len);
}
client->refbuf->len -= len;
return len;
if (!(client->refbuf && client->refbuf->len)) {
reader = (ssize_t(*)(void*,void*,size_t))connection_read_bytes;
userdata = client->con;
}
if (client->encoding) {
bytes = httpp_encoding_read(client->encoding, buf, len, reader, userdata);
} else {
bytes = reader(userdata, buf, len);
}
bytes = client->con->read (client->con, buf, len);
if (bytes == -1 && client->con->error)
ICECAST_LOG_DEBUG("reading from connection has failed");
......
......@@ -24,6 +24,7 @@
#include "acl.h"
#include "cfgfile.h"
#include "common/httpp/httpp.h"
#include "common/httpp/encoding.h"
typedef enum _protocol_tag {
ICECAST_PROTOCOL_HTTP = 0,
......@@ -53,6 +54,9 @@ typedef struct _client_tag
/* the client's http headers */
http_parser_t *parser;
/* Transfer Encoding if any */
httpp_encoding_t *encoding;
/* protocol client uses */
protocol_t protocol;
......
Subproject commit ae2a956d88417f4a9d45a72dc0cd80ee76b6a871
Subproject commit f5d9d955a28df8029d4a235feb275b32b2d9b900
......@@ -421,6 +421,11 @@ void connection_uses_ssl(connection_t *con)
#endif
}
ssize_t connection_read_bytes(connection_t *con, void *buf, size_t len)
{
return con->read(con, buf, len);
}
static sock_t wait_for_serversock(int timeout)
{
#ifdef HAVE_POLL
......@@ -868,8 +873,18 @@ static inline void source_startup(client_t *client, const char *uri)
} else {
refbuf_t *ok = refbuf_new(PER_CLIENT_REFBUF_SIZE);
const char *expectcontinue;
const char *transfer_encoding;
int status_to_send = 200;
transfer_encoding = httpp_getvar(source->parser, "transfer-encoding");
if (transfer_encoding && strcasecmp(transfer_encoding, HTTPP_ENCODING_IDENTITY) != 0) {
client->encoding = httpp_encoding_new(transfer_encoding);
if (!client->encoding) {
client_send_error(client, 501, 1, "Unimplemented");
return;
}
}
/* For PUT support we check for 100-continue and send back a 100 to stay in spec */
expectcontinue = httpp_getvar (source->parser, "expect");
......
......@@ -63,6 +63,8 @@ int connection_complete_source(struct source_tag *source, int response);
void connection_queue(connection_t *con);
void connection_uses_ssl(connection_t *con);
ssize_t connection_read_bytes(connection_t *con, void *buf, size_t len);
extern rwlock_t _source_shutdown_rwlock;
#endif /* __CONNECTION_H__ */
......@@ -671,6 +671,7 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
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;
case 501: statusmsg = "Unimplemented"; 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