Skip to content

Commit

Permalink
http: added support for chunked transfer encoding (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
richaas authored and alfredh committed Nov 4, 2017
1 parent 14e312f commit 5bb8c07
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 91 deletions.
13 changes: 9 additions & 4 deletions include/re_http.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ struct http_msg {
struct pl reason; /**< Response Reason phrase */
struct list hdrl; /**< List of HTTP headers (struct http_hdr) */
struct msg_ctype ctyp; /**< Content-type */
struct mbuf *mb; /**< Buffer containing the HTTP message */
struct mbuf *_mb; /**< Buffer containing the HTTP message */
struct mbuf *mb; /**< Buffer containing the HTTP body */
uint32_t clen; /**< Content length */
};

Expand Down Expand Up @@ -114,16 +115,20 @@ int http_msg_print(struct re_printf *pf, const struct http_msg *msg);
struct http_cli;
struct http_req;
struct dnsc;
struct tcp_conn;
struct tls_conn;

typedef void (http_resp_h)(int err, const struct http_msg *msg, void *arg);
typedef void (http_data_h)(struct mbuf *mb, void *arg);
typedef int (http_data_h)(const uint8_t *buf, size_t size,
const struct http_msg *msg, void *arg);
typedef void (http_conn_h)(struct tcp_conn *tc, struct tls_conn *sc,
void *arg);

int http_client_alloc(struct http_cli **clip, struct dnsc *dnsc);
int http_request(struct http_req **reqp, struct http_cli *cli, const char *met,
const char *uri, http_resp_h *resph, http_data_h *datah,
void *arg, const char *fmt, ...);
struct tcp_conn *http_req_tcp(struct http_req *req);
struct tls_conn *http_req_tls(struct http_req *req);
void http_req_set_conn_handler(struct http_req *req, http_conn_h *connh);


/* Server */
Expand Down
111 changes: 111 additions & 0 deletions src/http/chunk.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* @file http/chunk.c Chunked Transfer Encoding
*
* Copyright (C) 2011 Creytiv.com
*/

#include <re_types.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include "http.h"


static int decode_chunk_size(struct http_chunk *chunk, struct mbuf *mb)
{
while (mbuf_get_left(mb)) {

char ch = (char)mbuf_read_u8(mb);
uint8_t c;

if (ch == '\n') {
if (chunk->digit) {
chunk->digit = false;
chunk->param = false;

return 0;
}
else
continue;
}

if (chunk->param)
continue;

if ('0' <= ch && ch <= '9')
c = ch - '0';
else if ('A' <= ch && ch <= 'F')
c = ch - 'A' + 10;
else if ('a' <= ch && ch <= 'f')
c = ch - 'a' + 10;
else if (ch == '\r' || ch == ' ' || ch == '\t')
continue;
else if (ch == ';' && chunk->digit) {
chunk->param = true;
continue;
}
else
return EPROTO;

chunk->digit = true;

chunk->size <<= 4;
chunk->size += c;
}

return ENODATA;
}


static int decode_trailer(struct http_chunk *chunk, struct mbuf *mb)
{
while (mbuf_get_left(mb)) {

char ch = (char)mbuf_read_u8(mb);

if (ch == '\n') {
if (++chunk->lf >= 2)
return 0;
}
else if (ch != '\r')
chunk->lf = 0;
}

return ENODATA;
}


int http_chunk_decode(struct http_chunk *chunk, struct mbuf *mb, size_t *size)
{
int err;

if (!chunk || !mb || !size)
return EINVAL;

if (chunk->trailer) {
err = decode_trailer(chunk, mb);
if (err)
return err;

*size = 0;

return 0;
}

err = decode_chunk_size(chunk, mb);
if (err)
return err;

if (chunk->size == 0) {
chunk->trailer = true;
chunk->lf = 1;

err = decode_trailer(chunk, mb);
if (err)
return err;
}

*size = chunk->size;
chunk->size = 0;

return 0;
}
Loading

0 comments on commit 5bb8c07

Please sign in to comment.