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