mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-01-03 14:56:34 -05:00
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
This commit is contained in:
parent
79cb147c4a
commit
36d10121cf
39
src/client.c
39
src/client.c
@ -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;
|
||||
|
||||
|
@ -1 +1 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user