Skip to content

Commit f320bb3

Browse files
committed
Add hyper_str, headers_iter
1 parent 432e783 commit f320bb3

File tree

2 files changed

+128
-20
lines changed

2 files changed

+128
-20
lines changed

hyper-capi/examples/client.c

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
#include <stdlib.h>
2+
#include <stdio.h>
23
#include <unistd.h>
34
#include <errno.h>
45
#include <sys/select.h>
6+
7+
#include <sys/types.h>
8+
#include <sys/socket.h>
9+
#include <netdb.h>
10+
#include <string.h>
11+
512
#include "../include/hyper.h"
613

714

@@ -64,31 +71,76 @@ static size_t write_cb(void *userdata, hyper_waker *waker, const uint8_t *buf, s
6471
}
6572
}
6673

67-
int main() {
74+
static int connect_to(char *host, char *port) {
75+
struct addrinfo hints;
76+
memset(&hints, 0, sizeof(struct addrinfo));
77+
hints.ai_family = AF_UNSPEC;
78+
hints.ai_socktype = SOCK_STREAM;
79+
80+
struct addrinfo *result, *rp;
81+
if (getaddrinfo(host, port, &hints, &result) != 0) {
82+
return -1;
83+
}
84+
85+
int sfd;
86+
for (rp = result; rp != NULL; rp = rp->ai_next) {
87+
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
88+
if (sfd == -1) {
89+
continue;
90+
}
91+
92+
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) {
93+
break;
94+
} else {
95+
close(sfd);
96+
}
97+
}
98+
99+
freeaddrinfo(result);
100+
101+
// no address succeeded
102+
if (rp == NULL) {
103+
return -1;
104+
}
105+
106+
return sfd;
107+
}
108+
109+
static hyper_iter_step print_each_header(void *userdata, hyper_str name, hyper_str value) {
110+
printf("%.*s: %.*s", (int) name.len, name.buf, (int) value.len, value.buf);
111+
return HYPER_IT_CONTINUE;
112+
}
113+
114+
int main(int argc, char *argv[]) {
115+
116+
int fd = connect_to("httpbin.org", "80");
117+
if (fd < 0) {
118+
return 1;
119+
}
120+
68121

69122
struct conn_fds *all_fds = malloc(sizeof(struct conn_fds));
70123

124+
FD_ZERO(&all_fds->read);
125+
FD_ZERO(&all_fds->write);
126+
FD_ZERO(&all_fds->excep);
127+
71128
struct conn_data *conn = malloc(sizeof(struct conn_data));
72-
//TODO: YIKES
73-
// should do a connect() instead
74-
conn->fd = 3;
129+
130+
conn->fd = fd;
75131
conn->all_fds = all_fds;
76132
conn->read_waker = NULL;
77133
conn->write_waker = NULL;
78134

79135

80-
FD_ZERO(&all_fds->read);
81-
FD_ZERO(&all_fds->write);
82-
FD_ZERO(&all_fds->excep);
83-
84136
// Hookup the IO
85137
hyper_io *io = hyper_io_new();
86138
hyper_io_set_data(io, (void *)conn);
87139
hyper_io_set_read(io, read_cb);
88140
hyper_io_set_write(io, write_cb);
89141

90142
// Prepare client options
91-
hyper_clientconn_options *opts = hyper_clientconn_options_new();
143+
hyper_clientconn_options *opts = NULL;//hyper_clientconn_options_new();
92144

93145
hyper_task *handshake = hyper_clientconn_handshake(io, opts);
94146

@@ -124,8 +176,8 @@ int main() {
124176

125177
hyper_executor_push(exec, task);
126178

127-
// TODO: NEXT
128-
/*
179+
hyper_response *resp;
180+
129181
while (1) {
130182
hyper_executor_poll(exec);
131183
while (1) {
@@ -134,18 +186,31 @@ int main() {
134186
break;
135187
}
136188
switch (hyper_task_type(task)) {
137-
case HYPER_TASK_CLIENTCONN_HANDSHAKE:
189+
case HYPER_TASK_CLIENT_SEND:
138190
// Take the results
139-
client = hyper_task_value(task);
140-
break;
191+
resp = hyper_task_value(task);
192+
// fall through
141193
default:
142194
hyper_task_free(task);
143195
break;
144196
}
145197
}
146198

199+
// If the response is ready, break out for now...
200+
if (resp != NULL) {
201+
break;
202+
}
203+
147204
select(1, &all_fds->read, &all_fds->write, &all_fds->excep, NULL);
148205

149206
}
150-
*/
207+
208+
uint16_t http_status = hyper_response_status(resp);
209+
210+
printf("HTTP Status: %d", http_status);
211+
212+
hyper_headers *headers = hyper_response_headers(resp);
213+
hyper_headers_iter(headers, print_each_header, NULL);
214+
215+
return 0;
151216
}

hyper-capi/include/hyper.h

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,29 @@ typedef struct hyper_request hyper_request;
2020

2121
typedef struct hyper_response hyper_response;
2222

23+
typedef struct hyper_headers hyper_headers;
24+
2325
typedef struct hyper_task hyper_task;
2426

2527
typedef struct hyper_waker hyper_waker;
2628

2729
typedef struct hyper_executor hyper_executor;
2830

31+
typedef struct hyper_str {
32+
const uint8_t *buf;
33+
size_t len;
34+
} hyper_str;
35+
2936
typedef enum {
3037
HYPERE_OK,
3138
HYPERE_KABOOM,
3239
} hyper_error;
3340

41+
typedef enum {
42+
HYPER_IT_CONTINUE,
43+
HYPER_IT_BREAK,
44+
} hyper_iter_step;
45+
3446
// HTTP ClientConn
3547

3648
// Starts an HTTP client connection handshake using the provided IO transport
@@ -67,8 +79,8 @@ hyper_io *hyper_io_new();
6779
// This value is passed as an argument to the read and write callbacks.
6880
void hyper_io_set_data(hyper_io *io, void *userdata);
6981

70-
#define HYPER_IO_PENDING -2
71-
#define HYPER_IO_ERROR -3
82+
#define HYPER_IO_PENDING 0xFFFFFFFF
83+
#define HYPER_IO_ERROR 0xFFFFFFFE
7284

7385
// Set the read function for this IO transport.
7486
//
@@ -115,13 +127,44 @@ hyper_error hyper_request_add_header(hyper_request *request, uint8_t *name, size
115127

116128
// HTTP Responses
117129

130+
// Free an HTTP response after using it.
118131
void hyper_response_free(hyper_response *response);
119132

120-
uint16_t hyper_response_get_status(hyper_response *response);
133+
// Get the HTTP-Status code of this response.
134+
//
135+
// It will always be within the range of 100-599.
136+
uint16_t hyper_response_status(hyper_response *response);
137+
138+
// Gets a reference to the HTTP headers of this response.
139+
//
140+
// This is not an owned reference, so it should not be accessed after the
141+
// `hyper_response` has been freed.
142+
hyper_headers *hyper_response_headers(hyper_response *response);
121143

122-
size_t hyper_response_headers_len(hyper_response *response);
144+
// HTTP Headers
123145

124-
TODO hyper_response_headers_get(hyper_response *response, uint8_t *name, size_t name_len);
146+
// Sets the header with the provided name to the provided value.
147+
//
148+
// This overwrites any previous value set for the header.
149+
void hyper_headers_set(hyper_headers *headers, hyper_str name, hyper_str value);
150+
151+
// Adds the provided value to the list of the provided name.
152+
//
153+
// If there were already existing values for the name, this will append the
154+
// new value to the internal list.
155+
void hyper_headers_add(hyper_headers *headers, hyper_str name, hyper_str value);
156+
157+
// Iterates the headers passing each name and value pair to the callback.
158+
//
159+
// The `userdata` pointer is also passed to the callback.
160+
//
161+
// The callback should return `HYPER_IT_CONTINUE` to keep iterating, or
162+
// `HYPER_IT_BREAK` to stop.
163+
void hyper_headers_iter(hyper_headers *headers,
164+
hyper_iter_step (*func)(void *userdata,
165+
hyper_str name,
166+
hyper_str value),
167+
void *userdata);
125168

126169
// Futures and Executors
127170

0 commit comments

Comments
 (0)