Skip to content

Commit

Permalink
Model Body and Buf
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmonstar committed Aug 26, 2020
1 parent 03d9c43 commit 53276b2
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 15 deletions.
56 changes: 41 additions & 15 deletions hyper-capi/examples/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ int main(int argc, char *argv[]) {
if (!hyper_request_set_method(req, (uint8_t *)"POST", 4)) {
return 1;
}
if (!hyper_request_set_uri(req, (uint8_t *)"http://httpbin.org", sizeof("http://httpbin.org") - 1)) {
if (!hyper_request_set_uri(req, (uint8_t *)"/", sizeof("/") - 1)) {
return 1;
}

Expand All @@ -176,8 +176,11 @@ int main(int argc, char *argv[]) {

hyper_executor_push(exec, task);

hyper_response *resp;
// The body will be filled in after we get a response, and we will poll it
// multiple times, so it's declared out here.
hyper_body *resp_body = NULL;

// The polling state machine!
while (1) {
hyper_executor_poll(exec);
while (1) {
Expand All @@ -187,30 +190,53 @@ int main(int argc, char *argv[]) {
}
switch (hyper_task_type(task)) {
case HYPER_TASK_CLIENT_SEND:
;
// Take the results
resp = hyper_task_value(task);
// fall through
hyper_response *resp = hyper_task_value(task);
hyper_task_free(task);

uint16_t http_status = hyper_response_status(resp);

printf("HTTP Status: %d", http_status);

hyper_headers *headers = hyper_response_headers(resp);
hyper_headers_iter(headers, print_each_header, NULL);

resp_body = hyper_response_body(resp);
hyper_executor_push(exec, hyper_body_next(resp_body));

break;
case HYPER_TASK_BODY_NEXT:
;
// A body chunk is available
hyper_buf *chunk = hyper_task_value(task);
hyper_task_free(task);

if (!chunk) {
// body is complete!
printf("\n\nDone!");
return 0;
}

// Write the chunk to stdout
hyper_str s = hyper_buf_str(chunk);
write(1, s.buf, s.len);
hyper_buf_free(chunk);

// Queue up another body poll.
hyper_executor_push(exec, hyper_body_next(resp_body));
break;
default:
hyper_task_free(task);
break;
}
}

// If the response is ready, break out for now...
if (resp != NULL) {
break;
}

// All futures are pending on IO work, so select on the fds.
select(1, &all_fds->read, &all_fds->write, &all_fds->excep, NULL);

}

uint16_t http_status = hyper_response_status(resp);

printf("HTTP Status: %d", http_status);

hyper_headers *headers = hyper_response_headers(resp);
hyper_headers_iter(headers, print_each_header, NULL);

return 0;
}
50 changes: 50 additions & 0 deletions hyper-capi/include/hyper.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ typedef struct hyper_response hyper_response;

typedef struct hyper_headers hyper_headers;

typedef struct hyper_body hyper_body;

typedef struct hyper_buf hyper_buf;

typedef struct hyper_task hyper_task;

typedef struct hyper_waker hyper_waker;

typedef struct hyper_executor hyper_executor;

// A string reference.
//
// The data in here typically is not owned by this struct.
typedef struct hyper_str {
const uint8_t *buf;
size_t len;
Expand All @@ -43,6 +50,11 @@ typedef enum {
HYPER_IT_BREAK,
} hyper_iter_step;

typedef enum {
HYPER_POLL_READY,
HYPER_POLL_PENDING,
} hyper_poll;

// HTTP ClientConn

// Starts an HTTP client connection handshake using the provided IO transport
Expand Down Expand Up @@ -141,6 +153,11 @@ uint16_t hyper_response_status(hyper_response *response);
// `hyper_response` has been freed.
hyper_headers *hyper_response_headers(hyper_response *response);

// Take ownership of the body of this response.
//
// It is safe to free the response even after taking ownership of its body.
hyper_body *hyper_response_body(hyper_response *response);

// HTTP Headers

// Sets the header with the provided name to the provided value.
Expand All @@ -166,6 +183,38 @@ void hyper_headers_iter(hyper_headers *headers,
hyper_str value),
void *userdata);

// HTTP Body

// Sets the `userdata` that is passed to the `poll` callback.
void hyper_body_set_data(hyper_body *body, void *userdata);

// Set the poll function for this body.
//
// This function will be called each time more data is desired to write to
// the transport. Use `hyper_body_set_data` to set the `userdata` argument.
void hyper_body_set_poll(hyper_body *body,
hyper_poll (*func)(void *userdata,
hyper_waker *waker));

// Return a task that will yield the next chunk of bytes of the body, when
// available.
//
// This task has a return type tag of `HYPER_TASK_BODY_NEXT`, which will
// give a value of `hyper_buf *`.
//
// When the body is complete, the task's value will be `NULL`.
hyper_task *hyper_body_next(hyper_body *body);

// TODO: hyper_body_trailers()

// Free this buffer.
void hyper_buf_free(hyper_buf *buf);

// Get a reference to the bytes of this buf.
//
// The returned `hyper_str` is not safe to use after freeing the `hyper_buf *`.
hyper_str hyper_buf_str(hyper_buf *buf);

// Futures and Executors

hyper_executor *hyper_executor_new();
Expand All @@ -189,6 +238,7 @@ typedef enum {
HYPER_TASK_BG,
HYPER_TASK_CLIENTCONN_HANDSHAKE,
HYPER_TASK_CLIENT_SEND,
HYPER_TASK_BODY_NEXT,
} hyper_task_return_type;

// Query the return type of this task.
Expand Down

0 comments on commit 53276b2

Please sign in to comment.