Reformat lines with clang-format-3.5

This commit is contained in:
Tatsuhiro Tsujikawa 2014-11-27 23:39:04 +09:00
parent 2c830a4698
commit b1f807abd1
156 changed files with 16591 additions and 20018 deletions

View File

@ -42,8 +42,7 @@
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char* argv[])
{
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 3) {
@ -59,19 +58,16 @@ int main(int argc, char* argv[])
server.num_threads(num_threads);
if(argc >= 5) {
if (argc >= 5) {
server.tls(argv[3], argv[4]);
}
server.listen
("*", port,
[](const std::shared_ptr<request>& req,
const std::shared_ptr<response>& res)
{
res->write_head(200, { header{ "foo", "bar" } });
res->end("hello, world");
});
} catch (std::exception& e) {
server.listen("*", port, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
res->write_head(200, {header{"foo", "bar"}});
res->end("hello, world");
});
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}

View File

@ -45,8 +45,7 @@
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char* argv[])
{
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 4) {
@ -63,47 +62,44 @@ int main(int argc, char* argv[])
server.num_threads(num_threads);
if(argc >= 6) {
if (argc >= 6) {
server.tls(argv[4], argv[5]);
}
server.listen
("*", port,
[&docroot](const std::shared_ptr<request>& req,
const std::shared_ptr<response>& res)
{
auto path = percent_decode(req->path());
if(!check_path(path)) {
res->write_head(404);
res->end();
return;
}
server.listen("*", port, [&docroot](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
auto path = percent_decode(req->path());
if (!check_path(path)) {
res->write_head(404);
res->end();
return;
}
if(path == "/") {
path = "/index.html";
}
if (path == "/") {
path = "/index.html";
}
path = docroot + path;
auto fd = open(path.c_str(), O_RDONLY);
if(fd == -1) {
res->write_head(404);
res->end();
return;
}
path = docroot + path;
auto fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
res->write_head(404);
res->end();
return;
}
auto headers = std::vector<header>();
auto headers = std::vector<header>();
struct stat stbuf;
if(stat(path.c_str(), &stbuf) == 0) {
headers.push_back
(header{"content-length", std::to_string(stbuf.st_size)});
headers.push_back
(header{"last-modified", http_date(stbuf.st_mtim.tv_sec)});
}
res->write_head(200, std::move(headers));
res->end(file_reader_from_fd(fd));
});
} catch (std::exception& e) {
struct stat stbuf;
if (stat(path.c_str(), &stbuf) == 0) {
headers.push_back(
header{"content-length", std::to_string(stbuf.st_size)});
headers.push_back(
header{"last-modified", http_date(stbuf.st_mtim.tv_sec)});
}
res->write_head(200, std::move(headers));
res->end(file_reader_from_fd(fd));
});
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}

View File

@ -43,8 +43,7 @@
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char* argv[])
{
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 4) {
@ -61,89 +60,81 @@ int main(int argc, char* argv[])
server.num_threads(num_threads);
if(argc >= 5) {
if (argc >= 5) {
server.tls(argv[4], argv[5]);
}
server.num_concurrent_tasks(num_concurrent_tasks);
server.listen
("*", port,
[](const std::shared_ptr<request>& req,
const std::shared_ptr<response>& res)
{
res->write_head(200);
server.listen("*", port, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
res->write_head(200);
auto msgq = std::make_shared<std::deque<std::string>>();
auto msgq = std::make_shared<std::deque<std::string>>();
res->end
([msgq](uint8_t *buf, std::size_t len) -> std::pair<ssize_t, bool>
{
if(msgq->empty()) {
// if msgq is empty, tells the library that don't call
// this callback until we call res->resume(). This is
// done by returing std::make_pair(0, false).
return std::make_pair(0, false);
}
auto msg = std::move(msgq->front());
msgq->pop_front();
res->end([msgq](uint8_t * buf, std::size_t len)
-> std::pair<ssize_t, bool> {
if (msgq->empty()) {
// if msgq is empty, tells the library that don't call
// this callback until we call res->resume(). This is
// done by returing std::make_pair(0, false).
return std::make_pair(0, false);
}
auto msg = std::move(msgq->front());
msgq->pop_front();
if(msg.empty()) {
// The empty message signals the end of response in
// this simple protocol.
return std::make_pair(0, true);
}
if (msg.empty()) {
// The empty message signals the end of response in
// this simple protocol.
return std::make_pair(0, true);
}
auto nwrite = std::min(len, msg.size());
std::copy(std::begin(msg), std::begin(msg) + nwrite, buf);
if(msg.size() > nwrite) {
msgq->push_front(msg.substr(nwrite));
}
return std::make_pair(nwrite, false);
});
auto nwrite = std::min(len, msg.size());
std::copy(std::begin(msg), std::begin(msg) + nwrite, buf);
if (msg.size() > nwrite) {
msgq->push_front(msg.substr(nwrite));
}
return std::make_pair(nwrite, false);
});
req->run_task
([res, msgq](channel& channel)
{
// executed in different thread from request callback
// was called.
req->run_task([res, msgq](channel &channel) {
// executed in different thread from request callback
// was called.
// Using res and msgq is not safe inside this callback.
// But using them in callback passed to channel::post is
// safe.
// Using res and msgq is not safe inside this callback.
// But using them in callback passed to channel::post is
// safe.
// We just emit simple message "message N\n" in every 1
// second and 3 times in total.
for(std::size_t i = 0; i < 3; ++i) {
msgq->push_back("message " + std::to_string(i + 1) + "\n");
// We just emit simple message "message N\n" in every 1
// second and 3 times in total.
for (std::size_t i = 0; i < 3; ++i) {
msgq->push_back("message " + std::to_string(i + 1) + "\n");
channel.post([res]()
{
// executed in same thread where
// request callback was called.
channel.post([res]() {
// executed in same thread where
// request callback was called.
// Tells library we have new message.
res->resume();
});
// Tells library we have new message.
res->resume();
});
sleep(1);
}
sleep(1);
}
// Send empty message to signal the end of response
// body.
msgq->push_back("");
// Send empty message to signal the end of response
// body.
msgq->push_back("");
channel.post([res]()
{
// executed in same thread where request
// callback was called.
res->resume();
});
channel.post([res]() {
// executed in same thread where request
// callback was called.
res->resume();
});
});
});
});
} catch (std::exception& e) {
});
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}

View File

@ -50,19 +50,19 @@
#include <openssl/err.h>
#include <openssl/conf.h>
enum {
IO_NONE,
WANT_READ,
WANT_WRITE
};
enum { IO_NONE, WANT_READ, WANT_WRITE };
#define MAKE_NV(NAME, VALUE) \
{(uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE}
#define MAKE_NV(NAME, VALUE) \
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
#define MAKE_NV_CS(NAME, VALUE) \
{(uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
NGHTTP2_NV_FLAG_NONE}
#define MAKE_NV_CS(NAME, VALUE) \
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
NGHTTP2_NV_FLAG_NONE \
}
struct Connection {
SSL *ssl;
@ -103,10 +103,9 @@ struct URI {
* Returns copy of string |s| with the length |len|. The returned
* string is NULL-terminated.
*/
static char* strcopy(const char *s, size_t len)
{
static char *strcopy(const char *s, size_t len) {
char *dst;
dst = malloc(len+1);
dst = malloc(len + 1);
memcpy(dst, s, len);
dst[len] = '\0';
return dst;
@ -115,8 +114,7 @@ static char* strcopy(const char *s, size_t len)
/*
* Prints error message |msg| and exit.
*/
static void die(const char *msg)
{
static void die(const char *msg) {
fprintf(stderr, "FATAL: %s\n", msg);
exit(EXIT_FAILURE);
}
@ -125,8 +123,7 @@ static void die(const char *msg)
* Prints error containing the function name |func| and message |msg|
* and exit.
*/
static void dief(const char *func, const char *msg)
{
static void dief(const char *func, const char *msg) {
fprintf(stderr, "FATAL: %s: %s\n", func, msg);
exit(EXIT_FAILURE);
}
@ -135,8 +132,7 @@ static void dief(const char *func, const char *msg)
* Prints error containing the function name |func| and error code
* |error_code| and exit.
*/
static void diec(const char *func, int error_code)
{
static void diec(const char *func, int error_code) {
fprintf(stderr, "FATAL: %s: error_code=%d, msg=%s\n", func, error_code,
nghttp2_strerror(error_code));
exit(EXIT_FAILURE);
@ -148,21 +144,19 @@ static void diec(const char *func, int error_code)
* bytes actually written. See the documentation of
* nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *session _U_,
const uint8_t *data, size_t length, int flags _U_,
void *user_data)
{
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
struct Connection *connection;
int rv;
connection = (struct Connection*)user_data;
connection = (struct Connection *)user_data;
connection->want_io = IO_NONE;
ERR_clear_error();
rv = SSL_write(connection->ssl, data, (int)length);
if(rv < 0) {
if (rv < 0) {
int err = SSL_get_error(connection->ssl, rv);
if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io = (err == SSL_ERROR_WANT_READ ?
WANT_READ : WANT_WRITE);
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io =
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
rv = NGHTTP2_ERR_WOULDBLOCK;
} else {
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
@ -177,41 +171,39 @@ static ssize_t send_callback(nghttp2_session *session _U_,
* |length| bytes. Returns the number of bytes stored in |buf|. See
* the documentation of nghttp2_recv_callback for the details.
*/
static ssize_t recv_callback(nghttp2_session *session _U_,
uint8_t *buf, size_t length, int flags _U_,
void *user_data)
{
static ssize_t recv_callback(nghttp2_session *session _U_, uint8_t *buf,
size_t length, int flags _U_, void *user_data) {
struct Connection *connection;
int rv;
connection = (struct Connection*)user_data;
connection = (struct Connection *)user_data;
connection->want_io = IO_NONE;
ERR_clear_error();
rv = SSL_read(connection->ssl, buf, (int)length);
if(rv < 0) {
if (rv < 0) {
int err = SSL_get_error(connection->ssl, rv);
if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io = (err == SSL_ERROR_WANT_READ ?
WANT_READ : WANT_WRITE);
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io =
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
rv = NGHTTP2_ERR_WOULDBLOCK;
} else {
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
}
} else if(rv == 0) {
} else if (rv == 0) {
rv = NGHTTP2_ERR_EOF;
}
return rv;
}
static int on_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data _U_)
{
const nghttp2_frame *frame,
void *user_data _U_) {
size_t i;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)) {
if (nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)) {
const nghttp2_nv *nva = frame->headers.nva;
printf("[INFO] C ----------------------------> S (HEADERS)\n");
for(i = 0; i < frame->headers.nvlen; ++i) {
for (i = 0; i < frame->headers.nvlen; ++i) {
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": ");
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
@ -230,18 +222,18 @@ static int on_frame_send_callback(nghttp2_session *session,
}
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data _U_)
{
const nghttp2_frame *frame,
void *user_data _U_) {
size_t i;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
const nghttp2_nv *nva = frame->headers.nva;
struct Request *req;
req = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(req) {
if (req) {
printf("[INFO] C <---------------------------- S (HEADERS)\n");
for(i = 0; i < frame->headers.nvlen; ++i) {
for (i = 0; i < frame->headers.nvlen; ++i) {
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": ");
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
@ -266,18 +258,16 @@ static int on_frame_recv_callback(nghttp2_session *session,
* fetch 1 resource in this program, after reception of the response,
* we submit GOAWAY and close the session.
*/
static int on_stream_close_callback(nghttp2_session *session,
int32_t stream_id,
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code _U_,
void *user_data _U_)
{
void *user_data _U_) {
struct Request *req;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if(req) {
if (req) {
int rv;
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
if(rv != 0) {
if (rv != 0) {
diec("nghttp2_session_terminate_session", rv);
}
}
@ -290,16 +280,16 @@ static int on_stream_close_callback(nghttp2_session *session,
* The implementation of nghttp2_on_data_chunk_recv_callback type. We
* use this function to print the received response body.
*/
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags _U_,
int32_t stream_id,
static int on_data_chunk_recv_callback(nghttp2_session *session,
uint8_t flags _U_, int32_t stream_id,
const uint8_t *data, size_t len,
void *user_data _U_)
{
void *user_data _U_) {
struct Request *req;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if(req) {
if (req) {
printf("[INFO] C <---------------------------- S (DATA chunk)\n"
"%lu bytes\n", (unsigned long int)len);
"%lu bytes\n",
(unsigned long int)len);
fwrite(data, 1, len, stdout);
printf("\n");
}
@ -312,23 +302,22 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags _
* always required. Since we use nghttp2_session_recv(), the
* recv_callback is also required.
*/
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
{
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
nghttp2_session_callbacks_set_on_frame_send_callback
(callbacks, on_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
on_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
}
/*
@ -336,16 +325,14 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
* library supports, we terminate program.
*/
static int select_next_proto_cb(SSL* ssl _U_,
unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *arg _U_)
{
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
int rv;
/* nghttp2_select_next_protocol() selects HTTP/2 protocol the
nghttp2 library supports. */
rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
if(rv <= 0) {
if (rv <= 0) {
die("Server did not advertise HTTP/2 protocol");
}
return SSL_TLSEXT_ERR_OK;
@ -354,25 +341,23 @@ static int select_next_proto_cb(SSL* ssl _U_,
/*
* Setup SSL/TLS context.
*/
static void init_ssl_ctx(SSL_CTX *ssl_ctx)
{
static void init_ssl_ctx(SSL_CTX *ssl_ctx) {
/* Disable SSLv2 and enable all workarounds for buggy servers */
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
/* Set NPN callback */
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
}
static void ssl_handshake(SSL *ssl, int fd)
{
static void ssl_handshake(SSL *ssl, int fd) {
int rv;
if(SSL_set_fd(ssl, fd) == 0) {
if (SSL_set_fd(ssl, fd) == 0) {
dief("SSL_set_fd", ERR_error_string(ERR_get_error(), NULL));
}
ERR_clear_error();
rv = SSL_connect(ssl);
if(rv <= 0) {
if (rv <= 0) {
dief("SSL_connect", ERR_error_string(ERR_get_error(), NULL));
}
}
@ -381,8 +366,7 @@ static void ssl_handshake(SSL *ssl, int fd)
* Connects to the host |host| and port |port|. This function returns
* the file descriptor of the client socket.
*/
static int connect_to(const char *host, uint16_t port)
{
static int connect_to(const char *host, uint16_t port) {
struct addrinfo hints;
int fd = -1;
int rv;
@ -393,17 +377,18 @@ static int connect_to(const char *host, uint16_t port)
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
rv = getaddrinfo(host, service, &hints, &res);
if(rv != 0) {
if (rv != 0) {
dief("getaddrinfo", gai_strerror(rv));
}
for(rp = res; rp; rp = rp->ai_next) {
for (rp = res; rp; rp = rp->ai_next) {
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(fd == -1) {
if (fd == -1) {
continue;
}
while((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 &&
errno == EINTR);
if(rv == 0) {
while ((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 &&
errno == EINTR)
;
if (rv == 0) {
break;
}
close(fd);
@ -413,25 +398,25 @@ static int connect_to(const char *host, uint16_t port)
return fd;
}
static void make_non_block(int fd)
{
static void make_non_block(int fd) {
int flags, rv;
while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR);
if(flags == -1) {
while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
;
if (flags == -1) {
dief("fcntl", strerror(errno));
}
while((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR);
if(rv == -1) {
while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
;
if (rv == -1) {
dief("fcntl", strerror(errno));
}
}
static void set_tcp_nodelay(int fd)
{
static void set_tcp_nodelay(int fd) {
int val = 1;
int rv;
rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
if(rv == -1) {
if (rv == -1) {
dief("setsockopt", strerror(errno));
}
}
@ -439,15 +424,14 @@ static void set_tcp_nodelay(int fd)
/*
* Update |pollfd| based on the state of |connection|.
*/
static void ctl_poll(struct pollfd *pollfd, struct Connection *connection)
{
static void ctl_poll(struct pollfd *pollfd, struct Connection *connection) {
pollfd->events = 0;
if(nghttp2_session_want_read(connection->session) ||
connection->want_io == WANT_READ) {
if (nghttp2_session_want_read(connection->session) ||
connection->want_io == WANT_READ) {
pollfd->events |= POLLIN;
}
if(nghttp2_session_want_write(connection->session) ||
connection->want_io == WANT_WRITE) {
if (nghttp2_session_want_write(connection->session) ||
connection->want_io == WANT_WRITE) {
pollfd->events |= POLLOUT;
}
}
@ -457,24 +441,20 @@ static void ctl_poll(struct pollfd *pollfd, struct Connection *connection)
* function does not send packets; just append the request to the
* internal queue in |connection->session|.
*/
static void submit_request(struct Connection *connection, struct Request *req)
{
static void submit_request(struct Connection *connection, struct Request *req) {
int32_t stream_id;
const nghttp2_nv nva[] = {
/* Make sure that the last item is NULL */
MAKE_NV(":method", "GET"),
MAKE_NV_CS(":path", req->path),
MAKE_NV(":scheme", "https"),
MAKE_NV_CS(":authority", req->hostport),
MAKE_NV("accept", "*/*"),
MAKE_NV("user-agent", "nghttp2/"NGHTTP2_VERSION)
};
/* Make sure that the last item is NULL */
const nghttp2_nv nva[] = {MAKE_NV(":method", "GET"),
MAKE_NV_CS(":path", req->path),
MAKE_NV(":scheme", "https"),
MAKE_NV_CS(":authority", req->hostport),
MAKE_NV("accept", "*/*"),
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
stream_id = nghttp2_submit_request(connection->session, NULL,
nva, sizeof(nva)/sizeof(nva[0]),
NULL, req);
stream_id = nghttp2_submit_request(connection->session, NULL, nva,
sizeof(nva) / sizeof(nva[0]), NULL, req);
if(stream_id < 0) {
if (stream_id < 0) {
diec("nghttp2_submit_request", stream_id);
}
@ -485,21 +465,19 @@ static void submit_request(struct Connection *connection, struct Request *req)
/*
* Performs the network I/O.
*/
static void exec_io(struct Connection *connection)
{
static void exec_io(struct Connection *connection) {
int rv;
rv = nghttp2_session_recv(connection->session);
if(rv != 0) {
if (rv != 0) {
diec("nghttp2_session_recv", rv);
}
rv = nghttp2_session_send(connection->session);
if(rv != 0) {
if (rv != 0) {
diec("nghttp2_session_send", rv);
}
}
static void request_init(struct Request *req, const struct URI *uri)
{
static void request_init(struct Request *req, const struct URI *uri) {
req->host = strcopy(uri->host, uri->hostlen);
req->port = uri->port;
req->path = strcopy(uri->path, uri->pathlen);
@ -507,8 +485,7 @@ static void request_init(struct Request *req, const struct URI *uri)
req->stream_id = -1;
}
static void request_free(struct Request *req)
{
static void request_free(struct Request *req) {
free(req->host);
free(req->path);
free(req->hostport);
@ -517,8 +494,7 @@ static void request_free(struct Request *req)
/*
* Fetches the resource denoted by |uri|.
*/
static void fetch_uri(const struct URI *uri)
{
static void fetch_uri(const struct URI *uri) {
nghttp2_session_callbacks *callbacks;
int fd;
SSL_CTX *ssl_ctx;
@ -533,16 +509,16 @@ static void fetch_uri(const struct URI *uri)
/* Establish connection and setup SSL */
fd = connect_to(req.host, req.port);
if(fd == -1) {
if (fd == -1) {
die("Could not open file descriptor");
}
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if(ssl_ctx == NULL) {
if (ssl_ctx == NULL) {
dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL));
}
init_ssl_ctx(ssl_ctx);
ssl = SSL_new(ssl_ctx);
if(ssl == NULL) {
if (ssl == NULL) {
dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
}
/* To simplify the program, we perform SSL/TLS handshake in blocking
@ -564,18 +540,17 @@ static void fetch_uri(const struct URI *uri)
rv = nghttp2_session_callbacks_new(&callbacks);
if(rv != 0) {
if (rv != 0) {
diec("nghttp2_session_callbacks_new", rv);
}
setup_nghttp2_callbacks(callbacks);
rv = nghttp2_session_client_new(&connection.session, callbacks,
&connection);
rv = nghttp2_session_client_new(&connection.session, callbacks, &connection);
nghttp2_session_callbacks_del(callbacks);
if(rv != 0) {
if (rv != 0) {
diec("nghttp2_session_client_new", rv);
}
@ -586,16 +561,16 @@ static void fetch_uri(const struct URI *uri)
ctl_poll(pollfds, &connection);
/* Event loop */
while(nghttp2_session_want_read(connection.session) ||
nghttp2_session_want_write(connection.session)) {
while (nghttp2_session_want_read(connection.session) ||
nghttp2_session_want_write(connection.session)) {
int nfds = poll(pollfds, npollfds, -1);
if(nfds == -1) {
if (nfds == -1) {
dief("poll", strerror(errno));
}
if(pollfds[0].revents & (POLLIN | POLLOUT)) {
if (pollfds[0].revents & (POLLIN | POLLOUT)) {
exec_io(&connection);
}
if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
if ((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
die("Connection error");
}
ctl_poll(pollfds, &connection);
@ -611,96 +586,94 @@ static void fetch_uri(const struct URI *uri)
request_free(&req);
}
static int parse_uri(struct URI *res, const char *uri)
{
static int parse_uri(struct URI *res, const char *uri) {
/* We only interested in https */
size_t len, i, offset;
int ipv6addr = 0;
memset(res, 0, sizeof(struct URI));
len = strlen(uri);
if(len < 9 || memcmp("https://", uri, 8) != 0) {
if (len < 9 || memcmp("https://", uri, 8) != 0) {
return -1;
}
offset = 8;
res->host = res->hostport = &uri[offset];
res->hostlen = 0;
if(uri[offset] == '[') {
if (uri[offset] == '[') {
/* IPv6 literal address */
++offset;
++res->host;
ipv6addr = 1;
for(i = offset; i < len; ++i) {
if(uri[i] == ']') {
res->hostlen = i-offset;
offset = i+1;
for (i = offset; i < len; ++i) {
if (uri[i] == ']') {
res->hostlen = i - offset;
offset = i + 1;
break;
}
}
} else {
const char delims[] = ":/?#";
for(i = offset; i < len; ++i) {
if(strchr(delims, uri[i]) != NULL) {
for (i = offset; i < len; ++i) {
if (strchr(delims, uri[i]) != NULL) {
break;
}
}
res->hostlen = i-offset;
res->hostlen = i - offset;
offset = i;
}
if(res->hostlen == 0) {
if (res->hostlen == 0) {
return -1;
}
/* Assuming https */
res->port = 443;
if(offset < len) {
if(uri[offset] == ':') {
if (offset < len) {
if (uri[offset] == ':') {
/* port */
const char delims[] = "/?#";
int port = 0;
++offset;
for(i = offset; i < len; ++i) {
if(strchr(delims, uri[i]) != NULL) {
for (i = offset; i < len; ++i) {
if (strchr(delims, uri[i]) != NULL) {
break;
}
if('0' <= uri[i] && uri[i] <= '9') {
if ('0' <= uri[i] && uri[i] <= '9') {
port *= 10;
port += uri[i]-'0';
if(port > 65535) {
port += uri[i] - '0';
if (port > 65535) {
return -1;
}
} else {
return -1;
}
}
if(port == 0) {
if (port == 0) {
return -1;
}
offset = i;
res->port = port;
}
}
res->hostportlen = uri+offset+ipv6addr-res->host;
for(i = offset; i < len; ++i) {
if(uri[i] == '#') {
res->hostportlen = uri + offset + ipv6addr - res->host;
for (i = offset; i < len; ++i) {
if (uri[i] == '#') {
break;
}
}
if(i-offset == 0) {
if (i - offset == 0) {
res->path = "/";
res->pathlen = 1;
} else {
res->path = &uri[offset];
res->pathlen = i-offset;
res->pathlen = i - offset;
}
return 0;
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
struct URI uri;
struct sigaction act;
int rv;
if(argc < 2) {
if (argc < 2) {
die("Specify a https URI");
}
@ -714,7 +687,7 @@ int main(int argc, char **argv)
SSL_library_init();
rv = parse_uri(&uri, argv[1]);
if(rv != 0) {
if (rv != 0) {
die("parse_uri failed");
}
fetch_uri(&uri);

View File

@ -31,43 +31,39 @@
#include <nghttp2/nghttp2.h>
#define MAKE_NV(K, V) \
{ (uint8_t*)K, (uint8_t*)V, sizeof(K) - 1, sizeof(V) - 1, \
NGHTTP2_NV_FLAG_NONE }
#define MAKE_NV(K, V) \
{ \
(uint8_t *) K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
static void deflate(nghttp2_hd_deflater *deflater,
nghttp2_hd_inflater *inflater,
const nghttp2_nv * const nva, size_t nvlen);
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
size_t nvlen);
static int inflate_header_block(nghttp2_hd_inflater *inflater,
uint8_t *in, size_t inlen, int final);
static int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
size_t inlen, int final);
int main(int argc _U_, char **argv _U_)
{
int main(int argc _U_, char **argv _U_) {
int rv;
nghttp2_hd_deflater *deflater;
nghttp2_hd_inflater *inflater;
/* Define 1st header set. This is looks like a HTTP request. */
nghttp2_nv nva1[] = {
MAKE_NV(":scheme", "https"),
MAKE_NV(":authority", "example.org"),
MAKE_NV(":path", "/"),
MAKE_NV("user-agent", "libnghttp2"),
MAKE_NV("accept-encoding", "gzip, deflate")
};
MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
MAKE_NV(":path", "/"), MAKE_NV("user-agent", "libnghttp2"),
MAKE_NV("accept-encoding", "gzip, deflate")};
/* Define 2nd header set */
nghttp2_nv nva2[] = {
MAKE_NV(":scheme", "https"),
MAKE_NV(":authority", "example.org"),
MAKE_NV(":path", "/stylesheet/style.css"),
MAKE_NV("user-agent", "libnghttp2"),
MAKE_NV("accept-encoding", "gzip, deflate"),
MAKE_NV("referer", "https://example.org")
};
nghttp2_nv nva2[] = {MAKE_NV(":scheme", "https"),
MAKE_NV(":authority", "example.org"),
MAKE_NV(":path", "/stylesheet/style.css"),
MAKE_NV("user-agent", "libnghttp2"),
MAKE_NV("accept-encoding", "gzip, deflate"),
MAKE_NV("referer", "https://example.org")};
rv = nghttp2_hd_deflate_new(&deflater, 4096);
if(rv != 0) {
if (rv != 0) {
fprintf(stderr, "nghttp2_hd_deflate_init failed with error: %s\n",
nghttp2_strerror(rv));
exit(EXIT_FAILURE);
@ -75,7 +71,7 @@ int main(int argc _U_, char **argv _U_)
rv = nghttp2_hd_inflate_new(&inflater);
if(rv != 0) {
if (rv != 0) {
fprintf(stderr, "nghttp2_hd_inflate_init failed with error: %s\n",
nghttp2_strerror(rv));
exit(EXIT_FAILURE);
@ -95,9 +91,8 @@ int main(int argc _U_, char **argv _U_)
}
static void deflate(nghttp2_hd_deflater *deflater,
nghttp2_hd_inflater *inflater,
const nghttp2_nv * const nva, size_t nvlen)
{
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
size_t nvlen) {
ssize_t rv;
uint8_t *buf;
size_t buflen;
@ -107,13 +102,13 @@ static void deflate(nghttp2_hd_deflater *deflater,
sum = 0;
for(i = 0; i < nvlen; ++i) {
for (i = 0; i < nvlen; ++i) {
sum += nva[i].namelen + nva[i].valuelen;
}
printf("Input (%zu byte(s)):\n\n", sum);
for(i = 0; i < nvlen; ++i) {
for (i = 0; i < nvlen; ++i) {
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": ");
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
@ -125,7 +120,7 @@ static void deflate(nghttp2_hd_deflater *deflater,
rv = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, nvlen);
if(rv < 0) {
if (rv < 0) {
fprintf(stderr, "nghttp2_hd_deflate_hd() failed with error: %s\n",
nghttp2_strerror((int)rv));
@ -136,17 +131,17 @@ static void deflate(nghttp2_hd_deflater *deflater,
outlen = rv;
printf("\nDeflate (%zu byte(s), ratio %.02f):\n\n",
outlen, sum == 0 ? 0 : (double)outlen / sum);
printf("\nDeflate (%zu byte(s), ratio %.02f):\n\n", outlen,
sum == 0 ? 0 : (double)outlen / sum);
for(i = 0; i < outlen; ++i) {
if((i & 0x0fu) == 0) {
for (i = 0; i < outlen; ++i) {
if ((i & 0x0fu) == 0) {
printf("%08zX: ", i);
}
printf("%02X ", buf[i]);
if(((i + 1) & 0x0fu) == 0) {
if (((i + 1) & 0x0fu) == 0) {
printf("\n");
}
}
@ -157,7 +152,7 @@ static void deflate(nghttp2_hd_deflater *deflater,
header data. */
rv = inflate_header_block(inflater, buf, outlen, 1);
if(rv != 0) {
if (rv != 0) {
free(buf);
exit(EXIT_FAILURE);
@ -169,20 +164,18 @@ static void deflate(nghttp2_hd_deflater *deflater,
free(buf);
}
int inflate_header_block(nghttp2_hd_inflater *inflater,
uint8_t *in, size_t inlen, int final)
{
int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
size_t inlen, int final) {
ssize_t rv;
for(;;) {
for (;;) {
nghttp2_nv nv;
int inflate_flags = 0;
size_t proclen;
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags,
in, inlen, final);
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, in, inlen, final);
if(rv < 0) {
if (rv < 0) {
fprintf(stderr, "inflate failed with error code %zd", rv);
return -1;
}
@ -192,20 +185,19 @@ int inflate_header_block(nghttp2_hd_inflater *inflater,
in += proclen;
inlen -= proclen;
if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
fwrite(nv.name, nv.namelen, 1, stderr);
fprintf(stderr, ": ");
fwrite(nv.value, nv.valuelen, 1, stderr);
fprintf(stderr, "\n");
}
if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
nghttp2_hd_inflate_end_headers(inflater);
break;
}
if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
inlen == 0) {
if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) {
break;
}
}

View File

@ -47,7 +47,7 @@
#include "http-parser/http_parser.h"
#define ARRLEN(x) (sizeof(x)/sizeof(x[0]))
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
typedef struct {
/* The NULL-terminated URI string to retreive. */
@ -74,9 +74,8 @@ typedef struct {
http2_stream_data *stream_data;
} http2_session_data;
static http2_stream_data* create_http2_stream_data(const char *uri,
struct http_parser_url *u)
{
static http2_stream_data *create_http2_stream_data(const char *uri,
struct http_parser_url *u) {
/* MAX 5 digits (max 65535) + 1 ':' + 1 NULL (because of snprintf) */
size_t extra = 7;
http2_stream_data *stream_data = malloc(sizeof(http2_stream_data));
@ -87,29 +86,29 @@ static http2_stream_data* create_http2_stream_data(const char *uri,
stream_data->authoritylen = u->field_data[UF_HOST].len;
stream_data->authority = malloc(stream_data->authoritylen + extra);
memcpy(stream_data->authority,
&uri[u->field_data[UF_HOST].off], u->field_data[UF_HOST].len);
if(u->field_set & (1 << UF_PORT)) {
memcpy(stream_data->authority, &uri[u->field_data[UF_HOST].off],
u->field_data[UF_HOST].len);
if (u->field_set & (1 << UF_PORT)) {
stream_data->authoritylen +=
snprintf(stream_data->authority + u->field_data[UF_HOST].len, extra,
":%u", u->port);
snprintf(stream_data->authority + u->field_data[UF_HOST].len, extra,
":%u", u->port);
}
stream_data->pathlen = 0;
if(u->field_set & (1 << UF_PATH)) {
if (u->field_set & (1 << UF_PATH)) {
stream_data->pathlen = u->field_data[UF_PATH].len;
}
if(u->field_set & (1 << UF_QUERY)) {
if (u->field_set & (1 << UF_QUERY)) {
/* +1 for '?' character */
stream_data->pathlen += u->field_data[UF_QUERY].len + 1;
}
if(stream_data->pathlen > 0) {
if (stream_data->pathlen > 0) {
stream_data->path = malloc(stream_data->pathlen);
if(u->field_set & (1 << UF_PATH)) {
memcpy(stream_data->path,
&uri[u->field_data[UF_PATH].off], u->field_data[UF_PATH].len);
if (u->field_set & (1 << UF_PATH)) {
memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off],
u->field_data[UF_PATH].len);
}
if(u->field_set & (1 << UF_QUERY)) {
if (u->field_set & (1 << UF_QUERY)) {
memcpy(stream_data->path + u->field_data[UF_PATH].len + 1,
&uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
}
@ -119,16 +118,15 @@ static http2_stream_data* create_http2_stream_data(const char *uri,
return stream_data;
}
static void delete_http2_stream_data(http2_stream_data *stream_data)
{
static void delete_http2_stream_data(http2_stream_data *stream_data) {
free(stream_data->path);
free(stream_data->authority);
free(stream_data);
}
/* Initializes |session_data| */
static http2_session_data *create_http2_session_data(struct event_base *evbase)
{
static http2_session_data *
create_http2_session_data(struct event_base *evbase) {
http2_session_data *session_data = malloc(sizeof(http2_session_data));
memset(session_data, 0, sizeof(http2_session_data));
@ -136,11 +134,10 @@ static http2_session_data *create_http2_session_data(struct event_base *evbase)
return session_data;
}
static void delete_http2_session_data(http2_session_data *session_data)
{
static void delete_http2_session_data(http2_session_data *session_data) {
SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev);
if(ssl) {
if (ssl) {
SSL_shutdown(ssl);
}
bufferevent_free(session_data->bev);
@ -149,17 +146,15 @@ static void delete_http2_session_data(http2_session_data *session_data)
session_data->dnsbase = NULL;
nghttp2_session_del(session_data->session);
session_data->session = NULL;
if(session_data->stream_data) {
if (session_data->stream_data) {
delete_http2_stream_data(session_data->stream_data);
session_data->stream_data = NULL;
}
free(session_data);
}
static void print_header(FILE *f,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen)
{
static void print_header(FILE *f, const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen) {
fwrite(name, namelen, 1, f);
fprintf(f, ": ");
fwrite(value, valuelen, 1, f);
@ -169,13 +164,10 @@ static void print_header(FILE *f,
/* Print HTTP headers to |f|. Please note that this function does not
take into account that header name and value are sequence of
octets, therefore they may contain non-printable characters. */
static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen)
{
static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen) {
size_t i;
for(i = 0; i < nvlen; ++i) {
print_header(f,
nva[i].name, nva[i].namelen,
nva[i].value, nva[i].valuelen);
for (i = 0; i < nvlen; ++i) {
print_header(f, nva[i].name, nva[i].namelen, nva[i].value, nva[i].valuelen);
}
fprintf(f, "\n");
}
@ -183,11 +175,9 @@ static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen)
/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,
to the network. Because we are using libevent bufferevent, we just
write those bytes into bufferevent buffer. */
static ssize_t send_callback(nghttp2_session *session _U_,
const uint8_t *data, size_t length,
int flags _U_, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
bufferevent_write(bev, data, length);
return length;
@ -196,17 +186,15 @@ static ssize_t send_callback(nghttp2_session *session _U_,
/* nghttp2_on_header_callback: Called when nghttp2 library emits
single header name/value pair. */
static int on_header_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
uint8_t flags _U_,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
/* Print response headers for the initiated request. */
print_header(stderr, name, namelen, value, valuelen);
break;
@ -219,13 +207,12 @@ static int on_header_callback(nghttp2_session *session _U_,
started to receive header block. */
static int on_begin_headers_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
fprintf(stderr, "Response headers for stream ID=%d:\n",
frame->hd.stream_id);
}
@ -237,13 +224,12 @@ static int on_begin_headers_callback(nghttp2_session *session _U_,
/* nghttp2_on_frame_recv_callback: Called when nghttp2 library
received a complete frame from the remote peer. */
static int on_frame_recv_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
const nghttp2_frame *frame, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
fprintf(stderr, "All headers received\n");
}
break;
@ -256,13 +242,12 @@ static int on_frame_recv_callback(nghttp2_session *session _U_,
is meant to the stream we initiated, print the received data in
stdout, so that the user can redirect its output to the file
easily. */
static int on_data_chunk_recv_callback(nghttp2_session *session _U_, uint8_t flags _U_,
int32_t stream_id,
static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
uint8_t flags _U_, int32_t stream_id,
const uint8_t *data, size_t len,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
if(session_data->stream_data->stream_id == stream_id) {
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
if (session_data->stream_data->stream_id == stream_id) {
fwrite(data, len, 1, stdout);
}
return 0;
@ -272,19 +257,17 @@ static int on_data_chunk_recv_callback(nghttp2_session *session _U_, uint8_t fla
closed. This example program only deals with 1 HTTP request (1
stream), if it is closed, we send GOAWAY and tear down the
session */
static int on_stream_close_callback(nghttp2_session *session,
int32_t stream_id,
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
nghttp2_error_code error_code,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
int rv;
if(session_data->stream_data->stream_id == stream_id) {
fprintf(stderr, "Stream %d closed with error_code=%d\n",
stream_id, error_code);
if (session_data->stream_data->stream_id == stream_id) {
fprintf(stderr, "Stream %d closed with error_code=%d\n", stream_id,
error_code);
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
if(rv != 0) {
if (rv != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
@ -294,117 +277,111 @@ static int on_stream_close_callback(nghttp2_session *session,
/* NPN TLS extension client callback. We check that server advertised
the HTTP/2 protocol the nghttp2 library supports. If not, exit
the program. */
static int select_next_proto_cb(SSL* ssl _U_,
unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *arg _U_)
{
if(nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
}
return SSL_TLSEXT_ERR_OK;
}
/* Create SSL_CTX. */
static SSL_CTX* create_ssl_ctx(void)
{
static SSL_CTX *create_ssl_ctx(void) {
SSL_CTX *ssl_ctx;
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if(!ssl_ctx) {
if (!ssl_ctx) {
errx(1, "Could not create SSL/TLS context: %s",
ERR_error_string(ERR_get_error(), NULL));
}
SSL_CTX_set_options(ssl_ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
return ssl_ctx;
}
/* Create SSL object */
static SSL* create_ssl(SSL_CTX *ssl_ctx)
{
static SSL *create_ssl(SSL_CTX *ssl_ctx) {
SSL *ssl;
ssl = SSL_new(ssl_ctx);
if(!ssl) {
if (!ssl) {
errx(1, "Could not create SSL/TLS session object: %s",
ERR_error_string(ERR_get_error(), NULL));
}
return ssl;
}
static void initialize_nghttp2_session(http2_session_data *session_data)
{
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_session_callbacks *callbacks;
nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_client_new(&session_data->session, callbacks, session_data);
nghttp2_session_callbacks_del(callbacks);
}
static void send_client_connection_header(http2_session_data *session_data)
{
static void send_client_connection_header(http2_session_data *session_data) {
nghttp2_settings_entry iv[1] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
};
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
bufferevent_write(session_data->bev,
NGHTTP2_CLIENT_CONNECTION_PREFACE,
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
iv, ARRLEN(iv));
if(rv != 0) {
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
errx(1, "Could not submit SETTINGS: %s", nghttp2_strerror(rv));
}
}
#define MAKE_NV(NAME, VALUE, VALUELEN) \
{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, VALUELEN, \
NGHTTP2_NV_FLAG_NONE }
#define MAKE_NV(NAME, VALUE, VALUELEN) \
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
NGHTTP2_NV_FLAG_NONE \
}
#define MAKE_NV2(NAME, VALUE) \
{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE }
#define MAKE_NV2(NAME, VALUE) \
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
/* Send HTTP request to the remote peer */
static void submit_request(http2_session_data *session_data)
{
static void submit_request(http2_session_data *session_data) {
int32_t stream_id;
http2_stream_data *stream_data = session_data->stream_data;
const char *uri = stream_data->uri;
const struct http_parser_url *u = stream_data->u;
nghttp2_nv hdrs[] = {
MAKE_NV2(":method", "GET"),
MAKE_NV(":scheme",
&uri[u->field_data[UF_SCHEMA].off], u->field_data[UF_SCHEMA].len),
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
MAKE_NV(":path", stream_data->path, stream_data->pathlen)
};
MAKE_NV2(":method", "GET"),
MAKE_NV(":scheme", &uri[u->field_data[UF_SCHEMA].off],
u->field_data[UF_SCHEMA].len),
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
fprintf(stderr, "Request headers:\n");
print_headers(stderr, hdrs, ARRLEN(hdrs));
stream_id = nghttp2_submit_request(session_data->session, NULL,
hdrs, ARRLEN(hdrs), NULL, stream_data);
if(stream_id < 0) {
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
ARRLEN(hdrs), NULL, stream_data);
if (stream_id < 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
}
@ -413,12 +390,11 @@ static void submit_request(http2_session_data *session_data)
/* Serialize the frame and send (or buffer) the data to
bufferevent. */
static int session_send(http2_session_data *session_data)
{
static int session_send(http2_session_data *session_data) {
int rv;
rv = nghttp2_session_send(session_data->session);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@ -429,26 +405,25 @@ static int session_send(http2_session_data *session_data)
of bufferevent and feed them to nghttp2 library. This may invoke
nghttp2 callbacks. It may also queues the frame in nghttp2 session
context. To send them, we call session_send() in the end. */
static void readcb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
static void readcb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
ssize_t readlen;
struct evbuffer *input = bufferevent_get_input(bev);
size_t datalen = evbuffer_get_length(input);
unsigned char *data = evbuffer_pullup(input, -1);
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
if(readlen < 0) {
if (readlen < 0) {
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
delete_http2_session_data(session_data);
return;
}
if(evbuffer_drain(input, readlen) != 0) {
if (evbuffer_drain(input, readlen) != 0) {
warnx("Fatal error: evbuffer_drain failed");
delete_http2_session_data(session_data);
return;
}
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
@ -458,12 +433,11 @@ static void readcb(struct bufferevent *bev, void *ptr)
receiving GOAWAY, we check the some conditions on the nghttp2
library and output buffer of bufferevent. If it indicates we have
no business to this session, tear down the connection. */
static void writecb(struct bufferevent *bev _U_, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0 &&
evbuffer_get_length(bufferevent_get_output(session_data->bev)) == 0) {
static void writecb(struct bufferevent *bev _U_, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0 &&
evbuffer_get_length(bufferevent_get_output(session_data->bev)) == 0) {
delete_http2_session_data(session_data);
}
}
@ -473,10 +447,9 @@ static void writecb(struct bufferevent *bev _U_, void *ptr)
peer verification. After SSL/TLS handshake is over, initialize
nghttp2 library session, and send client connection header. Then
send HTTP request. */
static void eventcb(struct bufferevent *bev, short events, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(events & BEV_EVENT_CONNECTED) {
static void eventcb(struct bufferevent *bev, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) {
int fd = bufferevent_getfd(bev);
int val = 1;
fprintf(stderr, "Connected\n");
@ -484,41 +457,38 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr)
initialize_nghttp2_session(session_data);
send_client_connection_header(session_data);
submit_request(session_data);
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
}
return;
}
if(events & BEV_EVENT_EOF) {
if (events & BEV_EVENT_EOF) {
warnx("Disconnected from the remote host");
} else if(events & BEV_EVENT_ERROR) {
} else if (events & BEV_EVENT_ERROR) {
warnx("Network error");
} else if(events & BEV_EVENT_TIMEOUT) {
} else if (events & BEV_EVENT_TIMEOUT) {
warnx("Timeout");
}
delete_http2_session_data(session_data);
}
/* Start connecting to the remote peer |host:port| */
static void initiate_connection(struct event_base *evbase,
SSL_CTX *ssl_ctx,
static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx,
const char *host, uint16_t port,
http2_session_data *session_data)
{
http2_session_data *session_data) {
int rv;
struct bufferevent *bev;
SSL *ssl;
ssl = create_ssl(ssl_ctx);
bev = bufferevent_openssl_socket_new(evbase, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS |
BEV_OPT_CLOSE_ON_FREE);
bev = bufferevent_openssl_socket_new(
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
AF_UNSPEC, host, port);
if(rv != 0) {
if (rv != 0) {
errx(1, "Could not connect to the remote host %s", host);
}
session_data->bev = bev;
@ -526,8 +496,7 @@ static void initiate_connection(struct event_base *evbase,
/* Get resource denoted by the |uri|. The debug and error messages are
printed in stderr, while the response body is printed in stdout. */
static void run(const char *uri)
{
static void run(const char *uri) {
struct http_parser_url u;
char *host;
uint16_t port;
@ -538,11 +507,11 @@ static void run(const char *uri)
/* Parse the |uri| and stores its components in |u| */
rv = http_parser_parse_url(uri, strlen(uri), 0, &u);
if(rv != 0) {
if (rv != 0) {
errx(1, "Could not parse URI %s", uri);
}
host = strndup(&uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len);
if(!(u.field_set & (1 << UF_PORT))) {
if (!(u.field_set & (1 << UF_PORT))) {
port = 443;
} else {
port = u.port;
@ -565,11 +534,10 @@ static void run(const char *uri)
SSL_CTX_free(ssl_ctx);
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
struct sigaction act;
if(argc < 2) {
if (argc < 2) {
fprintf(stderr, "Usage: libevent-client HTTPS_URI\n");
exit(EXIT_FAILURE);
}

View File

@ -51,11 +51,13 @@
#define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
#define ARRLEN(x) (sizeof(x)/sizeof(x[0]))
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
#define MAKE_NV(NAME, VALUE) \
{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE }
#define MAKE_NV(NAME, VALUE) \
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
struct app_context;
typedef struct app_context app_context;
@ -83,43 +85,40 @@ struct app_context {
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
static int next_proto_cb(SSL *s _U_, const unsigned char **data, unsigned int *len,
void *arg _U_)
{
static int next_proto_cb(SSL *s _U_, const unsigned char **data,
unsigned int *len, void *arg _U_) {
*data = next_proto_list;
*len = (unsigned int)next_proto_list_len;
return SSL_TLSEXT_ERR_OK;
}
/* Create SSL_CTX. */
static SSL_CTX* create_ssl_ctx(const char *key_file, const char *cert_file)
{
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
SSL_CTX *ssl_ctx;
EC_KEY *ecdh;
ssl_ctx = SSL_CTX_new(SSLv23_server_method());
if(!ssl_ctx) {
if (!ssl_ctx) {
errx(1, "Could not create SSL/TLS context: %s",
ERR_error_string(ERR_get_error(), NULL));
}
SSL_CTX_set_options(ssl_ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if(!ecdh) {
if (!ecdh) {
errx(1, "EC_KEY_new_by_curv_name failed: %s",
ERR_error_string(ERR_get_error(), NULL));
}
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
EC_KEY_free(ecdh);
if(SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file,
SSL_FILETYPE_PEM) != 1) {
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) {
errx(1, "Could not read private key file %s", key_file);
}
if(SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
errx(1, "Could not read certificate file %s", cert_file);
}
@ -133,11 +132,10 @@ static SSL_CTX* create_ssl_ctx(const char *key_file, const char *cert_file)
}
/* Create SSL object */
static SSL* create_ssl(SSL_CTX *ssl_ctx)
{
static SSL *create_ssl(SSL_CTX *ssl_ctx) {
SSL *ssl;
ssl = SSL_new(ssl_ctx);
if(!ssl) {
if (!ssl) {
errx(1, "Could not create SSL/TLS session object: %s",
ERR_error_string(ERR_get_error(), NULL));
}
@ -145,28 +143,25 @@ static SSL* create_ssl(SSL_CTX *ssl_ctx)
}
static void add_stream(http2_session_data *session_data,
http2_stream_data *stream_data)
{
http2_stream_data *stream_data) {
stream_data->next = session_data->root.next;
session_data->root.next = stream_data;
stream_data->prev = &session_data->root;
if(stream_data->next) {
if (stream_data->next) {
stream_data->next->prev = stream_data;
}
}
static void remove_stream(http2_session_data *session_data _U_,
http2_stream_data *stream_data)
{
http2_stream_data *stream_data) {
stream_data->prev->next = stream_data->next;
if(stream_data->next) {
if (stream_data->next) {
stream_data->next->prev = stream_data->prev;
}
}
static http2_stream_data* create_http2_stream_data
(http2_session_data *session_data, int32_t stream_id)
{
static http2_stream_data *
create_http2_stream_data(http2_session_data *session_data, int32_t stream_id) {
http2_stream_data *stream_data;
stream_data = malloc(sizeof(http2_stream_data));
memset(stream_data, 0, sizeof(http2_stream_data));
@ -177,20 +172,18 @@ static http2_stream_data* create_http2_stream_data
return stream_data;
}
static void delete_http2_stream_data(http2_stream_data *stream_data)
{
if(stream_data->fd != -1) {
static void delete_http2_stream_data(http2_stream_data *stream_data) {
if (stream_data->fd != -1) {
close(stream_data->fd);
}
free(stream_data->request_path);
free(stream_data);
}
static http2_session_data* create_http2_session_data(app_context *app_ctx,
static http2_session_data *create_http2_session_data(app_context *app_ctx,
int fd,
struct sockaddr *addr,
int addrlen)
{
int addrlen) {
int rv;
http2_session_data *session_data;
SSL *ssl;
@ -202,12 +195,11 @@ static http2_session_data* create_http2_session_data(app_context *app_ctx,
memset(session_data, 0, sizeof(http2_session_data));
session_data->app_ctx = app_ctx;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
session_data->bev = bufferevent_openssl_socket_new
(app_ctx->evbase, fd, ssl,
BUFFEREVENT_SSL_ACCEPTING,
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
session_data->bev = bufferevent_openssl_socket_new(
app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
rv = getnameinfo(addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
if(rv != 0) {
if (rv != 0) {
session_data->client_addr = strdup("(unknown)");
} else {
session_data->client_addr = strdup(host);
@ -216,17 +208,16 @@ static http2_session_data* create_http2_session_data(app_context *app_ctx,
return session_data;
}
static void delete_http2_session_data(http2_session_data *session_data)
{
static void delete_http2_session_data(http2_session_data *session_data) {
http2_stream_data *stream_data;
SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev);
fprintf(stderr, "%s disconnected\n", session_data->client_addr);
if(ssl) {
if (ssl) {
SSL_shutdown(ssl);
}
bufferevent_free(session_data->bev);
nghttp2_session_del(session_data->session);
for(stream_data = session_data->root.next; stream_data;) {
for (stream_data = session_data->root.next; stream_data;) {
http2_stream_data *next = stream_data->next;
delete_http2_stream_data(stream_data);
stream_data = next;
@ -237,11 +228,10 @@ static void delete_http2_session_data(http2_session_data *session_data)
/* Serialize the frame and send (or buffer) the data to
bufferevent. */
static int session_send(http2_session_data *session_data)
{
static int session_send(http2_session_data *session_data) {
int rv;
rv = nghttp2_session_send(session_data->session);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@ -252,37 +242,34 @@ static int session_send(http2_session_data *session_data)
function. Invocation of nghttp2_session_mem_recv() may make
additional pending frames, so call session_send() at the end of the
function. */
static int session_recv(http2_session_data *session_data)
{
static int session_recv(http2_session_data *session_data) {
ssize_t readlen;
struct evbuffer *input = bufferevent_get_input(session_data->bev);
size_t datalen = evbuffer_get_length(input);
unsigned char *data = evbuffer_pullup(input, -1);
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
if(readlen < 0) {
if (readlen < 0) {
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
return -1;
}
if(evbuffer_drain(input, readlen) != 0) {
if (evbuffer_drain(input, readlen) != 0) {
warnx("Fatal error: evbuffer_drain failed");
return -1;
}
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
return -1;
}
return 0;
}
static ssize_t send_callback(nghttp2_session *session _U_,
const uint8_t *data, size_t length,
int flags _U_, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
/* Avoid excessive buffering in server side. */
if(evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
OUTPUT_WOULDBLOCK_THRESHOLD) {
if (evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
OUTPUT_WOULDBLOCK_THRESHOLD) {
return NGHTTP2_ERR_WOULDBLOCK;
}
bufferevent_write(bev, data, length);
@ -290,26 +277,24 @@ static ssize_t send_callback(nghttp2_session *session _U_,
}
/* Returns nonzero if the string |s| ends with the substring |sub| */
static int ends_with(const char *s, const char *sub)
{
static int ends_with(const char *s, const char *sub) {
size_t slen = strlen(s);
size_t sublen = strlen(sub);
if(slen < sublen) {
if (slen < sublen) {
return 0;
}
return memcmp(s + slen - sublen, sub, sublen) == 0;
}
/* Returns int value of hex string character |c| */
static uint8_t hex_to_uint(uint8_t c)
{
if('0' <= c && c <= '9') {
static uint8_t hex_to_uint(uint8_t c) {
if ('0' <= c && c <= '9') {
return c - '0';
}
if('A' <= c && c <= 'F') {
if ('A' <= c && c <= 'F') {
return c - 'A' + 10;
}
if('a' <= c && c <= 'f') {
if ('a' <= c && c <= 'f') {
return c - 'a' + 10;
}
return 0;
@ -319,16 +304,15 @@ static uint8_t hex_to_uint(uint8_t c)
and returns the decoded byte string in allocated buffer. The return
value is NULL terminated. The caller must free the returned
string. */
static char* percent_decode(const uint8_t *value, size_t valuelen)
{
static char *percent_decode(const uint8_t *value, size_t valuelen) {
char *res;
res = malloc(valuelen + 1);
if(valuelen > 3) {
if (valuelen > 3) {
size_t i, j;
for(i = 0, j = 0; i < valuelen - 2;) {
if(value[i] != '%' ||
!isxdigit(value[i + 1]) || !isxdigit(value[i + 2])) {
for (i = 0, j = 0; i < valuelen - 2;) {
if (value[i] != '%' || !isxdigit(value[i + 1]) ||
!isxdigit(value[i + 2])) {
res[j++] = value[i++];
continue;
}
@ -344,33 +328,33 @@ static char* percent_decode(const uint8_t *value, size_t valuelen)
return res;
}
static ssize_t file_read_callback
(nghttp2_session *session _U_, int32_t stream_id _U_,
uint8_t *buf, size_t length, uint32_t *data_flags,
nghttp2_data_source *source, void *user_data _U_)
{
static ssize_t file_read_callback(nghttp2_session *session _U_,
int32_t stream_id _U_, uint8_t *buf,
size_t length, uint32_t *data_flags,
nghttp2_data_source *source,
void *user_data _U_) {
int fd = source->fd;
ssize_t r;
while((r = read(fd, buf, length)) == -1 && errno == EINTR);
if(r == -1) {
while ((r = read(fd, buf, length)) == -1 && errno == EINTR)
;
if (r == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if(r == 0) {
if (r == 0) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
}
return r;
}
static int send_response(nghttp2_session *session, int32_t stream_id,
nghttp2_nv *nva, size_t nvlen, int fd)
{
nghttp2_nv *nva, size_t nvlen, int fd) {
int rv;
nghttp2_data_provider data_prd;
data_prd.source.fd = fd;
data_prd.read_callback = file_read_callback;
rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@ -378,25 +362,22 @@ static int send_response(nghttp2_session *session, int32_t stream_id,
}
const char ERROR_HTML[] = "<html><head><title>404</title></head>"
"<body><h1>404 Not Found</h1></body></html>";
"<body><h1>404 Not Found</h1></body></html>";
static int error_reply(nghttp2_session *session,
http2_stream_data *stream_data)
{
http2_stream_data *stream_data) {
int rv;
ssize_t writelen;
int pipefd[2];
nghttp2_nv hdrs[] = {
MAKE_NV(":status", "404")
};
nghttp2_nv hdrs[] = {MAKE_NV(":status", "404")};
rv = pipe(pipefd);
if(rv != 0) {
if (rv != 0) {
warn("Could not create pipe");
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
stream_data->stream_id,
NGHTTP2_INTERNAL_ERROR);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@ -406,15 +387,15 @@ static int error_reply(nghttp2_session *session,
writelen = write(pipefd[1], ERROR_HTML, sizeof(ERROR_HTML) - 1);
close(pipefd[1]);
if(writelen != sizeof(ERROR_HTML) - 1) {
if (writelen != sizeof(ERROR_HTML) - 1) {
close(pipefd[0]);
return -1;
}
stream_data->fd = pipefd[0];
if(send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs),
pipefd[0]) != 0) {
if (send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs),
pipefd[0]) != 0) {
close(pipefd[0]);
return -1;
}
@ -424,27 +405,26 @@ static int error_reply(nghttp2_session *session,
/* nghttp2_on_header_callback: Called when nghttp2 library emits
single header name/value pair. */
static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
uint8_t flags _U_,
void *user_data _U_)
{
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data _U_) {
http2_stream_data *stream_data;
const char PATH[] = ":path";
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
if (frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
break;
}
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
if(!stream_data || stream_data->request_path) {
stream_data =
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if (!stream_data || stream_data->request_path) {
break;
}
if(namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
if (namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
size_t j;
for(j = 0; j < valuelen && value[j] != '?'; ++j);
for (j = 0; j < valuelen && value[j] != '?'; ++j)
;
stream_data->request_path = percent_decode(value, j);
}
break;
@ -454,13 +434,12 @@ static int on_header_callback(nghttp2_session *session,
static int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
if(frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
return 0;
}
stream_data = create_http2_stream_data(session_data, frame->hd.stream_id);
@ -471,52 +450,47 @@ static int on_begin_headers_callback(nghttp2_session *session,
/* Minimum check for directory traversal. Returns nonzero if it is
safe. */
static int check_path(const char *path)
{
static int check_path(const char *path) {
/* We don't like '\' in url. */
return path[0] && path[0] == '/' &&
strchr(path, '\\') == NULL &&
strstr(path, "/../") == NULL &&
strstr(path, "/./") == NULL &&
!ends_with(path, "/..") && !ends_with(path, "/.");
return path[0] && path[0] == '/' && strchr(path, '\\') == NULL &&
strstr(path, "/../") == NULL && strstr(path, "/./") == NULL &&
!ends_with(path, "/..") && !ends_with(path, "/.");
}
static int on_request_recv(nghttp2_session *session,
http2_session_data *session_data,
http2_stream_data *stream_data)
{
http2_stream_data *stream_data) {
int fd;
nghttp2_nv hdrs[] = {
MAKE_NV(":status", "200")
};
nghttp2_nv hdrs[] = {MAKE_NV(":status", "200")};
char *rel_path;
if(!stream_data->request_path) {
if(error_reply(session, stream_data) != 0) {
if (!stream_data->request_path) {
if (error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
fprintf(stderr, "%s GET %s\n", session_data->client_addr,
stream_data->request_path);
if(!check_path(stream_data->request_path)) {
if(error_reply(session, stream_data) != 0) {
if (!check_path(stream_data->request_path)) {
if (error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
for(rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path);
for (rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path)
;
fd = open(rel_path, O_RDONLY);
if(fd == -1) {
if(error_reply(session, stream_data) != 0) {
if (fd == -1) {
if (error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
stream_data->fd = fd;
if(send_response(session, stream_data->stream_id, hdrs,
ARRLEN(hdrs), fd) != 0) {
if (send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs), fd) !=
0) {
close(fd);
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@ -524,20 +498,19 @@ static int on_request_recv(nghttp2_session *session,
}
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
const nghttp2_frame *frame, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_DATA:
case NGHTTP2_HEADERS:
/* Check that the client request has finished */
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data =
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
/* For DATA and HEADERS frame, this callback may be called after
on_stream_close_callback. Check that stream still alive. */
if(!stream_data) {
if (!stream_data) {
return 0;
}
return on_request_recv(session, session_data, stream_data);
@ -549,16 +522,13 @@ static int on_frame_recv_callback(nghttp2_session *session,
return 0;
}
static int on_stream_close_callback(nghttp2_session *session,
int32_t stream_id,
uint32_t error_code _U_,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
stream_data = nghttp2_session_get_stream_user_data(session, stream_id);
if(!stream_data) {
if (!stream_data) {
return 0;
}
remove_stream(session_data, stream_data);
@ -566,8 +536,7 @@ static int on_stream_close_callback(nghttp2_session *session,
return 0;
}
static void initialize_nghttp2_session(http2_session_data *session_data)
{
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
@ -581,19 +550,17 @@ static void initialize_nghttp2_session(http2_session_data *session_data)
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_server_new2(&session_data->session, callbacks, session_data,
option);
@ -604,16 +571,14 @@ static void initialize_nghttp2_session(http2_session_data *session_data)
/* Send HTTP/2 client connection header, which includes 24 bytes
magic octets and SETTINGS frame */
static int send_server_connection_header(http2_session_data *session_data)
{
static int send_server_connection_header(http2_session_data *session_data) {
nghttp2_settings_entry iv[1] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
};
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
iv, ARRLEN(iv));
if(rv != 0) {
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@ -622,10 +587,9 @@ static int send_server_connection_header(http2_session_data *session_data)
/* readcb for bufferevent after client connection header was
checked. */
static void readcb(struct bufferevent *bev _U_, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(session_recv(session_data) != 0) {
static void readcb(struct bufferevent *bev _U_, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (session_recv(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
@ -639,44 +603,42 @@ static void readcb(struct bufferevent *bev _U_, void *ptr)
process pending data in the output buffer. This is necessary
because we have a threshold on the buffer size to avoid too much
buffering. See send_callback(). */
static void writecb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
static void writecb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
return;
}
if(nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0) {
if (nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0) {
delete_http2_session_data(session_data);
return;
}
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
}
/* eventcb for bufferevent */
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(events & BEV_EVENT_CONNECTED) {
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) {
fprintf(stderr, "%s connected\n", session_data->client_addr);
initialize_nghttp2_session(session_data);
if(send_server_connection_header(session_data) != 0) {
if (send_server_connection_header(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
return;
}
if(events & BEV_EVENT_EOF) {
if (events & BEV_EVENT_EOF) {
fprintf(stderr, "%s EOF\n", session_data->client_addr);
} else if(events & BEV_EVENT_ERROR) {
} else if (events & BEV_EVENT_ERROR) {
fprintf(stderr, "%s network error\n", session_data->client_addr);
} else if(events & BEV_EVENT_TIMEOUT) {
} else if (events & BEV_EVENT_TIMEOUT) {
fprintf(stderr, "%s timeout\n", session_data->client_addr);
}
delete_http2_session_data(session_data);
@ -684,9 +646,8 @@ static void eventcb(struct bufferevent *bev _U_, short events, void *ptr)
/* callback for evconnlistener */
static void acceptcb(struct evconnlistener *listener _U_, int fd,
struct sockaddr *addr, int addrlen, void *arg)
{
app_context *app_ctx = (app_context*)arg;
struct sockaddr *addr, int addrlen, void *arg) {
app_context *app_ctx = (app_context *)arg;
http2_session_data *session_data;
session_data = create_http2_session_data(app_ctx, fd, addr, addrlen);
@ -695,8 +656,7 @@ static void acceptcb(struct evconnlistener *listener _U_, int fd,
}
static void start_listen(struct event_base *evbase, const char *service,
app_context *app_ctx)
{
app_context *app_ctx) {
int rv;
struct addrinfo hints;
struct addrinfo *res, *rp;
@ -710,16 +670,15 @@ static void start_listen(struct event_base *evbase, const char *service,
#endif /* AI_ADDRCONFIG */
rv = getaddrinfo(NULL, service, &hints, &res);
if(rv != 0) {
if (rv != 0) {
errx(1, NULL);
}
for(rp = res; rp; rp = rp->ai_next) {
for (rp = res; rp; rp = rp->ai_next) {
struct evconnlistener *listener;
listener = evconnlistener_new_bind(evbase, acceptcb, app_ctx,
LEV_OPT_CLOSE_ON_FREE |
LEV_OPT_REUSEABLE, 16,
rp->ai_addr, rp->ai_addrlen);
if(listener) {
listener = evconnlistener_new_bind(
evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
16, rp->ai_addr, rp->ai_addrlen);
if (listener) {
freeaddrinfo(res);
return;
@ -729,16 +688,14 @@ static void start_listen(struct event_base *evbase, const char *service,
}
static void initialize_app_context(app_context *app_ctx, SSL_CTX *ssl_ctx,
struct event_base *evbase)
{
struct event_base *evbase) {
memset(app_ctx, 0, sizeof(app_context));
app_ctx->ssl_ctx = ssl_ctx;
app_ctx->evbase = evbase;
}
static void run(const char *service,
const char *key_file, const char *cert_file)
{
static void run(const char *service, const char *key_file,
const char *cert_file) {
SSL_CTX *ssl_ctx;
app_context app_ctx;
struct event_base *evbase;
@ -754,11 +711,10 @@ static void run(const char *service,
SSL_CTX_free(ssl_ctx);
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
struct sigaction act;
if(argc < 4) {
if (argc < 4) {
fprintf(stderr, "Usage: libevent-server PORT KEY_FILE CERT_FILE\n");
exit(EXIT_FAILURE);
}

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
#ifndef NGHTTP2_H
#define NGHTTP2_H
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@ -186,7 +186,7 @@ typedef struct {
*
* The length of :macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`.
*/
#define NGHTTP2_CLIENT_CONNECTION_HEADER_LEN \
#define NGHTTP2_CLIENT_CONNECTION_HEADER_LEN \
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN
/**
@ -621,7 +621,6 @@ typedef struct {
uint8_t reserved;
} nghttp2_frame_hd;
/**
* @union
*
@ -681,10 +680,9 @@ typedef enum {
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session
* failure.
*/
typedef ssize_t (*nghttp2_data_source_read_callback)
(nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length, uint32_t *data_flags,
nghttp2_data_source *source, void *user_data);
typedef ssize_t (*nghttp2_data_source_read_callback)(
nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length,
uint32_t *data_flags, nghttp2_data_source *source, void *user_data);
/**
* @struct
@ -1113,9 +1111,9 @@ typedef union {
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_send_callback()`.
*/
typedef ssize_t (*nghttp2_send_callback)
(nghttp2_session *session,
const uint8_t *data, size_t length, int flags, void *user_data);
typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session,
const uint8_t *data, size_t length,
int flags, void *user_data);
/**
* @functypedef
@ -1141,9 +1139,9 @@ typedef ssize_t (*nghttp2_send_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_recv_callback()`.
*/
typedef ssize_t (*nghttp2_recv_callback)
(nghttp2_session *session,
uint8_t *buf, size_t length, int flags, void *user_data);
typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf,
size_t length, int flags,
void *user_data);
/**
* @functypedef
@ -1179,8 +1177,9 @@ typedef ssize_t (*nghttp2_recv_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_frame_recv_callback()`.
*/
typedef int (*nghttp2_on_frame_recv_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data);
/**
* @functypedef
@ -1206,9 +1205,9 @@ typedef int (*nghttp2_on_frame_recv_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_invalid_frame_recv_callback()`.
*/
typedef int (*nghttp2_on_invalid_frame_recv_callback)
(nghttp2_session *session, const nghttp2_frame *frame,
uint32_t error_code, void *user_data);
typedef int (*nghttp2_on_invalid_frame_recv_callback)(
nghttp2_session *session, const nghttp2_frame *frame, uint32_t error_code,
void *user_data);
/**
* @functypedef
@ -1240,9 +1239,11 @@ typedef int (*nghttp2_on_invalid_frame_recv_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_data_chunk_recv_callback()`.
*/
typedef int (*nghttp2_on_data_chunk_recv_callback)
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
const uint8_t *data, size_t len, void *user_data);
typedef int (*nghttp2_on_data_chunk_recv_callback)(nghttp2_session *session,
uint8_t flags,
int32_t stream_id,
const uint8_t *data,
size_t len, void *user_data);
/**
* @functypedef
@ -1260,8 +1261,9 @@ typedef int (*nghttp2_on_data_chunk_recv_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_before_frame_send_callback()`.
*/
typedef int (*nghttp2_before_frame_send_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
typedef int (*nghttp2_before_frame_send_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data);
/**
* @functypedef
@ -1278,8 +1280,9 @@ typedef int (*nghttp2_before_frame_send_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_frame_send_callback()`.
*/
typedef int (*nghttp2_on_frame_send_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
typedef int (*nghttp2_on_frame_send_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data);
/**
* @functypedef
@ -1299,9 +1302,10 @@ typedef int (*nghttp2_on_frame_send_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_frame_not_send_callback()`.
*/
typedef int (*nghttp2_on_frame_not_send_callback)
(nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code,
void *user_data);
typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
int lib_error_code,
void *user_data);
/**
* @functypedef
@ -1325,9 +1329,10 @@ typedef int (*nghttp2_on_frame_not_send_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_stream_close_callback()`.
*/
typedef int (*nghttp2_on_stream_close_callback)
(nghttp2_session *session, int32_t stream_id, uint32_t error_code,
void *user_data);
typedef int (*nghttp2_on_stream_close_callback)(nghttp2_session *session,
int32_t stream_id,
uint32_t error_code,
void *user_data);
/**
* @functypedef
@ -1353,8 +1358,9 @@ typedef int (*nghttp2_on_stream_close_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_begin_headers_callback()`.
*/
typedef int (*nghttp2_on_begin_headers_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data);
/**
* @functypedef
@ -1417,13 +1423,11 @@ typedef int (*nghttp2_on_begin_headers_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_header_callback()`.
*/
typedef int (*nghttp2_on_header_callback)
(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
uint8_t flags,
void *user_data);
typedef int (*nghttp2_on_header_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
uint8_t flags, void *user_data);
/**
* @functypedef
@ -1442,11 +1446,10 @@ typedef int (*nghttp2_on_header_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_select_padding_callback()`.
*/
typedef ssize_t (*nghttp2_select_padding_callback)
(nghttp2_session *session,
const nghttp2_frame *frame,
size_t max_payloadlen,
void *user_data);
typedef ssize_t (*nghttp2_select_padding_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
size_t max_payloadlen,
void *user_data);
/**
* @functypedef
@ -1472,12 +1475,10 @@ typedef ssize_t (*nghttp2_select_padding_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_data_source_read_length_callback()`.
*/
typedef ssize_t (*nghttp2_data_source_read_length_callback)
(nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
int32_t session_remote_window_size,
int32_t stream_remote_window_size,
uint32_t remote_max_frame_size,
void *user_data);
typedef ssize_t (*nghttp2_data_source_read_length_callback)(
nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
int32_t session_remote_window_size, int32_t stream_remote_window_size,
uint32_t remote_max_frame_size, void *user_data);
/**
* @functypedef
@ -1501,8 +1502,9 @@ typedef ssize_t (*nghttp2_data_source_read_length_callback)
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_begin_frame_callback()`.
*/
typedef int (*nghttp2_on_begin_frame_callback)
(nghttp2_session *session, const nghttp2_frame_hd *hd, void *user_data);
typedef int (*nghttp2_on_begin_frame_callback)(nghttp2_session *session,
const nghttp2_frame_hd *hd,
void *user_data);
struct nghttp2_session_callbacks;
@ -1541,7 +1543,6 @@ int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr);
*/
void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks);
/**
* @function
*
@ -1550,8 +1551,8 @@ void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks);
* uses solely `nghttp2_session_mem_send()` to serialize data to
* transmit.
*/
void nghttp2_session_callbacks_set_send_callback
(nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback);
void nghttp2_session_callbacks_set_send_callback(
nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback);
/**
* @function
@ -1561,8 +1562,8 @@ void nghttp2_session_callbacks_set_send_callback
* application uses solely `nghttp2_session_mem_recv()` to process
* received data.
*/
void nghttp2_session_callbacks_set_recv_callback
(nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback);
void nghttp2_session_callbacks_set_recv_callback(
nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback);
/**
* @function
@ -1570,9 +1571,9 @@ void nghttp2_session_callbacks_set_recv_callback
* Sets callback function invoked by `nghttp2_session_recv()` when a
* frame is received.
*/
void nghttp2_session_callbacks_set_on_frame_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_recv_callback on_frame_recv_callback);
void nghttp2_session_callbacks_set_on_frame_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_recv_callback on_frame_recv_callback);
/**
* @function
@ -1580,9 +1581,9 @@ void nghttp2_session_callbacks_set_on_frame_recv_callback
* Sets callback function invoked by `nghttp2_session_recv()` when an
* invalid non-DATA frame is received.
*/
void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback);
void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback);
/**
* @function
@ -1590,27 +1591,27 @@ void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
* Sets callback function invoked when a chunk of data in DATA frame
* is received.
*/
void nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback);
void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback);
/**
* @function
*
* Sets callback function invoked before a non-DATA frame is sent.
*/
void nghttp2_session_callbacks_set_before_frame_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_before_frame_send_callback before_frame_send_callback);
void nghttp2_session_callbacks_set_before_frame_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_before_frame_send_callback before_frame_send_callback);
/**
* @function
*
* Sets callback function invoked after a frame is sent.
*/
void nghttp2_session_callbacks_set_on_frame_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_send_callback on_frame_send_callback);
void nghttp2_session_callbacks_set_on_frame_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_send_callback on_frame_send_callback);
/**
* @function
@ -1618,18 +1619,18 @@ void nghttp2_session_callbacks_set_on_frame_send_callback
* Sets callback function invoked when a non-DATA frame is not sent
* because of an error.
*/
void nghttp2_session_callbacks_set_on_frame_not_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_not_send_callback on_frame_not_send_callback);
void nghttp2_session_callbacks_set_on_frame_not_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_not_send_callback on_frame_not_send_callback);
/**
* @function
*
* Sets callback function invoked when the stream is closed.
*/
void nghttp2_session_callbacks_set_on_stream_close_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_stream_close_callback on_stream_close_callback);
void nghttp2_session_callbacks_set_on_stream_close_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_stream_close_callback on_stream_close_callback);
/**
* @function
@ -1637,9 +1638,9 @@ void nghttp2_session_callbacks_set_on_stream_close_callback
* Sets callback function invoked when the reception of header block
* in HEADERS or PUSH_PROMISE is started.
*/
void nghttp2_session_callbacks_set_on_begin_headers_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_begin_headers_callback on_begin_headers_callback);
void nghttp2_session_callbacks_set_on_begin_headers_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_begin_headers_callback on_begin_headers_callback);
/**
* @function
@ -1647,9 +1648,9 @@ void nghttp2_session_callbacks_set_on_begin_headers_callback
* Sets callback function invoked when a header name/value pair is
* received.
*/
void nghttp2_session_callbacks_set_on_header_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_header_callback on_header_callback);
void nghttp2_session_callbacks_set_on_header_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_header_callback on_header_callback);
/**
* @function
@ -1658,9 +1659,9 @@ void nghttp2_session_callbacks_set_on_header_callback
* how many padding bytes are required for the transmission of the
* given frame.
*/
void nghttp2_session_callbacks_set_select_padding_callback
(nghttp2_session_callbacks *cbs,
nghttp2_select_padding_callback select_padding_callback);
void nghttp2_session_callbacks_set_select_padding_callback(
nghttp2_session_callbacks *cbs,
nghttp2_select_padding_callback select_padding_callback);
/**
* @function
@ -1668,18 +1669,18 @@ void nghttp2_session_callbacks_set_select_padding_callback
* Sets callback function determine the length allowed in
* :type:`nghttp2_data_source_read_callback`.
*/
void nghttp2_session_callbacks_set_data_source_read_length_callback
(nghttp2_session_callbacks *cbs,
nghttp2_data_source_read_length_callback data_source_read_length_callback);
void nghttp2_session_callbacks_set_data_source_read_length_callback(
nghttp2_session_callbacks *cbs,
nghttp2_data_source_read_length_callback data_source_read_length_callback);
/**
* @function
*
* Sets callback function invoked when a frame header is received.
*/
void nghttp2_session_callbacks_set_on_begin_frame_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_begin_frame_callback on_begin_frame_callback);
void nghttp2_session_callbacks_set_on_begin_frame_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_begin_frame_callback on_begin_frame_callback);
struct nghttp2_option;
@ -1836,8 +1837,7 @@ int nghttp2_session_server_new(nghttp2_session **session_ptr,
*/
int nghttp2_session_client_new2(nghttp2_session **session_ptr,
const nghttp2_session_callbacks *callbacks,
void *user_data,
const nghttp2_option *option);
void *user_data, const nghttp2_option *option);
/**
* @function
@ -1862,8 +1862,7 @@ int nghttp2_session_client_new2(nghttp2_session **session_ptr,
*/
int nghttp2_session_server_new2(nghttp2_session **session_ptr,
const nghttp2_session_callbacks *callbacks,
void *user_data,
const nghttp2_option *option);
void *user_data, const nghttp2_option *option);
/**
* @function
@ -2053,8 +2052,8 @@ int nghttp2_session_recv(nghttp2_session *session);
* when |session| was configured as server and
* `nghttp2_option_set_recv_client_preface()` is used.
*/
ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
const uint8_t *in, size_t inlen);
ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
size_t inlen);
/**
* @function
@ -2108,7 +2107,7 @@ int nghttp2_session_want_write(nghttp2_session *session);
* ``NULL``. If the stream does not exist, this function returns
* ``NULL``.
*/
void* nghttp2_session_get_stream_user_data(nghttp2_session *session,
void *nghttp2_session_get_stream_user_data(nghttp2_session *session,
int32_t stream_id);
/**
@ -2155,8 +2154,9 @@ size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session);
*
* This function returns -1 if it fails.
*/
int32_t nghttp2_session_get_stream_effective_recv_data_length
(nghttp2_session *session, int32_t stream_id);
int32_t
nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session,
int32_t stream_id);
/**
* @function
@ -2168,8 +2168,9 @@ int32_t nghttp2_session_get_stream_effective_recv_data_length
*
* This function returns -1 if it fails.
*/
int32_t nghttp2_session_get_stream_effective_local_window_size
(nghttp2_session *session, int32_t stream_id);
int32_t
nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session,
int32_t stream_id);
/**
* @function
@ -2185,8 +2186,8 @@ int32_t nghttp2_session_get_stream_effective_local_window_size
*
* This function returns -1 if it fails.
*/
int32_t nghttp2_session_get_effective_recv_data_length
(nghttp2_session *session);
int32_t
nghttp2_session_get_effective_recv_data_length(nghttp2_session *session);
/**
* @function
@ -2198,8 +2199,8 @@ int32_t nghttp2_session_get_effective_recv_data_length
*
* This function returns -1 if it fails.
*/
int32_t nghttp2_session_get_effective_local_window_size
(nghttp2_session *session);
int32_t
nghttp2_session_get_effective_local_window_size(nghttp2_session *session);
/**
* @function
@ -2215,7 +2216,7 @@ int32_t nghttp2_session_get_effective_local_window_size
*
* This function returns -1 if it fails.
*/
int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session* session,
int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session *session,
int32_t stream_id);
/**
@ -2225,7 +2226,7 @@ int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session* session,
*
* This function always succeeds.
*/
int32_t nghttp2_session_get_remote_window_size(nghttp2_session* session);
int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session);
/**
* @function
@ -2233,7 +2234,7 @@ int32_t nghttp2_session_get_remote_window_size(nghttp2_session* session);
* Returns 1 if local peer half closed the given stream |stream_id|.
* Returns 0 if it did not. Returns -1 if no such stream exists.
*/
int nghttp2_session_get_stream_local_close(nghttp2_session* session,
int nghttp2_session_get_stream_local_close(nghttp2_session *session,
int32_t stream_id);
/**
@ -2242,7 +2243,7 @@ int nghttp2_session_get_stream_local_close(nghttp2_session* session,
* Returns 1 if remote peer half closed the given stream |stream_id|.
* Returns 0 if it did not. Returns -1 if no such stream exists.
*/
int nghttp2_session_get_stream_remote_close(nghttp2_session* session,
int nghttp2_session_get_stream_remote_close(nghttp2_session *session,
int32_t stream_id);
/**
@ -2361,8 +2362,7 @@ int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id,
*/
int nghttp2_session_upgrade(nghttp2_session *session,
const uint8_t *settings_payload,
size_t settings_payloadlen,
void *stream_user_data);
size_t settings_payloadlen, void *stream_user_data);
/**
* @function
@ -2385,8 +2385,7 @@ int nghttp2_session_upgrade(nghttp2_session *session,
* :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
* The provided |buflen| size is too small to hold the output.
*/
ssize_t nghttp2_pack_settings_payload(uint8_t *buf,
size_t buflen,
ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
const nghttp2_settings_entry *iv,
size_t niv);
@ -2396,7 +2395,7 @@ ssize_t nghttp2_pack_settings_payload(uint8_t *buf,
* Returns string describing the |lib_error_code|. The
* |lib_error_code| must be one of the :enum:`nghttp2_error`.
*/
const char* nghttp2_strerror(int lib_error_code);
const char *nghttp2_strerror(int lib_error_code);
/**
* @function
@ -2537,8 +2536,7 @@ int32_t nghttp2_submit_request(nghttp2_session *session,
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* The |stream_id| is 0.
*/
int nghttp2_submit_response(nghttp2_session *session,
int32_t stream_id,
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd);
@ -2711,8 +2709,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
* The |stream_id| is 0.
*/
int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
uint32_t error_code);
int32_t stream_id, uint32_t error_code);
/**
* @function
@ -2750,7 +2747,6 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
const nghttp2_settings_entry *iv, size_t niv);
/**
* @function
*
@ -2805,8 +2801,8 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
*
*/
int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const nghttp2_nv *nva, size_t nvlen,
int32_t stream_id, const nghttp2_nv *nva,
size_t nvlen,
void *promised_stream_user_data);
/**
@ -2866,8 +2862,7 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
* The |opaque_data_len| is too large.
*/
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
int32_t last_stream_id,
uint32_t error_code,
int32_t last_stream_id, uint32_t error_code,
const uint8_t *opaque_data, size_t opaque_data_len);
/**
@ -2937,8 +2932,7 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
* |origin_len| is is too large.
*/
int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
uint32_t max_age, uint16_t port,
int32_t stream_id, uint32_t max_age, uint16_t port,
const uint8_t *protocol_id, size_t protocol_id_len,
const uint8_t *host, size_t host_len,
const uint8_t *origin, size_t origin_len);
@ -3143,9 +3137,9 @@ int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
* :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
* The provided |buflen| size is too small to hold the output.
*/
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t *buf, size_t buflen,
const nghttp2_nv *nva, size_t nvlen);
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
size_t buflen, const nghttp2_nv *nva,
size_t nvlen);
/**
* @function
@ -3302,9 +3296,9 @@ typedef enum {
* }
*
*/
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags,
uint8_t *in, size_t inlen, int in_final);
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
int *inflate_flags, uint8_t *in, size_t inlen,
int in_final);
/**
* @function

View File

@ -28,8 +28,7 @@
#include "nghttp2_helper.h"
void nghttp2_buf_init(nghttp2_buf *buf)
{
void nghttp2_buf_init(nghttp2_buf *buf) {
buf->begin = NULL;
buf->end = NULL;
buf->pos = NULL;
@ -37,15 +36,13 @@ void nghttp2_buf_init(nghttp2_buf *buf)
buf->mark = NULL;
}
int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial)
{
int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial) {
nghttp2_buf_init(buf);
return nghttp2_buf_reserve(buf, initial);
}
void nghttp2_buf_free(nghttp2_buf *buf)
{
if(buf == NULL) {
void nghttp2_buf_free(nghttp2_buf *buf) {
if (buf == NULL) {
return;
}
@ -53,21 +50,20 @@ void nghttp2_buf_free(nghttp2_buf *buf)
buf->begin = NULL;
}
int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap)
{
int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap) {
uint8_t *ptr;
size_t cap;
cap = nghttp2_buf_cap(buf);
if(cap >= new_cap) {
if (cap >= new_cap) {
return 0;
}
new_cap = nghttp2_max(new_cap, cap * 2);
ptr = realloc(buf->begin, new_cap);
if(ptr == NULL) {
if (ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -80,30 +76,27 @@ int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap)
return 0;
}
void nghttp2_buf_reset(nghttp2_buf *buf)
{
void nghttp2_buf_reset(nghttp2_buf *buf) {
buf->pos = buf->last = buf->mark = buf->begin;
}
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len)
{
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) {
buf->begin = buf->pos = buf->last = buf->mark = begin;
buf->end = begin + len;
}
static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length)
{
static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length) {
int rv;
*chain = malloc(sizeof(nghttp2_buf_chain));
if(*chain == NULL) {
if (*chain == NULL) {
return NGHTTP2_ERR_NOMEM;
}
(*chain)->next = NULL;
rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length);
if(rv != 0) {
if (rv != 0) {
free(*chain);
return NGHTTP2_ERR_NOMEM;
}
@ -111,36 +104,32 @@ static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length)
return 0;
}
static void buf_chain_del(nghttp2_buf_chain *chain)
{
static void buf_chain_del(nghttp2_buf_chain *chain) {
nghttp2_buf_free(&chain->buf);
free(chain);
}
int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk)
{
size_t max_chunk) {
return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0);
}
int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk, size_t offset)
{
size_t max_chunk, size_t offset) {
return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset);
}
int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk, size_t chunk_keep, size_t offset)
{
size_t max_chunk, size_t chunk_keep, size_t offset) {
int rv;
nghttp2_buf_chain *chain;
if(chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
if (chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
rv = buf_chain_new(&chain, chunk_length);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -159,17 +148,16 @@ int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
return 0;
}
int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length)
{
int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) {
int rv;
nghttp2_buf_chain *chain;
if(chunk_length < bufs->offset) {
if (chunk_length < bufs->offset) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
rv = buf_chain_new(&chain, chunk_length);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -186,15 +174,14 @@ int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length)
return 0;
}
void nghttp2_bufs_free(nghttp2_bufs *bufs)
{
void nghttp2_bufs_free(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *next_chain;
if(bufs == NULL) {
if (bufs == NULL) {
return;
}
for(chain = bufs->head; chain;) {
for (chain = bufs->head; chain;) {
next_chain = chain->next;
buf_chain_del(chain);
@ -205,12 +192,11 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs)
bufs->head = NULL;
}
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len)
{
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len) {
nghttp2_buf_chain *chain;
chain = malloc(sizeof(nghttp2_buf_chain));
if(chain == NULL) {
if (chain == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -231,9 +217,8 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len)
return 0;
}
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs)
{
if(bufs == NULL) {
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
if (bufs == NULL) {
return;
}
@ -241,12 +226,11 @@ void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs)
bufs->head = NULL;
}
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs)
{
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
nghttp2_buf_chain *ci;
for(ci = bufs->cur; ci; ci = ci->next) {
if(nghttp2_buf_len(&ci->buf) == 0) {
for (ci = bufs->cur; ci; ci = ci->next) {
if (nghttp2_buf_len(&ci->buf) == 0) {
return;
} else {
bufs->cur = ci;
@ -254,42 +238,40 @@ void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs)
}
}
ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs)
{
ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
nghttp2_buf_chain *ci;
ssize_t len;
len = 0;
for(ci = bufs->head; ci; ci = ci->next) {
for (ci = bufs->head; ci; ci = ci->next) {
len += nghttp2_buf_len(&ci->buf);
}
return len;
}
static ssize_t bufs_avail(nghttp2_bufs *bufs)
{
static ssize_t bufs_avail(nghttp2_bufs *bufs) {
return (ssize_t)(nghttp2_buf_avail(&bufs->cur->buf) +
(bufs->chunk_length - bufs->offset) * (bufs->max_chunk - bufs->chunk_used));
(bufs->chunk_length - bufs->offset) *
(bufs->max_chunk - bufs->chunk_used));
}
static int bufs_alloc_chain(nghttp2_bufs *bufs)
{
static int bufs_alloc_chain(nghttp2_bufs *bufs) {
int rv;
nghttp2_buf_chain *chain;
if(bufs->cur->next) {
if (bufs->cur->next) {
bufs->cur = bufs->cur->next;
return 0;
}
if(bufs->max_chunk == bufs->chunk_used) {
if (bufs->max_chunk == bufs->chunk_used) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
rv = buf_chain_new(&chain, bufs->chunk_length);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -307,26 +289,25 @@ static int bufs_alloc_chain(nghttp2_bufs *bufs)
return 0;
}
int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len)
{
int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
int rv;
size_t nwrite;
nghttp2_buf *buf;
const uint8_t *p;
if(bufs_avail(bufs) < (ssize_t)len) {
if (bufs_avail(bufs) < (ssize_t)len) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
p = data;
while(len) {
while (len) {
buf = &bufs->cur->buf;
nwrite = nghttp2_min((size_t)nghttp2_buf_avail(buf), len);
if(nwrite == 0) {
if (nwrite == 0) {
rv = bufs_alloc_chain(bufs);
if(rv != 0) {
if (rv != 0) {
return rv;
}
continue;
@ -340,31 +321,29 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len)
return 0;
}
static int bufs_ensure_addb(nghttp2_bufs *bufs)
{
static int bufs_ensure_addb(nghttp2_bufs *bufs) {
int rv;
nghttp2_buf *buf;
buf = &bufs->cur->buf;
if(nghttp2_buf_avail(buf) > 0) {
if (nghttp2_buf_avail(buf) > 0) {
return 0;
}
rv = bufs_alloc_chain(bufs);
if(rv != 0) {
if (rv != 0) {
return rv;
}
return 0;
}
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b)
{
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -373,12 +352,11 @@ int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b)
return 0;
}
int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b)
{
int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -387,12 +365,11 @@ int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b)
return 0;
}
int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b)
{
int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -401,12 +378,11 @@ int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b)
return 0;
}
int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b)
{
int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -415,8 +391,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b)
return 0;
}
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out)
{
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
size_t len;
nghttp2_buf_chain *chain;
nghttp2_buf *buf;
@ -425,28 +400,27 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out)
len = 0;
for(chain = bufs->head; chain; chain = chain->next) {
for (chain = bufs->head; chain; chain = chain->next) {
len += nghttp2_buf_len(&chain->buf);
}
if(!len) {
if (!len) {
res = NULL;
} else {
res = malloc(len);
if(res == NULL) {
if (res == NULL) {
return NGHTTP2_ERR_NOMEM;
}
}
nghttp2_buf_wrap_init(&resbuf, res, len);
for(chain = bufs->head; chain; chain = chain->next) {
for (chain = bufs->head; chain; chain = chain->next) {
buf = &chain->buf;
if(resbuf.last) {
resbuf.last = nghttp2_cpymem(resbuf.last,
buf->pos, nghttp2_buf_len(buf));
if (resbuf.last) {
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
}
nghttp2_buf_reset(buf);
@ -460,27 +434,26 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out)
return (ssize_t)len;
}
void nghttp2_bufs_reset(nghttp2_bufs *bufs)
{
void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *ci;
size_t k;
k = bufs->chunk_keep;
for(ci = bufs->head; ci; ci = ci->next) {
for (ci = bufs->head; ci; ci = ci->next) {
nghttp2_buf_reset(&ci->buf);
nghttp2_buf_shift_right(&ci->buf, bufs->offset);
if(--k == 0) {
if (--k == 0) {
break;
}
}
if(ci) {
if (ci) {
chain = ci->next;
ci->next = NULL;
for(ci = chain; ci;) {
for (ci = chain; ci;) {
chain = ci->next;
buf_chain_del(ci);
@ -494,17 +467,12 @@ void nghttp2_bufs_reset(nghttp2_bufs *bufs)
bufs->cur = bufs->head;
}
int nghttp2_bufs_advance(nghttp2_bufs *bufs)
{
return bufs_alloc_chain(bufs);
}
int nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); }
int nghttp2_bufs_next_present(nghttp2_bufs *bufs)
{
int nghttp2_bufs_next_present(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain;
chain = bufs->cur->next;
return chain && nghttp2_buf_len(&chain->buf);
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_BUF_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -58,17 +58,17 @@ typedef struct {
#define nghttp2_buf_pos_offset(BUF) ((ssize_t)((BUF)->pos - (BUF)->begin))
#define nghttp2_buf_last_offset(BUF) ((ssize_t)((BUF)->last - (BUF)->begin))
#define nghttp2_buf_shift_right(BUF, AMT) \
do { \
(BUF)->pos += AMT; \
(BUF)->last += AMT; \
} while(0)
#define nghttp2_buf_shift_right(BUF, AMT) \
do { \
(BUF)->pos += AMT; \
(BUF)->last += AMT; \
} while (0)
#define nghttp2_buf_shift_left(BUF, AMT) \
do { \
(BUF)->pos -= AMT; \
(BUF)->last -= AMT; \
} while(0)
#define nghttp2_buf_shift_left(BUF, AMT) \
do { \
(BUF)->pos -= AMT; \
(BUF)->last -= AMT; \
} while (0)
/*
* Initializes the |buf|. No memory is allocated in this function. Use
@ -76,7 +76,6 @@ typedef struct {
*/
void nghttp2_buf_init(nghttp2_buf *buf);
/*
* Initializes the |buf| and allocates at least |initial| bytes of
* memory.
@ -264,15 +263,15 @@ int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
*/
int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
#define nghttp2_bufs_fast_addb(BUFS, B) \
do { \
*(BUFS)->cur->buf.last++ = B; \
} while(0)
#define nghttp2_bufs_fast_addb(BUFS, B) \
do { \
*(BUFS)->cur->buf.last++ = B; \
} while (0)
#define nghttp2_bufs_fast_addb_hold(BUFS, B) \
do { \
*(BUFS)->cur->buf.last = B; \
} while(0)
#define nghttp2_bufs_fast_addb_hold(BUFS, B) \
do { \
*(BUFS)->cur->buf.last = B; \
} while (0)
/*
* Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
@ -294,15 +293,15 @@ int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
*/
int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
#define nghttp2_bufs_fast_orb(BUFS, B) \
do { \
*(BUFS)->cur->buf.last++ |= B; \
} while(0)
#define nghttp2_bufs_fast_orb(BUFS, B) \
do { \
*(BUFS)->cur->buf.last++ |= B; \
} while (0)
#define nghttp2_bufs_fast_orb_hold(BUFS, B) \
do { \
*(BUFS)->cur->buf.last |= B; \
} while(0)
#define nghttp2_bufs_fast_orb_hold(BUFS, B) \
do { \
*(BUFS)->cur->buf.last |= B; \
} while (0)
/*
* Copies all data stored in |bufs| to the contagious buffer. This
@ -342,10 +341,10 @@ void nghttp2_bufs_reset(nghttp2_bufs *bufs);
int nghttp2_bufs_advance(nghttp2_bufs *bufs);
/* Sets bufs->cur to bufs->head */
#define nghttp2_bufs_rewind(BUFS) \
do { \
(BUFS)->cur = (BUFS)->head; \
} while(0)
#define nghttp2_bufs_rewind(BUFS) \
do { \
(BUFS)->cur = (BUFS)->head; \
} while (0)
/*
* Move bufs->cur, from the current position, using next member, to

View File

@ -26,114 +26,98 @@
#include <stdlib.h>
int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr)
{
int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr) {
*callbacks_ptr = calloc(1, sizeof(nghttp2_session_callbacks));
if(*callbacks_ptr == NULL) {
if (*callbacks_ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
return 0;
}
void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks)
{
void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks) {
free(callbacks);
}
void nghttp2_session_callbacks_set_send_callback
(nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback)
{
void nghttp2_session_callbacks_set_send_callback(
nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback) {
cbs->send_callback = send_callback;
}
void nghttp2_session_callbacks_set_recv_callback
(nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback)
{
void nghttp2_session_callbacks_set_recv_callback(
nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) {
cbs->recv_callback = recv_callback;
}
void nghttp2_session_callbacks_set_on_frame_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_recv_callback on_frame_recv_callback)
{
void nghttp2_session_callbacks_set_on_frame_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
cbs->on_frame_recv_callback = on_frame_recv_callback;
}
void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback)
{
void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
cbs->on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
}
void nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback)
{
void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
cbs->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
}
void nghttp2_session_callbacks_set_before_frame_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_before_frame_send_callback before_frame_send_callback)
{
void nghttp2_session_callbacks_set_before_frame_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_before_frame_send_callback before_frame_send_callback) {
cbs->before_frame_send_callback = before_frame_send_callback;
}
void nghttp2_session_callbacks_set_on_frame_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_send_callback on_frame_send_callback)
{
void nghttp2_session_callbacks_set_on_frame_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_send_callback on_frame_send_callback) {
cbs->on_frame_send_callback = on_frame_send_callback;
}
void nghttp2_session_callbacks_set_on_frame_not_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_not_send_callback on_frame_not_send_callback)
{
void nghttp2_session_callbacks_set_on_frame_not_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
cbs->on_frame_not_send_callback = on_frame_not_send_callback;
}
void nghttp2_session_callbacks_set_on_stream_close_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_stream_close_callback on_stream_close_callback)
{
void nghttp2_session_callbacks_set_on_stream_close_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_stream_close_callback on_stream_close_callback) {
cbs->on_stream_close_callback = on_stream_close_callback;
}
void nghttp2_session_callbacks_set_on_begin_headers_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_begin_headers_callback on_begin_headers_callback)
{
void nghttp2_session_callbacks_set_on_begin_headers_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_begin_headers_callback on_begin_headers_callback) {
cbs->on_begin_headers_callback = on_begin_headers_callback;
}
void nghttp2_session_callbacks_set_on_header_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_header_callback on_header_callback)
{
void nghttp2_session_callbacks_set_on_header_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_header_callback on_header_callback) {
cbs->on_header_callback = on_header_callback;
}
void nghttp2_session_callbacks_set_select_padding_callback
(nghttp2_session_callbacks *cbs,
nghttp2_select_padding_callback select_padding_callback)
{
void nghttp2_session_callbacks_set_select_padding_callback(
nghttp2_session_callbacks *cbs,
nghttp2_select_padding_callback select_padding_callback) {
cbs->select_padding_callback = select_padding_callback;
}
void nghttp2_session_callbacks_set_data_source_read_length_callback
(nghttp2_session_callbacks *cbs,
nghttp2_data_source_read_length_callback data_source_read_length_callback)
{
void nghttp2_session_callbacks_set_data_source_read_length_callback(
nghttp2_session_callbacks *cbs,
nghttp2_data_source_read_length_callback data_source_read_length_callback) {
cbs->read_length_callback = data_source_read_length_callback;
}
void nghttp2_session_callbacks_set_on_begin_frame_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_begin_frame_callback on_begin_frame_callback)
{
void nghttp2_session_callbacks_set_on_begin_frame_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
cbs->on_begin_frame_callback = on_begin_frame_callback;
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_CALLBACKS_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -33,17 +33,15 @@
#include "nghttp2_net.h"
#include "nghttp2_priority_spec.h"
void nghttp2_frame_pack_frame_hd(uint8_t* buf, const nghttp2_frame_hd *hd)
{
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) {
nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8));
buf[3]= hd->type;
buf[3] = hd->type;
buf[4] = hd->flags;
nghttp2_put_uint32be(&buf[5], hd->stream_id);
/* ignore hd->reserved for now */
}
void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t* buf)
{
void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf) {
hd->length = nghttp2_get_uint32(&buf[0]) >> 8;
hd->type = buf[3];
hd->flags = buf[4];
@ -51,10 +49,8 @@ void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t* buf)
hd->reserved = 0;
}
void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length,
uint8_t type, uint8_t flags,
int32_t stream_id)
{
void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
uint8_t flags, int32_t stream_id) {
hd->length = length;
hd->type = type;
hd->flags = flags;
@ -62,73 +58,59 @@ void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length,
hd->reserved = 0;
}
void nghttp2_frame_headers_init(nghttp2_headers *frame,
uint8_t flags, int32_t stream_id,
nghttp2_headers_category cat,
void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
int32_t stream_id, nghttp2_headers_category cat,
const nghttp2_priority_spec *pri_spec,
nghttp2_nv *nva, size_t nvlen)
{
nghttp2_nv *nva, size_t nvlen) {
nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_HEADERS, flags, stream_id);
frame->padlen = 0;
frame->nva = nva;
frame->nvlen = nvlen;
frame->cat = cat;
if(pri_spec) {
if (pri_spec) {
frame->pri_spec = *pri_spec;
} else {
nghttp2_priority_spec_default_init(&frame->pri_spec);
}
}
void nghttp2_frame_headers_free(nghttp2_headers *frame)
{
void nghttp2_frame_headers_free(nghttp2_headers *frame) {
nghttp2_nv_array_del(frame->nva);
}
void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
const nghttp2_priority_spec *pri_spec)
{
const nghttp2_priority_spec *pri_spec) {
nghttp2_frame_hd_init(&frame->hd, NGHTTP2_PRIORITY_SPECLEN, NGHTTP2_PRIORITY,
NGHTTP2_FLAG_NONE, stream_id);
frame->pri_spec = *pri_spec;
}
void nghttp2_frame_priority_free(nghttp2_priority *frame _U_)
{}
void nghttp2_frame_priority_free(nghttp2_priority *frame _U_) {}
void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame,
int32_t stream_id,
uint32_t error_code)
{
void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
uint32_t error_code) {
nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE,
stream_id);
frame->error_code = error_code;
}
void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame _U_)
{}
void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame _U_) {}
void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
nghttp2_settings_entry *iv, size_t niv)
{
nghttp2_settings_entry *iv, size_t niv) {
nghttp2_frame_hd_init(&frame->hd, niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH,
NGHTTP2_SETTINGS, flags, 0);
frame->niv = niv;
frame->iv = iv;
}
void nghttp2_frame_settings_free(nghttp2_settings *frame)
{
free(frame->iv);
}
void nghttp2_frame_settings_free(nghttp2_settings *frame) { free(frame->iv); }
void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame,
uint8_t flags, int32_t stream_id,
void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
int32_t stream_id,
int32_t promised_stream_id,
nghttp2_nv *nva, size_t nvlen)
{
nghttp2_nv *nva, size_t nvlen) {
nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_PUSH_PROMISE, flags, stream_id);
frame->padlen = 0;
frame->nva = nva;
@ -137,30 +119,26 @@ void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame,
frame->reserved = 0;
}
void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame)
{
void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame) {
nghttp2_nv_array_del(frame->nva);
}
void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags,
const uint8_t *opaque_data)
{
const uint8_t *opaque_data) {
nghttp2_frame_hd_init(&frame->hd, 8, NGHTTP2_PING, flags, 0);
if(opaque_data) {
if (opaque_data) {
memcpy(frame->opaque_data, opaque_data, sizeof(frame->opaque_data));
} else {
memset(frame->opaque_data, 0, sizeof(frame->opaque_data));
}
}
void nghttp2_frame_ping_free(nghttp2_ping *frame _U_)
{}
void nghttp2_frame_ping_free(nghttp2_ping *frame _U_) {}
void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
uint32_t error_code,
uint8_t *opaque_data, size_t opaque_data_len)
{
nghttp2_frame_hd_init(&frame->hd, 8+opaque_data_len, NGHTTP2_GOAWAY,
uint32_t error_code, uint8_t *opaque_data,
size_t opaque_data_len) {
nghttp2_frame_hd_init(&frame->hd, 8 + opaque_data_len, NGHTTP2_GOAWAY,
NGHTTP2_FLAG_NONE, 0);
frame->last_stream_id = last_stream_id;
frame->error_code = error_code;
@ -169,33 +147,25 @@ void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
frame->reserved = 0;
}
void nghttp2_frame_goaway_free(nghttp2_goaway *frame)
{
void nghttp2_frame_goaway_free(nghttp2_goaway *frame) {
free(frame->opaque_data);
}
void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
uint8_t flags,
int32_t stream_id,
int32_t window_size_increment)
{
nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_WINDOW_UPDATE, flags,
stream_id);
uint8_t flags, int32_t stream_id,
int32_t window_size_increment) {
nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_WINDOW_UPDATE, flags, stream_id);
frame->window_size_increment = window_size_increment;
frame->reserved = 0;
}
void nghttp2_frame_window_update_free(nghttp2_window_update *frame _U_)
{}
void nghttp2_frame_window_update_free(nghttp2_window_update *frame _U_) {}
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
uint32_t max_age,
uint16_t port,
uint8_t *protocol_id,
size_t protocol_id_len,
uint8_t *host, size_t host_len,
uint8_t *origin, size_t origin_len)
{
uint32_t max_age, uint16_t port,
uint8_t *protocol_id, size_t protocol_id_len,
uint8_t *host, size_t host_len, uint8_t *origin,
size_t origin_len) {
size_t payloadlen;
nghttp2_ext_altsvc *altsvc;
@ -216,46 +186,40 @@ void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
altsvc->origin_len = origin_len;
}
void nghttp2_frame_altsvc_free(nghttp2_extension *frame)
{
void nghttp2_frame_altsvc_free(nghttp2_extension *frame) {
nghttp2_ext_altsvc *altsvc;
altsvc = frame->payload;
if(altsvc == NULL) {
if (altsvc == NULL) {
return;
}
free(altsvc->protocol_id);
}
size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen)
{
size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) {
return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0);
}
void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
int32_t stream_id)
{
int32_t stream_id) {
/* At this moment, the length of DATA frame is unknown */
nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id);
frame->padlen = 0;
}
void nghttp2_frame_data_free(nghttp2_data *frame _U_)
{}
void nghttp2_frame_data_free(nghttp2_data *frame _U_) {}
size_t nghttp2_frame_priority_len(uint8_t flags)
{
if(flags & NGHTTP2_FLAG_PRIORITY) {
size_t nghttp2_frame_priority_len(uint8_t flags) {
if (flags & NGHTTP2_FLAG_PRIORITY) {
return NGHTTP2_PRIORITY_SPECLEN;
}
return 0;
}
size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame)
{
size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) {
return nghttp2_frame_priority_len(frame->hd.flags);
}
@ -272,8 +236,7 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame)
* We don't process any padding here.
*/
static int frame_pack_headers_shared(nghttp2_bufs *bufs,
nghttp2_frame_hd *frame_hd)
{
nghttp2_frame_hd *frame_hd) {
nghttp2_buf *buf;
nghttp2_buf_chain *ci, *ce;
nghttp2_frame_hd hd;
@ -283,20 +246,20 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
hd = *frame_hd;
hd.length = nghttp2_buf_len(buf);
DEBUGF(fprintf(stderr,
"send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length));
DEBUGF(fprintf(stderr, "send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n",
hd.length));
/* We have multiple frame buffers, which means one or more
CONTINUATION frame is involved. Remove END_HEADERS flag from the
first frame. */
if(bufs->head != bufs->cur) {
if (bufs->head != bufs->cur) {
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
}
buf->pos -= NGHTTP2_FRAME_HDLEN;
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
if(bufs->head != bufs->cur) {
if (bufs->head != bufs->cur) {
/* 2nd and later frames are CONTINUATION frames. */
hd.type = NGHTTP2_CONTINUATION;
/* We don't have no flags except for last CONTINUATION */
@ -304,13 +267,13 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
ce = bufs->cur;
for(ci = bufs->head->next; ci != ce; ci = ci->next) {
for (ci = bufs->head->next; ci != ce; ci = ci->next) {
buf = &ci->buf;
hd.length = nghttp2_buf_len(buf);
DEBUGF(fprintf(stderr,
"send: int CONTINUATION, payloadlen=%zu\n", hd.length));
DEBUGF(fprintf(stderr, "send: int CONTINUATION, payloadlen=%zu\n",
hd.length));
buf->pos -= NGHTTP2_FRAME_HDLEN;
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
@ -321,8 +284,8 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
/* Set END_HEADERS flag for last CONTINUATION */
hd.flags = NGHTTP2_FLAG_END_HEADERS;
DEBUGF(fprintf(stderr,
"send: last CONTINUATION, payloadlen=%zu\n", hd.length));
DEBUGF(fprintf(stderr, "send: last CONTINUATION, payloadlen=%zu\n",
hd.length));
buf->pos -= NGHTTP2_FRAME_HDLEN;
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
@ -331,10 +294,8 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
return 0;
}
int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
nghttp2_headers *frame,
nghttp2_hd_deflater *deflater)
{
int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
nghttp2_hd_deflater *deflater) {
size_t nv_offset;
int rv;
nghttp2_buf *buf;
@ -351,17 +312,17 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
/* This call will adjust buf->last to the correct position */
rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
rv = NGHTTP2_ERR_HEADER_COMP;
}
buf->pos -= nv_offset;
if(rv != 0) {
if (rv != 0) {
return rv;
}
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec);
}
@ -372,10 +333,9 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
}
void nghttp2_frame_pack_priority_spec(uint8_t *buf,
const nghttp2_priority_spec *pri_spec)
{
const nghttp2_priority_spec *pri_spec) {
nghttp2_put_uint32be(buf, pri_spec->stream_id);
if(pri_spec->exclusive) {
if (pri_spec->exclusive) {
buf[0] |= 0x80;
}
buf[4] = pri_spec->weight - 1;
@ -384,8 +344,7 @@ void nghttp2_frame_pack_priority_spec(uint8_t *buf,
void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
uint8_t flags _U_,
const uint8_t *payload,
size_t payloadlen _U_)
{
size_t payloadlen _U_) {
int32_t dep_stream_id;
uint8_t exclusive;
int32_t weight;
@ -399,9 +358,8 @@ void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
const uint8_t *payload,
size_t payloadlen)
{
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
size_t payloadlen) {
if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, frame->hd.flags,
payload, payloadlen);
} else {
@ -414,8 +372,7 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
return 0;
}
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame)
{
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
nghttp2_buf *buf;
assert(bufs->head == bufs->cur);
@ -437,15 +394,13 @@ int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame)
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
const uint8_t *payload,
size_t payloadlen)
{
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, frame->hd.flags,
payload, payloadlen);
size_t payloadlen) {
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, frame->hd.flags, payload,
payloadlen);
}
int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
nghttp2_rst_stream *frame)
{
nghttp2_rst_stream *frame) {
nghttp2_buf *buf;
assert(bufs->head == bufs->cur);
@ -466,20 +421,18 @@ int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
const uint8_t *payload,
size_t payloadlen _U_)
{
size_t payloadlen _U_) {
frame->error_code = nghttp2_get_uint32(payload);
}
int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame)
{
int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) {
nghttp2_buf *buf;
assert(bufs->head == bufs->cur);
buf = &bufs->head->buf;
if(nghttp2_buf_avail(buf) < (ssize_t)frame->hd.length) {
if (nghttp2_buf_avail(buf) < (ssize_t)frame->hd.length) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
@ -487,18 +440,17 @@ int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame)
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
buf->last += nghttp2_frame_pack_settings_payload(buf->last,
frame->iv, frame->niv);
buf->last +=
nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv);
return 0;
}
size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
const nghttp2_settings_entry *iv,
size_t niv)
{
size_t niv) {
size_t i;
for(i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
for (i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
nghttp2_put_uint16be(buf, iv[i].settings_id);
nghttp2_put_uint32be(buf + 2, iv[i].value);
}
@ -507,16 +459,15 @@ size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
nghttp2_settings_entry *iv,
size_t niv)
{
size_t niv) {
size_t payloadlen = niv * sizeof(nghttp2_settings_entry);
if(niv == 0) {
if (niv == 0) {
frame->iv = NULL;
} else {
frame->iv = malloc(payloadlen);
if(frame->iv == NULL) {
if (frame->iv == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -528,8 +479,7 @@ int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
}
void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
const uint8_t *payload)
{
const uint8_t *payload) {
iv->settings_id = nghttp2_get_uint16(&payload[0]);
iv->value = nghttp2_get_uint32(&payload[2]);
}
@ -537,26 +487,24 @@ void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
size_t *niv_ptr,
const uint8_t *payload,
size_t payloadlen)
{
size_t payloadlen) {
size_t i;
*niv_ptr = payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
if(*niv_ptr == 0) {
if (*niv_ptr == 0) {
*iv_ptr = NULL;
return 0;
}
*iv_ptr = malloc((*niv_ptr) * sizeof(nghttp2_settings_entry));
*iv_ptr = malloc((*niv_ptr)*sizeof(nghttp2_settings_entry));
if(*iv_ptr == NULL) {
if (*iv_ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
for(i = 0; i < *niv_ptr; ++i) {
for (i = 0; i < *niv_ptr; ++i) {
size_t off = i * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]);
}
@ -566,8 +514,7 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
nghttp2_push_promise *frame,
nghttp2_hd_deflater *deflater)
{
nghttp2_hd_deflater *deflater) {
size_t nv_offset = 4;
int rv;
nghttp2_buf *buf;
@ -582,13 +529,13 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
/* This call will adjust buf->last to the correct position */
rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
rv = NGHTTP2_ERR_HEADER_COMP;
}
buf->pos -= nv_offset;
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -602,17 +549,15 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
const uint8_t *payload,
size_t payloadlen _U_)
{
frame->promised_stream_id = nghttp2_get_uint32(payload) &
NGHTTP2_STREAM_ID_MASK;
size_t payloadlen _U_) {
frame->promised_stream_id =
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
frame->nva = NULL;
frame->nvlen = 0;
return 0;
}
int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame)
{
int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
nghttp2_buf *buf;
assert(bufs->head == bufs->cur);
@ -625,21 +570,19 @@ int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame)
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
buf->last = nghttp2_cpymem(buf->last, frame->opaque_data,
sizeof(frame->opaque_data));
buf->last =
nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
return 0;
}
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
const uint8_t *payload,
size_t payloadlen _U_)
{
size_t payloadlen _U_) {
memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
}
int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame)
{
int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame) {
int rv;
nghttp2_buf *buf;
@ -659,11 +602,11 @@ int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame)
rv = nghttp2_bufs_add(bufs, frame->opaque_data, frame->opaque_data_len);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -674,8 +617,7 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen _U_,
uint8_t *var_gift_payload,
size_t var_gift_payloadlen)
{
size_t var_gift_payloadlen) {
frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
frame->error_code = nghttp2_get_uint32(payload + 4);
@ -685,12 +627,11 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen)
{
size_t payloadlen) {
uint8_t *var_gift_payload;
size_t var_gift_payloadlen;
if(payloadlen > 8) {
if (payloadlen > 8) {
var_gift_payloadlen = payloadlen - 8;
} else {
var_gift_payloadlen = 0;
@ -698,12 +639,12 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
payloadlen -= var_gift_payloadlen;
if(!var_gift_payloadlen) {
if (!var_gift_payloadlen) {
var_gift_payload = NULL;
} else {
var_gift_payload = malloc(var_gift_payloadlen);
if(var_gift_payload == NULL) {
if (var_gift_payload == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -717,8 +658,7 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
}
int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
nghttp2_window_update *frame)
{
nghttp2_window_update *frame) {
nghttp2_buf *buf;
assert(bufs->head == bufs->cur);
@ -739,14 +679,12 @@ int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
const uint8_t *payload,
size_t payloadlen _U_)
{
frame->window_size_increment = nghttp2_get_uint32(payload) &
NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
size_t payloadlen _U_) {
frame->window_size_increment =
nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
}
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame)
{
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
int rv;
nghttp2_buf *buf;
nghttp2_ext_altsvc *altsvc;
@ -771,30 +709,30 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame)
++buf->last;
rv = nghttp2_bufs_add(bufs, altsvc->protocol_id, altsvc->protocol_id_len);
if(rv != 0) {
if (rv != 0) {
goto fail;
}
rv = nghttp2_bufs_addb(bufs, altsvc->host_len);
if(rv != 0) {
if (rv != 0) {
goto fail;
}
rv = nghttp2_bufs_add(bufs, altsvc->host, altsvc->host_len);
if(rv != 0) {
if (rv != 0) {
goto fail;
}
rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len);
if(rv != 0) {
if (rv != 0) {
goto fail;
}
return 0;
fail:
fail:
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
@ -805,8 +743,7 @@ int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
const uint8_t *payload,
size_t payloadlen _U_,
uint8_t *var_gift_payload,
size_t var_gift_payloadlen)
{
size_t var_gift_payloadlen) {
nghttp2_buf buf;
nghttp2_ext_altsvc *altsvc;
@ -824,7 +761,7 @@ int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
buf.last += var_gift_payloadlen;
/* 1 for Host-Len */
if(nghttp2_buf_len(&buf) < 1 + (ssize_t)altsvc->protocol_id_len) {
if (nghttp2_buf_len(&buf) < 1 + (ssize_t)altsvc->protocol_id_len) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
@ -834,7 +771,7 @@ int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
altsvc->host_len = *buf.pos;
++buf.pos;
if(nghttp2_buf_len(&buf) < (ssize_t)altsvc->host_len) {
if (nghttp2_buf_len(&buf) < (ssize_t)altsvc->host_len) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
@ -847,19 +784,18 @@ int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
return 0;
}
nghttp2_settings_entry* nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
size_t niv)
{
nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
size_t niv) {
nghttp2_settings_entry *iv_copy;
size_t len = niv*sizeof(nghttp2_settings_entry);
size_t len = niv * sizeof(nghttp2_settings_entry);
if(len == 0) {
if (len == 0) {
return NULL;
}
iv_copy = malloc(len);
if(iv_copy == NULL) {
if (iv_copy == NULL) {
return NULL;
}
@ -868,31 +804,26 @@ nghttp2_settings_entry* nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
return iv_copy;
}
int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b)
{
int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b) {
return a->namelen == b->namelen && a->valuelen == b->valuelen &&
memcmp(a->name, b->name, a->namelen) == 0 &&
memcmp(a->value, b->value, a->valuelen) == 0;
memcmp(a->name, b->name, a->namelen) == 0 &&
memcmp(a->value, b->value, a->valuelen) == 0;
}
void nghttp2_nv_array_del(nghttp2_nv *nva)
{
free(nva);
}
void nghttp2_nv_array_del(nghttp2_nv *nva) { free(nva); }
static int bytes_compar(const uint8_t *a, size_t alen,
const uint8_t *b, size_t blen)
{
static int bytes_compar(const uint8_t *a, size_t alen, const uint8_t *b,
size_t blen) {
int rv;
if(alen == blen) {
if (alen == blen) {
return memcmp(a, b, alen);
}
if(alen < blen) {
if (alen < blen) {
rv = memcmp(a, b, alen);
if(rv == 0) {
if (rv == 0) {
return -1;
}
@ -901,68 +832,64 @@ static int bytes_compar(const uint8_t *a, size_t alen,
rv = memcmp(a, b, blen);
if(rv == 0) {
if (rv == 0) {
return 1;
}
return rv;
}
int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs)
{
int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs) {
return bytes_compar(lhs->name, lhs->namelen, rhs->name, rhs->namelen);
}
static int nv_compar(const void *lhs, const void *rhs)
{
const nghttp2_nv *a = (const nghttp2_nv*)lhs;
const nghttp2_nv *b = (const nghttp2_nv*)rhs;
static int nv_compar(const void *lhs, const void *rhs) {
const nghttp2_nv *a = (const nghttp2_nv *)lhs;
const nghttp2_nv *b = (const nghttp2_nv *)rhs;
int rv;
rv = bytes_compar(a->name, a->namelen, b->name, b->namelen);
if(rv == 0) {
if (rv == 0) {
return bytes_compar(a->value, a->valuelen, b->value, b->valuelen);
}
return rv;
}
void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen)
{
void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen) {
qsort(nva, nvlen, sizeof(nghttp2_nv), nv_compar);
}
int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
const nghttp2_nv *nva, size_t nvlen)
{
int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
size_t nvlen) {
size_t i;
uint8_t *data;
size_t buflen = 0;
nghttp2_nv *p;
for(i = 0; i < nvlen; ++i) {
for (i = 0; i < nvlen; ++i) {
buflen += nva[i].namelen + nva[i].valuelen;
}
if(nvlen == 0) {
if (nvlen == 0) {
*nva_ptr = NULL;
return 0;
}
buflen += sizeof(nghttp2_nv)*nvlen;
buflen += sizeof(nghttp2_nv) * nvlen;
*nva_ptr = malloc(buflen);
if(*nva_ptr == NULL) {
if (*nva_ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
p = *nva_ptr;
data = (uint8_t*)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen;
data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen;
for(i = 0; i < nvlen; ++i) {
for (i = 0; i < nvlen; ++i) {
p->flags = nva[i].flags;
memcpy(data, nva[i].name, nva[i].namelen);
@ -979,31 +906,30 @@ int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
return 0;
}
int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv)
{
int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
size_t i;
for(i = 0; i < niv; ++i) {
switch(iv[i].settings_id) {
for (i = 0; i < niv; ++i) {
switch (iv[i].settings_id) {
case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
if(iv[i].value > NGHTTP2_MAX_HEADER_TABLE_SIZE) {
if (iv[i].value > NGHTTP2_MAX_HEADER_TABLE_SIZE) {
return 0;
}
break;
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
break;
case NGHTTP2_SETTINGS_ENABLE_PUSH:
if(iv[i].value != 0 && iv[i].value != 1) {
if (iv[i].value != 0 && iv[i].value != 1) {
return 0;
}
break;
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
if(iv[i].value > (uint32_t)NGHTTP2_MAX_WINDOW_SIZE) {
if (iv[i].value > (uint32_t)NGHTTP2_MAX_WINDOW_SIZE) {
return 0;
}
break;
case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
if(iv[i].value < NGHTTP2_MAX_FRAME_SIZE_MIN ||
iv[i].value > NGHTTP2_MAX_FRAME_SIZE_MAX) {
if (iv[i].value < NGHTTP2_MAX_FRAME_SIZE_MIN ||
iv[i].value > NGHTTP2_MAX_FRAME_SIZE_MAX) {
return 0;
}
break;
@ -1014,8 +940,7 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv)
return 1;
}
static void frame_set_pad(nghttp2_buf *buf, size_t padlen)
{
static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
size_t trail_padlen;
size_t newlen;
@ -1043,11 +968,10 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen)
}
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
size_t padlen)
{
size_t padlen) {
nghttp2_buf *buf;
if(padlen == 0) {
if (padlen == 0) {
DEBUGF(fprintf(stderr, "send: padlen = 0, nothing to do\n"));
return 0;
@ -1082,8 +1006,8 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
hd->length += padlen;
hd->flags |= NGHTTP2_FLAG_PADDED;
DEBUGF(fprintf(stderr, "send: final payloadlen=%zu, padlen=%zu\n",
hd->length, padlen));
DEBUGF(fprintf(stderr, "send: final payloadlen=%zu, padlen=%zu\n", hd->length,
padlen));
return 0;
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_FRAME_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -49,7 +49,7 @@
/* The one frame buffer length for tranmission. We may use several of
them to support CONTINUATION. To account for Pad Length field, we
allocate extra 1 byte, which saves extra large memcopying. */
#define NGHTTP2_FRAMEBUF_CHUNKLEN \
#define NGHTTP2_FRAMEBUF_CHUNKLEN \
(NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN)
/* Number of inbound buffer */
@ -57,7 +57,8 @@
/* The default length of DATA frame payload. This should be small enough
* for the data payload and the header to fit into 1 TLS record */
#define NGHTTP2_DATA_PAYLOADLEN ((NGHTTP2_MAX_FRAME_SIZE_MIN) - (NGHTTP2_FRAME_HDLEN))
#define NGHTTP2_DATA_PAYLOADLEN \
((NGHTTP2_MAX_FRAME_SIZE_MIN) - (NGHTTP2_FRAME_HDLEN))
/* Maximum headers payload length, calculated in compressed form.
This applies to transmission only. */
@ -84,21 +85,18 @@
#define NGHTTP2_MAX_PADLEN 256
/* Union of extension frame payload */
typedef union {
nghttp2_ext_altsvc altsvc;
} nghttp2_ext_frame_payload;
typedef union { nghttp2_ext_altsvc altsvc; } nghttp2_ext_frame_payload;
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t* buf);
void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf);
/**
* Initializes frame header |hd| with given parameters. Reserved bit
* is set to 0.
*/
void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length,
uint8_t type, uint8_t flags,
int32_t stream_id);
void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
uint8_t flags, int32_t stream_id);
/**
* Returns the number of priority field depending on the |flags|. If
@ -121,8 +119,7 @@ void nghttp2_frame_pack_priority_spec(uint8_t *buf,
* assumes the |payload| contains whole priority specification.
*/
void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
uint8_t flags,
const uint8_t *payload,
uint8_t flags, const uint8_t *payload,
size_t payloadlen);
/*
@ -151,8 +148,7 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
nghttp2_headers *frame,
int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
nghttp2_hd_deflater *deflater);
/*
@ -175,8 +171,7 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
*
* This function always succeeds and returns 0.
*/
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs,
nghttp2_priority *frame);
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
/*
* Unpacks PRIORITY wire format into |frame|.
@ -405,7 +400,6 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
*/
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame);
/*
* Unpacks ALTSVC frame byte sequence into |frame|.
* The |payload| of length |payloadlen| contains first 8 bytes of
@ -434,22 +428,19 @@ int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
* ownership of |nva|, so caller must not free it. If |stream_id| is
* not assigned yet, it must be -1.
*/
void nghttp2_frame_headers_init(nghttp2_headers *frame,
uint8_t flags, int32_t stream_id,
nghttp2_headers_category cat,
void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
int32_t stream_id, nghttp2_headers_category cat,
const nghttp2_priority_spec *pri_spec,
nghttp2_nv *nva, size_t nvlen);
void nghttp2_frame_headers_free(nghttp2_headers *frame);
void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
const nghttp2_priority_spec *pri_spec);
void nghttp2_frame_priority_free(nghttp2_priority *frame);
void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame,
int32_t stream_id,
void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
uint32_t error_code);
void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame);
@ -458,8 +449,8 @@ void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame);
* Initializes PUSH_PROMISE frame |frame| with given values. |frame|
* takes ownership of |nva|, so caller must not free it.
*/
void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame,
uint8_t flags, int32_t stream_id,
void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
int32_t stream_id,
int32_t promised_stream_id,
nghttp2_nv *nva, size_t nvlen);
@ -492,14 +483,13 @@ void nghttp2_frame_ping_free(nghttp2_ping *frame);
* free it. If the |opaque_data_len| is 0, opaque_data could be NULL.
*/
void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
uint32_t error_code,
uint8_t *opaque_data, size_t opaque_data_len);
uint32_t error_code, uint8_t *opaque_data,
size_t opaque_data_len);
void nghttp2_frame_goaway_free(nghttp2_goaway *frame);
void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
uint8_t flags,
int32_t stream_id,
uint8_t flags, int32_t stream_id,
int32_t window_size_increment);
void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
@ -511,12 +501,10 @@ void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
|protocol_id_len|, |host_len| and |origin_len| are all zero,
|protocol_id| can be NULL. */
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
uint32_t max_age,
uint16_t port,
uint8_t *protocol_id,
size_t protocol_id_len,
uint8_t *host, size_t host_len,
uint8_t *origin, size_t origin_len);
uint32_t max_age, uint16_t port,
uint8_t *protocol_id, size_t protocol_id_len,
uint8_t *host, size_t host_len, uint8_t *origin,
size_t origin_len);
/*
* Frees resources used by |frame|. This function does not free
@ -541,7 +529,7 @@ void nghttp2_frame_data_free(nghttp2_data *frame);
* entries in |iv|. This function returns the pointer to the copy if
* it succeeds, or NULL.
*/
nghttp2_settings_entry* nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
size_t niv);
/*
@ -563,8 +551,8 @@ void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen);
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
const nghttp2_nv *nva, size_t nvlen);
int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
size_t nvlen);
/*
* Returns nonzero if the name/value pair |a| equals to |b|. The name

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
#define NGHTTP2_HD_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -183,9 +183,8 @@ struct nghttp2_hd_inflater {
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags,
uint8_t *name, size_t namelen,
uint8_t *value, size_t valuelen,
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
size_t namelen, uint8_t *value, size_t valuelen,
uint32_t name_hash, uint32_t value_hash);
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
@ -248,8 +247,8 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);
* Out of buffer space.
*/
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs,
const nghttp2_nv *nva, size_t nvlen);
nghttp2_bufs *bufs, const nghttp2_nv *nva,
size_t nvlen);
/*
* Initializes |inflater| for inflating name/values pairs.
@ -279,13 +278,13 @@ int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
/* For unittesting purpose */
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
size_t index);
/* For unittesting purpose */
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,
uint32_t initial, size_t shift,
uint8_t *in, uint8_t *last, size_t prefix);
uint32_t initial, size_t shift, uint8_t *in,
uint8_t *last, size_t prefix);
/* Huffman encoding/decoding functions */
@ -310,8 +309,8 @@ size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len);
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs,
const uint8_t *src, size_t srclen);
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen);
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
@ -339,7 +338,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
* Decoding process has failed.
*/
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_bufs *bufs,
const uint8_t *src, size_t srclen, int final);
nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen, int final);
#endif /* NGHTTP2_HD_H */

View File

@ -41,19 +41,17 @@ extern const nghttp2_huff_decode huff_decode_table[][16];
* unfilled bits in the pointed location is returned.
*/
static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
size_t rembits,
const nghttp2_huff_sym *sym)
{
size_t rembits, const nghttp2_huff_sym *sym) {
int rv;
size_t nbits = sym->nbits;
for(;;) {
if(rembits > nbits) {
if(*avail_ptr) {
for (;;) {
if (rembits > nbits) {
if (*avail_ptr) {
nghttp2_bufs_fast_orb_hold(bufs, sym->code << (rembits - nbits));
} else {
rv = nghttp2_bufs_orb_hold(bufs, sym->code << (rembits - nbits));
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -65,12 +63,12 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
break;
}
if(*avail_ptr) {
if (*avail_ptr) {
nghttp2_bufs_fast_orb(bufs, sym->code >> (nbits - rembits));
--*avail_ptr;
} else {
rv = nghttp2_bufs_orb(bufs, sym->code >> (nbits - rembits));
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -80,15 +78,15 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
nbits -= rembits;
rembits = 8;
if(nbits == 0) {
if (nbits == 0) {
break;
}
if(*avail_ptr) {
if (*avail_ptr) {
nghttp2_bufs_fast_addb_hold(bufs, 0);
} else {
rv = nghttp2_bufs_addb_hold(bufs, 0);
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -98,21 +96,19 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
return (ssize_t)rembits;
}
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len)
{
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) {
size_t i;
size_t nbits = 0;
for(i = 0; i < len; ++i) {
for (i = 0; i < len; ++i) {
nbits += huff_sym_table[src[i]].nbits;
}
/* pad the prefix of EOS (256) */
return (nbits + 7) / 8;
}
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs,
const uint8_t *src, size_t srclen)
{
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen) {
int rv;
ssize_t rembits = 8;
size_t i;
@ -120,34 +116,34 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs,
avail = nghttp2_bufs_cur_avail(bufs);
for(i = 0; i < srclen; ++i) {
for (i = 0; i < srclen; ++i) {
const nghttp2_huff_sym *sym = &huff_sym_table[src[i]];
if(rembits == 8) {
if(avail) {
if (rembits == 8) {
if (avail) {
nghttp2_bufs_fast_addb_hold(bufs, 0);
} else {
rv = nghttp2_bufs_addb_hold(bufs, 0);
if(rv != 0) {
if (rv != 0) {
return rv;
}
avail = nghttp2_bufs_cur_avail(bufs);
}
}
rembits = huff_encode_sym(bufs, &avail, rembits, sym);
if(rembits < 0) {
if (rembits < 0) {
return (int)rembits;
}
}
/* 256 is special terminal symbol, pad with its prefix */
if(rembits < 8) {
if (rembits < 8) {
const nghttp2_huff_sym *sym = &huff_sym_table[256];
/* Caution we no longer adjust avail here */
if(avail) {
if (avail) {
nghttp2_bufs_fast_orb(bufs, sym->code >> (sym->nbits - rembits));
} else {
rv = nghttp2_bufs_orb(bufs, sym->code >> (sym->nbits - rembits));
if(rv != 0) {
if (rv != 0) {
return rv;
}
}
@ -156,16 +152,14 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs,
return 0;
}
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx)
{
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
ctx->state = 0;
ctx->accept = 1;
}
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_bufs *bufs,
const uint8_t *src, size_t srclen, int final)
{
nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen, int final) {
size_t i, j;
int rv;
size_t avail;
@ -174,22 +168,22 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
/* We use the decoding algorithm described in
http://graphics.ics.uci.edu/pub/Prefix.pdf */
for(i = 0; i < srclen; ++i) {
for (i = 0; i < srclen; ++i) {
uint8_t in = src[i] >> 4;
for(j = 0; j < 2; ++j) {
for (j = 0; j < 2; ++j) {
const nghttp2_huff_decode *t;
t = &huff_decode_table[ctx->state][in];
if(t->flags & NGHTTP2_HUFF_FAIL) {
if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP;
}
if(t->flags & NGHTTP2_HUFF_SYM) {
if(avail) {
if (t->flags & NGHTTP2_HUFF_SYM) {
if (avail) {
nghttp2_bufs_fast_addb(bufs, t->sym);
--avail;
} else {
rv = nghttp2_bufs_addb(bufs, t->sym);
if(rv != 0) {
if (rv != 0) {
return rv;
}
avail = nghttp2_bufs_cur_avail(bufs);
@ -200,7 +194,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
in = src[i] & 0xf;
}
}
if(final && !ctx->accept) {
if (final && !ctx->accept) {
return NGHTTP2_ERR_HEADER_COMP;
}
return (ssize_t)i;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_HD_HUFFMAN_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

File diff suppressed because it is too large Load Diff

View File

@ -29,42 +29,37 @@
#include "nghttp2_net.h"
void nghttp2_put_uint16be(uint8_t *buf, uint16_t n)
{
void nghttp2_put_uint16be(uint8_t *buf, uint16_t n) {
uint16_t x = htons(n);
memcpy(buf, &x, sizeof(uint16_t));
}
void nghttp2_put_uint32be(uint8_t *buf, uint32_t n)
{
void nghttp2_put_uint32be(uint8_t *buf, uint32_t n) {
uint32_t x = htonl(n);
memcpy(buf, &x, sizeof(uint32_t));
}
uint16_t nghttp2_get_uint16(const uint8_t *data)
{
uint16_t nghttp2_get_uint16(const uint8_t *data) {
uint16_t n;
memcpy(&n, data, sizeof(uint16_t));
return ntohs(n);
}
uint32_t nghttp2_get_uint32(const uint8_t *data)
{
uint32_t nghttp2_get_uint32(const uint8_t *data) {
uint32_t n;
memcpy(&n, data, sizeof(uint32_t));
return ntohl(n);
}
void* nghttp2_memdup(const void* src, size_t n)
{
void* dest;
void *nghttp2_memdup(const void *src, size_t n) {
void *dest;
if(n == 0) {
if (n == 0) {
return NULL;
}
dest = malloc(n);
if(dest == NULL) {
if (dest == NULL) {
return NULL;
}
memcpy(dest, src, n);
@ -73,76 +68,75 @@ void* nghttp2_memdup(const void* src, size_t n)
/* Generated by gendowncasetbl.py */
static const int DOWNCASE_TBL[] = {
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
};
void nghttp2_downcase(uint8_t *s, size_t len)
{
void nghttp2_downcase(uint8_t *s, size_t len) {
size_t i;
for(i = 0; i < len; ++i) {
for (i = 0; i < len; ++i) {
s[i] = DOWNCASE_TBL[s[i]];
}
}
@ -176,26 +170,25 @@ void nghttp2_downcase(uint8_t *s, size_t len)
int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
int32_t *recv_window_size_ptr,
int32_t *recv_reduction_ptr,
int32_t *delta_ptr)
{
if(*delta_ptr > 0) {
int32_t *delta_ptr) {
if (*delta_ptr > 0) {
int32_t new_recv_window_size =
nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr;
if(new_recv_window_size < 0) {
nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr;
if (new_recv_window_size < 0) {
/* The delta size is strictly more than received bytes. Increase
local_window_size by that difference. */
int32_t recv_reduction_diff;
if(*local_window_size_ptr >
NGHTTP2_MAX_WINDOW_SIZE + new_recv_window_size) {
if (*local_window_size_ptr >
NGHTTP2_MAX_WINDOW_SIZE + new_recv_window_size) {
return NGHTTP2_ERR_FLOW_CONTROL;
}
*local_window_size_ptr -= new_recv_window_size;
/* If there is recv_reduction due to earlier window_size
reduction, we have to adjust it too. */
recv_reduction_diff = nghttp2_min(*recv_reduction_ptr,
-new_recv_window_size);
recv_reduction_diff =
nghttp2_min(*recv_reduction_ptr, -new_recv_window_size);
*recv_reduction_ptr -= recv_reduction_diff;
if(*recv_window_size_ptr < 0) {
if (*recv_window_size_ptr < 0) {
*recv_window_size_ptr += recv_reduction_diff;
} else {
/* If *recv_window_size_ptr > 0, then those bytes are going to
@ -213,9 +206,9 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
}
return 0;
} else {
if(*local_window_size_ptr + *delta_ptr < 0 ||
*recv_window_size_ptr < INT32_MIN - *delta_ptr ||
*recv_reduction_ptr > INT32_MAX + *delta_ptr) {
if (*local_window_size_ptr + *delta_ptr < 0 ||
*recv_window_size_ptr < INT32_MIN - *delta_ptr ||
*recv_reduction_ptr > INT32_MAX + *delta_ptr) {
return NGHTTP2_ERR_FLOW_CONTROL;
}
/* Decreasing local window size. Note that we achieve this without
@ -231,14 +224,12 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
}
int nghttp2_should_send_window_update(int32_t local_window_size,
int32_t recv_window_size)
{
int32_t recv_window_size) {
return recv_window_size >= local_window_size / 2;
}
const char* nghttp2_strerror(int error_code)
{
switch(error_code) {
const char *nghttp2_strerror(int error_code) {
switch (error_code) {
case 0:
return "Success";
case NGHTTP2_ERR_INVALID_ARGUMENT:
@ -308,94 +299,78 @@ const char* nghttp2_strerror(int error_code)
}
}
void nghttp2_free(void *ptr)
{
free(ptr);
}
void nghttp2_free(void *ptr) { free(ptr); }
/* Generated by gennmchartbl.py */
static int VALID_HD_NAME_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */,
0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */,
1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */, 0 /* , */,
1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */,
1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */,
0 /* A */, 0 /* B */, 0 /* C */, 0 /* D */, 0 /* E */,
0 /* F */, 0 /* G */, 0 /* H */, 0 /* I */, 0 /* J */,
0 /* K */, 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 0 /* T */,
0 /* U */, 0 /* V */, 0 /* W */, 0 /* X */, 0 /* Y */,
0 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 1 /* ^ */,
1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 1 /* | */,
0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */,
0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
0 /* 0xff */
};
int nghttp2_check_header_name(const uint8_t *name, size_t len)
{
int nghttp2_check_header_name(const uint8_t *name, size_t len) {
const uint8_t *last;
if(len == 0) {
if (len == 0) {
return 0;
}
if(*name == ':') {
if(len == 1) {
if (*name == ':') {
if (len == 1) {
return 0;
}
++name;
--len;
}
for(last = name + len; name != last; ++name) {
if(!VALID_HD_NAME_CHARS[*name]) {
for (last = name + len; name != last; ++name) {
if (!VALID_HD_NAME_CHARS[*name]) {
return 0;
}
}
@ -404,85 +379,71 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len)
/* Generated by genvchartbl.py */
static int VALID_HD_VALUE_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 1 /* HT */,
0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
0 /* RS */, 0 /* US */, 1 /* SPC */, 1 /* ! */, 1 /* " */,
1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */,
1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */,
1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */, 1 /* @ */,
1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */,
1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */,
1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */,
1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */,
1 /* Z */, 1 /* [ */, 1 /* \ */, 1 /* ] */, 1 /* ^ */,
1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */, 1 /* | */,
1 /* } */, 1 /* ~ */, 0 /* DEL */, 1 /* 0x80 */, 1 /* 0x81 */,
1 /* 0x82 */, 1 /* 0x83 */, 1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */,
1 /* 0x87 */, 1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */, 1 /* 0x90 */,
1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */, 1 /* 0x94 */, 1 /* 0x95 */,
1 /* 0x96 */, 1 /* 0x97 */, 1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */,
1 /* 0x9b */, 1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */, 1 /* 0xa4 */,
1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */, 1 /* 0xa8 */, 1 /* 0xa9 */,
1 /* 0xaa */, 1 /* 0xab */, 1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */,
1 /* 0xaf */, 1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */, 1 /* 0xb8 */,
1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */, 1 /* 0xbc */, 1 /* 0xbd */,
1 /* 0xbe */, 1 /* 0xbf */, 1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */,
1 /* 0xc3 */, 1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */, 1 /* 0xcc */,
1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */, 1 /* 0xd0 */, 1 /* 0xd1 */,
1 /* 0xd2 */, 1 /* 0xd3 */, 1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */,
1 /* 0xd7 */, 1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */, 1 /* 0xe0 */,
1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */, 1 /* 0xe4 */, 1 /* 0xe5 */,
1 /* 0xe6 */, 1 /* 0xe7 */, 1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */,
1 /* 0xeb */, 1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */, 1 /* 0xf4 */,
1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */, 1 /* 0xf8 */, 1 /* 0xf9 */,
1 /* 0xfa */, 1 /* 0xfb */, 1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */,
1 /* 0xff */
};
int nghttp2_check_header_value(const uint8_t *value, size_t len)
{
int nghttp2_check_header_value(const uint8_t *value, size_t len) {
const uint8_t *last;
for(last = value + len; value != last; ++value) {
if(!VALID_HD_VALUE_CHARS[*value]) {
for (last = value + len; value != last; ++value) {
if (!VALID_HD_VALUE_CHARS[*value]) {
return 0;
}
}
return 1;
}
uint8_t* nghttp2_cpymem(uint8_t *dest, const void *src, size_t len)
{
uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len) {
memcpy(dest, src, len);
return dest + len;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_HELPER_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -68,7 +68,7 @@ uint32_t nghttp2_get_uint32(const uint8_t *data);
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
void* nghttp2_memdup(const void* src, size_t n);
void *nghttp2_memdup(const void *src, size_t n);
void nghttp2_downcase(uint8_t *s, size_t len);
@ -112,6 +112,6 @@ void nghttp2_free(void *ptr);
* by the |dest|, assuming that the |dest| is at lest |len| bytes long
* . Returns dest + len.
*/
uint8_t* nghttp2_cpymem(uint8_t *dest, const void *src, size_t len);
uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len);
#endif /* NGHTTP2_HELPER_H */

View File

@ -26,7 +26,7 @@
#define NGHTTP2_INT_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
/* Macros, types and constants for internal use */
@ -34,7 +34,9 @@
#ifdef DEBUGBUILD
#define DEBUGF(x) x
#else
#define DEBUGF(x) do { } while(0)
#define DEBUGF(x) \
do { \
} while (0)
#endif
typedef int (*nghttp2_compar)(const void *lhs, const void *rhs);

View File

@ -28,11 +28,10 @@
#define INITIAL_TABLE_LENGTH 256
int nghttp2_map_init(nghttp2_map *map)
{
int nghttp2_map_init(nghttp2_map *map) {
map->tablelen = INITIAL_TABLE_LENGTH;
map->table = calloc(map->tablelen, sizeof(nghttp2_map_entry*));
if(map->table == NULL) {
map->table = calloc(map->tablelen, sizeof(nghttp2_map_entry *));
if (map->table == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -41,19 +40,15 @@ int nghttp2_map_init(nghttp2_map *map)
return 0;
}
void nghttp2_map_free(nghttp2_map *map)
{
free(map->table);
}
void nghttp2_map_free(nghttp2_map *map) { free(map->table); }
void nghttp2_map_each_free(nghttp2_map *map,
int (*func)(nghttp2_map_entry *entry, void *ptr),
void *ptr)
{
void *ptr) {
size_t i;
for(i = 0; i < map->tablelen; ++i) {
for (i = 0; i < map->tablelen; ++i) {
nghttp2_map_entry *entry;
for(entry = map->table[i]; entry;) {
for (entry = map->table[i]; entry;) {
nghttp2_map_entry *next = entry->next;
func(entry, ptr);
entry = next;
@ -64,15 +59,14 @@ void nghttp2_map_each_free(nghttp2_map *map,
int nghttp2_map_each(nghttp2_map *map,
int (*func)(nghttp2_map_entry *entry, void *ptr),
void *ptr)
{
void *ptr) {
int rv;
size_t i;
for(i = 0; i < map->tablelen; ++i) {
for (i = 0; i < map->tablelen; ++i) {
nghttp2_map_entry *entry;
for(entry = map->table[i]; entry; entry = entry->next) {
for (entry = map->table[i]; entry; entry = entry->next) {
rv = func(entry, ptr);
if(rv != 0) {
if (rv != 0) {
return rv;
}
}
@ -80,32 +74,29 @@ int nghttp2_map_each(nghttp2_map *map,
return 0;
}
void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key)
{
void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key) {
entry->key = key;
entry->next = NULL;
}
/* Same hash function in android HashMap source code. */
/* The |mod| must be power of 2 */
static int32_t hash(int32_t h, size_t mod)
{
static int32_t hash(int32_t h, size_t mod) {
h ^= (h >> 20) ^ (h >> 12);
h ^= (h >> 7) ^ (h >> 4);
return h & (mod - 1);
}
static int insert(nghttp2_map_entry **table, size_t tablelen,
nghttp2_map_entry *entry)
{
nghttp2_map_entry *entry) {
int32_t h = hash(entry->key, tablelen);
if(table[h] == NULL) {
if (table[h] == NULL) {
table[h] = entry;
} else {
nghttp2_map_entry *p;
/* We won't allow duplicated key, so check it out. */
for(p = table[h]; p; p = p->next) {
if(p->key == entry->key) {
for (p = table[h]; p; p = p->next) {
if (p->key == entry->key) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
}
@ -116,18 +107,17 @@ static int insert(nghttp2_map_entry **table, size_t tablelen,
}
/* new_tablelen must be power of 2 */
static int resize(nghttp2_map *map, size_t new_tablelen)
{
static int resize(nghttp2_map *map, size_t new_tablelen) {
size_t i;
nghttp2_map_entry **new_table;
new_table = calloc(new_tablelen, sizeof(nghttp2_map_entry*));
if(new_table == NULL) {
new_table = calloc(new_tablelen, sizeof(nghttp2_map_entry *));
if (new_table == NULL) {
return NGHTTP2_ERR_NOMEM;
}
for(i = 0; i < map->tablelen; ++i) {
for (i = 0; i < map->tablelen; ++i) {
nghttp2_map_entry *entry;
for(entry = map->table[i]; entry;) {
for (entry = map->table[i]; entry;) {
nghttp2_map_entry *next = entry->next;
entry->next = NULL;
/* This function must succeed */
@ -142,46 +132,43 @@ static int resize(nghttp2_map *map, size_t new_tablelen)
return 0;
}
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry)
{
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry) {
int rv;
/* Load factor is 0.75 */
if((map->size + 1) * 4 > map->tablelen * 3) {
if ((map->size + 1) * 4 > map->tablelen * 3) {
rv = resize(map, map->tablelen * 2);
if(rv != 0) {
if (rv != 0) {
return rv;
}
}
rv = insert(map->table, map->tablelen, new_entry);
if(rv != 0) {
if (rv != 0) {
return rv;
}
++map->size;
return 0;
}
nghttp2_map_entry* nghttp2_map_find(nghttp2_map *map, key_type key)
{
nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key) {
int32_t h;
nghttp2_map_entry *entry;
h = hash(key, map->tablelen);
for(entry = map->table[h]; entry; entry = entry->next) {
if(entry->key == key) {
for (entry = map->table[h]; entry; entry = entry->next) {
if (entry->key == key) {
return entry;
}
}
return NULL;
}
int nghttp2_map_remove(nghttp2_map *map, key_type key)
{
int nghttp2_map_remove(nghttp2_map *map, key_type key) {
int32_t h;
nghttp2_map_entry *entry, *prev;
h = hash(key, map->tablelen);
prev = NULL;
for(entry = map->table[h]; entry; entry = entry->next) {
if(entry->key == key) {
if(prev == NULL) {
for (entry = map->table[h]; entry; entry = entry->next) {
if (entry->key == key) {
if (prev == NULL) {
map->table[h] = entry->next;
} else {
prev->next = entry->next;
@ -194,7 +181,4 @@ int nghttp2_map_remove(nghttp2_map *map, key_type key)
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
size_t nghttp2_map_size(nghttp2_map *map)
{
return map->size;
}
size_t nghttp2_map_size(nghttp2_map *map) { return map->size; }

View File

@ -26,7 +26,7 @@
#define NGHTTP2_MAP_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -98,7 +98,7 @@ int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *entry);
* Returns the entry associated by the key |key|. If there is no such
* entry, this function returns NULL.
*/
nghttp2_map_entry* nghttp2_map_find(nghttp2_map *map, key_type key);
nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key);
/*
* Removes the entry associated by the key |key| from the |map|. The

View File

@ -26,19 +26,19 @@
#define NGHTTP2_NET_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#include <winsock2.h>
#endif /* HAVE_WINSOCK2_H */
#endif /* NGHTTP2_NET_H */

View File

@ -27,28 +27,26 @@
#include <string.h>
int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen)
{
const unsigned char *in, unsigned int inlen) {
int http_selected = 0;
unsigned int i = 0;
for(; i < inlen; i += in[i]+1) {
if(in[i] == NGHTTP2_PROTO_VERSION_ID_LEN &&
i + 1 + in[i] <= inlen &&
memcmp(&in[i+1], NGHTTP2_PROTO_VERSION_ID, in[i]) == 0) {
*out = (unsigned char*)&in[i+1];
for (; i < inlen; i += in [i] + 1) {
if (in[i] == NGHTTP2_PROTO_VERSION_ID_LEN && i + 1 + in[i] <= inlen &&
memcmp(&in[i + 1], NGHTTP2_PROTO_VERSION_ID, in[i]) == 0) {
*out = (unsigned char *)&in[i + 1];
*outlen = in[i];
return 1;
}
if(in[i] == 8 && i + 1 + in[i] <= inlen &&
memcmp(&in[i+1], "http/1.1", in[i]) == 0) {
if (in[i] == 8 && i + 1 + in[i] <= inlen &&
memcmp(&in[i + 1], "http/1.1", in[i]) == 0) {
http_selected = 1;
*out = (unsigned char*)&in[i+1];
*out = (unsigned char *)&in[i + 1];
*outlen = in[i];
/* Go through to the next iteration, because "HTTP/2" may be
there */
}
}
if(http_selected) {
if (http_selected) {
return 0;
} else {
return -1;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_NPN_H
#ifdef HAVE_CONFIG
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG */
#include <nghttp2/nghttp2.h>

View File

@ -24,38 +24,30 @@
*/
#include "nghttp2_option.h"
int nghttp2_option_new(nghttp2_option **option_ptr)
{
int nghttp2_option_new(nghttp2_option **option_ptr) {
*option_ptr = calloc(1, sizeof(nghttp2_option));
if(*option_ptr == NULL) {
if (*option_ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
return 0;
}
void nghttp2_option_del(nghttp2_option *option)
{
free(option);
}
void nghttp2_option_del(nghttp2_option *option) { free(option); }
void nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val)
{
void nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val) {
option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE;
option->no_auto_window_update = val;
}
void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
uint32_t val)
{
uint32_t val) {
option->opt_set_mask |= NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS;
option->peer_max_concurrent_streams = val;
}
void nghttp2_option_set_recv_client_preface
(nghttp2_option *option, int val)
{
void nghttp2_option_set_recv_client_preface(nghttp2_option *option, int val) {
option->opt_set_mask |= NGHTTP2_OPT_RECV_CLIENT_PREFACE;
option->recv_client_preface = val;
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_OPTION_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,17 +26,16 @@
#include <assert.h>
void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
{
void nghttp2_outbound_item_free(nghttp2_outbound_item *item) {
nghttp2_frame *frame;
if(item == NULL) {
if (item == NULL) {
return;
}
frame = &item->frame;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_DATA:
nghttp2_frame_data_free(&frame->data);
break;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_OUTBOUND_ITEM_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -24,11 +24,10 @@
*/
#include "nghttp2_pq.h"
int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar)
{
int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar) {
pq->capacity = 128;
pq->q = malloc(pq->capacity * sizeof(void*));
if(pq->q == NULL) {
pq->q = malloc(pq->capacity * sizeof(void *));
if (pq->q == NULL) {
return NGHTTP2_ERR_NOMEM;
}
pq->length = 0;
@ -36,38 +35,34 @@ int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar)
return 0;
}
void nghttp2_pq_free(nghttp2_pq *pq)
{
void nghttp2_pq_free(nghttp2_pq *pq) {
free(pq->q);
pq->q = NULL;
}
static void swap(nghttp2_pq *pq, size_t i, size_t j)
{
static void swap(nghttp2_pq *pq, size_t i, size_t j) {
void *t = pq->q[i];
pq->q[i] = pq->q[j];
pq->q[j] = t;
}
static void bubble_up(nghttp2_pq *pq, size_t index)
{
if(index == 0) {
static void bubble_up(nghttp2_pq *pq, size_t index) {
if (index == 0) {
return;
} else {
size_t parent = (index-1)/2;
if(pq->compar(pq->q[parent], pq->q[index]) > 0) {
size_t parent = (index - 1) / 2;
if (pq->compar(pq->q[parent], pq->q[index]) > 0) {
swap(pq, parent, index);
bubble_up(pq, parent);
}
}
}
int nghttp2_pq_push(nghttp2_pq *pq, void *item)
{
if(pq->capacity <= pq->length) {
int nghttp2_pq_push(nghttp2_pq *pq, void *item) {
if (pq->capacity <= pq->length) {
void *nq;
nq = realloc(pq->q, (pq->capacity*2) * sizeof(void*));
if(nq == NULL) {
nq = realloc(pq->q, (pq->capacity * 2) * sizeof(void *));
if (nq == NULL) {
return NGHTTP2_ERR_NOMEM;
}
pq->capacity *= 2;
@ -75,70 +70,60 @@ int nghttp2_pq_push(nghttp2_pq *pq, void *item)
}
pq->q[pq->length] = item;
++pq->length;
bubble_up(pq, pq->length-1);
bubble_up(pq, pq->length - 1);
return 0;
}
void* nghttp2_pq_top(nghttp2_pq *pq)
{
if(pq->length == 0) {
void *nghttp2_pq_top(nghttp2_pq *pq) {
if (pq->length == 0) {
return NULL;
} else {
return pq->q[0];
}
}
static void bubble_down(nghttp2_pq *pq, size_t index)
{
size_t lchild = index*2+1;
static void bubble_down(nghttp2_pq *pq, size_t index) {
size_t lchild = index * 2 + 1;
size_t minindex = index;
size_t i, j;
for(i = 0; i < 2; ++i) {
j = lchild+i;
if(j >= pq->length) {
for (i = 0; i < 2; ++i) {
j = lchild + i;
if (j >= pq->length) {
break;
}
if(pq->compar(pq->q[minindex], pq->q[j]) > 0) {
if (pq->compar(pq->q[minindex], pq->q[j]) > 0) {
minindex = j;
}
}
if(minindex != index) {
if (minindex != index) {
swap(pq, index, minindex);
bubble_down(pq, minindex);
}
}
void nghttp2_pq_pop(nghttp2_pq *pq)
{
if(pq->length > 0) {
pq->q[0] = pq->q[pq->length-1];
void nghttp2_pq_pop(nghttp2_pq *pq) {
if (pq->length > 0) {
pq->q[0] = pq->q[pq->length - 1];
--pq->length;
bubble_down(pq, 0);
}
}
int nghttp2_pq_empty(nghttp2_pq *pq)
{
return pq->length == 0;
}
int nghttp2_pq_empty(nghttp2_pq *pq) { return pq->length == 0; }
size_t nghttp2_pq_size(nghttp2_pq *pq)
{
return pq->length;
}
size_t nghttp2_pq_size(nghttp2_pq *pq) { return pq->length; }
void nghttp2_pq_update(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg)
{
void nghttp2_pq_update(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg) {
size_t i;
int rv = 0;
if(pq->length == 0) {
if (pq->length == 0) {
return;
}
for(i = 0; i < pq->length; ++i) {
for (i = 0; i < pq->length; ++i) {
rv |= (*fun)(pq->q[i], arg);
}
if(rv) {
for(i = pq->length; i > 0; --i) {
if (rv) {
for (i = pq->length; i > 0; --i) {
bubble_down(pq, i - 1);
}
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_PQ_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -78,7 +78,7 @@ int nghttp2_pq_push(nghttp2_pq *pq, void *item);
* Returns item at the top of the queue |pq|. If the queue is empty,
* this function returns NULL.
*/
void* nghttp2_pq_top(nghttp2_pq *pq);
void *nghttp2_pq_top(nghttp2_pq *pq);
/*
* Pops item at the top of the queue |pq|. The popped item is not

View File

@ -26,23 +26,19 @@
void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec,
int32_t stream_id, int32_t weight,
int exclusive)
{
int exclusive) {
pri_spec->stream_id = stream_id;
pri_spec->weight = weight;
pri_spec->exclusive = exclusive != 0;
}
void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec)
{
void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec) {
pri_spec->stream_id = 0;
pri_spec->weight = NGHTTP2_DEFAULT_WEIGHT;
pri_spec->exclusive = 0;
}
int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec)
{
int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) {
return pri_spec->stream_id == 0 &&
pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT &&
pri_spec->exclusive == 0;
pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && pri_spec->exclusive == 0;
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_PRIORITY_SPEC_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -27,18 +27,16 @@
#include <string.h>
#include <assert.h>
void nghttp2_queue_init(nghttp2_queue *queue)
{
void nghttp2_queue_init(nghttp2_queue *queue) {
queue->front = queue->back = NULL;
}
void nghttp2_queue_free(nghttp2_queue *queue)
{
if(!queue) {
void nghttp2_queue_free(nghttp2_queue *queue) {
if (!queue) {
return;
} else {
nghttp2_queue_cell *p = queue->front;
while(p) {
while (p) {
nghttp2_queue_cell *next = p->next;
free(p);
p = next;
@ -46,16 +44,15 @@ void nghttp2_queue_free(nghttp2_queue *queue)
}
}
int nghttp2_queue_push(nghttp2_queue *queue, void *data)
{
nghttp2_queue_cell *new_cell = (nghttp2_queue_cell*)malloc
(sizeof(nghttp2_queue_cell));
if(!new_cell) {
int nghttp2_queue_push(nghttp2_queue *queue, void *data) {
nghttp2_queue_cell *new_cell =
(nghttp2_queue_cell *)malloc(sizeof(nghttp2_queue_cell));
if (!new_cell) {
return NGHTTP2_ERR_NOMEM;
}
new_cell->data = data;
new_cell->next = NULL;
if(queue->back) {
if (queue->back) {
queue->back->next = new_cell;
queue->back = new_cell;
@ -65,30 +62,24 @@ int nghttp2_queue_push(nghttp2_queue *queue, void *data)
return 0;
}
void nghttp2_queue_pop(nghttp2_queue *queue)
{
void nghttp2_queue_pop(nghttp2_queue *queue) {
nghttp2_queue_cell *front = queue->front;
assert(front);
queue->front = front->next;
if(front == queue->back) {
if (front == queue->back) {
queue->back = NULL;
}
free(front);
}
void* nghttp2_queue_front(nghttp2_queue *queue)
{
void *nghttp2_queue_front(nghttp2_queue *queue) {
assert(queue->front);
return queue->front->data;
}
void* nghttp2_queue_back(nghttp2_queue *queue)
{
void *nghttp2_queue_back(nghttp2_queue *queue) {
assert(queue->back);
return queue->back->data;
}
int nghttp2_queue_empty(nghttp2_queue *queue)
{
return queue->front == NULL;
}
int nghttp2_queue_empty(nghttp2_queue *queue) { return queue->front == NULL; }

View File

@ -26,7 +26,7 @@
#define NGHTTP2_QUEUE_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -36,16 +36,14 @@ typedef struct nghttp2_queue_cell {
struct nghttp2_queue_cell *next;
} nghttp2_queue_cell;
typedef struct {
nghttp2_queue_cell *front, *back;
} nghttp2_queue;
typedef struct { nghttp2_queue_cell *front, *back; } nghttp2_queue;
void nghttp2_queue_init(nghttp2_queue *queue);
void nghttp2_queue_free(nghttp2_queue *queue);
int nghttp2_queue_push(nghttp2_queue *queue, void *data);
void nghttp2_queue_pop(nghttp2_queue *queue);
void* nghttp2_queue_front(nghttp2_queue *queue);
void* nghttp2_queue_back(nghttp2_queue *queue);
void *nghttp2_queue_front(nghttp2_queue *queue);
void *nghttp2_queue_back(nghttp2_queue *queue);
int nghttp2_queue_empty(nghttp2_queue *queue);
#endif /* NGHTTP2_QUEUE_H */

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
#define NGHTTP2_SESSION_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -264,7 +264,7 @@ int nghttp2_session_is_my_stream_id(nghttp2_session *session,
* Don't call nghttp2_outbound_item_free() until frame member is
* initialized.
*/
void nghttp2_session_outbound_item_init(nghttp2_session* session,
void nghttp2_session_outbound_item_init(nghttp2_session *session,
nghttp2_outbound_item *item);
/*
@ -298,8 +298,7 @@ int nghttp2_session_add_item(nghttp2_session *session,
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_session_add_rst_stream(nghttp2_session *session,
int32_t stream_id,
int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
uint32_t error_code);
/*
@ -332,10 +331,8 @@ int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags,
* NGHTTP2_ERR_INVALID_ARGUMENT
* The |opaque_data_len| is too large.
*/
int nghttp2_session_add_goaway(nghttp2_session *session,
int32_t last_stream_id,
uint32_t error_code,
const uint8_t *opaque_data,
int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id,
uint32_t error_code, const uint8_t *opaque_data,
size_t opaque_data_len);
/*
@ -378,9 +375,8 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
* This function returns a pointer to created new stream object, or
* NULL.
*/
nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
int32_t stream_id,
uint8_t flags,
nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
int32_t stream_id, uint8_t flags,
nghttp2_priority_spec *pri_spec,
nghttp2_stream_state initial_state,
void *stream_user_data);
@ -461,7 +457,6 @@ void nghttp2_session_adjust_closed_stream(nghttp2_session *session,
int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session,
nghttp2_stream *stream);
int nghttp2_session_end_request_headers_received(nghttp2_session *session,
nghttp2_frame *frame,
nghttp2_stream *stream);
@ -505,7 +500,6 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
nghttp2_frame *frame,
nghttp2_stream *stream);
/*
* Called when PRIORITY is received, assuming |frame| is properly
* initialized.
@ -551,8 +545,7 @@ int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
* The read_callback failed
*/
int nghttp2_session_on_settings_received(nghttp2_session *session,
nghttp2_frame *frame,
int noack);
nghttp2_frame *frame, int noack);
/*
* Called when PUSH_PROMISE is received, assuming |frame| is properly
@ -652,7 +645,7 @@ int nghttp2_session_on_data_received(nghttp2_session *session,
* could be NULL if such stream does not exist. This function returns
* NULL if stream is marked as closed.
*/
nghttp2_stream* nghttp2_session_get_stream(nghttp2_session *session,
nghttp2_stream *nghttp2_session_get_stream(nghttp2_session *session,
int32_t stream_id);
/*
@ -660,7 +653,7 @@ nghttp2_stream* nghttp2_session_get_stream(nghttp2_session *session,
* returns stream object even if it is marked as closed or in
* NGHTTP2_STREAM_IDLE state.
*/
nghttp2_stream* nghttp2_session_get_stream_raw(nghttp2_session *session,
nghttp2_stream *nghttp2_session_get_stream_raw(nghttp2_session *session,
int32_t stream_id);
/*
@ -680,17 +673,15 @@ nghttp2_stream* nghttp2_session_get_stream_raw(nghttp2_session *session,
* NGHTTP2_ERR_CALLBACK_FAILURE
* The read_callback failed (session error).
*/
int nghttp2_session_pack_data(nghttp2_session *session,
nghttp2_bufs *bufs,
size_t datamax,
nghttp2_frame *frame,
int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
size_t datamax, nghttp2_frame *frame,
nghttp2_data_aux_data *aux_data);
/*
* Returns top of outbound frame queue. This function returns NULL if
* queue is empty.
*/
nghttp2_outbound_item* nghttp2_session_get_ob_pq_top(nghttp2_session *session);
nghttp2_outbound_item *nghttp2_session_get_ob_pq_top(nghttp2_session *session);
/*
* Pops and returns next item to send. If there is no such item,
@ -699,8 +690,8 @@ nghttp2_outbound_item* nghttp2_session_get_ob_pq_top(nghttp2_session *session);
* session->ob_ss_pq has item and max concurrent streams is reached,
* then this function returns NULL.
*/
nghttp2_outbound_item* nghttp2_session_pop_next_ob_item
(nghttp2_session *session);
nghttp2_outbound_item *
nghttp2_session_pop_next_ob_item(nghttp2_session *session);
/*
* Returns next item to send. If there is no such item, this function
@ -709,8 +700,8 @@ nghttp2_outbound_item* nghttp2_session_pop_next_ob_item
* session->ob_ss_pq has item and max concurrent streams is reached,
* then this function returns NULL.
*/
nghttp2_outbound_item* nghttp2_session_get_next_ob_item
(nghttp2_session *session);
nghttp2_outbound_item *
nghttp2_session_get_next_ob_item(nghttp2_session *session);
/*
* Updates local settings with the |iv|. The number of elements in the
@ -742,9 +733,9 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_session_reprioritize_stream
(nghttp2_session *session, nghttp2_stream *stream,
const nghttp2_priority_spec *pri_spec);
int nghttp2_session_reprioritize_stream(nghttp2_session *session,
nghttp2_stream *stream,
const nghttp2_priority_spec *pri_spec);
/*
* Terminates current |session| with the |error_code|. The |reason|
@ -758,7 +749,8 @@ int nghttp2_session_reprioritize_stream
* NGHTTP2_ERR_INVALID_ARGUMENT
* The |reason| is too long.
*/
int nghttp2_session_terminate_session_with_reason
(nghttp2_session *session, uint32_t error_code, const char *reason);
int nghttp2_session_terminate_session_with_reason(nghttp2_session *session,
uint32_t error_code,
const char *reason);
#endif /* NGHTTP2_SESSION_H */

View File

@ -31,14 +31,11 @@
#include "nghttp2_helper.h"
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
uint8_t flags,
nghttp2_stream_state initial_state,
int32_t weight,
nghttp2_stream_roots *roots,
uint8_t flags, nghttp2_stream_state initial_state,
int32_t weight, nghttp2_stream_roots *roots,
int32_t remote_initial_window_size,
int32_t local_initial_window_size,
void *stream_user_data)
{
void *stream_user_data) {
nghttp2_map_entry_init(&stream->map_entry, stream_id);
stream->stream_id = stream_id;
stream->flags = flags;
@ -74,21 +71,18 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
stream->root_next = NULL;
}
void nghttp2_stream_free(nghttp2_stream *stream _U_)
{
void nghttp2_stream_free(nghttp2_stream *stream _U_) {
/* We don't free stream->data_item. If it is assigned to aob, then
active_outbound_item_reset() will delete it. If it is queued,
then it is deleted when pq is deleted in nghttp2_session_del().
Otherwise, nghttp2_session_del() will delete it. */
}
void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag)
{
void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
stream->shut_flags |= flag;
}
static int stream_push_data(nghttp2_stream *stream, nghttp2_session *session)
{
static int stream_push_data(nghttp2_stream *stream, nghttp2_session *session) {
int rv;
nghttp2_outbound_item *item;
@ -99,22 +93,22 @@ static int stream_push_data(nghttp2_stream *stream, nghttp2_session *session)
/* If item is now sent, don't push it to the queue. Otherwise, we
may push same item twice. */
if(session->aob.item == item) {
if (session->aob.item == item) {
return 0;
}
if(item->weight > stream->effective_weight) {
if (item->weight > stream->effective_weight) {
item->weight = stream->effective_weight;
}
item->cycle = session->last_cycle;
switch(item->frame.hd.type) {
switch (item->frame.hd.type) {
case NGHTTP2_DATA:
rv = nghttp2_pq_push(&session->ob_da_pq, item);
break;
case NGHTTP2_HEADERS:
if(stream->state == NGHTTP2_STREAM_RESERVED) {
if (stream->state == NGHTTP2_STREAM_RESERVED) {
rv = nghttp2_pq_push(&session->ob_ss_pq, item);
} else {
rv = nghttp2_pq_push(&session->ob_pq, item);
@ -125,7 +119,7 @@ static int stream_push_data(nghttp2_stream *stream, nghttp2_session *session)
assert(0);
}
if(rv != 0) {
if (rv != 0) {
return rv;
}
@ -134,28 +128,27 @@ static int stream_push_data(nghttp2_stream *stream, nghttp2_session *session)
return 0;
}
static nghttp2_stream* stream_first_sib(nghttp2_stream *stream)
{
for(; stream->sib_prev; stream = stream->sib_prev);
static nghttp2_stream *stream_first_sib(nghttp2_stream *stream) {
for (; stream->sib_prev; stream = stream->sib_prev)
;
return stream;
}
static nghttp2_stream* stream_last_sib(nghttp2_stream *stream)
{
for(; stream->sib_next; stream = stream->sib_next);
static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
for (; stream->sib_next; stream = stream->sib_next)
;
return stream;
}
static nghttp2_stream* stream_update_dep_length(nghttp2_stream *stream,
ssize_t delta)
{
static nghttp2_stream *stream_update_dep_length(nghttp2_stream *stream,
ssize_t delta) {
stream->num_substreams += delta;
stream = stream_first_sib(stream);
if(stream->dep_prev) {
if (stream->dep_prev) {
return stream_update_dep_length(stream->dep_prev, delta);
}
@ -163,17 +156,15 @@ static nghttp2_stream* stream_update_dep_length(nghttp2_stream *stream,
}
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
int32_t weight)
{
int32_t weight) {
weight = stream->weight * weight / stream->sum_dep_weight;
return nghttp2_max(1, weight);
}
int32_t nghttp2_stream_dep_distributed_effective_weight
(nghttp2_stream *stream, int32_t weight)
{
if(stream->sum_norest_weight == 0) {
int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream,
int32_t weight) {
if (stream->sum_norest_weight == 0) {
return stream->effective_weight;
}
@ -182,10 +173,10 @@ int32_t nghttp2_stream_dep_distributed_effective_weight
return nghttp2_max(1, weight);
}
static int32_t stream_dep_distributed_top_effective_weight
(nghttp2_stream *stream, int32_t weight)
{
if(stream->sum_top_weight == 0) {
static int32_t
stream_dep_distributed_top_effective_weight(nghttp2_stream *stream,
int32_t weight) {
if (stream->sum_top_weight == 0) {
return stream->effective_weight;
}
@ -199,31 +190,30 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream);
/* Updates effective_weight of descendant streams in subtree of
|stream|. We assume that stream->effective_weight is already set
right. */
static void stream_update_dep_effective_weight(nghttp2_stream *stream)
{
static void stream_update_dep_effective_weight(nghttp2_stream *stream) {
nghttp2_stream *si;
DEBUGF(fprintf(stderr, "stream: update_dep_effective_weight "
"stream(%p)=%d, weight=%d, sum_norest_weight=%d, "
"sum_top_weight=%d\n",
"stream(%p)=%d, weight=%d, sum_norest_weight=%d, "
"sum_top_weight=%d\n",
stream, stream->stream_id, stream->weight,
stream->sum_norest_weight, stream->sum_top_weight));
/* stream->sum_norest_weight == 0 means there is no
NGHTTP2_STREAM_DPRI_TOP under stream */
if(stream->dpri != NGHTTP2_STREAM_DPRI_NO_DATA ||
stream->sum_norest_weight == 0) {
if (stream->dpri != NGHTTP2_STREAM_DPRI_NO_DATA ||
stream->sum_norest_weight == 0) {
return;
}
/* If there is no direct descendant whose dpri is
NGHTTP2_STREAM_DPRI_TOP, indirect descendants have the chance to
send data, so recursively set weight for descendants. */
if(stream->sum_top_weight == 0) {
for(si = stream->dep_next; si; si = si->sib_next) {
if(si->dpri != NGHTTP2_STREAM_DPRI_REST) {
si->effective_weight = nghttp2_stream_dep_distributed_effective_weight
(stream, si->weight);
if (stream->sum_top_weight == 0) {
for (si = stream->dep_next; si; si = si->sib_next) {
if (si->dpri != NGHTTP2_STREAM_DPRI_REST) {
si->effective_weight =
nghttp2_stream_dep_distributed_effective_weight(stream, si->weight);
}
stream_update_dep_effective_weight(si);
@ -235,10 +225,10 @@ static void stream_update_dep_effective_weight(nghttp2_stream *stream)
NGHTTP2_STREAM_DPRI_TOP, we won't give a chance to indirect
descendants, since closed or blocked stream's weight is
distributed among its siblings */
for(si = stream->dep_next; si; si = si->sib_next) {
if(si->dpri == NGHTTP2_STREAM_DPRI_TOP) {
si->effective_weight = stream_dep_distributed_top_effective_weight
(stream, si->weight);
for (si = stream->dep_next; si; si = si->sib_next) {
if (si->dpri == NGHTTP2_STREAM_DPRI_TOP) {
si->effective_weight =
stream_dep_distributed_top_effective_weight(stream, si->weight);
DEBUGF(fprintf(stderr, "stream: stream=%d top eweight=%d\n",
si->stream_id, si->effective_weight));
@ -246,7 +236,7 @@ static void stream_update_dep_effective_weight(nghttp2_stream *stream)
continue;
}
if(si->dpri == NGHTTP2_STREAM_DPRI_NO_DATA) {
if (si->dpri == NGHTTP2_STREAM_DPRI_NO_DATA) {
DEBUGF(fprintf(stderr, "stream: stream=%d no_data, ignored\n",
si->stream_id));
@ -254,25 +244,24 @@ static void stream_update_dep_effective_weight(nghttp2_stream *stream)
them NGHTTP2_STREAM_DPRI_REST again. */
stream_update_dep_set_rest(si->dep_next);
} else {
DEBUGF(fprintf(stderr, "stream: stream=%d rest, ignored\n",
si->stream_id));
DEBUGF(
fprintf(stderr, "stream: stream=%d rest, ignored\n", si->stream_id));
}
}
}
static void stream_update_dep_set_rest(nghttp2_stream *stream)
{
if(stream == NULL) {
static void stream_update_dep_set_rest(nghttp2_stream *stream) {
if (stream == NULL) {
return;
}
DEBUGF(fprintf(stderr, "stream: stream=%d is rest\n", stream->stream_id));
if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
return;
}
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
stream->dpri = NGHTTP2_STREAM_DPRI_REST;
stream_update_dep_set_rest(stream->sib_next);
@ -288,24 +277,23 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream)
* Performs dfs starting |stream|, search stream which can become
* NGHTTP2_STREAM_DPRI_TOP and set its dpri.
*/
static void stream_update_dep_set_top(nghttp2_stream *stream)
{
static void stream_update_dep_set_top(nghttp2_stream *stream) {
nghttp2_stream *si;
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
return;
}
if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
DEBUGF(fprintf(stderr, "stream: stream=%d data is top\n",
stream->stream_id));
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
DEBUGF(
fprintf(stderr, "stream: stream=%d data is top\n", stream->stream_id));
stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
return;
}
for(si = stream->dep_next; si; si = si->sib_next) {
for (si = stream->dep_next; si; si = si->sib_next) {
stream_update_dep_set_top(si);
}
}
@ -321,22 +309,20 @@ static void stream_update_dep_set_top(nghttp2_stream *stream)
* Out of memory.
*/
static int stream_update_dep_queue_top(nghttp2_stream *stream,
nghttp2_session *session)
{
nghttp2_session *session) {
int rv;
nghttp2_stream *si;
if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
return 0;
}
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
if(!stream->data_item->queued) {
DEBUGF(fprintf(stderr, "stream: stream=%d enqueue\n",
stream->stream_id));
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
if (!stream->data_item->queued) {
DEBUGF(fprintf(stderr, "stream: stream=%d enqueue\n", stream->stream_id));
rv = stream_push_data(stream, session);
if(rv != 0) {
if (rv != 0) {
return rv;
}
}
@ -344,10 +330,10 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream,
return 0;
}
for(si = stream->dep_next; si; si = si->sib_next) {
for (si = stream->dep_next; si; si = si->sib_next) {
rv = stream_update_dep_queue_top(si, session);
if(rv != 0) {
if (rv != 0) {
return rv;
}
}
@ -369,32 +355,31 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream,
* stream->sum_norest_weight. It just adds up the weight of direct
* descendants whose dpri is NGHTTP2_STREAM_DPRI_TOP.
*/
static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream)
{
static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) {
nghttp2_stream *si;
int rv;
stream->sum_norest_weight = 0;
stream->sum_top_weight = 0;
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
return 1;
}
if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
return 0;
}
rv = 0;
for(si = stream->dep_next; si; si = si->sib_next) {
for (si = stream->dep_next; si; si = si->sib_next) {
if(stream_update_dep_sum_norest_weight(si)) {
if (stream_update_dep_sum_norest_weight(si)) {
rv = 1;
stream->sum_norest_weight += si->weight;
}
if(si->dpri == NGHTTP2_STREAM_DPRI_TOP) {
if (si->dpri == NGHTTP2_STREAM_DPRI_TOP) {
stream->sum_top_weight += si->weight;
}
}
@ -403,8 +388,7 @@ static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream)
}
static int stream_update_dep_on_attach_data(nghttp2_stream *stream,
nghttp2_session *session)
{
nghttp2_session *session) {
nghttp2_stream *root_stream;
stream->dpri = NGHTTP2_STREAM_DPRI_REST;
@ -424,8 +408,7 @@ static int stream_update_dep_on_attach_data(nghttp2_stream *stream,
}
static int stream_update_dep_on_detach_data(nghttp2_stream *stream,
nghttp2_session *session)
{
nghttp2_session *session) {
nghttp2_stream *root_stream;
stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA;
@ -442,8 +425,7 @@ static int stream_update_dep_on_detach_data(nghttp2_stream *stream,
int nghttp2_stream_attach_data(nghttp2_stream *stream,
nghttp2_outbound_item *data_item,
nghttp2_session *session)
{
nghttp2_session *session) {
assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
assert(stream->data_item == NULL);
@ -456,8 +438,7 @@ int nghttp2_stream_attach_data(nghttp2_stream *stream,
}
int nghttp2_stream_detach_data(nghttp2_stream *stream,
nghttp2_session *session)
{
nghttp2_session *session) {
DEBUGF(fprintf(stderr, "stream: stream=%d detach data=%p\n",
stream->stream_id, stream->data_item));
@ -468,8 +449,7 @@ int nghttp2_stream_detach_data(nghttp2_stream *stream,
}
int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_session *session)
{
nghttp2_session *session) {
assert(stream->data_item);
DEBUGF(fprintf(stderr, "stream: stream=%d defer data=%p cause=%02x\n",
@ -481,8 +461,7 @@ int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
}
int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_session *session)
{
nghttp2_session *session) {
assert(stream->data_item);
DEBUGF(fprintf(stderr, "stream: stream=%d resume data=%p flags=%02x\n",
@ -490,75 +469,65 @@ int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags,
stream->flags &= ~flags;
if(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) {
if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) {
return 0;
}
return stream_update_dep_on_attach_data(stream, session);
}
int nghttp2_stream_check_deferred_data(nghttp2_stream *stream)
{
int nghttp2_stream_check_deferred_data(nghttp2_stream *stream) {
return stream->data_item &&
(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
}
int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream)
{
int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream) {
return stream->data_item &&
(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
}
static int update_initial_window_size
(int32_t *window_size_ptr,
int32_t new_initial_window_size,
int32_t old_initial_window_size)
{
static int update_initial_window_size(int32_t *window_size_ptr,
int32_t new_initial_window_size,
int32_t old_initial_window_size) {
int64_t new_window_size = (int64_t)(*window_size_ptr) +
new_initial_window_size - old_initial_window_size;
if(INT32_MIN > new_window_size ||
new_window_size > NGHTTP2_MAX_WINDOW_SIZE) {
new_initial_window_size - old_initial_window_size;
if (INT32_MIN > new_window_size ||
new_window_size > NGHTTP2_MAX_WINDOW_SIZE) {
return -1;
}
*window_size_ptr = (int32_t)new_window_size;
return 0;
}
int nghttp2_stream_update_remote_initial_window_size
(nghttp2_stream *stream,
int32_t new_initial_window_size,
int32_t old_initial_window_size)
{
int nghttp2_stream_update_remote_initial_window_size(
nghttp2_stream *stream, int32_t new_initial_window_size,
int32_t old_initial_window_size) {
return update_initial_window_size(&stream->remote_window_size,
new_initial_window_size,
old_initial_window_size);
}
int nghttp2_stream_update_local_initial_window_size
(nghttp2_stream *stream,
int32_t new_initial_window_size,
int32_t old_initial_window_size)
{
int nghttp2_stream_update_local_initial_window_size(
nghttp2_stream *stream, int32_t new_initial_window_size,
int32_t old_initial_window_size) {
return update_initial_window_size(&stream->local_window_size,
new_initial_window_size,
old_initial_window_size);
}
void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream)
{
void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
stream->state = NGHTTP2_STREAM_OPENED;
}
nghttp2_stream* nghttp2_stream_get_dep_root(nghttp2_stream *stream)
{
for(;;) {
if(stream->sib_prev) {
nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream) {
for (;;) {
if (stream->sib_prev) {
stream = stream->sib_prev;
continue;
}
if(stream->dep_prev) {
if (stream->dep_prev) {
stream = stream->dep_prev;
continue;
@ -571,17 +540,16 @@ nghttp2_stream* nghttp2_stream_get_dep_root(nghttp2_stream *stream)
}
int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream,
nghttp2_stream *target)
{
if(stream == NULL) {
nghttp2_stream *target) {
if (stream == NULL) {
return 0;
}
if(stream == target) {
if (stream == target) {
return 1;
}
if(nghttp2_stream_dep_subtree_find(stream->sib_next, target)) {
if (nghttp2_stream_dep_subtree_find(stream->sib_next, target)) {
return 1;
}
@ -589,8 +557,7 @@ int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream,
}
void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
nghttp2_stream *stream)
{
nghttp2_stream *stream) {
nghttp2_stream *si;
nghttp2_stream *root_stream;
@ -598,14 +565,13 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
DEBUGF(fprintf(stderr,
"stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n",
dep_stream, dep_stream->stream_id,
stream, stream->stream_id));
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
stream->sum_dep_weight = dep_stream->sum_dep_weight;
dep_stream->sum_dep_weight = stream->weight;
if(dep_stream->dep_next) {
for(si = dep_stream->dep_next; si; si = si->sib_next) {
if (dep_stream->dep_next) {
for (si = dep_stream->dep_next; si; si = si->sib_next) {
stream->num_substreams += si->num_substreams;
}
@ -624,21 +590,18 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
++stream->roots->num_streams;
}
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream)
{
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
dep_stream->dep_next = stream;
stream->dep_prev = dep_stream;
}
static void link_sib(nghttp2_stream *prev_stream, nghttp2_stream *stream)
{
static void link_sib(nghttp2_stream *prev_stream, nghttp2_stream *stream) {
prev_stream->sib_next = stream;
stream->sib_prev = prev_stream;
}
static void insert_link_dep(nghttp2_stream *dep_stream,
nghttp2_stream *stream)
{
nghttp2_stream *stream) {
nghttp2_stream *sib_next;
assert(stream->sib_prev == NULL);
@ -652,8 +615,7 @@ static void insert_link_dep(nghttp2_stream *dep_stream,
link_dep(dep_stream, stream);
}
static void unlink_sib(nghttp2_stream *stream)
{
static void unlink_sib(nghttp2_stream *stream) {
nghttp2_stream *prev, *next, *dep_next;
prev = stream->sib_prev;
@ -661,7 +623,7 @@ static void unlink_sib(nghttp2_stream *stream)
assert(prev);
if(dep_next) {
if (dep_next) {
/*
* prev--stream(--sib_next--...)
* |
@ -671,7 +633,7 @@ static void unlink_sib(nghttp2_stream *stream)
link_sib(prev, dep_next);
if(stream->sib_next) {
if (stream->sib_next) {
link_sib(stream_last_sib(dep_next), stream->sib_next);
}
} else {
@ -682,14 +644,13 @@ static void unlink_sib(nghttp2_stream *stream)
prev->sib_next = next;
if(next) {
if (next) {
next->sib_prev = prev;
}
}
}
static void unlink_dep(nghttp2_stream *stream)
{
static void unlink_dep(nghttp2_stream *stream) {
nghttp2_stream *prev, *next, *dep_next;
prev = stream->dep_prev;
@ -697,7 +658,7 @@ static void unlink_dep(nghttp2_stream *stream)
assert(prev);
if(dep_next) {
if (dep_next) {
/*
* prev
* |
@ -707,10 +668,10 @@ static void unlink_dep(nghttp2_stream *stream)
*/
link_dep(prev, dep_next);
if(stream->sib_next) {
if (stream->sib_next) {
link_sib(stream_last_sib(dep_next), stream->sib_next);
}
} else if(stream->sib_next) {
} else if (stream->sib_next) {
/*
* prev
* |
@ -727,22 +688,19 @@ static void unlink_dep(nghttp2_stream *stream)
}
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
nghttp2_stream *stream)
{
nghttp2_stream *stream) {
nghttp2_stream *root_stream;
assert(stream->data_item == NULL);
DEBUGF(fprintf(stderr,
"stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n",
dep_stream, dep_stream->stream_id,
stream, stream->stream_id));
DEBUGF(fprintf(stderr, "stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n",
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
root_stream = stream_update_dep_length(dep_stream, 1);
dep_stream->sum_dep_weight += stream->weight;
if(dep_stream->dep_next == NULL) {
if (dep_stream->dep_next == NULL) {
link_dep(dep_stream, stream);
} else {
insert_link_dep(dep_stream, stream);
@ -754,20 +712,19 @@ void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
++stream->roots->num_streams;
}
void nghttp2_stream_dep_remove(nghttp2_stream *stream)
{
void nghttp2_stream_dep_remove(nghttp2_stream *stream) {
nghttp2_stream *prev, *next, *dep_prev, *si, *root_stream;
int32_t sum_dep_weight_delta;
root_stream = NULL;
DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n",
stream, stream->stream_id));
DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n", stream,
stream->stream_id));
/* Distribute weight of |stream| to direct descendants */
sum_dep_weight_delta = -stream->weight;
for(si = stream->dep_next; si; si = si->sib_next) {
for (si = stream->dep_next; si; si = si->sib_next) {
si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
sum_dep_weight_delta += si->weight;
@ -777,15 +734,15 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
dep_prev = prev->dep_prev;
if(dep_prev) {
if (dep_prev) {
root_stream = stream_update_dep_length(dep_prev, -1);
dep_prev->sum_dep_weight += sum_dep_weight_delta;
}
if(stream->sib_prev) {
if (stream->sib_prev) {
unlink_sib(stream);
} else if(stream->dep_prev) {
} else if (stream->dep_prev) {
unlink_dep(stream);
} else {
nghttp2_stream_roots_remove(stream->roots, stream);
@ -793,7 +750,7 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
/* stream is a root of tree. Removing stream makes its
descendants a root of its own subtree. */
for(si = stream->dep_next; si;) {
for (si = stream->dep_next; si;) {
next = si->sib_next;
si->dep_prev = NULL;
@ -809,7 +766,7 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
}
}
if(root_stream) {
if (root_stream) {
stream_update_dep_sum_norest_weight(root_stream);
stream_update_dep_effective_weight(root_stream);
}
@ -827,23 +784,21 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *stream,
nghttp2_session *session)
{
nghttp2_session *session) {
nghttp2_stream *last_sib;
nghttp2_stream *dep_next;
nghttp2_stream *root_stream;
size_t delta_substreams;
DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d "
"stream(%p)=%d\n",
dep_stream, dep_stream->stream_id,
stream, stream->stream_id));
"stream(%p)=%d\n",
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
delta_substreams = stream->num_substreams;
stream_update_dep_set_rest(stream);
if(dep_stream->dep_next) {
if (dep_stream->dep_next) {
/* dep_stream->num_substreams includes dep_stream itself */
stream->num_substreams += dep_stream->num_substreams - 1;
@ -856,7 +811,7 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
link_dep(dep_stream, stream);
if(stream->dep_next) {
if (stream->dep_next) {
last_sib = stream_last_sib(stream->dep_next);
link_sib(last_sib, dep_next);
@ -884,18 +839,16 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *stream,
nghttp2_session *session)
{
nghttp2_session *session) {
nghttp2_stream *root_stream;
DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
"stream(%p)=%d\n",
dep_stream, dep_stream->stream_id,
stream, stream->stream_id));
"stream(%p)=%d\n",
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
stream_update_dep_set_rest(stream);
if(dep_stream->dep_next) {
if (dep_stream->dep_next) {
dep_stream->sum_dep_weight += stream->weight;
insert_link_dep(dep_stream, stream);
@ -916,18 +869,17 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
return stream_update_dep_queue_top(root_stream, session);
}
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
{
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
nghttp2_stream *prev, *next, *dep_prev, *root_stream;
DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n",
stream, stream->stream_id));
DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n", stream,
stream->stream_id));
if(stream->sib_prev) {
if (stream->sib_prev) {
prev = stream->sib_prev;
prev->sib_next = stream->sib_next;
if(prev->sib_next) {
if (prev->sib_next) {
prev->sib_next->sib_prev = prev;
}
@ -935,13 +887,13 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
dep_prev = prev->dep_prev;
} else if(stream->dep_prev) {
} else if (stream->dep_prev) {
dep_prev = stream->dep_prev;
next = stream->sib_next;
dep_prev->dep_next = next;
if(next) {
if (next) {
next->dep_prev = dep_prev;
next->sib_prev = NULL;
@ -953,7 +905,7 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
dep_prev = NULL;
}
if(dep_prev) {
if (dep_prev) {
dep_prev->sum_dep_weight -= stream->weight;
root_stream = stream_update_dep_length(dep_prev, -stream->num_substreams);
@ -968,10 +920,9 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
}
int nghttp2_stream_dep_make_root(nghttp2_stream *stream,
nghttp2_session *session)
{
DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n",
stream, stream->stream_id));
nghttp2_session *session) {
DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n", stream,
stream->stream_id));
nghttp2_stream_roots_add(stream->roots, stream);
@ -987,13 +938,13 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream,
return stream_update_dep_queue_top(stream, session);
}
int nghttp2_stream_dep_all_your_stream_are_belong_to_us
(nghttp2_stream *stream, nghttp2_session *session)
{
int
nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream,
nghttp2_session *session) {
nghttp2_stream *first, *si;
DEBUGF(fprintf(stderr, "stream: ALL YOUR STREAM ARE BELONG TO US "
"stream(%p)=%d\n",
"stream(%p)=%d\n",
stream, stream->stream_id));
first = stream->roots->head;
@ -1001,23 +952,23 @@ int nghttp2_stream_dep_all_your_stream_are_belong_to_us
/* stream must not be include in stream->roots->head list */
assert(first != stream);
if(first) {
if (first) {
nghttp2_stream *prev;
prev = first;
DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n",
first, first->stream_id));
DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n", first,
first->stream_id));
stream->sum_dep_weight += first->weight;
stream->num_substreams += first->num_substreams;
for(si = first->root_next; si; si = si->root_next) {
for (si = first->root_next; si; si = si->root_next) {
assert(si != stream);
DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n",
si, si->stream_id));
DEBUGF(
fprintf(stderr, "stream: root stream(%p)=%d\n", si, si->stream_id));
stream->sum_dep_weight += si->weight;
stream->num_substreams += si->num_substreams;
@ -1027,7 +978,7 @@ int nghttp2_stream_dep_all_your_stream_are_belong_to_us
prev = si;
}
if(stream->dep_next) {
if (stream->dep_next) {
nghttp2_stream *sib_next;
sib_next = stream->dep_next;
@ -1046,27 +997,22 @@ int nghttp2_stream_dep_all_your_stream_are_belong_to_us
return nghttp2_stream_dep_make_root(stream, session);
}
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream)
{
return stream->dep_prev || stream->dep_next ||
stream->sib_prev || stream->sib_next ||
stream->root_next || stream->root_prev ||
stream->roots->head == stream;
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) {
return stream->dep_prev || stream->dep_next || stream->sib_prev ||
stream->sib_next || stream->root_next || stream->root_prev ||
stream->roots->head == stream;
}
void nghttp2_stream_roots_init(nghttp2_stream_roots *roots)
{
void nghttp2_stream_roots_init(nghttp2_stream_roots *roots) {
roots->head = NULL;
roots->num_streams = 0;
}
void nghttp2_stream_roots_free(nghttp2_stream_roots *roots _U_)
{}
void nghttp2_stream_roots_free(nghttp2_stream_roots *roots _U_) {}
void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
nghttp2_stream *stream)
{
if(roots->head) {
nghttp2_stream *stream) {
if (roots->head) {
stream->root_next = roots->head;
roots->head->root_prev = stream;
}
@ -1075,21 +1021,20 @@ void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
}
void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
nghttp2_stream *stream)
{
nghttp2_stream *stream) {
nghttp2_stream *root_prev, *root_next;
root_prev = stream->root_prev;
root_next = stream->root_next;
if(root_prev) {
if (root_prev) {
root_prev->root_next = root_next;
if(root_next) {
if (root_next) {
root_next->root_prev = root_prev;
}
} else {
if(root_next) {
if (root_next) {
root_next->root_prev = NULL;
}
@ -1100,11 +1045,10 @@ void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
stream->root_next = NULL;
}
void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots)
{
void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots) {
nghttp2_stream *si, *next;
for(si = roots->head; si;) {
for (si = roots->head; si;) {
next = si->root_next;
si->root_prev = NULL;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_STREAM_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -94,7 +94,7 @@ typedef enum {
NGHTTP2_STREAM_FLAG_DEFERRED_USER = 0x08,
/* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c
NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c
} nghttp2_stream_flag;
@ -189,10 +189,8 @@ struct nghttp2_stream {
};
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
uint8_t flags,
nghttp2_stream_state initial_state,
int32_t weight,
nghttp2_stream_roots *roots,
uint8_t flags, nghttp2_stream_state initial_state,
int32_t weight, nghttp2_stream_roots *roots,
int32_t remote_initial_window_size,
int32_t local_initial_window_size,
void *stream_user_data);
@ -250,10 +248,9 @@ int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream);
* This function returns 0 if it succeeds or -1. The failure is due to
* overflow.
*/
int nghttp2_stream_update_remote_initial_window_size
(nghttp2_stream *stream,
int32_t new_initial_window_size,
int32_t old_initial_window_size);
int nghttp2_stream_update_remote_initial_window_size(
nghttp2_stream *stream, int32_t new_initial_window_size,
int32_t old_initial_window_size);
/*
* Updates the local window size with the new value
@ -263,10 +260,9 @@ int nghttp2_stream_update_remote_initial_window_size
* This function returns 0 if it succeeds or -1. The failure is due to
* overflow.
*/
int nghttp2_stream_update_local_initial_window_size
(nghttp2_stream *stream,
int32_t new_initial_window_size,
int32_t old_initial_window_size);
int nghttp2_stream_update_local_initial_window_size(
nghttp2_stream *stream, int32_t new_initial_window_size,
int32_t old_initial_window_size);
/*
* Call this function if promised stream |stream| is replied with
@ -279,7 +275,7 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream);
* Returns the stream positioned in root of the dependency tree the
* |stream| belongs to.
*/
nghttp2_stream* nghttp2_stream_get_dep_root(nghttp2_stream *stream);
nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream);
/*
* Returns nonzero if |target| is found in subtree of |stream|.
@ -302,8 +298,8 @@ int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
* rather than stream->weight. This function is used to determine
* weight in dependency tree.
*/
int32_t nghttp2_stream_dep_distributed_effective_weight
(nghttp2_stream *stream, int32_t weight);
int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream,
int32_t weight);
/*
* Makes the |stream| depend on the |dep_stream|. This dependency is
@ -320,8 +316,7 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
* not exclusive. This function assumes |stream->data| is NULL and no
* dpri members are changed in this dependency tree.
*/
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
nghttp2_stream *stream);
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream);
/*
* Removes the |stream| from the current dependency tree. This
@ -421,8 +416,9 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream,
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_stream_dep_all_your_stream_are_belong_to_us
(nghttp2_stream *stream, nghttp2_session *session);
int
nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream,
nghttp2_session *session);
/*
* Returns nonzero if |stream| is in any dependency tree.

View File

@ -35,49 +35,44 @@
/* This function takes ownership of |nva_copy|. Regardless of the
return value, the caller must not free |nva_copy| after this
function returns. */
static int32_t submit_headers_shared
(nghttp2_session *session,
uint8_t flags,
int32_t stream_id,
const nghttp2_priority_spec *pri_spec,
nghttp2_nv *nva_copy,
size_t nvlen,
const nghttp2_data_provider *data_prd,
void *stream_user_data,
uint8_t attach_stream)
{
static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const nghttp2_priority_spec *pri_spec,
nghttp2_nv *nva_copy, size_t nvlen,
const nghttp2_data_provider *data_prd,
void *stream_user_data,
uint8_t attach_stream) {
int rv;
uint8_t flags_copy;
nghttp2_outbound_item *item = NULL;
nghttp2_frame *frame = NULL;
nghttp2_headers_category hcat;
if(stream_id == 0) {
if (stream_id == 0) {
rv = NGHTTP2_ERR_INVALID_ARGUMENT;
goto fail;
}
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
if (item == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail;
}
nghttp2_session_outbound_item_init(session, item);
if(data_prd != NULL && data_prd->read_callback != NULL) {
if (data_prd != NULL && data_prd->read_callback != NULL) {
item->aux_data.headers.data_prd = *data_prd;
}
item->aux_data.headers.stream_user_data = stream_user_data;
item->aux_data.headers.attach_stream = attach_stream;
flags_copy =
(flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
NGHTTP2_FLAG_END_HEADERS;
flags_copy = (flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
NGHTTP2_FLAG_END_HEADERS;
if(stream_id == -1) {
if(session->next_stream_id > INT32_MAX) {
if (stream_id == -1) {
if (session->next_stream_id > INT32_MAX) {
rv = NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
goto fail;
}
@ -93,56 +88,51 @@ static int32_t submit_headers_shared
frame = &item->frame;
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id,
hcat, pri_spec, nva_copy, nvlen);
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat,
pri_spec, nva_copy, nvlen);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
if (rv != 0) {
nghttp2_frame_headers_free(&frame->headers);
goto fail2;
}
if(hcat == NGHTTP2_HCAT_REQUEST) {
if (hcat == NGHTTP2_HCAT_REQUEST) {
return stream_id;
}
return 0;
fail:
fail:
/* nghttp2_frame_headers_init() takes ownership of nva_copy. */
nghttp2_nv_array_del(nva_copy);
fail2:
fail2:
free(item);
return rv;
}
static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec)
{
if(pri_spec->weight < NGHTTP2_MIN_WEIGHT) {
static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec) {
if (pri_spec->weight < NGHTTP2_MIN_WEIGHT) {
pri_spec->weight = NGHTTP2_MIN_WEIGHT;
} else if(pri_spec->weight > NGHTTP2_MAX_WEIGHT) {
} else if (pri_spec->weight > NGHTTP2_MAX_WEIGHT) {
pri_spec->weight = NGHTTP2_MAX_WEIGHT;
}
}
static int32_t submit_headers_shared_nva
(nghttp2_session *session,
uint8_t flags,
int32_t stream_id,
const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva,
size_t nvlen,
const nghttp2_data_provider *data_prd,
void *stream_user_data,
uint8_t attach_stream)
{
static int32_t submit_headers_shared_nva(nghttp2_session *session,
uint8_t flags, int32_t stream_id,
const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd,
void *stream_user_data,
uint8_t attach_stream) {
int rv;
nghttp2_nv *nva_copy;
nghttp2_priority_spec copy_pri_spec;
if(pri_spec) {
if (pri_spec) {
copy_pri_spec = *pri_spec;
adjust_priority_spec_weight(&copy_pri_spec);
} else {
@ -150,54 +140,50 @@ static int32_t submit_headers_shared_nva
}
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
if(rv < 0) {
if (rv < 0) {
return rv;
}
return submit_headers_shared(session, flags, stream_id,
&copy_pri_spec, nva_copy, nvlen, data_prd,
stream_user_data, attach_stream);
return submit_headers_shared(session, flags, stream_id, &copy_pri_spec,
nva_copy, nvlen, data_prd, stream_user_data,
attach_stream);
}
int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen,
void *stream_user_data)
{
void *stream_user_data) {
flags &= NGHTTP2_FLAG_END_STREAM;
if(pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) {
if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) {
flags |= NGHTTP2_FLAG_PRIORITY;
} else {
pri_spec = NULL;
}
return submit_headers_shared_nva(session, flags, stream_id, pri_spec,
nva, nvlen, NULL, stream_user_data, 0);
return submit_headers_shared_nva(session, flags, stream_id, pri_spec, nva,
nvlen, NULL, stream_user_data, 0);
}
int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags _U_,
const uint8_t *opaque_data)
{
const uint8_t *opaque_data) {
return nghttp2_session_add_ping(session, NGHTTP2_FLAG_NONE, opaque_data);
}
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
int32_t stream_id,
const nghttp2_priority_spec *pri_spec)
{
const nghttp2_priority_spec *pri_spec) {
int rv;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_priority_spec copy_pri_spec;
if(stream_id == 0 || pri_spec == NULL) {
if (stream_id == 0 || pri_spec == NULL) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
if(stream_id == pri_spec->stream_id) {
if (stream_id == pri_spec->stream_id) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
@ -207,7 +193,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
if (item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -219,7 +205,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
if (rv != 0) {
nghttp2_frame_priority_free(&frame->priority);
free(item);
@ -230,10 +216,8 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
}
int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags _U_,
int32_t stream_id,
uint32_t error_code)
{
if(stream_id == 0) {
int32_t stream_id, uint32_t error_code) {
if (stream_id == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
@ -241,25 +225,21 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags _U_,
}
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags _U_,
int32_t last_stream_id,
uint32_t error_code,
const uint8_t *opaque_data, size_t opaque_data_len)
{
return nghttp2_session_add_goaway(session, last_stream_id,
error_code, opaque_data, opaque_data_len);
int32_t last_stream_id, uint32_t error_code,
const uint8_t *opaque_data, size_t opaque_data_len) {
return nghttp2_session_add_goaway(session, last_stream_id, error_code,
opaque_data, opaque_data_len);
}
int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags _U_,
const nghttp2_settings_entry *iv, size_t niv)
{
const nghttp2_settings_entry *iv, size_t niv) {
return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
}
int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
int32_t stream_id,
const nghttp2_nv *nva, size_t nvlen,
void *promised_stream_user_data)
{
int32_t stream_id, const nghttp2_nv *nva,
size_t nvlen,
void *promised_stream_user_data) {
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_nv *nva_copy;
@ -267,21 +247,21 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
int32_t promised_stream_id;
int rv;
if(stream_id == 0) {
if (stream_id == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
if(!session->server) {
if (!session->server) {
return NGHTTP2_ERR_PROTO;
}
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
if (session->next_stream_id > INT32_MAX) {
return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
}
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
if (item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -292,7 +272,7 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
frame = &item->frame;
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
if(rv < 0) {
if (rv < 0) {
free(item);
return rv;
}
@ -302,13 +282,12 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
promised_stream_id = session->next_stream_id;
session->next_stream_id += 2;
nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy,
stream_id, promised_stream_id,
nva_copy, nvlen);
nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy, stream_id,
promised_stream_id, nva_copy, nvlen);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
if (rv != 0) {
nghttp2_frame_push_promise_free(&frame->push_promise);
free(item);
@ -320,44 +299,41 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
int32_t window_size_increment)
{
int32_t window_size_increment) {
int rv;
nghttp2_stream *stream = 0;
if(window_size_increment == 0) {
if (window_size_increment == 0) {
return 0;
}
flags = 0;
if(stream_id == 0) {
rv = nghttp2_adjust_local_window_size(&session->local_window_size,
&session->recv_window_size,
&session->recv_reduction,
&window_size_increment);
if(rv != 0) {
if (stream_id == 0) {
rv = nghttp2_adjust_local_window_size(
&session->local_window_size, &session->recv_window_size,
&session->recv_reduction, &window_size_increment);
if (rv != 0) {
return rv;
}
} else {
stream = nghttp2_session_get_stream(session, stream_id);
if(!stream) {
if (!stream) {
return 0;
}
rv = nghttp2_adjust_local_window_size(&stream->local_window_size,
&stream->recv_window_size,
&stream->recv_reduction,
&window_size_increment);
if(rv != 0) {
rv = nghttp2_adjust_local_window_size(
&stream->local_window_size, &stream->recv_window_size,
&stream->recv_reduction, &window_size_increment);
if (rv != 0) {
return rv;
}
}
if(window_size_increment > 0) {
if(stream_id == 0) {
if (window_size_increment > 0) {
if (stream_id == 0) {
session->consumed_size =
nghttp2_max(0, session->consumed_size - window_size_increment);
nghttp2_max(0, session->consumed_size - window_size_increment);
} else {
stream->consumed_size =
nghttp2_max(0, stream->consumed_size - window_size_increment);
nghttp2_max(0, stream->consumed_size - window_size_increment);
}
return nghttp2_session_add_window_update(session, flags, stream_id,
@ -367,12 +343,10 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
}
int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
int32_t stream_id,
uint32_t max_age, uint16_t port,
int32_t stream_id, uint32_t max_age, uint16_t port,
const uint8_t *protocol_id, size_t protocol_id_len,
const uint8_t *host, size_t host_len,
const uint8_t *origin, size_t origin_len)
{
const uint8_t *origin, size_t origin_len) {
int rv;
size_t varlen;
uint8_t *var, *varp;
@ -381,26 +355,26 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
nghttp2_ext_altsvc *altsvc;
uint8_t *copy_protocol_id, *copy_host, *copy_origin;
if(!session->server) {
if (!session->server) {
return NGHTTP2_ERR_PROTO;
}
varlen = protocol_id_len + host_len + origin_len;
/* 9 = fixed part 8 bytes + HOST_LEN 1 byte */
if(varlen + 9 > NGHTTP2_MAX_PAYLOADLEN) {
if (varlen + 9 > NGHTTP2_MAX_PAYLOADLEN) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
altsvc = malloc(sizeof(nghttp2_ext_altsvc));
if(altsvc == NULL) {
if (altsvc == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail;
}
if(varlen == 0) {
if (varlen == 0) {
var = NULL;
copy_protocol_id = NULL;
copy_host = NULL;
@ -408,7 +382,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
} else {
var = malloc(varlen);
if(var == NULL) {
if (var == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto var_alloc_fail;
@ -433,7 +407,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
if (item == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto frame_alloc_fail;
@ -445,12 +419,12 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
frame->ext.payload = altsvc;
nghttp2_frame_altsvc_init(&frame->ext, stream_id, max_age, port,
copy_protocol_id, protocol_id_len,
copy_host, host_len, copy_origin, origin_len);
copy_protocol_id, protocol_id_len, copy_host,
host_len, copy_origin, origin_len);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
if (rv != 0) {
nghttp2_frame_altsvc_free(&frame->ext);
free(item);
free(altsvc);
@ -460,25 +434,24 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
return 0;
frame_alloc_fail:
frame_alloc_fail:
free(var);
var_alloc_fail:
var_alloc_fail:
free(altsvc);
fail:
fail:
return rv;
}
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
const nghttp2_data_provider *data_prd)
{
const nghttp2_data_provider *data_prd) {
uint8_t flags = NGHTTP2_FLAG_NONE;
if(data_prd == NULL || data_prd->read_callback == NULL) {
if (data_prd == NULL || data_prd->read_callback == NULL) {
flags |= NGHTTP2_FLAG_END_STREAM;
}
if(pri_spec) {
if (pri_spec) {
flags |= NGHTTP2_FLAG_PRIORITY;
}
@ -489,57 +462,50 @@ int32_t nghttp2_submit_request(nghttp2_session *session,
const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd,
void *stream_user_data)
{
void *stream_user_data) {
uint8_t flags;
if(pri_spec && nghttp2_priority_spec_check_default(pri_spec)) {
if (pri_spec && nghttp2_priority_spec_check_default(pri_spec)) {
pri_spec = NULL;
}
flags = set_request_flags(pri_spec, data_prd);
return submit_headers_shared_nva(session, flags, -1, pri_spec,
nva, nvlen,
return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
data_prd, stream_user_data, 0);
}
static uint8_t set_response_flags(const nghttp2_data_provider *data_prd)
{
static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) {
uint8_t flags = NGHTTP2_FLAG_NONE;
if(data_prd == NULL || data_prd->read_callback == NULL) {
if (data_prd == NULL || data_prd->read_callback == NULL) {
flags |= NGHTTP2_FLAG_END_STREAM;
}
return flags;
}
int nghttp2_submit_response(nghttp2_session *session,
int32_t stream_id,
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd)
{
const nghttp2_data_provider *data_prd) {
uint8_t flags = set_response_flags(data_prd);
return submit_headers_shared_nva(session, flags, stream_id,
NULL, nva, nvlen,
return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
data_prd, NULL, 1);
}
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const nghttp2_data_provider *data_prd)
{
const nghttp2_data_provider *data_prd) {
int rv;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_data_aux_data *aux_data;
uint8_t nflags = flags & NGHTTP2_FLAG_END_STREAM;
if(stream_id == 0) {
if (stream_id == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
if (item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
@ -555,7 +521,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
nghttp2_frame_data_init(&frame->data, NGHTTP2_FLAG_NONE, stream_id);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
if (rv != 0) {
nghttp2_frame_data_free(&frame->data);
free(item);
return rv;
@ -563,16 +529,14 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
return 0;
}
ssize_t nghttp2_pack_settings_payload(uint8_t *buf,
size_t buflen,
ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
const nghttp2_settings_entry *iv,
size_t niv)
{
if(!nghttp2_iv_check(iv, niv)) {
size_t niv) {
if (!nghttp2_iv_check(iv, niv)) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
if(buflen < (niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH)) {
if (buflen < (niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH)) {
return NGHTTP2_ERR_INSUFF_BUFSIZE;
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_SUBMIT_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -23,21 +23,16 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
static nghttp2_info version = {
NGHTTP2_VERSION_AGE,
NGHTTP2_VERSION_NUM,
NGHTTP2_VERSION,
NGHTTP2_PROTO_VERSION_ID
};
static nghttp2_info version = {NGHTTP2_VERSION_AGE, NGHTTP2_VERSION_NUM,
NGHTTP2_VERSION, NGHTTP2_PROTO_VERSION_ID};
nghttp2_info *nghttp2_version(int least_version)
{
if(least_version > NGHTTP2_VERSION_NUM)
nghttp2_info *nghttp2_version(int least_version) {
if (least_version > NGHTTP2_VERSION_NUM)
return NULL;
return &version;
}

View File

@ -30,30 +30,21 @@
namespace nghttp2 {
ParserData::ParserData(const std::string& base_uri)
: base_uri(base_uri)
{}
ParserData::ParserData(const std::string &base_uri) : base_uri(base_uri) {}
HtmlParser::HtmlParser(const std::string& base_uri)
: base_uri_(base_uri),
parser_ctx_(nullptr),
parser_data_(base_uri)
{}
HtmlParser::HtmlParser(const std::string &base_uri)
: base_uri_(base_uri), parser_ctx_(nullptr), parser_data_(base_uri) {}
HtmlParser::~HtmlParser()
{
htmlFreeParserCtxt(parser_ctx_);
}
HtmlParser::~HtmlParser() { htmlFreeParserCtxt(parser_ctx_); }
namespace {
const char* get_attr(const xmlChar **attrs, const char *name)
{
if(attrs == nullptr) {
const char *get_attr(const xmlChar **attrs, const char *name) {
if (attrs == nullptr) {
return nullptr;
}
for(; *attrs; attrs += 2) {
if(util::strieq(reinterpret_cast<const char*>(attrs[0]), name)) {
return reinterpret_cast<const char*>(attrs[1]);
for (; *attrs; attrs += 2) {
if (util::strieq(reinterpret_cast<const char *>(attrs[0]), name)) {
return reinterpret_cast<const char *>(attrs[1]);
}
}
return nullptr;
@ -61,46 +52,42 @@ const char* get_attr(const xmlChar **attrs, const char *name)
} // namespace
namespace {
void add_link(ParserData *parser_data, const char *uri, RequestPriority pri)
{
auto u = xmlBuildURI(reinterpret_cast<const xmlChar*>(uri),
reinterpret_cast<const xmlChar*>
(parser_data->base_uri.c_str()));
if(u) {
parser_data->links.push_back(std::make_pair(reinterpret_cast<char*>(u),
pri));
void add_link(ParserData *parser_data, const char *uri, RequestPriority pri) {
auto u = xmlBuildURI(
reinterpret_cast<const xmlChar *>(uri),
reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str()));
if (u) {
parser_data->links.push_back(
std::make_pair(reinterpret_cast<char *>(u), pri));
free(u);
}
}
} // namespace
namespace {
void start_element_func
(void* user_data,
const xmlChar *name,
const xmlChar **attrs)
{
auto parser_data = static_cast<ParserData*>(user_data);
if(util::strieq(reinterpret_cast<const char*>(name), "link")) {
void start_element_func(void *user_data, const xmlChar *name,
const xmlChar **attrs) {
auto parser_data = static_cast<ParserData *>(user_data);
if (util::strieq(reinterpret_cast<const char *>(name), "link")) {
auto rel_attr = get_attr(attrs, "rel");
auto href_attr = get_attr(attrs, "href");
if(!href_attr) {
if (!href_attr) {
return;
}
if(util::strieq(rel_attr, "shortcut icon")) {
if (util::strieq(rel_attr, "shortcut icon")) {
add_link(parser_data, href_attr, REQ_PRI_LOWEST);
} else if(util::strieq(rel_attr, "stylesheet")) {
} else if (util::strieq(rel_attr, "stylesheet")) {
add_link(parser_data, href_attr, REQ_PRI_MEDIUM);
}
} else if(util::strieq(reinterpret_cast<const char*>(name), "img")) {
} else if (util::strieq(reinterpret_cast<const char *>(name), "img")) {
auto src_attr = get_attr(attrs, "src");
if(!src_attr) {
if (!src_attr) {
return;
}
add_link(parser_data, src_attr, REQ_PRI_LOWEST);
} else if(util::strieq(reinterpret_cast<const char*>(name), "script")) {
} else if (util::strieq(reinterpret_cast<const char *>(name), "script")) {
auto src_attr = get_attr(attrs, "src");
if(!src_attr) {
if (!src_attr) {
return;
}
add_link(parser_data, src_attr, REQ_PRI_LOW);
@ -109,55 +96,51 @@ void start_element_func
} // namespace
namespace {
xmlSAXHandler saxHandler =
{
nullptr, // internalSubsetSAXFunc
nullptr, // isStandaloneSAXFunc
nullptr, // hasInternalSubsetSAXFunc
nullptr, // hasExternalSubsetSAXFunc
nullptr, // resolveEntitySAXFunc
nullptr, // getEntitySAXFunc
nullptr, // entityDeclSAXFunc
nullptr, // notationDeclSAXFunc
nullptr, // attributeDeclSAXFunc
nullptr, // elementDeclSAXFunc
nullptr, // unparsedEntityDeclSAXFunc
nullptr, // setDocumentLocatorSAXFunc
nullptr, // startDocumentSAXFunc
nullptr, // endDocumentSAXFunc
xmlSAXHandler saxHandler = {
nullptr, // internalSubsetSAXFunc
nullptr, // isStandaloneSAXFunc
nullptr, // hasInternalSubsetSAXFunc
nullptr, // hasExternalSubsetSAXFunc
nullptr, // resolveEntitySAXFunc
nullptr, // getEntitySAXFunc
nullptr, // entityDeclSAXFunc
nullptr, // notationDeclSAXFunc
nullptr, // attributeDeclSAXFunc
nullptr, // elementDeclSAXFunc
nullptr, // unparsedEntityDeclSAXFunc
nullptr, // setDocumentLocatorSAXFunc
nullptr, // startDocumentSAXFunc
nullptr, // endDocumentSAXFunc
&start_element_func, // startElementSAXFunc
nullptr, // endElementSAXFunc
nullptr, // referenceSAXFunc
nullptr, // charactersSAXFunc
nullptr, // ignorableWhitespaceSAXFunc
nullptr, // processingInstructionSAXFunc
nullptr, // commentSAXFunc
nullptr, // warningSAXFunc
nullptr, // errorSAXFunc
nullptr, // fatalErrorSAXFunc
nullptr, // getParameterEntitySAXFunc
nullptr, // cdataBlockSAXFunc
nullptr, // externalSubsetSAXFunc
0, // unsigned int initialized
nullptr, // void * _private
nullptr, // startElementNsSAX2Func
nullptr, // endElementNsSAX2Func
nullptr, // xmlStructuredErrorFunc
};
nullptr, // endElementSAXFunc
nullptr, // referenceSAXFunc
nullptr, // charactersSAXFunc
nullptr, // ignorableWhitespaceSAXFunc
nullptr, // processingInstructionSAXFunc
nullptr, // commentSAXFunc
nullptr, // warningSAXFunc
nullptr, // errorSAXFunc
nullptr, // fatalErrorSAXFunc
nullptr, // getParameterEntitySAXFunc
nullptr, // cdataBlockSAXFunc
nullptr, // externalSubsetSAXFunc
0, // unsigned int initialized
nullptr, // void * _private
nullptr, // startElementNsSAX2Func
nullptr, // endElementNsSAX2Func
nullptr, // xmlStructuredErrorFunc
};
} // namespace
int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin)
{
if(!parser_ctx_) {
parser_ctx_ = htmlCreatePushParserCtxt(&saxHandler,
&parser_data_,
chunk, size,
base_uri_.c_str(),
XML_CHAR_ENCODING_NONE);
if(!parser_ctx_) {
int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin) {
if (!parser_ctx_) {
parser_ctx_ =
htmlCreatePushParserCtxt(&saxHandler, &parser_data_, chunk, size,
base_uri_.c_str(), XML_CHAR_ENCODING_NONE);
if (!parser_ctx_) {
return -1;
} else {
if(fin) {
if (fin) {
return parse_chunk_internal(nullptr, 0, fin);
} else {
return 0;
@ -168,26 +151,20 @@ int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin)
}
}
int HtmlParser::parse_chunk_internal(const char *chunk, size_t size,
int fin)
{
int HtmlParser::parse_chunk_internal(const char *chunk, size_t size, int fin) {
int rv = htmlParseChunk(parser_ctx_, chunk, size, fin);
if(rv == 0) {
if (rv == 0) {
return 0;
} else {
return -1;
}
}
const std::vector<std::pair<std::string, RequestPriority>>&
HtmlParser::get_links() const
{
const std::vector<std::pair<std::string, RequestPriority>> &
HtmlParser::get_links() const {
return parser_data_.links;
}
void HtmlParser::clear_links()
{
parser_data_.links.clear();
}
void HtmlParser::clear_links() { parser_data_.links.clear(); }
} // namespace nghttp2

View File

@ -48,19 +48,19 @@ enum RequestPriority {
struct ParserData {
std::string base_uri;
std::vector<std::pair<std::string, RequestPriority>> links;
ParserData(const std::string& base_uri);
ParserData(const std::string &base_uri);
};
#ifdef HAVE_LIBXML2
class HtmlParser {
public:
HtmlParser(const std::string& base_uri);
HtmlParser(const std::string &base_uri);
~HtmlParser();
int parse_chunk(const char *chunk, size_t size, int fin);
const std::vector<std::pair<std::string, RequestPriority>>&
get_links() const;
const std::vector<std::pair<std::string, RequestPriority>> &get_links() const;
void clear_links();
private:
int parse_chunk_internal(const char *chunk, size_t size, int fin);
@ -73,11 +73,14 @@ private:
class HtmlParser {
public:
HtmlParser(const std::string& base_uri) {}
HtmlParser(const std::string &base_uri) {}
int parse_chunk(const char *chunk, size_t size, int fin) { return 0; }
const std::vector<std::pair<std::string, RequestPriority>>&
get_links() const { return links_; }
const std::vector<std::pair<std::string, RequestPriority>> &
get_links() const {
return links_;
}
void clear_links() {}
private:
std::vector<std::pair<std::string, RequestPriority>> links_;
};

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@
#include <nghttp2/nghttp2.h>
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@ -112,36 +112,31 @@ public:
int on_connect();
int verify_npn_result();
int submit_file_response(const std::string& status,
Stream *stream,
time_t last_modified,
off_t file_length,
int submit_file_response(const std::string &status, Stream *stream,
time_t last_modified, off_t file_length,
nghttp2_data_provider *data_prd);
int submit_response(const std::string& status,
int32_t stream_id,
int submit_response(const std::string &status, int32_t stream_id,
nghttp2_data_provider *data_prd);
int submit_response
(const std::string& status,
int32_t stream_id,
const Headers& headers,
nghttp2_data_provider *data_prd);
int submit_response(const std::string &status, int32_t stream_id,
const Headers &headers, nghttp2_data_provider *data_prd);
int submit_non_final_response(const std::string& status, int32_t stream_id);
int submit_non_final_response(const std::string &status, int32_t stream_id);
int submit_push_promise(Stream *stream, const std::string& push_path);
int submit_push_promise(Stream *stream, const std::string &push_path);
int submit_rst_stream(Stream *stream, uint32_t error_code);
void add_stream(int32_t stream_id, std::unique_ptr<Stream> stream);
void remove_stream(int32_t stream_id);
Stream* get_stream(int32_t stream_id);
Stream *get_stream(int32_t stream_id);
int64_t session_id() const;
Sessions* get_sessions() const;
const Config* get_config() const;
Sessions *get_sessions() const;
const Config *get_config() const;
void remove_settings_timer();
void terminate_session(uint32_t error_code);
private:
std::map<int32_t, std::unique_ptr<Stream>> id2stream_;
int64_t session_id_;
@ -155,18 +150,18 @@ private:
class HttpServer {
public:
HttpServer(const Config* config);
HttpServer(const Config *config);
int listen();
int run();
const Config* get_config() const;
const Config *get_config() const;
private:
const Config *config_;
};
ssize_t file_read_callback
(nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length, int *eof,
nghttp2_data_source *source, void *user_data);
ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length, int *eof,
nghttp2_data_source *source, void *user_data);
} // namespace nghttp2

View File

@ -52,9 +52,8 @@
namespace nghttp2 {
namespace {
const char* strstatus(uint32_t error_code)
{
switch(error_code) {
const char *strstatus(uint32_t error_code) {
switch (error_code) {
case NGHTTP2_NO_ERROR:
return "NO_ERROR";
case NGHTTP2_PROTOCOL_ERROR:
@ -90,9 +89,8 @@ const char* strstatus(uint32_t error_code)
} // namespace
namespace {
const char* strsettingsid(int32_t id)
{
switch(id) {
const char *strsettingsid(int32_t id) {
switch (id) {
case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
return "SETTINGS_HEADER_TABLE_SIZE";
case NGHTTP2_SETTINGS_ENABLE_PUSH:
@ -112,9 +110,8 @@ const char* strsettingsid(int32_t id)
} // namespace
namespace {
const char* strframetype(uint8_t type)
{
switch(type) {
const char *strframetype(uint8_t type) {
switch (type) {
case NGHTTP2_DATA:
return "DATA";
case NGHTTP2_HEADERS:
@ -145,44 +142,28 @@ namespace {
bool color_output = false;
} // namespace
void set_color_output(bool f)
{
color_output = f;
}
void set_color_output(bool f) { color_output = f; }
namespace {
FILE *outfile = stdout;
} // namespace
void set_output(FILE *file)
{
outfile = file;
}
void set_output(FILE *file) { outfile = file; }
namespace {
void print_frame_attr_indent()
{
fprintf(outfile, " ");
}
void print_frame_attr_indent() { fprintf(outfile, " "); }
} // namespace
namespace {
const char* ansi_esc(const char *code)
{
return color_output ? code : "";
}
const char *ansi_esc(const char *code) { return color_output ? code : ""; }
} // namespace
namespace {
const char* ansi_escend()
{
return color_output ? "\033[0m" : "";
}
const char *ansi_escend() { return color_output ? "\033[0m" : ""; }
} // namespace
namespace {
void print_nv(nghttp2_nv *nv)
{
void print_nv(nghttp2_nv *nv) {
fprintf(outfile, "%s", ansi_esc("\033[1;34m"));
fwrite(nv->name, nv->namelen, 1, outfile);
fprintf(outfile, "%s: ", ansi_escend());
@ -191,10 +172,9 @@ void print_nv(nghttp2_nv *nv)
}
} // namespace
namespace {
void print_nv(nghttp2_nv *nva, size_t nvlen)
{
void print_nv(nghttp2_nv *nva, size_t nvlen) {
auto end = nva + nvlen;
for(; nva != end; ++nva) {
for (; nva != end; ++nva) {
print_frame_attr_indent();
print_nv(nva);
@ -202,57 +182,53 @@ void print_nv(nghttp2_nv *nva, size_t nvlen)
}
} // namelen
void print_timer()
{
void print_timer() {
auto millis = get_timer();
fprintf(outfile, "%s[%3ld.%03ld]%s",
ansi_esc("\033[33m"),
(long int)(millis.count()/1000), (long int)(millis.count()%1000),
fprintf(outfile, "%s[%3ld.%03ld]%s", ansi_esc("\033[33m"),
(long int)(millis.count() / 1000), (long int)(millis.count() % 1000),
ansi_escend());
}
namespace {
void print_frame_hd(const nghttp2_frame_hd& hd)
{
fprintf(outfile, "<length=%zu, flags=0x%02x, stream_id=%d>\n",
hd.length, hd.flags, hd.stream_id);
void print_frame_hd(const nghttp2_frame_hd &hd) {
fprintf(outfile, "<length=%zu, flags=0x%02x, stream_id=%d>\n", hd.length,
hd.flags, hd.stream_id);
}
} // namespace
namespace {
void print_flags(const nghttp2_frame_hd& hd)
{
void print_flags(const nghttp2_frame_hd &hd) {
std::string s;
switch(hd.type) {
switch (hd.type) {
case NGHTTP2_DATA:
if(hd.flags & NGHTTP2_FLAG_END_STREAM) {
if (hd.flags & NGHTTP2_FLAG_END_STREAM) {
s += "END_STREAM";
}
if(hd.flags & NGHTTP2_FLAG_PADDED) {
if(!s.empty()) {
if (hd.flags & NGHTTP2_FLAG_PADDED) {
if (!s.empty()) {
s += " | ";
}
s += "PADDED";
}
break;
case NGHTTP2_HEADERS:
if(hd.flags & NGHTTP2_FLAG_END_STREAM) {
if (hd.flags & NGHTTP2_FLAG_END_STREAM) {
s += "END_STREAM";
}
if(hd.flags & NGHTTP2_FLAG_END_HEADERS) {
if(!s.empty()) {
if (hd.flags & NGHTTP2_FLAG_END_HEADERS) {
if (!s.empty()) {
s += " | ";
}
s += "END_HEADERS";
}
if(hd.flags & NGHTTP2_FLAG_PADDED) {
if(!s.empty()) {
if (hd.flags & NGHTTP2_FLAG_PADDED) {
if (!s.empty()) {
s += " | ";
}
s += "PADDED";
}
if(hd.flags & NGHTTP2_FLAG_PRIORITY) {
if(!s.empty()) {
if (hd.flags & NGHTTP2_FLAG_PRIORITY) {
if (!s.empty()) {
s += " | ";
}
s += "PRIORITY";
@ -262,23 +238,23 @@ void print_flags(const nghttp2_frame_hd& hd)
case NGHTTP2_PRIORITY:
break;
case NGHTTP2_SETTINGS:
if(hd.flags & NGHTTP2_FLAG_ACK) {
if (hd.flags & NGHTTP2_FLAG_ACK) {
s += "ACK";
}
break;
case NGHTTP2_PUSH_PROMISE:
if(hd.flags & NGHTTP2_FLAG_END_HEADERS) {
if (hd.flags & NGHTTP2_FLAG_END_HEADERS) {
s += "END_HEADERS";
}
if(hd.flags & NGHTTP2_FLAG_PADDED) {
if(!s.empty()) {
if (hd.flags & NGHTTP2_FLAG_PADDED) {
if (!s.empty()) {
s += " | ";
}
s += "PADDED";
}
break;
case NGHTTP2_PING:
if(hd.flags & NGHTTP2_FLAG_ACK) {
if (hd.flags & NGHTTP2_FLAG_ACK) {
s += "ACK";
}
break;
@ -287,33 +263,26 @@ void print_flags(const nghttp2_frame_hd& hd)
}
} // namespace
enum print_type {
PRINT_SEND,
PRINT_RECV
};
enum print_type { PRINT_SEND, PRINT_RECV };
namespace {
const char* frame_name_ansi_esc(print_type ptype)
{
const char *frame_name_ansi_esc(print_type ptype) {
return ansi_esc(ptype == PRINT_SEND ? "\033[1;35m" : "\033[1;36m");
}
} // namespace
namespace {
void print_frame(print_type ptype, const nghttp2_frame *frame)
{
fprintf(outfile, "%s%s%s frame ",
frame_name_ansi_esc(ptype),
strframetype(frame->hd.type),
ansi_escend());
void print_frame(print_type ptype, const nghttp2_frame *frame) {
fprintf(outfile, "%s%s%s frame ", frame_name_ansi_esc(ptype),
strframetype(frame->hd.type), ansi_escend());
print_frame_hd(frame->hd);
if(frame->hd.flags) {
if (frame->hd.flags) {
print_frame_attr_indent();
print_flags(frame->hd);
}
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_DATA:
if(frame->data.padlen > 0) {
if (frame->data.padlen > 0) {
print_frame_attr_indent();
fprintf(outfile, "(padlen=%zu)\n", frame->data.padlen);
}
@ -321,14 +290,13 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
case NGHTTP2_HEADERS:
print_frame_attr_indent();
fprintf(outfile, "(padlen=%zu", frame->headers.padlen);
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
fprintf(outfile, ", stream_id=%d, weight=%u, exclusive=%d",
frame->headers.pri_spec.stream_id,
frame->headers.pri_spec.weight,
frame->headers.pri_spec.stream_id, frame->headers.pri_spec.weight,
frame->headers.pri_spec.exclusive);
}
fprintf(outfile, ")\n");
switch(frame->headers.cat) {
switch (frame->headers.cat) {
case NGHTTP2_HCAT_REQUEST:
print_frame_attr_indent();
fprintf(outfile, "; Open new stream\n");
@ -350,8 +318,7 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
print_frame_attr_indent();
fprintf(outfile, "(stream_id=%d, weight=%u, exclusive=%d)\n",
frame->priority.pri_spec.stream_id,
frame->priority.pri_spec.weight,
frame->priority.pri_spec.stream_id, frame->priority.pri_spec.weight,
frame->priority.pri_spec.exclusive);
break;
@ -365,19 +332,17 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
print_frame_attr_indent();
fprintf(outfile, "(niv=%lu)\n",
static_cast<unsigned long>(frame->settings.niv));
for(size_t i = 0; i < frame->settings.niv; ++i) {
for (size_t i = 0; i < frame->settings.niv; ++i) {
print_frame_attr_indent();
fprintf(outfile, "[%s(0x%02x):%u]\n",
strsettingsid(frame->settings.iv[i].settings_id),
frame->settings.iv[i].settings_id,
frame->settings.iv[i].value);
frame->settings.iv[i].settings_id, frame->settings.iv[i].value);
}
break;
case NGHTTP2_PUSH_PROMISE:
print_frame_attr_indent();
fprintf(outfile, "(padlen=%zu, promised_stream_id=%d)\n",
frame->push_promise.padlen,
frame->push_promise.promised_stream_id);
frame->push_promise.padlen, frame->push_promise.promised_stream_id);
print_nv(frame->push_promise.nva, frame->push_promise.nvlen);
break;
case NGHTTP2_PING:
@ -387,11 +352,9 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
break;
case NGHTTP2_GOAWAY:
print_frame_attr_indent();
fprintf(outfile,
"(last_stream_id=%d, error_code=%s(0x%02x), "
"opaque_data(%u)=[%s])\n",
frame->goaway.last_stream_id,
strstatus(frame->goaway.error_code),
fprintf(outfile, "(last_stream_id=%d, error_code=%s(0x%02x), "
"opaque_data(%u)=[%s])\n",
frame->goaway.last_stream_id, strstatus(frame->goaway.error_code),
frame->goaway.error_code,
static_cast<unsigned int>(frame->goaway.opaque_data_len),
util::ascii_dump(frame->goaway.opaque_data,
@ -405,24 +368,24 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
case NGHTTP2_EXT_ALTSVC: {
print_frame_attr_indent();
auto altsvc = static_cast<const nghttp2_ext_altsvc*>(frame->ext.payload);
auto altsvc = static_cast<const nghttp2_ext_altsvc *>(frame->ext.payload);
fprintf(outfile, "(max-age=%u, port=%u, protocol_id=",
altsvc->max_age, altsvc->port);
fprintf(outfile, "(max-age=%u, port=%u, protocol_id=", altsvc->max_age,
altsvc->port);
if(altsvc->protocol_id_len) {
if (altsvc->protocol_id_len) {
fwrite(altsvc->protocol_id, altsvc->protocol_id_len, 1, outfile);
}
fprintf(outfile, ", host=");
if(altsvc->host_len) {
if (altsvc->host_len) {
fwrite(altsvc->host, altsvc->host_len, 1, outfile);
}
fprintf(outfile, ", origin=");
if(altsvc->origin_len) {
if (altsvc->origin_len) {
fwrite(altsvc->origin, altsvc->origin_len, 1, outfile);
}
@ -437,16 +400,12 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
} // namespace
int verbose_on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
uint8_t flags,
void *user_data)
{
nghttp2_nv nv = {
const_cast<uint8_t*>(name), const_cast<uint8_t*>(value),
namelen, valuelen
};
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags,
void *user_data) {
nghttp2_nv nv = {const_cast<uint8_t *>(name), const_cast<uint8_t *>(value),
namelen, valuelen};
print_timer();
fprintf(outfile, " recv (stream_id=%d, noind=%d) ", frame->hd.stream_id,
@ -458,9 +417,9 @@ int verbose_on_header_callback(nghttp2_session *session,
return 0;
}
int verbose_on_frame_recv_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
int verbose_on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data) {
print_timer();
fprintf(outfile, " recv ");
print_frame(PRINT_RECV, frame);
@ -468,10 +427,10 @@ int verbose_on_frame_recv_callback
return 0;
}
int verbose_on_invalid_frame_recv_callback
(nghttp2_session *session, const nghttp2_frame *frame,
uint32_t error_code, void *user_data)
{
int verbose_on_invalid_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame,
uint32_t error_code,
void *user_data) {
print_timer();
fprintf(outfile, " [INVALID; status=%s] recv ", strstatus(error_code));
print_frame(PRINT_RECV, frame);
@ -479,9 +438,9 @@ int verbose_on_invalid_frame_recv_callback
return 0;
}
int verbose_on_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
int verbose_on_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data) {
print_timer();
fprintf(outfile, " send ");
print_frame(PRINT_SEND, frame);
@ -489,13 +448,12 @@ int verbose_on_frame_send_callback
return 0;
}
int verbose_on_data_chunk_recv_callback
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
const uint8_t *data, size_t len, void *user_data)
{
int verbose_on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
print_timer();
auto srecv = nghttp2_session_get_stream_effective_recv_data_length
(session, stream_id);
auto srecv =
nghttp2_session_get_stream_effective_recv_data_length(session, stream_id);
auto crecv = nghttp2_session_get_effective_recv_data_length(session);
fprintf(outfile,
@ -510,24 +468,18 @@ namespace {
std::chrono::steady_clock::time_point base_tv;
} // namespace
void reset_timer()
{
base_tv = std::chrono::steady_clock::now();
}
void reset_timer() { base_tv = std::chrono::steady_clock::now(); }
std::chrono::milliseconds get_timer()
{
std::chrono::milliseconds get_timer() {
return time_delta(std::chrono::steady_clock::now(), base_tv);
}
std::chrono::steady_clock::time_point get_time()
{
std::chrono::steady_clock::time_point get_time() {
return std::chrono::steady_clock::now();
}
ssize_t deflate_data(uint8_t *out, size_t outlen,
const uint8_t *in, size_t inlen)
{
ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
size_t inlen) {
int rv;
z_stream zst;
uint8_t temp_out[8192];
@ -538,15 +490,15 @@ ssize_t deflate_data(uint8_t *out, size_t outlen,
zst.zfree = Z_NULL;
zst.opaque = Z_NULL;
rv = deflateInit2(&zst, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
31, 9, Z_DEFAULT_STRATEGY);
rv = deflateInit2(&zst, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 9,
Z_DEFAULT_STRATEGY);
if(rv != Z_OK) {
if (rv != Z_OK) {
return -1;
}
zst.avail_in = inlen;
zst.next_in = (uint8_t*)in;
zst.next_in = (uint8_t *)in;
zst.avail_out = temp_outlen;
zst.next_out = temp_out;
@ -554,13 +506,13 @@ ssize_t deflate_data(uint8_t *out, size_t outlen,
deflateEnd(&zst);
if(rv != Z_STREAM_END) {
if (rv != Z_STREAM_END) {
return -1;
}
temp_outlen -= zst.avail_out;
if(temp_outlen > outlen) {
if (temp_outlen > outlen) {
return -1;
}

View File

@ -40,31 +40,29 @@
namespace nghttp2 {
int verbose_on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
uint8_t flags,
void *user_data);
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags, void *user_data);
int verbose_on_frame_recv_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
int verbose_on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data);
int verbose_on_invalid_frame_recv_callback
(nghttp2_session *session, const nghttp2_frame *frame,
uint32_t error_code, void *user_data);
int verbose_on_invalid_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame,
uint32_t error_code,
void *user_data);
int verbose_on_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
int verbose_on_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data);
int verbose_on_data_chunk_recv_callback
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
const uint8_t *data, size_t len, void *user_data);
int verbose_on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data);
// Returns difference between |a| and |b| in milliseconds, assuming
// |a| is more recent than |b|.
template<typename TimePoint>
std::chrono::milliseconds time_delta(const TimePoint& a, const TimePoint& b)
{
template <typename TimePoint>
std::chrono::milliseconds time_delta(const TimePoint &a, const TimePoint &b) {
return std::chrono::duration_cast<std::chrono::milliseconds>(a - b);
}
@ -88,8 +86,8 @@ void set_color_output(bool f);
// used.
void set_output(FILE *file);
ssize_t deflate_data(uint8_t *out, size_t outlen,
const uint8_t *in, size_t inlen);
ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
size_t inlen);
} // namespace nghttp2

View File

@ -56,81 +56,62 @@ namespace asio_http2 {
namespace server {
/// Represents a single connection from a client.
template<typename socket_type>
class connection
: public std::enable_shared_from_this<connection<socket_type>>,
private boost::noncopyable
{
template <typename socket_type>
class connection : public std::enable_shared_from_this<connection<socket_type>>,
private boost::noncopyable {
public:
/// Construct a connection with the given io_service.
template<typename... SocketArgs>
explicit connection(request_cb cb,
boost::asio::io_service& task_io_service,
SocketArgs&&... args)
: socket_(std::forward<SocketArgs>(args)...),
request_cb_(std::move(cb)),
task_io_service_(task_io_service),
writing_(false)
{}
template <typename... SocketArgs>
explicit connection(request_cb cb, boost::asio::io_service &task_io_service,
SocketArgs &&... args)
: socket_(std::forward<SocketArgs>(args)...), request_cb_(std::move(cb)),
task_io_service_(task_io_service), writing_(false) {}
/// Start the first asynchronous operation for the connection.
void start()
{
handler_ = std::make_shared<http2_handler>
(socket_.get_io_service(),
task_io_service_,
[this]()
{
do_write();
},
request_cb_);
if(handler_->start() != 0) {
void start() {
handler_ = std::make_shared<http2_handler>(
socket_.get_io_service(), task_io_service_, [this]() { do_write(); },
request_cb_);
if (handler_->start() != 0) {
return;
}
do_read();
}
socket_type& socket()
{
return socket_;
}
socket_type &socket() { return socket_; }
void do_read()
{
void do_read() {
auto self = this->shared_from_this();
socket_.async_read_some
(boost::asio::buffer(buffer_),
[this, self](const boost::system::error_code& e,
std::size_t bytes_transferred)
{
if (!e) {
if(handler_->on_read(buffer_, bytes_transferred) != 0) {
return;
}
socket_.async_read_some(boost::asio::buffer(buffer_),
[this, self](const boost::system::error_code &e,
std::size_t bytes_transferred) {
if (!e) {
if (handler_->on_read(buffer_, bytes_transferred) != 0) {
return;
}
do_write();
do_write();
if(!writing_ && handler_->should_stop()) {
return;
}
if (!writing_ && handler_->should_stop()) {
return;
}
do_read();
}
do_read();
}
// If an error occurs then no new asynchronous operations are
// started. This means that all shared_ptr references to the
// connection object will disappear and the object will be
// destroyed automatically after this handler returns. The
// connection class's destructor closes the socket.
});
// If an error occurs then no new asynchronous operations are
// started. This means that all shared_ptr references to the
// connection object will disappear and the object will be
// destroyed automatically after this handler returns. The
// connection class's destructor closes the socket.
});
}
void do_write()
{
void do_write() {
auto self = this->shared_from_this();
if(writing_) {
if (writing_) {
return;
}
@ -139,27 +120,25 @@ public:
rv = handler_->on_write(outbuf_, nwrite);
if(rv != 0) {
if (rv != 0) {
return;
}
if(nwrite == 0) {
if (nwrite == 0) {
return;
}
writing_ = true;
boost::asio::async_write
(socket_, boost::asio::buffer(outbuf_, nwrite),
[this, self](const boost::system::error_code& e,
std::size_t)
{
if(!e) {
writing_ = false;
boost::asio::async_write(
socket_, boost::asio::buffer(outbuf_, nwrite),
[this, self](const boost::system::error_code &e, std::size_t) {
if (!e) {
writing_ = false;
do_write();
}
});
do_write();
}
});
// No new asynchronous operations are started. This means that all
// shared_ptr references to the connection object will disappear and
@ -172,7 +151,7 @@ private:
request_cb request_cb_;
boost::asio::io_service& task_io_service_;
boost::asio::io_service &task_io_service_;
std::shared_ptr<http2_handler> handler_;

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,7 @@ public:
channel_impl();
void post(void_cb cb);
void strand(boost::asio::io_service::strand *strand);
private:
boost::asio::io_service::strand *strand_;
};
@ -59,12 +60,12 @@ class request_impl {
public:
request_impl();
const std::vector<header>& headers() const;
const std::string& method() const;
const std::string& scheme() const;
const std::string& authority() const;
const std::string& host() const;
const std::string& path() const;
const std::vector<header> &headers() const;
const std::string &method() const;
const std::string &scheme() const;
const std::string &authority() const;
const std::string &host() const;
const std::string &path() const;
bool push(std::string method, std::string path,
std::vector<header> headers = {});
@ -89,6 +90,7 @@ public:
void stream(std::weak_ptr<http2_stream> s);
void call_on_data(const uint8_t *data, std::size_t len);
void call_on_end();
private:
std::vector<header> headers_;
std::string method_;
@ -113,11 +115,12 @@ public:
bool closed() const;
unsigned int status_code() const;
const std::vector<header>& headers() const;
const std::vector<header> &headers() const;
bool started() const;
void handler(std::weak_ptr<http2_handler> h);
void stream(std::weak_ptr<http2_stream> s);
read_cb::result_type call_read(uint8_t *data, std::size_t len);
private:
std::vector<header> headers_;
read_cb read_cb_;
@ -132,8 +135,9 @@ public:
http2_stream(int32_t stream_id);
int32_t get_stream_id() const;
const std::shared_ptr<request>& get_request();
const std::shared_ptr<response>& get_response();
const std::shared_ptr<request> &get_request();
const std::shared_ptr<response> &get_response();
private:
std::shared_ptr<request> request_;
std::shared_ptr<response> response_;
@ -141,19 +145,18 @@ private:
};
struct callback_guard {
callback_guard(http2_handler& h);
callback_guard(http2_handler &h);
~callback_guard();
http2_handler& handler;
http2_handler &handler;
};
typedef std::function<void(void)> connection_write;
class http2_handler : public std::enable_shared_from_this<http2_handler> {
public:
http2_handler(boost::asio::io_service& io_service,
boost::asio::io_service& task_io_service,
connection_write writefun,
request_cb cb);
http2_handler(boost::asio::io_service &io_service,
boost::asio::io_service &task_io_service,
connection_write writefun, request_cb cb);
~http2_handler();
@ -163,11 +166,11 @@ public:
void close_stream(int32_t stream_id);
std::shared_ptr<http2_stream> find_stream(int32_t stream_id);
void call_on_request(http2_stream& stream);
void call_on_request(http2_stream &stream);
bool should_stop() const;
int start_response(http2_stream& stream);
int start_response(http2_stream &stream);
void stream_error(int32_t stream_id, uint32_t error_code);
@ -177,40 +180,37 @@ public:
void leave_callback();
bool inside_callback() const;
void resume(http2_stream& stream);
void resume(http2_stream &stream);
int push_promise(http2_stream& stream, std::string method,
std::string path,
int push_promise(http2_stream &stream, std::string method, std::string path,
std::vector<header> headers);
bool run_task(thread_cb start);
boost::asio::io_service& io_service();
boost::asio::io_service &io_service();
template<size_t N>
int on_read(const boost::array<uint8_t, N>& buffer, std::size_t len)
{
template <size_t N>
int on_read(const boost::array<uint8_t, N> &buffer, std::size_t len) {
callback_guard cg(*this);
int rv;
rv = nghttp2_session_mem_recv(session_, buffer.data(), len);
if(rv < 0) {
if (rv < 0) {
return -1;
}
return 0;
}
template<size_t N>
int on_write(boost::array<uint8_t, N>& buffer, std::size_t& len)
{
template <size_t N>
int on_write(boost::array<uint8_t, N> &buffer, std::size_t &len) {
callback_guard cg(*this);
len = 0;
if(buf_) {
if (buf_) {
std::copy(buf_, buf_ + buflen_, std::begin(buffer));
len += buflen_;
@ -219,18 +219,18 @@ public:
buflen_ = 0;
}
for(;;) {
for (;;) {
const uint8_t *data;
auto nread = nghttp2_session_mem_send(session_, &data);
if(nread < 0) {
if (nread < 0) {
return -1;
}
if(nread == 0) {
if (nread == 0) {
break;
}
if(len + nread > buffer.size()) {
if (len + nread > buffer.size()) {
buf_ = data;
buflen_ = nread;
@ -249,8 +249,8 @@ private:
std::map<int32_t, std::shared_ptr<http2_stream>> streams_;
connection_write writefun_;
request_cb request_cb_;
boost::asio::io_service& io_service_;
boost::asio::io_service& task_io_service_;
boost::asio::io_service &io_service_;
boost::asio::io_service &task_io_service_;
std::shared_ptr<boost::asio::io_service::strand> strand_;
nghttp2_session *session_;
const uint8_t *buf_;

View File

@ -40,76 +40,55 @@ namespace asio_http2 {
namespace server {
http2::http2()
: impl_(util::make_unique<http2_impl>())
{}
http2::http2() : impl_(util::make_unique<http2_impl>()) {}
http2::~http2()
{}
http2::~http2() {}
void http2::listen(const std::string& address, uint16_t port, request_cb cb)
{
void http2::listen(const std::string &address, uint16_t port, request_cb cb) {
impl_->listen(address, port, std::move(cb));
}
void http2::num_threads(size_t num_threads)
{
impl_->num_threads(num_threads);
}
void http2::num_threads(size_t num_threads) { impl_->num_threads(num_threads); }
void http2::tls(std::string private_key_file,
std::string certificate_file)
{
void http2::tls(std::string private_key_file, std::string certificate_file) {
impl_->tls(std::move(private_key_file), std::move(certificate_file));
}
void http2::num_concurrent_tasks(size_t num_concurrent_tasks)
{
void http2::num_concurrent_tasks(size_t num_concurrent_tasks) {
impl_->num_concurrent_tasks(num_concurrent_tasks);
}
void http2::backlog(int backlog)
{
impl_->backlog(backlog);
}
void http2::backlog(int backlog) { impl_->backlog(backlog); }
http2_impl::http2_impl()
: num_threads_(1),
num_concurrent_tasks_(1),
backlog_(-1)
{}
: num_threads_(1), num_concurrent_tasks_(1), backlog_(-1) {}
namespace {
std::vector<unsigned char>&
get_alpn_token()
{
std::vector<unsigned char> &get_alpn_token() {
static auto alpn_token = util::get_default_alpn();
return alpn_token;
}
} // namespace
void http2_impl::listen(const std::string& address, uint16_t port,
request_cb cb)
{
void http2_impl::listen(const std::string &address, uint16_t port,
request_cb cb) {
std::unique_ptr<boost::asio::ssl::context> ssl_ctx;
if(!private_key_file_.empty() && !certificate_file_.empty()) {
ssl_ctx = util::make_unique<boost::asio::ssl::context>
(boost::asio::ssl::context::sslv23);
if (!private_key_file_.empty() && !certificate_file_.empty()) {
ssl_ctx = util::make_unique<boost::asio::ssl::context>(
boost::asio::ssl::context::sslv23);
ssl_ctx->use_private_key_file(private_key_file_,
boost::asio::ssl::context::pem);
boost::asio::ssl::context::pem);
ssl_ctx->use_certificate_chain_file(certificate_file_);
auto ctx = ssl_ctx->native_handle();
SSL_CTX_set_options(ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_SINGLE_ECDH_USE |
SSL_OP_NO_TICKET |
SSL_OP_CIPHER_SERVER_PREFERENCE);
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET |
SSL_OP_CIPHER_SERVER_PREFERENCE);
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
@ -117,103 +96,86 @@ void http2_impl::listen(const std::string& address, uint16_t port,
SSL_CTX_set_cipher_list(ctx, ssl::DEFAULT_CIPHER_LIST);
auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if(ecdh) {
if (ecdh) {
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
EC_KEY_free(ecdh);
}
SSL_CTX_set_next_protos_advertised_cb
(ctx,
[](SSL *s, const unsigned char **data, unsigned int *len, void *arg) {
auto& token = get_alpn_token();
SSL_CTX_set_next_protos_advertised_cb(
ctx,
[](SSL *s, const unsigned char **data, unsigned int *len, void *arg) {
auto &token = get_alpn_token();
*data = token.data();
*len = token.size();
*data = token.data();
*len = token.size();
return SSL_TLSEXT_ERR_OK;
}, nullptr);
return SSL_TLSEXT_ERR_OK;
},
nullptr);
}
server(address, port, num_threads_, num_concurrent_tasks_,
std::move(cb), std::move(ssl_ctx), backlog_).run();
server(address, port, num_threads_, num_concurrent_tasks_, std::move(cb),
std::move(ssl_ctx), backlog_).run();
}
void http2_impl::num_threads(size_t num_threads)
{
num_threads_ = num_threads;
}
void http2_impl::num_threads(size_t num_threads) { num_threads_ = num_threads; }
void http2_impl::tls(std::string private_key_file,
std::string certificate_file)
{
std::string certificate_file) {
private_key_file_ = std::move(private_key_file);
certificate_file_ = std::move(certificate_file);
}
void http2_impl::num_concurrent_tasks(size_t num_concurrent_tasks)
{
void http2_impl::num_concurrent_tasks(size_t num_concurrent_tasks) {
num_concurrent_tasks_ = num_concurrent_tasks;
}
void http2_impl::backlog(int backlog)
{
backlog_ = backlog;
}
void http2_impl::backlog(int backlog) { backlog_ = backlog; }
} // namespace server
template<typename T, typename F>
std::shared_ptr<util::Defer<T, F>> defer_shared(T&& t, F f)
{
template <typename T, typename F>
std::shared_ptr<util::Defer<T, F>> defer_shared(T &&t, F f) {
return std::make_shared<util::Defer<T, F>>(std::forward<T>(t),
std::forward<F>(f));
}
read_cb file_reader(const std::string& path)
{
read_cb file_reader(const std::string &path) {
auto fd = open(path.c_str(), O_RDONLY);
if(fd == -1) {
if (fd == -1) {
return read_cb();
}
return file_reader_from_fd(fd);
}
read_cb file_reader_from_fd(int fd)
{
read_cb file_reader_from_fd(int fd) {
auto d = defer_shared(static_cast<int>(fd), close);
return [fd, d](uint8_t *buf, size_t len) -> read_cb::result_type
{
int rv;
while((rv = read(fd, buf, len)) == -1 && errno == EINTR);
return [fd, d](uint8_t *buf, size_t len) -> read_cb::result_type {
int rv;
while ((rv = read(fd, buf, len)) == -1 && errno == EINTR)
;
if(rv == -1) {
return std::make_pair(-1, false);
}
if (rv == -1) {
return std::make_pair(-1, false);
}
if(rv == 0) {
return std::make_pair(rv, true);
}
if (rv == 0) {
return std::make_pair(rv, true);
}
return std::make_pair(rv, false);
};
return std::make_pair(rv, false);
};
}
bool check_path(const std::string& path)
{
return util::check_path(path);
}
bool check_path(const std::string &path) { return util::check_path(path); }
std::string percent_decode(const std::string& s)
{
std::string percent_decode(const std::string &s) {
return util::percentDecode(std::begin(s), std::end(s));
}
std::string http_date(int64_t t)
{
return util::http_date(t);
}
std::string http_date(int64_t t) { return util::http_date(t); }
} // namespace asio_http2

View File

@ -40,12 +40,12 @@ class server;
class http2_impl {
public:
http2_impl();
void listen(const std::string& address, uint16_t port,
request_cb cb);
void listen(const std::string &address, uint16_t port, request_cb cb);
void num_threads(size_t num_threads);
void tls(std::string private_key_file, std::string certificate_file);
void num_concurrent_tasks(size_t num_concurrent_tasks);
void backlog(int backlog);
private:
std::string private_key_file_;
std::string certificate_file_;

View File

@ -48,9 +48,7 @@ namespace server {
io_service_pool::io_service_pool(std::size_t pool_size,
std::size_t thread_pool_size)
: next_io_service_(0),
thread_pool_size_(thread_pool_size)
{
: next_io_service_(0), thread_pool_size_(thread_pool_size) {
if (pool_size == 0) {
throw std::runtime_error("io_service_pool size is 0");
}
@ -64,54 +62,45 @@ io_service_pool::io_service_pool(std::size_t pool_size,
work_.push_back(work);
}
auto work = std::make_shared<boost::asio::io_service::work>
(task_io_service_);
auto work = std::make_shared<boost::asio::io_service::work>(task_io_service_);
work_.push_back(work);
}
void io_service_pool::run()
{
for(std::size_t i = 0; i < thread_pool_size_; ++i) {
thread_pool_.create_thread
([this]()
{
task_io_service_.run();
});
void io_service_pool::run() {
for (std::size_t i = 0; i < thread_pool_size_; ++i) {
thread_pool_.create_thread([this]() { task_io_service_.run(); });
}
// Create a pool of threads to run all of the io_services.
auto futs = std::vector<std::future<std::size_t>>();
for (std::size_t i = 0; i < io_services_.size(); ++i) {
futs.push_back
(std::async(std::launch::async,
(size_t(boost::asio::io_service::*)(void))
&boost::asio::io_service::run,
io_services_[i]));
futs.push_back(std::async(std::launch::async,
(size_t (boost::asio::io_service::*)(void)) &
boost::asio::io_service::run,
io_services_[i]));
}
// Wait for all threads in the pool to exit.
for (auto& fut : futs) {
for (auto &fut : futs) {
fut.get();
}
thread_pool_.join_all();
}
void io_service_pool::stop()
{
void io_service_pool::stop() {
// Explicitly stop all io_services.
for (auto& iosv : io_services_) {
for (auto &iosv : io_services_) {
iosv->stop();
}
task_io_service_.stop();
}
boost::asio::io_service& io_service_pool::get_io_service()
{
boost::asio::io_service &io_service_pool::get_io_service() {
// Use a round-robin scheme to choose the next io_service to use.
auto& io_service = *io_services_[next_io_service_];
auto &io_service = *io_services_[next_io_service_];
++next_io_service_;
if (next_io_service_ == io_services_.size()) {
next_io_service_ = 0;
@ -119,8 +108,7 @@ boost::asio::io_service& io_service_pool::get_io_service()
return io_service;
}
boost::asio::io_service& io_service_pool::get_task_io_service()
{
boost::asio::io_service &io_service_pool::get_task_io_service() {
return task_io_service_;
}

View File

@ -54,13 +54,10 @@ namespace asio_http2 {
namespace server {
/// A pool of io_service objects.
class io_service_pool
: private boost::noncopyable
{
class io_service_pool : private boost::noncopyable {
public:
/// Construct the io_service pool.
explicit io_service_pool(std::size_t pool_size,
std::size_t thread_pool_size);
explicit io_service_pool(std::size_t pool_size, std::size_t thread_pool_size);
/// Run all io_service objects in the pool.
void run();
@ -69,9 +66,9 @@ public:
void stop();
/// Get an io_service to use.
boost::asio::io_service& get_io_service();
boost::asio::io_service &get_io_service();
boost::asio::io_service& get_task_io_service();
boost::asio::io_service &get_task_io_service();
private:
typedef std::shared_ptr<boost::asio::io_service> io_service_ptr;

View File

@ -42,20 +42,16 @@ namespace nghttp2 {
namespace asio_http2 {
namespace server {
server::server(const std::string& address, uint16_t port,
std::size_t io_service_pool_size,
std::size_t thread_pool_size,
server::server(const std::string &address, uint16_t port,
std::size_t io_service_pool_size, std::size_t thread_pool_size,
request_cb cb,
std::unique_ptr<boost::asio::ssl::context> ssl_ctx,
int backlog)
: io_service_pool_(io_service_pool_size, thread_pool_size),
signals_(io_service_pool_.get_io_service()),
tick_timer_(io_service_pool_.get_io_service(),
boost::posix_time::seconds(1)),
acceptor_(io_service_pool_.get_io_service()),
ssl_ctx_(std::move(ssl_ctx)),
request_cb_(std::move(cb))
{
std::unique_ptr<boost::asio::ssl::context> ssl_ctx, int backlog)
: io_service_pool_(io_service_pool_size, thread_pool_size),
signals_(io_service_pool_.get_io_service()),
tick_timer_(io_service_pool_.get_io_service(),
boost::posix_time::seconds(1)),
acceptor_(io_service_pool_.get_io_service()),
ssl_ctx_(std::move(ssl_ctx)), request_cb_(std::move(cb)) {
// Register to handle the signals that indicate when the server should exit.
// It is safe to register for the same signal multiple times in a program,
// provided all registration for the specified signal is made through Asio.
@ -64,11 +60,8 @@ server::server(const std::string& address, uint16_t port,
#if defined(SIGQUIT)
signals_.add(SIGQUIT);
#endif // defined(SIGQUIT)
signals_.async_wait([this](const boost::system::error_code& error,
int signal_number)
{
io_service_pool_.stop();
});
signals_.async_wait([this](const boost::system::error_code &error,
int signal_number) { io_service_pool_.stop(); });
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
boost::asio::ip::tcp::resolver resolver(acceptor_.get_io_service());
@ -77,7 +70,7 @@ server::server(const std::string& address, uint16_t port,
acceptor_.open(endpoint.protocol());
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor_.bind(endpoint);
if(backlog == -1) {
if (backlog == -1) {
acceptor_.listen();
} else {
acceptor_.listen(backlog);
@ -88,80 +81,68 @@ server::server(const std::string& address, uint16_t port,
start_timer();
}
void server::run()
{
io_service_pool_.run();
}
void server::run() { io_service_pool_.run(); }
std::shared_ptr<std::string> cached_date;
namespace {
void update_date()
{
void update_date() {
cached_date = std::make_shared<std::string>(util::http_date(time(nullptr)));
}
} // namespace
void server::start_timer()
{
void server::start_timer() {
update_date();
tick_timer_.async_wait
([this](const boost::system::error_code& e)
{
tick_timer_.expires_at(tick_timer_.expires_at() +
boost::posix_time::seconds(1));
start_timer();
});
tick_timer_.async_wait([this](const boost::system::error_code &e) {
tick_timer_.expires_at(tick_timer_.expires_at() +
boost::posix_time::seconds(1));
start_timer();
});
}
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
void server::start_accept()
{
if(ssl_ctx_) {
auto new_connection =
std::make_shared<connection<ssl_socket>>
(request_cb_, io_service_pool_.get_task_io_service(),
io_service_pool_.get_io_service(), *ssl_ctx_);
void server::start_accept() {
if (ssl_ctx_) {
auto new_connection = std::make_shared<connection<ssl_socket>>(
request_cb_, io_service_pool_.get_task_io_service(),
io_service_pool_.get_io_service(), *ssl_ctx_);
acceptor_.async_accept
(new_connection->socket().lowest_layer(),
[this, new_connection](const boost::system::error_code& e)
{
if(!e) {
new_connection->socket().lowest_layer().set_option
(boost::asio::ip::tcp::no_delay(true));
new_connection->socket().async_handshake
(boost::asio::ssl::stream_base::server,
[new_connection](const boost::system::error_code& e)
{
if(!e) {
new_connection->start();
}
});
}
acceptor_.async_accept(
new_connection->socket().lowest_layer(),
[this, new_connection](const boost::system::error_code &e) {
if (!e) {
new_connection->socket().lowest_layer().set_option(
boost::asio::ip::tcp::no_delay(true));
new_connection->socket().async_handshake(
boost::asio::ssl::stream_base::server,
[new_connection](const boost::system::error_code &e) {
if (!e) {
new_connection->start();
}
});
}
start_accept();
});
start_accept();
});
} else {
auto new_connection =
std::make_shared<connection<boost::asio::ip::tcp::socket>>
(request_cb_, io_service_pool_.get_task_io_service(),
io_service_pool_.get_io_service());
std::make_shared<connection<boost::asio::ip::tcp::socket>>(
request_cb_, io_service_pool_.get_task_io_service(),
io_service_pool_.get_io_service());
acceptor_.async_accept
(new_connection->socket(),
[this, new_connection](const boost::system::error_code& e)
{
if (!e) {
new_connection->socket().set_option
(boost::asio::ip::tcp::no_delay(true));
new_connection->start();
}
acceptor_.async_accept(
new_connection->socket(),
[this, new_connection](const boost::system::error_code &e) {
if (!e) {
new_connection->socket().set_option(
boost::asio::ip::tcp::no_delay(true));
new_connection->start();
}
start_accept();
});
start_accept();
});
}
}

View File

@ -58,16 +58,13 @@ namespace asio_http2 {
namespace server {
/// The top-level class of the HTTP server.
class server
: private boost::noncopyable
{
class server : private boost::noncopyable {
public:
/// Construct the server to listen on the specified TCP address and port, and
/// serve up files from the given directory.
explicit server(const std::string& address, uint16_t port,
explicit server(const std::string &address, uint16_t port,
std::size_t io_service_pool_size,
std::size_t thread_pool_size,
request_cb cb,
std::size_t thread_pool_size, request_cb cb,
std::unique_ptr<boost::asio::ssl::context> ssl_ctx,
int backlog = -1);

View File

@ -33,28 +33,24 @@ namespace nghttp2 {
namespace base64 {
template<typename InputIterator>
std::string encode(InputIterator first, InputIterator last)
{
template <typename InputIterator>
std::string encode(InputIterator first, InputIterator last) {
static const char CHAR_TABLE[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
};
std::string res;
size_t len = last-first;
if(len == 0) {
size_t len = last - first;
if (len == 0) {
return res;
}
size_t r = len%3;
InputIterator j = last-r;
size_t r = len % 3;
InputIterator j = last - r;
char temp[4];
while(first != j) {
while (first != j) {
int n = static_cast<unsigned char>(*first++) << 16;
n += static_cast<unsigned char>(*first++) << 8;
n += static_cast<unsigned char>(*first++);
@ -64,7 +60,7 @@ std::string encode(InputIterator first, InputIterator last)
temp[3] = CHAR_TABLE[n & 0x3fu];
res.append(temp, sizeof(temp));
}
if(r == 2) {
if (r == 2) {
int n = static_cast<unsigned char>(*first++) << 16;
n += static_cast<unsigned char>(*first++) << 8;
temp[0] = CHAR_TABLE[n >> 18];
@ -72,7 +68,7 @@ std::string encode(InputIterator first, InputIterator last)
temp[2] = CHAR_TABLE[(n >> 6) & 0x3fu];
temp[3] = '=';
res.append(temp, sizeof(temp));
} else if(r == 1) {
} else if (r == 1) {
int n = static_cast<unsigned char>(*first++) << 16;
temp[0] = CHAR_TABLE[n >> 18];
temp[1] = CHAR_TABLE[(n >> 12) & 0x3fu];
@ -83,89 +79,82 @@ std::string encode(InputIterator first, InputIterator last)
return res;
}
template<typename InputIterator>
InputIterator getNext
(InputIterator first,
InputIterator last,
const int* tbl)
{
for(; first != last; ++first) {
if(tbl[static_cast<size_t>(*first)] != -1 || *first == '=') {
template <typename InputIterator>
InputIterator getNext(InputIterator first, InputIterator last, const int *tbl) {
for (; first != last; ++first) {
if (tbl[static_cast<size_t>(*first)] != -1 || *first == '=') {
break;
}
}
return first;
}
template<typename InputIterator>
std::string decode(InputIterator first, InputIterator last)
{
template <typename InputIterator>
std::string decode(InputIterator first, InputIterator last) {
static const int INDEX_TABLE[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1};
std::string res;
InputIterator k[4];
int eq = 0;
for(; first != last;) {
for(int i = 1; i <= 4; ++i) {
k[i-1] = getNext(first, last, INDEX_TABLE);
if(k[i-1] == last) {
for (; first != last;) {
for (int i = 1; i <= 4; ++i) {
k[i - 1] = getNext(first, last, INDEX_TABLE);
if (k[i - 1] == last) {
// If i == 1, input may look like this: "TWFu\n" (i.e.,
// garbage at the end)
if(i != 1) {
if (i != 1) {
res.clear();
}
return res;
} else if(*k[i-1] == '=' && eq == 0) {
} else if (*k[i - 1] == '=' && eq == 0) {
eq = i;
}
first = k[i-1]+1;
first = k[i - 1] + 1;
}
if(eq) {
if (eq) {
break;
}
int n = (INDEX_TABLE[static_cast<unsigned char>(*k[0])] << 18)+
(INDEX_TABLE[static_cast<unsigned char>(*k[1])] << 12)+
(INDEX_TABLE[static_cast<unsigned char>(*k[2])] << 6)+
INDEX_TABLE[static_cast<unsigned char>(*k[3])];
int n = (INDEX_TABLE[static_cast<unsigned char>(*k[0])] << 18) +
(INDEX_TABLE[static_cast<unsigned char>(*k[1])] << 12) +
(INDEX_TABLE[static_cast<unsigned char>(*k[2])] << 6) +
INDEX_TABLE[static_cast<unsigned char>(*k[3])];
res += n >> 16;
res += n >> 8 & 0xffu;
res += n & 0xffu;
}
if(eq) {
if(eq <= 2) {
if (eq) {
if (eq <= 2) {
res.clear();
return res;
} else {
for(int i = eq; i <= 4; ++i) {
if(*k[i-1] != '=') {
for (int i = eq; i <= 4; ++i) {
if (*k[i - 1] != '=') {
res.clear();
return res;
}
}
if(eq == 3) {
int n = (INDEX_TABLE[static_cast<unsigned char>(*k[0])] << 18)+
(INDEX_TABLE[static_cast<unsigned char>(*k[1])] << 12);
if (eq == 3) {
int n = (INDEX_TABLE[static_cast<unsigned char>(*k[0])] << 18) +
(INDEX_TABLE[static_cast<unsigned char>(*k[1])] << 12);
res += n >> 16;
} else if(eq == 4) {
int n = (INDEX_TABLE[static_cast<unsigned char>(*k[0])] << 18)+
(INDEX_TABLE[static_cast<unsigned char>(*k[1])] << 12)+
(INDEX_TABLE[static_cast<unsigned char>(*k[2])] << 6);
} else if (eq == 4) {
int n = (INDEX_TABLE[static_cast<unsigned char>(*k[0])] << 18) +
(INDEX_TABLE[static_cast<unsigned char>(*k[1])] << 12) +
(INDEX_TABLE[static_cast<unsigned char>(*k[2])] << 6);
res += n >> 16;
res += n >> 8 & 0xffu;
}

View File

@ -25,19 +25,17 @@
#include "comp_helper.h"
#include <string.h>
static void dump_val(json_t *jent, const char *key, uint8_t *val, size_t len)
{
static void dump_val(json_t *jent, const char *key, uint8_t *val, size_t len) {
json_object_set_new(jent, key, json_pack("s#", val, len));
}
json_t* dump_header_table(nghttp2_hd_context *context)
{
json_t *dump_header_table(nghttp2_hd_context *context) {
json_t *obj, *entries;
size_t i;
obj = json_object();
entries = json_array();
for(i = 0; i < context->hd_table.len; ++i) {
for (i = 0; i < context->hd_table.len; ++i) {
nghttp2_hd_entry *ent = nghttp2_hd_table_get(context, i);
json_t *outent = json_object();
json_object_set_new(outent, "index", json_integer(i + 1));
@ -55,9 +53,8 @@ json_t* dump_header_table(nghttp2_hd_context *context)
return obj;
}
json_t* dump_header(const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen)
{
json_t *dump_header(const uint8_t *name, size_t namelen, const uint8_t *value,
size_t valuelen) {
json_t *nv_pair = json_object();
char *cname = malloc(namelen + 1);
memcpy(cname, name, namelen);
@ -67,29 +64,25 @@ json_t* dump_header(const uint8_t *name, size_t namelen,
return nv_pair;
}
json_t* dump_headers(const nghttp2_nv *nva, size_t nvlen)
{
json_t *dump_headers(const nghttp2_nv *nva, size_t nvlen) {
json_t *headers;
size_t i;
headers = json_array();
for(i = 0; i < nvlen; ++i) {
json_array_append_new(headers,
dump_header(nva[i].name, nva[i].namelen,
nva[i].value, nva[i].valuelen));
for (i = 0; i < nvlen; ++i) {
json_array_append_new(headers, dump_header(nva[i].name, nva[i].namelen,
nva[i].value, nva[i].valuelen));
}
return headers;
}
void output_json_header(void)
{
void output_json_header(void) {
printf("{\n"
" \"cases\":\n"
" [\n");
}
void output_json_footer(void)
{
void output_json_footer(void) {
printf(" ]\n"
"}\n");
}

View File

@ -26,19 +26,19 @@
#define NGHTTP2_COMP_HELPER_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif // HAVE_CONFIG_H
#include <jansson.h>
#include "nghttp2_hd.h"
json_t* dump_header_table(nghttp2_hd_context *context);
json_t *dump_header_table(nghttp2_hd_context *context);
json_t* dump_header(const uint8_t *name, size_t namelen,
const uint8_t *value, size_t vlauelen);
json_t *dump_header(const uint8_t *name, size_t namelen, const uint8_t *value,
size_t vlauelen);
json_t* dump_headers(const nghttp2_nv *nva, size_t nvlen);
json_t *dump_headers(const nghttp2_nv *nva, size_t nvlen);
void output_json_header(void);

View File

@ -23,7 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif // HAVE_CONFIG_H
#include <unistd.h>
@ -45,7 +45,6 @@ extern "C" {
#include "nghttp2_frame.h"
#include "comp_helper.h"
}
typedef struct {
@ -60,28 +59,24 @@ static deflate_config config;
static size_t input_sum;
static size_t output_sum;
static char to_hex_digit(uint8_t n)
{
if(n > 9) {
static char to_hex_digit(uint8_t n) {
if (n > 9) {
return n - 10 + 'a';
}
return n + '0';
}
static void to_hex(char *dest, const uint8_t *src, size_t len)
{
static void to_hex(char *dest, const uint8_t *src, size_t len) {
size_t i;
for(i = 0; i < len; ++i) {
for (i = 0; i < len; ++i) {
*dest++ = to_hex_digit(src[i] >> 4);
*dest++ = to_hex_digit(src[i] & 0xf);
}
}
static void output_to_json(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs, size_t inputlen,
const std::vector<nghttp2_nv>& nva,
int seq)
{
static void output_to_json(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
size_t inputlen, const std::vector<nghttp2_nv> &nva,
int seq) {
auto len = nghttp2_bufs_len(bufs);
auto hex = std::vector<char>(len * 2);
auto obj = json_object();
@ -94,26 +89,25 @@ static void output_to_json(nghttp2_hd_deflater *deflater,
json_real(comp_ratio));
auto hexp = hex.data();
for(auto ci = bufs->head; ci; ci = ci->next) {
for (auto ci = bufs->head; ci; ci = ci->next) {
auto buf = &ci->buf;
to_hex(hexp, buf->pos, nghttp2_buf_len(buf));
hexp += nghttp2_buf_len(buf);
}
if(len == 0) {
if (len == 0) {
json_object_set_new(obj, "wire", json_string(""));
} else {
json_object_set_new(obj, "wire", json_pack("s#", hex.data(), hex.size()));
}
json_object_set_new(obj, "headers", dump_headers(nva.data(), nva.size()));
if(seq == 0) {
if (seq == 0) {
// We only change the header table size only once at the beginning
json_object_set_new(obj, "header_table_size",
json_integer(config.table_size));
}
if(config.dump_header_table) {
json_object_set_new(obj, "header_table",
dump_header_table(&deflater->ctx));
if (config.dump_header_table) {
json_object_set_new(obj, "header_table", dump_header_table(&deflater->ctx));
}
json_dumpf(obj, stdout, JSON_PRESERVE_ORDER | JSON_INDENT(2));
printf("\n");
@ -121,17 +115,16 @@ static void output_to_json(nghttp2_hd_deflater *deflater,
}
static void deflate_hd(nghttp2_hd_deflater *deflater,
const std::vector<nghttp2_nv>& nva,
size_t inputlen, int seq)
{
const std::vector<nghttp2_nv> &nva, size_t inputlen,
int seq) {
ssize_t rv;
nghttp2_bufs bufs;
nghttp2_bufs_init2(&bufs, 4096, 16, 0);
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs,
(nghttp2_nv*)nva.data(), nva.size());
if(rv < 0) {
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, (nghttp2_nv *)nva.data(),
nva.size());
if (rv < 0) {
fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq);
exit(EXIT_FAILURE);
}
@ -143,44 +136,43 @@ static void deflate_hd(nghttp2_hd_deflater *deflater,
nghttp2_bufs_free(&bufs);
}
static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
{
static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater,
int seq) {
size_t inputlen = 0;
auto js = json_object_get(obj, "headers");
if(js == nullptr) {
if (js == nullptr) {
fprintf(stderr, "'headers' key is missing at %d\n", seq);
return -1;
}
if(!json_is_array(js)) {
fprintf(stderr,
"The value of 'headers' key must be an array at %d\n", seq);
if (!json_is_array(js)) {
fprintf(stderr, "The value of 'headers' key must be an array at %d\n", seq);
return -1;
}
auto len = json_array_size(js);
auto nva = std::vector<nghttp2_nv>(len);
for(size_t i = 0; i < len; ++i) {
for (size_t i = 0; i < len; ++i) {
auto nv_pair = json_array_get(js, i);
const char *name;
json_t *value;
if(!json_is_object(nv_pair) || json_object_size(nv_pair) != 1) {
if (!json_is_object(nv_pair) || json_object_size(nv_pair) != 1) {
fprintf(stderr, "bad formatted name/value pair object at %d\n", seq);
return -1;
}
json_object_foreach(nv_pair, name, value) {
nva[i].name = (uint8_t*)name;
nva[i].name = (uint8_t *)name;
nva[i].namelen = strlen(name);
if(!json_is_string(value)) {
if (!json_is_string(value)) {
fprintf(stderr, "value is not string at %d\n", seq);
return -1;
}
nva[i].value = (uint8_t*)json_string_value(value);
nva[i].value = (uint8_t *)json_string_value(value);
nva[i].valuelen = strlen(json_string_value(value));
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
@ -194,37 +186,34 @@ static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
return 0;
}
static void init_deflater(nghttp2_hd_deflater *deflater)
{
static void init_deflater(nghttp2_hd_deflater *deflater) {
nghttp2_hd_deflate_init2(deflater, config.deflate_table_size);
nghttp2_hd_deflate_change_table_size(deflater, config.table_size);
}
static void deinit_deflater(nghttp2_hd_deflater *deflater)
{
static void deinit_deflater(nghttp2_hd_deflater *deflater) {
nghttp2_hd_deflate_free(deflater);
}
static int perform(void)
{
static int perform(void) {
json_error_t error;
nghttp2_hd_deflater deflater;
auto json = json_loadf(stdin, 0, &error);
if(json == nullptr) {
if (json == nullptr) {
fprintf(stderr, "JSON loading failed\n");
exit(EXIT_FAILURE);
}
auto cases = json_object_get(json, "cases");
if(cases == nullptr) {
if (cases == nullptr) {
fprintf(stderr, "Missing 'cases' key in root object\n");
exit(EXIT_FAILURE);
}
if(!json_is_array(cases)) {
if (!json_is_array(cases)) {
fprintf(stderr, "'cases' must be JSON array\n");
exit(EXIT_FAILURE);
}
@ -233,17 +222,16 @@ static int perform(void)
output_json_header();
auto len = json_array_size(cases);
for(size_t i = 0; i < len; ++i) {
for (size_t i = 0; i < len; ++i) {
auto obj = json_array_get(cases, i);
if(!json_is_object(obj)) {
fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n",
i);
if (!json_is_object(obj)) {
fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n", i);
continue;
}
if(deflate_hd_json(obj, &deflater, i) != 0) {
if (deflate_hd_json(obj, &deflater, i) != 0) {
continue;
}
if(i + 1 < len) {
if (i + 1 < len) {
printf(",\n");
}
}
@ -253,65 +241,67 @@ static int perform(void)
return 0;
}
static int perform_from_http1text(void)
{
static int perform_from_http1text(void) {
char line[1 << 14];
int seq = 0;
nghttp2_hd_deflater deflater;
init_deflater(&deflater);
output_json_header();
for(;;) {
for (;;) {
std::vector<nghttp2_nv> nva;
int end = 0;
size_t inputlen = 0;
for(;;) {
for (;;) {
char *rv = fgets(line, sizeof(line), stdin);
char *val, *val_end;
if(rv == nullptr) {
if (rv == nullptr) {
end = 1;
break;
} else if(line[0] == '\n') {
} else if (line[0] == '\n') {
break;
}
nva.emplace_back();
auto& nv = nva.back();
auto &nv = nva.back();
val = strchr(line+1, ':');
if(val == nullptr) {
val = strchr(line + 1, ':');
if (val == nullptr) {
fprintf(stderr, "Bad HTTP/1 header field format at %d.\n", seq);
exit(EXIT_FAILURE);
}
*val = '\0';
++val;
for(; *val && (*val == ' ' || *val == '\t'); ++val);
for(val_end = val; *val_end && (*val_end != '\r' && *val_end != '\n');
++val_end);
for (; *val && (*val == ' ' || *val == '\t'); ++val)
;
for (val_end = val; *val_end && (*val_end != '\r' && *val_end != '\n');
++val_end)
;
*val_end = '\0';
nv.namelen = strlen(line);
nv.valuelen = strlen(val);
nv.name = (uint8_t*)strdup(line);
nv.value = (uint8_t*)strdup(val);
nv.name = (uint8_t *)strdup(line);
nv.value = (uint8_t *)strdup(val);
nv.flags = NGHTTP2_NV_FLAG_NONE;
inputlen += nv.namelen + nv.valuelen;
}
if(!end) {
if(seq > 0) {
if (!end) {
if (seq > 0) {
printf(",\n");
}
deflate_hd(&deflater, nva, inputlen, seq);
}
for(auto& nv : nva) {
for (auto &nv : nva) {
free(nv.name);
free(nv.value);
}
if(end) break;
if (end)
break;
++seq;
}
output_json_footer();
@ -319,8 +309,7 @@ static int perform_from_http1text(void)
return 0;
}
static void print_help(void)
{
static void print_help(void) {
std::cout << R"(HPACK HTTP/2 header encoder
Usage: deflatehd [OPTIONS] < INPUT
@ -385,33 +374,30 @@ OPTIONS:
buffer.
Default: 4096
-d, --dump-header-table
Output dynamic header table.)"
<< std::endl;
Output dynamic header table.)" << std::endl;
}
static struct option long_options[] = {
{"http1text", no_argument, nullptr, 't'},
{"table-size", required_argument, nullptr, 's'},
{"deflate-table-size", required_argument, nullptr, 'S'},
{"dump-header-table", no_argument, nullptr, 'd'},
{nullptr, 0, nullptr, 0 }
};
{"http1text", no_argument, nullptr, 't'},
{"table-size", required_argument, nullptr, 's'},
{"deflate-table-size", required_argument, nullptr, 'S'},
{"dump-header-table", no_argument, nullptr, 'd'},
{nullptr, 0, nullptr, 0}};
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
char *end;
config.table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
config.deflate_table_size = NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE;
config.http1text = 0;
config.dump_header_table = 0;
while(1) {
while (1) {
int option_index = 0;
int c = getopt_long(argc, argv, "S:dhs:t", long_options, &option_index);
if(c == -1) {
if (c == -1) {
break;
}
switch(c) {
switch (c) {
case 'h':
print_help();
exit(EXIT_SUCCESS);
@ -423,7 +409,7 @@ int main(int argc, char **argv)
// --table-size
errno = 0;
config.table_size = strtoul(optarg, &end, 10);
if(errno == ERANGE || *end != '\0') {
if (errno == ERANGE || *end != '\0') {
fprintf(stderr, "-s: Bad option value\n");
exit(EXIT_FAILURE);
}
@ -432,7 +418,7 @@ int main(int argc, char **argv)
// --deflate-table-size
errno = 0;
config.deflate_table_size = strtoul(optarg, &end, 10);
if(errno == ERANGE || *end != '\0') {
if (errno == ERANGE || *end != '\0') {
fprintf(stderr, "-S: Bad option value\n");
exit(EXIT_FAILURE);
}
@ -447,7 +433,7 @@ int main(int argc, char **argv)
break;
}
}
if(config.http1text) {
if (config.http1text) {
perform_from_http1text();
} else {
perform();
@ -455,7 +441,7 @@ int main(int argc, char **argv)
auto comp_ratio = input_sum == 0 ? 0.0 : (double)output_sum / input_sum;
fprintf(stderr, "Overall: input=%zu output=%zu ratio=%.02f\n",
input_sum, output_sum, comp_ratio);
fprintf(stderr, "Overall: input=%zu output=%zu ratio=%.02f\n", input_sum,
output_sum, comp_ratio);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@ class Session;
struct Config {
std::vector<std::vector<nghttp2_nv>> nva;
std::vector<std::vector<const char*>> nv;
std::vector<std::vector<const char *>> nv;
nghttp2::Headers custom_headers;
std::string scheme;
std::string host;
@ -64,12 +64,7 @@ struct Config {
ssize_t max_concurrent_streams;
size_t window_bits;
size_t connection_window_bits;
enum {
PROTO_HTTP2,
PROTO_SPDY2,
PROTO_SPDY3,
PROTO_SPDY3_1
} no_tls_proto;
enum { PROTO_HTTP2, PROTO_SPDY2, PROTO_SPDY3, PROTO_SPDY3_1 } no_tls_proto;
uint16_t port;
uint16_t default_port;
bool verbose;
@ -105,10 +100,7 @@ struct Stats {
size_t status[6];
};
enum ClientState {
CLIENT_IDLE,
CLIENT_CONNECTED
};
enum ClientState { CLIENT_IDLE, CLIENT_CONNECTED };
struct Client;
@ -163,8 +155,7 @@ struct Client {
int on_read();
int on_write();
void on_request(int32_t stream_id);
void on_header(int32_t stream_id,
const uint8_t *name, size_t namelen,
void on_header(int32_t stream_id, const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen);
void on_stream_close(int32_t stream_id, bool success);
};

View File

@ -35,26 +35,18 @@ using namespace nghttp2;
namespace h2load {
Http2Session::Http2Session(Client *client)
: client_(client),
session_(nullptr)
{}
: client_(client), session_(nullptr) {}
Http2Session::~Http2Session()
{
nghttp2_session_del(session_);
}
Http2Session::~Http2Session() { nghttp2_session_del(session_); }
namespace {
int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
uint8_t flags,
void *user_data)
{
auto client = static_cast<Client*>(user_data);
if(frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
const uint8_t *value, size_t valuelen, uint8_t flags,
void *user_data) {
auto client = static_cast<Client *>(user_data);
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
return 0;
}
client->on_header(frame->hd.stream_id, name, namelen, value, valuelen);
@ -63,13 +55,11 @@ int on_header_callback(nghttp2_session *session,
} // namespace
namespace {
int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
auto client = static_cast<Client*>(user_data);
if(frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) {
auto client = static_cast<Client *>(user_data);
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
return 0;
}
client->worker->stats.bytes_head += frame->hd.length;
@ -78,29 +68,25 @@ int on_frame_recv_callback(nghttp2_session *session,
} // namespace
namespace {
int on_data_chunk_recv_callback
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
const uint8_t *data, size_t len, void *user_data)
{
auto client = static_cast<Client*>(user_data);
int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
auto client = static_cast<Client *>(user_data);
client->worker->stats.bytes_body += len;
return 0;
}
} // namespace
namespace {
int on_stream_close_callback
(nghttp2_session *session, int32_t stream_id, uint32_t error_code,
void *user_data)
{
auto client = static_cast<Client*>(user_data);
int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *user_data) {
auto client = static_cast<Client *>(user_data);
client->on_stream_close(stream_id, error_code == NGHTTP2_NO_ERROR);
return 0;
}
} // namespace
void Http2Session::on_connect()
{
void Http2Session::on_connect() {
int rv;
nghttp2_session_callbacks *callbacks;
@ -108,19 +94,19 @@ void Http2Session::on_connect()
nghttp2_session_callbacks_new(&callbacks);
auto callbacks_deleter =
util::defer(callbacks, nghttp2_session_callbacks_del);
util::defer(callbacks, nghttp2_session_callbacks_del);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_client_new(&session_, callbacks, client_);
@ -136,9 +122,9 @@ void Http2Session::on_connect()
assert(rv == 0);
auto extra_connection_window =
(1 << client_->worker->config->connection_window_bits) - 1
- NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
if(extra_connection_window != 0) {
(1 << client_->worker->config->connection_window_bits) - 1 -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
if (extra_connection_window != 0) {
nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0,
extra_connection_window);
}
@ -147,34 +133,31 @@ void Http2Session::on_connect()
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
}
void Http2Session::submit_request()
{
void Http2Session::submit_request() {
auto config = client_->worker->config;
auto& nva = config->nva[client_->reqidx++];
auto &nva = config->nva[client_->reqidx++];
if(client_->reqidx == config->nva.size()) {
if (client_->reqidx == config->nva.size()) {
client_->reqidx = 0;
}
auto stream_id = nghttp2_submit_request(session_, nullptr,
nva.data(), nva.size(),
nullptr, nullptr);
auto stream_id = nghttp2_submit_request(session_, nullptr, nva.data(),
nva.size(), nullptr, nullptr);
assert(stream_id > 0);
client_->on_request(stream_id);
}
ssize_t Http2Session::on_read()
{
ssize_t Http2Session::on_read() {
int rv;
size_t nread = 0;
auto input = bufferevent_get_input(client_->bev);
for(;;) {
for (;;) {
auto inputlen = evbuffer_get_contiguous_space(input);
if(inputlen == 0) {
if (inputlen == 0) {
assert(evbuffer_get_length(input) == 0);
return nread;
@ -184,53 +167,51 @@ ssize_t Http2Session::on_read()
rv = nghttp2_session_mem_recv(session_, mem, inputlen);
if(rv < 0) {
if (rv < 0) {
return -1;
}
nread += rv;
if(evbuffer_drain(input, rv) != 0) {
if (evbuffer_drain(input, rv) != 0) {
return -1;
}
}
}
int Http2Session::on_write()
{
int Http2Session::on_write() {
int rv;
uint8_t buf[16384];
auto output = bufferevent_get_output(client_->bev);
util::EvbufferBuffer evbbuf(output, buf, sizeof(buf));
for(;;) {
for (;;) {
const uint8_t *data;
auto datalen = nghttp2_session_mem_send(session_, &data);
if(datalen < 0) {
if (datalen < 0) {
return -1;
}
if(datalen == 0) {
if (datalen == 0) {
break;
}
rv = evbbuf.add(data, datalen);
if(rv != 0) {
if (rv != 0) {
return -1;
}
}
rv = evbbuf.flush();
if(rv != 0) {
if (rv != 0) {
return -1;
}
if(nghttp2_session_want_read(session_) == 0 &&
nghttp2_session_want_write(session_) == 0 &&
evbuffer_get_length(output) == 0) {
if (nghttp2_session_want_read(session_) == 0 &&
nghttp2_session_want_write(session_) == 0 &&
evbuffer_get_length(output) == 0) {
return -1;
}
return 0;
}
void Http2Session::terminate()
{
void Http2Session::terminate() {
nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR);
}

View File

@ -42,6 +42,7 @@ public:
virtual ssize_t on_read();
virtual int on_write();
virtual void terminate();
private:
Client *client_;
nghttp2_session *session_;

View File

@ -34,23 +34,16 @@ using namespace nghttp2;
namespace h2load {
SpdySession::SpdySession(Client *client, uint16_t spdy_version)
: client_(client),
session_(nullptr),
spdy_version_(spdy_version)
{}
: client_(client), session_(nullptr), spdy_version_(spdy_version) {}
SpdySession::~SpdySession()
{
spdylay_session_del(session_);
}
SpdySession::~SpdySession() { spdylay_session_del(session_); }
namespace {
void before_ctrl_send_callback
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data)
{
auto client = static_cast<Client*>(user_data);
if(type != SPDYLAY_SYN_STREAM) {
void before_ctrl_send_callback(spdylay_session *session,
spdylay_frame_type type, spdylay_frame *frame,
void *user_data) {
auto client = static_cast<Client *>(user_data);
if (type != SPDYLAY_SYN_STREAM) {
return;
}
client->on_request(frame->syn_stream.stream_id);
@ -58,71 +51,61 @@ void before_ctrl_send_callback
} // namespace
namespace {
void on_ctrl_recv_callback(spdylay_session *session,
spdylay_frame_type type,
spdylay_frame *frame,
void *user_data)
{
auto client = static_cast<Client*>(user_data);
if(type != SPDYLAY_SYN_REPLY) {
void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
spdylay_frame *frame, void *user_data) {
auto client = static_cast<Client *>(user_data);
if (type != SPDYLAY_SYN_REPLY) {
return;
}
for(auto p = frame->syn_reply.nv; *p; p += 2) {
for (auto p = frame->syn_reply.nv; *p; p += 2) {
auto name = *p;
auto value = *(p + 1);
client->on_header(frame->syn_reply.stream_id,
reinterpret_cast<const uint8_t*>(name),
strlen(name),
reinterpret_cast<const uint8_t*>(value),
strlen(value));
reinterpret_cast<const uint8_t *>(name), strlen(name),
reinterpret_cast<const uint8_t *>(value), strlen(value));
}
client->worker->stats.bytes_head += frame->syn_reply.hd.length;
}
} // namespace
namespace {
void on_data_chunk_recv_callback
(spdylay_session *session, uint8_t flags, int32_t stream_id,
const uint8_t *data, size_t len, void *user_data)
{
auto client = static_cast<Client*>(user_data);
void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
auto client = static_cast<Client *>(user_data);
client->worker->stats.bytes_body += len;
auto spdy_session = static_cast<SpdySession*>(client->session.get());
auto spdy_session = static_cast<SpdySession *>(client->session.get());
spdy_session->handle_window_update(stream_id, len);
}
} // namespace
namespace {
void on_stream_close_callback
(spdylay_session *session, int32_t stream_id, spdylay_status_code status_code,
void *user_data)
{
auto client = static_cast<Client*>(user_data);
void on_stream_close_callback(spdylay_session *session, int32_t stream_id,
spdylay_status_code status_code,
void *user_data) {
auto client = static_cast<Client *>(user_data);
client->on_stream_close(stream_id, status_code == SPDYLAY_OK);
}
} // namespace
namespace {
ssize_t send_callback(spdylay_session *session,
const uint8_t *data, size_t length, int flags,
void *user_data)
{
auto client = static_cast<Client*>(user_data);
auto spdy_session = static_cast<SpdySession*>(client->session.get());
ssize_t send_callback(spdylay_session *session, const uint8_t *data,
size_t length, int flags, void *user_data) {
auto client = static_cast<Client *>(user_data);
auto spdy_session = static_cast<SpdySession *>(client->session.get());
int rv;
rv = spdy_session->sendbuf.add(data, length);
if(rv != 0) {
if (rv != 0) {
return SPDYLAY_ERR_CALLBACK_FAILURE;
}
return length;
}
} //namespace
} // namespace
void SpdySession::on_connect()
{
void SpdySession::on_connect() {
spdylay_session_callbacks callbacks = {0};
callbacks.send_callback = send_callback;
callbacks.before_ctrl_send_callback = before_ctrl_send_callback;
@ -133,8 +116,8 @@ void SpdySession::on_connect()
spdylay_session_client_new(&session_, spdy_version_, &callbacks, client_);
int val = 1;
spdylay_session_set_option(session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE,
&val, sizeof(val));
spdylay_session_set_option(session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE, &val,
sizeof(val));
spdylay_settings_entry iv[1];
iv[0].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
@ -145,36 +128,34 @@ void SpdySession::on_connect()
auto config = client_->worker->config;
if(spdy_version_ >= SPDYLAY_PROTO_SPDY3_1 &&
config->connection_window_bits > 16) {
auto delta = (1 << config->connection_window_bits)
- SPDYLAY_INITIAL_WINDOW_SIZE;
if (spdy_version_ >= SPDYLAY_PROTO_SPDY3_1 &&
config->connection_window_bits > 16) {
auto delta =
(1 << config->connection_window_bits) - SPDYLAY_INITIAL_WINDOW_SIZE;
spdylay_submit_window_update(session_, 0, delta);
}
}
void SpdySession::submit_request()
{
void SpdySession::submit_request() {
auto config = client_->worker->config;
auto& nv = config->nv[client_->reqidx++];
auto &nv = config->nv[client_->reqidx++];
if(client_->reqidx == config->nv.size()) {
if (client_->reqidx == config->nv.size()) {
client_->reqidx = 0;
}
spdylay_submit_request(session_, 0, nv.data(), nullptr, nullptr);
}
ssize_t SpdySession::on_read()
{
ssize_t SpdySession::on_read() {
int rv;
size_t nread = 0;
auto input = bufferevent_get_input(client_->bev);
for(;;) {
for (;;) {
auto inputlen = evbuffer_get_contiguous_space(input);
if(inputlen == 0) {
if (inputlen == 0) {
assert(evbuffer_get_length(input) == 0);
return nread;
@ -184,65 +165,62 @@ ssize_t SpdySession::on_read()
rv = spdylay_session_mem_recv(session_, mem, inputlen);
if(rv < 0) {
if (rv < 0) {
return -1;
}
nread += rv;
if(evbuffer_drain(input, rv) != 0) {
if (evbuffer_drain(input, rv) != 0) {
return -1;
}
}
}
int SpdySession::on_write()
{
int SpdySession::on_write() {
int rv;
uint8_t buf[16384];
sendbuf.reset(bufferevent_get_output(client_->bev), buf, sizeof(buf));
rv = spdylay_session_send(session_);
if(rv != 0) {
if (rv != 0) {
return -1;
}
rv = sendbuf.flush();
if(rv != 0) {
if (rv != 0) {
return -1;
}
if(spdylay_session_want_read(session_) == 0 &&
spdylay_session_want_write(session_) == 0 &&
evbuffer_get_length(bufferevent_get_output(client_->bev)) == 0) {
if (spdylay_session_want_read(session_) == 0 &&
spdylay_session_want_write(session_) == 0 &&
evbuffer_get_length(bufferevent_get_output(client_->bev)) == 0) {
return -1;
}
return 0;
}
void SpdySession::terminate()
{
void SpdySession::terminate() {
spdylay_session_fail_session(session_, SPDYLAY_OK);
}
namespace {
int32_t determine_window_update_transmission(spdylay_session *session,
int32_t stream_id,
size_t window_bits)
{
size_t window_bits) {
int32_t recv_length;
if(stream_id == 0) {
if (stream_id == 0) {
recv_length = spdylay_session_get_recv_data_length(session);
} else {
recv_length = spdylay_session_get_stream_recv_data_length
(session, stream_id);
recv_length =
spdylay_session_get_stream_recv_data_length(session, stream_id);
}
auto window_size = 1 << window_bits;
if(recv_length != -1 && recv_length >= window_size / 2) {
if (recv_length != -1 && recv_length >= window_size / 2) {
return recv_length;
}
@ -250,26 +228,25 @@ int32_t determine_window_update_transmission(spdylay_session *session,
}
} // namespace
void SpdySession::handle_window_update(int32_t stream_id, size_t recvlen)
{
void SpdySession::handle_window_update(int32_t stream_id, size_t recvlen) {
auto config = client_->worker->config;
size_t connection_window_bits;
if(config->connection_window_bits > 16) {
if (config->connection_window_bits > 16) {
connection_window_bits = config->connection_window_bits;
} else {
connection_window_bits = 16;
}
auto delta = determine_window_update_transmission
(session_, 0, connection_window_bits);
if(delta > 0) {
auto delta =
determine_window_update_transmission(session_, 0, connection_window_bits);
if (delta > 0) {
spdylay_submit_window_update(session_, 0, delta);
}
delta = determine_window_update_transmission
(session_, stream_id, config->window_bits);
if(delta > 0) {
delta = determine_window_update_transmission(session_, stream_id,
config->window_bits);
if (delta > 0) {
spdylay_submit_window_update(session_, stream_id, delta);
}
}

View File

@ -48,6 +48,7 @@ public:
void handle_window_update(int32_t stream_id, size_t recvlen);
nghttp2::util::EvbufferBuffer sendbuf;
private:
Client *client_;
spdylay_session *session_;

View File

@ -30,66 +30,112 @@ namespace nghttp2 {
namespace http2 {
std::string get_status_string(unsigned int status_code)
{
switch(status_code) {
case 100: return "100 Continue";
case 101: return "101 Switching Protocols";
case 200: return "200 OK";
case 201: return "201 Created";
case 202: return "202 Accepted";
case 203: return "203 Non-Authoritative Information";
case 204: return "204 No Content";
case 205: return "205 Reset Content";
case 206: return "206 Partial Content";
case 300: return "300 Multiple Choices";
case 301: return "301 Moved Permanently";
case 302: return "302 Found";
case 303: return "303 See Other";
case 304: return "304 Not Modified";
case 305: return "305 Use Proxy";
// case 306: return "306 (Unused)";
case 307: return "307 Temporary Redirect";
case 308: return "308 Permanent Redirect";
case 400: return "400 Bad Request";
case 401: return "401 Unauthorized";
case 402: return "402 Payment Required";
case 403: return "403 Forbidden";
case 404: return "404 Not Found";
case 405: return "405 Method Not Allowed";
case 406: return "406 Not Acceptable";
case 407: return "407 Proxy Authentication Required";
case 408: return "408 Request Timeout";
case 409: return "409 Conflict";
case 410: return "410 Gone";
case 411: return "411 Length Required";
case 412: return "412 Precondition Failed";
case 413: return "413 Payload Too Large";
case 414: return "414 URI Too Long";
case 415: return "415 Unsupported Media Type";
case 416: return "416 Requested Range Not Satisfiable";
case 417: return "417 Expectation Failed";
case 421: return "421 Misdirected Request";
case 426: return "426 Upgrade Required";
case 428: return "428 Precondition Required";
case 429: return "429 Too Many Requests";
case 431: return "431 Request Header Fields Too Large";
case 500: return "500 Internal Server Error";
case 501: return "501 Not Implemented";
case 502: return "502 Bad Gateway";
case 503: return "503 Service Unavailable";
case 504: return "504 Gateway Timeout";
case 505: return "505 HTTP Version Not Supported";
case 511: return "511 Network Authentication Required";
default: return util::utos(status_code);
std::string get_status_string(unsigned int status_code) {
switch (status_code) {
case 100:
return "100 Continue";
case 101:
return "101 Switching Protocols";
case 200:
return "200 OK";
case 201:
return "201 Created";
case 202:
return "202 Accepted";
case 203:
return "203 Non-Authoritative Information";
case 204:
return "204 No Content";
case 205:
return "205 Reset Content";
case 206:
return "206 Partial Content";
case 300:
return "300 Multiple Choices";
case 301:
return "301 Moved Permanently";
case 302:
return "302 Found";
case 303:
return "303 See Other";
case 304:
return "304 Not Modified";
case 305:
return "305 Use Proxy";
// case 306: return "306 (Unused)";
case 307:
return "307 Temporary Redirect";
case 308:
return "308 Permanent Redirect";
case 400:
return "400 Bad Request";
case 401:
return "401 Unauthorized";
case 402:
return "402 Payment Required";
case 403:
return "403 Forbidden";
case 404:
return "404 Not Found";
case 405:
return "405 Method Not Allowed";
case 406:
return "406 Not Acceptable";
case 407:
return "407 Proxy Authentication Required";
case 408:
return "408 Request Timeout";
case 409:
return "409 Conflict";
case 410:
return "410 Gone";
case 411:
return "411 Length Required";
case 412:
return "412 Precondition Failed";
case 413:
return "413 Payload Too Large";
case 414:
return "414 URI Too Long";
case 415:
return "415 Unsupported Media Type";
case 416:
return "416 Requested Range Not Satisfiable";
case 417:
return "417 Expectation Failed";
case 421:
return "421 Misdirected Request";
case 426:
return "426 Upgrade Required";
case 428:
return "428 Precondition Required";
case 429:
return "429 Too Many Requests";
case 431:
return "431 Request Header Fields Too Large";
case 500:
return "500 Internal Server Error";
case 501:
return "501 Not Implemented";
case 502:
return "502 Bad Gateway";
case 503:
return "503 Service Unavailable";
case 504:
return "504 Gateway Timeout";
case 505:
return "505 HTTP Version Not Supported";
case 511:
return "511 Network Authentication Required";
default:
return util::utos(status_code);
}
}
void capitalize(std::string& s, size_t offset)
{
void capitalize(std::string &s, size_t offset) {
s[offset] = util::upcase(s[offset]);
for(size_t i = offset+1, eoi = s.size(); i < eoi; ++i) {
if(s[i-1] == '-') {
for (size_t i = offset + 1, eoi = s.size(); i < eoi; ++i) {
if (s[i - 1] == '-') {
s[i] = util::upcase(s[i]);
} else {
s[i] = util::lowcase(s[i]);
@ -97,10 +143,9 @@ void capitalize(std::string& s, size_t offset)
}
}
bool lws(const char *value)
{
for(; *value; ++value) {
switch(*value) {
bool lws(const char *value) {
for (; *value; ++value) {
switch (*value) {
case '\t':
case ' ':
continue;
@ -111,8 +156,7 @@ bool lws(const char *value)
return true;
}
void sanitize_header_value(std::string& s, size_t offset)
{
void sanitize_header_value(std::string &s, size_t offset) {
// Since both nghttp2 and spdylay do not allow \n and \r in header
// values, we don't have to do this anymore.
@ -123,40 +167,32 @@ void sanitize_header_value(std::string& s, size_t offset)
// }
}
void copy_url_component(std::string& dest, const http_parser_url *u, int field,
const char* url)
{
if(u->field_set & (1 << field)) {
dest.assign(url+u->field_data[field].off, u->field_data[field].len);
void copy_url_component(std::string &dest, const http_parser_url *u, int field,
const char *url) {
if (u->field_set & (1 << field)) {
dest.assign(url + u->field_data[field].off, u->field_data[field].len);
}
}
bool check_http2_allowed_header(const char *name)
{
return check_http2_allowed_header(reinterpret_cast<const uint8_t*>(name),
bool check_http2_allowed_header(const char *name) {
return check_http2_allowed_header(reinterpret_cast<const uint8_t *>(name),
strlen(name));
}
bool check_http2_allowed_header(const uint8_t *name, size_t namelen)
{
return
!util::strieq("connection", name, namelen) &&
!util::strieq("host", name, namelen) &&
!util::strieq("keep-alive", name, namelen) &&
!util::strieq("proxy-connection", name, namelen) &&
!util::strieq("te", name, namelen) &&
!util::strieq("transfer-encoding", name, namelen) &&
!util::strieq("upgrade", name, namelen);
bool check_http2_allowed_header(const uint8_t *name, size_t namelen) {
return !util::strieq("connection", name, namelen) &&
!util::strieq("host", name, namelen) &&
!util::strieq("keep-alive", name, namelen) &&
!util::strieq("proxy-connection", name, namelen) &&
!util::strieq("te", name, namelen) &&
!util::strieq("transfer-encoding", name, namelen) &&
!util::strieq("upgrade", name, namelen);
}
namespace {
const char *DISALLOWED_HD[] = {
"connection",
"keep-alive",
"proxy-connection",
"te",
"transfer-encoding",
"upgrade",
"connection", "keep-alive", "proxy-connection",
"te", "transfer-encoding", "upgrade",
};
} // namespace
@ -166,10 +202,7 @@ auto DISALLOWED_HDLEN = util::array_size(DISALLOWED_HD);
namespace {
const char *REQUEST_PSEUDO_HD[] = {
":authority",
":method",
":path",
":scheme",
":authority", ":method", ":path", ":scheme",
};
} // namespace
@ -179,7 +212,7 @@ auto REQUEST_PSEUDO_HDLEN = util::array_size(REQUEST_PSEUDO_HD);
namespace {
const char *RESPONSE_PSEUDO_HD[] = {
":status",
":status",
};
} // namespace
@ -189,17 +222,9 @@ auto RESPONSE_PSEUDO_HDLEN = util::array_size(RESPONSE_PSEUDO_HD);
namespace {
const char *IGN_HD[] = {
"connection",
"http2-settings",
"keep-alive",
"proxy-connection",
"server",
"te",
"transfer-encoding",
"upgrade",
"via",
"x-forwarded-for",
"x-forwarded-proto",
"connection", "http2-settings", "keep-alive", "proxy-connection",
"server", "te", "transfer-encoding", "upgrade",
"via", "x-forwarded-for", "x-forwarded-proto",
};
} // namespace
@ -209,16 +234,9 @@ auto IGN_HDLEN = util::array_size(IGN_HD);
namespace {
const char *HTTP1_IGN_HD[] = {
"connection",
"cookie",
"http2-settings",
"keep-alive",
"proxy-connection",
"server",
"upgrade",
"via",
"x-forwarded-for",
"x-forwarded-proto",
"connection", "cookie", "http2-settings", "keep-alive",
"proxy-connection", "server", "upgrade", "via",
"x-forwarded-for", "x-forwarded-proto",
};
} // namespace
@ -226,49 +244,43 @@ namespace {
auto HTTP1_IGN_HDLEN = util::array_size(HTTP1_IGN_HD);
} // namespace
bool name_less(const Headers::value_type& lhs,
const Headers::value_type& rhs)
{
if(lhs.name.c_str()[0] == ':') {
if(rhs.name.c_str()[0] != ':') {
bool name_less(const Headers::value_type &lhs, const Headers::value_type &rhs) {
if (lhs.name.c_str()[0] == ':') {
if (rhs.name.c_str()[0] != ':') {
return true;
}
} else if(rhs.name.c_str()[0] == ':') {
} else if (rhs.name.c_str()[0] == ':') {
return false;
}
return lhs.name < rhs.name;
}
bool check_http2_headers(const Headers& nva)
{
for(size_t i = 0; i < DISALLOWED_HDLEN; ++i) {
if(std::binary_search(std::begin(nva), std::end(nva),
Header(DISALLOWED_HD[i], ""), name_less)) {
bool check_http2_headers(const Headers &nva) {
for (size_t i = 0; i < DISALLOWED_HDLEN; ++i) {
if (std::binary_search(std::begin(nva), std::end(nva),
Header(DISALLOWED_HD[i], ""), name_less)) {
return false;
}
}
return true;
}
bool check_http2_request_headers(const Headers& nva)
{
bool check_http2_request_headers(const Headers &nva) {
return check_http2_headers(nva);
}
bool check_http2_response_headers(const Headers& nva)
{
bool check_http2_response_headers(const Headers &nva) {
return check_http2_headers(nva);
}
namespace {
template<typename InputIterator>
template <typename InputIterator>
bool check_pseudo_header(const uint8_t *name, size_t namelen,
InputIterator allowed_first,
InputIterator allowed_last)
{
for(auto i = allowed_first; i != allowed_last; ++i) {
if(util::streq(*i, name, namelen)) {
InputIterator allowed_last) {
for (auto i = allowed_first; i != allowed_last; ++i) {
if (util::streq(*i, name, namelen)) {
return true;
}
}
@ -277,21 +289,18 @@ bool check_pseudo_header(const uint8_t *name, size_t namelen,
}
} // namespace
bool check_http2_request_pseudo_header(const uint8_t *name, size_t namelen)
{
bool check_http2_request_pseudo_header(const uint8_t *name, size_t namelen) {
return check_pseudo_header(name, namelen, REQUEST_PSEUDO_HD,
REQUEST_PSEUDO_HD + REQUEST_PSEUDO_HDLEN);
}
bool check_http2_response_pseudo_header(const uint8_t *name, size_t namelen)
{
bool check_http2_response_pseudo_header(const uint8_t *name, size_t namelen) {
return check_pseudo_header(name, namelen, RESPONSE_PSEUDO_HD,
RESPONSE_PSEUDO_HD + RESPONSE_PSEUDO_HDLEN);
}
void normalize_headers(Headers& nva)
{
for(auto& kv : nva) {
void normalize_headers(Headers &nva) {
for (auto &kv : nva) {
util::inp_strlower(kv.name);
}
std::stable_sort(std::begin(nva), std::end(nva), name_less);
@ -299,112 +308,98 @@ void normalize_headers(Headers& nva)
Headers::value_type to_header(const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
bool no_index)
{
return Header(std::string(reinterpret_cast<const char*>(name),
namelen),
std::string(reinterpret_cast<const char*>(value),
valuelen),
bool no_index) {
return Header(std::string(reinterpret_cast<const char *>(name), namelen),
std::string(reinterpret_cast<const char *>(value), valuelen),
no_index);
}
void add_header(Headers& nva,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
bool no_index)
{
void add_header(Headers &nva, const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen, bool no_index) {
nva.push_back(to_header(name, namelen, value, valuelen, no_index));
}
const Headers::value_type* get_unique_header(const Headers& nva,
const char *name)
{
const Headers::value_type *get_unique_header(const Headers &nva,
const char *name) {
auto nv = Headers::value_type(name, "");
auto i = std::lower_bound(std::begin(nva), std::end(nva), nv, name_less);
if(i != std::end(nva) && (*i).name == nv.name) {
if (i != std::end(nva) && (*i).name == nv.name) {
auto j = i + 1;
if(j == std::end(nva) || (*j).name != nv.name) {
if (j == std::end(nva) || (*j).name != nv.name) {
return &(*i);
}
}
return nullptr;
}
const Headers::value_type* get_header(const Headers& nva, const char *name)
{
const Headers::value_type *get_header(const Headers &nva, const char *name) {
auto nv = Headers::value_type(name, "");
auto i = std::lower_bound(std::begin(nva), std::end(nva), nv, name_less);
if(i != std::end(nva) && (*i).name == nv.name) {
if (i != std::end(nva) && (*i).name == nv.name) {
return &(*i);
}
return nullptr;
}
std::string value_to_str(const Headers::value_type *nv)
{
if(nv) {
std::string value_to_str(const Headers::value_type *nv) {
if (nv) {
return nv->value;
}
return "";
}
bool value_lws(const Headers::value_type *nv)
{
bool value_lws(const Headers::value_type *nv) {
return (*nv).value.find_first_not_of("\t ") == std::string::npos;
}
bool non_empty_value(const Headers::value_type *nv)
{
bool non_empty_value(const Headers::value_type *nv) {
return nv && !value_lws(nv);
}
nghttp2_nv make_nv(const std::string& name, const std::string& value,
bool no_index)
{
nghttp2_nv make_nv(const std::string &name, const std::string &value,
bool no_index) {
uint8_t flags;
flags = no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE;
return {(uint8_t*)name.c_str(), (uint8_t*)value.c_str(),
name.size(), value.size(), flags};
return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(),
value.size(), flags};
}
void copy_norm_headers_to_nva
(std::vector<nghttp2_nv>& nva, const Headers& headers)
{
void copy_norm_headers_to_nva(std::vector<nghttp2_nv> &nva,
const Headers &headers) {
size_t i, j;
for(i = 0, j = 0; i < headers.size() && j < IGN_HDLEN;) {
auto& kv = headers[i];
for (i = 0, j = 0; i < headers.size() && j < IGN_HDLEN;) {
auto &kv = headers[i];
int rv = strcmp(kv.name.c_str(), IGN_HD[j]);
if(rv < 0) {
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
if (rv < 0) {
if (!kv.name.empty() && kv.name.c_str()[0] != ':') {
nva.push_back(make_nv(kv.name, kv.value, kv.no_index));
}
++i;
} else if(rv > 0) {
} else if (rv > 0) {
++j;
} else {
++i;
}
}
for(; i < headers.size(); ++i) {
auto& kv = headers[i];
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
for (; i < headers.size(); ++i) {
auto &kv = headers[i];
if (!kv.name.empty() && kv.name.c_str()[0] != ':') {
nva.push_back(make_nv(kv.name, kv.value, kv.no_index));
}
}
}
void build_http1_headers_from_norm_headers
(std::string& hdrs, const Headers& headers)
{
void build_http1_headers_from_norm_headers(std::string &hdrs,
const Headers &headers) {
size_t i, j;
for(i = 0, j = 0; i < headers.size() && j < HTTP1_IGN_HDLEN;) {
auto& kv = headers[i];
for (i = 0, j = 0; i < headers.size() && j < HTTP1_IGN_HDLEN;) {
auto &kv = headers[i];
auto rv = strcmp(kv.name.c_str(), HTTP1_IGN_HD[j]);
if(rv < 0) {
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
if (rv < 0) {
if (!kv.name.empty() && kv.name.c_str()[0] != ':') {
hdrs += kv.name;
capitalize(hdrs, hdrs.size() - kv.name.size());
hdrs += ": ";
@ -413,16 +408,16 @@ void build_http1_headers_from_norm_headers
hdrs += "\r\n";
}
++i;
} else if(rv > 0) {
} else if (rv > 0) {
++j;
} else {
++i;
}
}
for(; i < headers.size(); ++i) {
auto& kv = headers[i];
for (; i < headers.size(); ++i) {
auto &kv = headers[i];
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
if (!kv.name.empty() && kv.name.c_str()[0] != ':') {
hdrs += kv.name;
capitalize(hdrs, hdrs.size() - kv.name.size());
hdrs += ": ";
@ -434,42 +429,39 @@ void build_http1_headers_from_norm_headers
}
int32_t determine_window_update_transmission(nghttp2_session *session,
int32_t stream_id)
{
int32_t stream_id) {
int32_t recv_length, window_size;
if(stream_id == 0) {
if (stream_id == 0) {
recv_length = nghttp2_session_get_effective_recv_data_length(session);
window_size = nghttp2_session_get_effective_local_window_size(session);
} else {
recv_length = nghttp2_session_get_stream_effective_recv_data_length
(session, stream_id);
window_size = nghttp2_session_get_stream_effective_local_window_size
(session, stream_id);
recv_length = nghttp2_session_get_stream_effective_recv_data_length(
session, stream_id);
window_size = nghttp2_session_get_stream_effective_local_window_size(
session, stream_id);
}
if(recv_length != -1 && window_size != -1) {
if(recv_length >= window_size / 2) {
if (recv_length != -1 && window_size != -1) {
if (recv_length >= window_size / 2) {
return recv_length;
}
}
return -1;
}
void dump_nv(FILE *out, const char **nv)
{
for(size_t i = 0; nv[i]; i += 2) {
void dump_nv(FILE *out, const char **nv) {
for (size_t i = 0; nv[i]; i += 2) {
fwrite(nv[i], strlen(nv[i]), 1, out);
fwrite(": ", 2, 1, out);
fwrite(nv[i+1], strlen(nv[i+1]), 1, out);
fwrite(nv[i + 1], strlen(nv[i + 1]), 1, out);
fwrite("\n", 1, 1, out);
}
fwrite("\n", 1, 1, out);
fflush(out);
}
void dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen)
{
void dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen) {
auto end = nva + nvlen;
for(; nva != end; ++nva) {
for (; nva != end; ++nva) {
fwrite(nva->name, nva->namelen, 1, out);
fwrite(": ", 2, 1, out);
fwrite(nva->value, nva->valuelen, 1, out);
@ -479,9 +471,8 @@ void dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen)
fflush(out);
}
void dump_nv(FILE *out, const Headers& nva)
{
for(auto& nv : nva) {
void dump_nv(FILE *out, const Headers &nva) {
for (auto &nv : nva) {
fwrite(nv.name.c_str(), nv.name.size(), 1, out);
fwrite(": ", 2, 1, out);
fwrite(nv.value.c_str(), nv.value.size(), 1, out);
@ -491,54 +482,52 @@ void dump_nv(FILE *out, const Headers& nva)
fflush(out);
}
std::string rewrite_location_uri(const std::string& uri,
const http_parser_url& u,
const std::string& request_host,
const std::string& upstream_scheme,
uint16_t upstream_port)
{
std::string rewrite_location_uri(const std::string &uri,
const http_parser_url &u,
const std::string &request_host,
const std::string &upstream_scheme,
uint16_t upstream_port) {
// We just rewrite host and optionally port. We don't rewrite https
// link. Not sure it happens in practice.
if(u.field_set & (1 << UF_SCHEMA)) {
if (u.field_set & (1 << UF_SCHEMA)) {
auto field = &u.field_data[UF_SCHEMA];
if(!util::streq("http", &uri[field->off], field->len)) {
if (!util::streq("http", &uri[field->off], field->len)) {
return "";
}
}
if((u.field_set & (1 << UF_HOST)) == 0) {
if ((u.field_set & (1 << UF_HOST)) == 0) {
return "";
}
auto field = &u.field_data[UF_HOST];
if(!util::startsWith(std::begin(request_host), std::end(request_host),
&uri[field->off], &uri[field->off] + field->len) ||
(request_host.size() != field->len &&
request_host[field->len] != ':')) {
if (!util::startsWith(std::begin(request_host), std::end(request_host),
&uri[field->off], &uri[field->off] + field->len) ||
(request_host.size() != field->len && request_host[field->len] != ':')) {
return "";
}
std::string res = upstream_scheme;
res += "://";
res.append(&uri[field->off], field->len);
if(upstream_scheme == "http") {
if(upstream_port != 80) {
if (upstream_scheme == "http") {
if (upstream_port != 80) {
res += ":";
res += util::utos(upstream_port);
}
} else if(upstream_scheme == "https") {
if(upstream_port != 443) {
} else if (upstream_scheme == "https") {
if (upstream_port != 443) {
res += ":";
res += util::utos(upstream_port);
}
}
if(u.field_set & (1 << UF_PATH)) {
if (u.field_set & (1 << UF_PATH)) {
field = &u.field_data[UF_PATH];
res.append(&uri[field->off], field->len);
}
if(u.field_set & (1 << UF_QUERY)) {
if (u.field_set & (1 << UF_QUERY)) {
field = &u.field_data[UF_QUERY];
res += "?";
res.append(&uri[field->off], field->len);
}
if(u.field_set & (1 << UF_FRAGMENT)) {
if (u.field_set & (1 << UF_FRAGMENT)) {
field = &u.field_data[UF_FRAGMENT];
res += "#";
res.append(&uri[field->off], field->len);
@ -546,34 +535,32 @@ std::string rewrite_location_uri(const std::string& uri,
return res;
}
int check_nv(const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen)
{
if(!nghttp2_check_header_name(name, namelen)) {
int check_nv(const uint8_t *name, size_t namelen, const uint8_t *value,
size_t valuelen) {
if (!nghttp2_check_header_name(name, namelen)) {
return 0;
}
if(!nghttp2_check_header_value(value, valuelen)) {
if (!nghttp2_check_header_value(value, valuelen)) {
return 0;
}
return 1;
}
int parse_http_status_code(const std::string& src)
{
if(src.size() != 3) {
int parse_http_status_code(const std::string &src) {
if (src.size() != 3) {
return -1;
}
int status = 0;
for(auto c : src) {
if(!isdigit(c)) {
for (auto c : src) {
if (!isdigit(c)) {
return -1;
}
status *= 10;
status += c - '0';
}
if(status < 100) {
if (status < 100) {
return -1;
}

View File

@ -39,23 +39,16 @@
namespace nghttp2 {
struct Header {
Header(std::string name, std::string value, bool no_index=false)
: name(std::move(name)),
value(std::move(value)),
no_index(no_index)
{}
Header(std::string name, std::string value, bool no_index = false)
: name(std::move(name)), value(std::move(value)), no_index(no_index) {}
Header()
: no_index(false)
{}
Header() : no_index(false) {}
bool operator==(const Header& other) const
{
bool operator==(const Header &other) const {
return name == other.name && value == other.value;
}
bool operator<(const Header& rhs) const
{
bool operator<(const Header &rhs) const {
return name < rhs.name || (name == rhs.name && value < rhs.value);
}
@ -70,18 +63,18 @@ namespace http2 {
std::string get_status_string(unsigned int status_code);
void capitalize(std::string& s, size_t offset);
void capitalize(std::string &s, size_t offset);
// Returns true if |value| is LWS
bool lws(const char *value);
void sanitize_header_value(std::string& s, size_t offset);
void sanitize_header_value(std::string &s, size_t offset);
// Copies the |field| component value from |u| and |url| to the
// |dest|. If |u| does not have |field|, then this function does
// nothing.
void copy_url_component(std::string& dest, const http_parser_url *u, int field,
const char* url);
void copy_url_component(std::string &dest, const http_parser_url *u, int field,
const char *url);
// Returns true if the header field |name| with length |namelen| bytes
// is valid for HTTP/2.
@ -94,13 +87,13 @@ bool check_http2_allowed_header(const char *name);
// Checks that headers |nva| do not contain disallowed header fields
// in HTTP/2 spec. This function returns true if |nva| does not
// contains such headers.
bool check_http2_headers(const Headers& nva);
bool check_http2_headers(const Headers &nva);
// Calls check_http2_headers()
bool check_http2_request_headers(const Headers& nva);
bool check_http2_request_headers(const Headers &nva);
// Calls check_http2_headers()
bool check_http2_response_headers(const Headers& nva);
bool check_http2_response_headers(const Headers &nva);
// Returns true if |name| is allowed pusedo header for request.
bool check_http2_request_pseudo_header(const uint8_t *name, size_t namelen);
@ -108,9 +101,9 @@ bool check_http2_request_pseudo_header(const uint8_t *name, size_t namelen);
// Returns true if |name| is allowed pusedo header for response.
bool check_http2_response_pseudo_header(const uint8_t *name, size_t namelen);
bool name_less(const Headers::value_type& lhs, const Headers::value_type& rhs);
bool name_less(const Headers::value_type &lhs, const Headers::value_type &rhs);
void normalize_headers(Headers& nva);
void normalize_headers(Headers &nva);
Headers::value_type to_header(const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
@ -119,22 +112,20 @@ Headers::value_type to_header(const uint8_t *name, size_t namelen,
// Add name/value pairs to |nva|. If |no_index| is true, this
// name/value pair won't be indexed when it is forwarded to the next
// hop.
void add_header(Headers& nva,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
bool no_index);
void add_header(Headers &nva, const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen, bool no_index);
// Returns the iterator to the entry in |nva| which has name |name|
// and the |name| is uinque in the |nva|. If no such entry exist,
// returns nullptr.
const Headers::value_type* get_unique_header(const Headers& nva,
const Headers::value_type *get_unique_header(const Headers &nva,
const char *name);
// Returns the iterator to the entry in |nva| which has name
// |name|. If more than one entries which have the name |name|, first
// occurrence in |nva| is returned. If no such entry exist, returns
// nullptr.
const Headers::value_type* get_header(const Headers& nva, const char *name);
const Headers::value_type *get_header(const Headers &nva, const char *name);
// Returns nv->second if nv is not nullptr. Otherwise, returns "".
std::string value_to_str(const Headers::value_type *nv);
@ -150,44 +141,42 @@ bool non_empty_value(const Headers::value_type *nv);
// returned value only references the data pointer to name.c_str() and
// value.c_str(). If |no_index| is true, nghttp2_nv flags member has
// NGHTTP2_NV_FLAG_NO_INDEX flag set.
nghttp2_nv make_nv(const std::string& name, const std::string& value,
nghttp2_nv make_nv(const std::string &name, const std::string &value,
bool no_index = false);
// Create nghttp2_nv from string literal |name| and |value|.
template<size_t N, size_t M>
nghttp2_nv make_nv_ll(const char(&name)[N], const char(&value)[M])
{
return {(uint8_t*)name, (uint8_t*)value, N - 1, M - 1, NGHTTP2_NV_FLAG_NONE};
template <size_t N, size_t M>
nghttp2_nv make_nv_ll(const char (&name)[N], const char (&value)[M]) {
return {(uint8_t *)name, (uint8_t *)value, N - 1, M - 1,
NGHTTP2_NV_FLAG_NONE};
}
// Create nghttp2_nv from string literal |name| and c-string |value|.
template<size_t N>
nghttp2_nv make_nv_lc(const char(&name)[N], const char *value)
{
return {(uint8_t*)name, (uint8_t*)value, N - 1, strlen(value),
NGHTTP2_NV_FLAG_NONE};
template <size_t N>
nghttp2_nv make_nv_lc(const char (&name)[N], const char *value) {
return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value),
NGHTTP2_NV_FLAG_NONE};
}
// Create nghttp2_nv from string literal |name| and std::string
// |value|.
template<size_t N>
nghttp2_nv make_nv_ls(const char(&name)[N], const std::string& value)
{
return {(uint8_t*)name, (uint8_t*)value.c_str(), N - 1, value.size(),
NGHTTP2_NV_FLAG_NONE};
template <size_t N>
nghttp2_nv make_nv_ls(const char (&name)[N], const std::string &value) {
return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(),
NGHTTP2_NV_FLAG_NONE};
}
// Appends headers in |headers| to |nv|. Certain headers, including
// disallowed headers in HTTP/2 spec and headers which require
// special handling (i.e. via), are not copied.
void copy_norm_headers_to_nva
(std::vector<nghttp2_nv>& nva, const Headers& headers);
void copy_norm_headers_to_nva(std::vector<nghttp2_nv> &nva,
const Headers &headers);
// Appends HTTP/1.1 style header lines to |hdrs| from headers in
// |headers|. Certain headers, which requires special handling
// (i.e. via and cookie), are not appended.
void build_http1_headers_from_norm_headers
(std::string& hdrs, const Headers& headers);
void build_http1_headers_from_norm_headers(std::string &hdrs,
const Headers &headers);
// Return positive window_size_increment if WINDOW_UPDATE should be
// sent for the stream |stream_id|. If |stream_id| == 0, this function
@ -206,7 +195,7 @@ void dump_nv(FILE *out, const char **nv);
void dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen);
// Dumps name/value pairs in |nva| to |out|.
void dump_nv(FILE *out, const Headers& nva);
void dump_nv(FILE *out, const Headers &nva);
// Rewrites redirection URI which usually appears in location header
// field. The |uri| is the URI in the location header field. The |u|
@ -218,20 +207,20 @@ void dump_nv(FILE *out, const Headers& nva);
// This function returns the new rewritten URI on success. If the
// location URI is not subject to the rewrite, this function returns
// emtpy string.
std::string rewrite_location_uri(const std::string& uri,
const http_parser_url& u,
const std::string& request_host,
const std::string& upstream_scheme,
std::string rewrite_location_uri(const std::string &uri,
const http_parser_url &u,
const std::string &request_host,
const std::string &upstream_scheme,
uint16_t upstream_port);
// Checks the header name/value pair using nghttp2_check_header_name()
// and nghttp2_check_header_value(). If both function returns nonzero,
// this function returns nonzero.
int check_nv(const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen);
int check_nv(const uint8_t *name, size_t namelen, const uint8_t *value,
size_t valuelen);
// Returns parsed HTTP status code. Returns -1 on failure.
int parse_http_status_code(const std::string& src);
int parse_http_status_code(const std::string &src);
} // namespace http2

View File

@ -37,15 +37,16 @@
using namespace nghttp2;
#define MAKE_NV(K, V) {(uint8_t*)K, (uint8_t*)V, \
sizeof(K) - 1, sizeof(V) - 1, \
NGHTTP2_NV_FLAG_NONE}
#define MAKE_NV(K, V) \
{ \
(uint8_t *) K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
namespace shrpx {
namespace {
void check_nv(const Header& a, const nghttp2_nv *b)
{
void check_nv(const Header &a, const nghttp2_nv *b) {
CU_ASSERT(a.name.size() == b->namelen);
CU_ASSERT(a.value.size() == b->valuelen);
CU_ASSERT(memcmp(a.name.c_str(), b->name, b->namelen) == 0);
@ -53,69 +54,52 @@ void check_nv(const Header& a, const nghttp2_nv *b)
}
} // namespace
void test_http2_add_header(void)
{
void test_http2_add_header(void) {
auto nva = Headers();
http2::add_header(nva, (const uint8_t*)"alpha", 5,
(const uint8_t*)"123", 3, false);
http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"123", 3,
false);
CU_ASSERT(Headers::value_type("alpha", "123") == nva[0]);
CU_ASSERT(!nva[0].no_index);
nva.clear();
http2::add_header(nva, (const uint8_t*)"alpha", 5,
(const uint8_t*)"", 0, true);
http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"", 0,
true);
CU_ASSERT(Headers::value_type("alpha", "") == nva[0]);
CU_ASSERT(nva[0].no_index);
}
void test_http2_check_http2_headers(void)
{
auto nva1 = Headers{
{ "alpha", "1" },
{ "bravo", "2" },
{ "upgrade", "http2" }
};
void test_http2_check_http2_headers(void) {
auto nva1 = Headers{{"alpha", "1"}, {"bravo", "2"}, {"upgrade", "http2"}};
CU_ASSERT(!http2::check_http2_headers(nva1));
auto nva2 = Headers{
{ "connection", "1" },
{ "delta", "2" },
{ "echo", "3" }
};
auto nva2 = Headers{{"connection", "1"}, {"delta", "2"}, {"echo", "3"}};
CU_ASSERT(!http2::check_http2_headers(nva2));
auto nva3 = Headers{
{ "alpha", "1" },
{ "bravo", "2" },
{ "te2", "3" }
};
auto nva3 = Headers{{"alpha", "1"}, {"bravo", "2"}, {"te2", "3"}};
CU_ASSERT(http2::check_http2_headers(nva3));
auto n1 = ":authority";
auto n1u8 = reinterpret_cast<const uint8_t*>(n1);
auto n1u8 = reinterpret_cast<const uint8_t *>(n1);
CU_ASSERT(http2::check_http2_request_pseudo_header(n1u8, strlen(n1)));
CU_ASSERT(!http2::check_http2_response_pseudo_header(n1u8, strlen(n1)));
auto n2 = ":status";
auto n2u8 = reinterpret_cast<const uint8_t*>(n2);
auto n2u8 = reinterpret_cast<const uint8_t *>(n2);
CU_ASSERT(!http2::check_http2_request_pseudo_header(n2u8, strlen(n2)));
CU_ASSERT(http2::check_http2_response_pseudo_header(n2u8, strlen(n2)));
}
void test_http2_get_unique_header(void)
{
auto nva = Headers{
{ "alpha", "1" },
{ "bravo", "2" },
{ "bravo", "3" },
{ "charlie", "4" },
{ "delta", "5" },
{ "echo", "6" }
};
void test_http2_get_unique_header(void) {
auto nva = Headers{{"alpha", "1"},
{"bravo", "2"},
{"bravo", "3"},
{"charlie", "4"},
{"delta", "5"},
{"echo", "6"}};
const Headers::value_type *rv;
rv = http2::get_unique_header(nva, "delta");
CU_ASSERT(rv != nullptr);
@ -128,16 +112,13 @@ void test_http2_get_unique_header(void)
CU_ASSERT(rv == nullptr);
}
void test_http2_get_header(void)
{
auto nva = Headers{
{ "alpha", "1" },
{ "bravo", "2" },
{ "bravo", "3" },
{ "charlie", "4" },
{ "delta", "5" },
{ "echo", "6" }
};
void test_http2_get_header(void) {
auto nva = Headers{{"alpha", "1"},
{"bravo", "2"},
{"bravo", "3"},
{"charlie", "4"},
{"delta", "5"},
{"echo", "6"}};
const Headers::value_type *rv;
rv = http2::get_header(nva, "delta");
CU_ASSERT(rv != nullptr);
@ -151,15 +132,9 @@ void test_http2_get_header(void)
CU_ASSERT(rv == nullptr);
}
void test_http2_value_lws(void)
{
void test_http2_value_lws(void) {
auto nva = Headers{
{ "0", "alpha" },
{ "1", " alpha" },
{ "2", "" },
{" 3", " " },
{" 4", " a "}
};
{"0", "alpha"}, {"1", " alpha"}, {"2", ""}, {" 3", " "}, {" 4", " a "}};
CU_ASSERT(!http2::value_lws(&nva[0]));
CU_ASSERT(!http2::value_lws(&nva[1]));
CU_ASSERT(http2::value_lws(&nva[2]));
@ -168,32 +143,30 @@ void test_http2_value_lws(void)
}
namespace {
auto headers = Headers
{{"alpha", "0", true},
{"bravo", "1"},
{"connection", "2"},
{"connection", "3"},
{"delta", "4"},
{"expect", "5"},
{"foxtrot", "6"},
{"tango", "7"},
{"te", "8"},
{"te", "9"},
{"x-forwarded-proto", "10"},
{"x-forwarded-proto", "11"},
{"zulu", "12"}};
auto headers = Headers{{"alpha", "0", true},
{"bravo", "1"},
{"connection", "2"},
{"connection", "3"},
{"delta", "4"},
{"expect", "5"},
{"foxtrot", "6"},
{"tango", "7"},
{"te", "8"},
{"te", "9"},
{"x-forwarded-proto", "10"},
{"x-forwarded-proto", "11"},
{"zulu", "12"}};
} // namespace
void test_http2_copy_norm_headers_to_nva(void)
{
void test_http2_copy_norm_headers_to_nva(void) {
std::vector<nghttp2_nv> nva;
http2::copy_norm_headers_to_nva(nva, headers);
CU_ASSERT(7 == nva.size());
auto ans = std::vector<int>{0, 1, 4, 5, 6, 7, 12};
for(size_t i = 0; i < ans.size(); ++i) {
for (size_t i = 0; i < ans.size(); ++i) {
check_nv(headers[ans[i]], &nva[i]);
if(ans[i] == 0) {
if (ans[i] == 0) {
CU_ASSERT(nva[i].flags & NGHTTP2_NV_FLAG_NO_INDEX);
} else {
CU_ASSERT(NGHTTP2_NV_FLAG_NONE == nva[i].flags);
@ -201,20 +174,18 @@ void test_http2_copy_norm_headers_to_nva(void)
}
}
void test_http2_build_http1_headers_from_norm_headers(void)
{
void test_http2_build_http1_headers_from_norm_headers(void) {
std::string hdrs;
http2::build_http1_headers_from_norm_headers(hdrs, headers);
CU_ASSERT(hdrs ==
"Alpha: 0\r\n"
"Bravo: 1\r\n"
"Delta: 4\r\n"
"Expect: 5\r\n"
"Foxtrot: 6\r\n"
"Tango: 7\r\n"
"Te: 8\r\n"
"Te: 9\r\n"
"Zulu: 12\r\n");
CU_ASSERT(hdrs == "Alpha: 0\r\n"
"Bravo: 1\r\n"
"Delta: 4\r\n"
"Expect: 5\r\n"
"Foxtrot: 6\r\n"
"Tango: 7\r\n"
"Te: 8\r\n"
"Te: 9\r\n"
"Zulu: 12\r\n");
hdrs.clear();
// Both nghttp2 and spdylay do not allow \r and \n in header value
@ -226,62 +197,50 @@ void test_http2_build_http1_headers_from_norm_headers(void)
// CU_ASSERT(hdrs == "Alpha: bravo charlie \r\n");
}
void test_http2_lws(void)
{
void test_http2_lws(void) {
CU_ASSERT(!http2::lws("alpha"));
CU_ASSERT(http2::lws(" "));
CU_ASSERT(http2::lws(""));
}
namespace {
void check_rewrite_location_uri(const std::string& new_uri,
const std::string& uri,
const std::string& req_host,
const std::string& upstream_scheme,
uint16_t upstream_port)
{
void check_rewrite_location_uri(const std::string &new_uri,
const std::string &uri,
const std::string &req_host,
const std::string &upstream_scheme,
uint16_t upstream_port) {
http_parser_url u;
memset(&u, 0, sizeof(u));
CU_ASSERT(0 == http_parser_parse_url(uri.c_str(), uri.size(), 0, &u));
CU_ASSERT(new_uri ==
http2::rewrite_location_uri(uri, u, req_host,
upstream_scheme, upstream_port));
CU_ASSERT(new_uri == http2::rewrite_location_uri(
uri, u, req_host, upstream_scheme, upstream_port));
}
} // namespace
void test_http2_rewrite_location_uri(void)
{
void test_http2_rewrite_location_uri(void) {
check_rewrite_location_uri("https://localhost:3000/alpha?bravo#charlie",
"http://localhost:3001/alpha?bravo#charlie",
"localhost:3001", "https", 3000);
check_rewrite_location_uri("https://localhost/",
"http://localhost:3001/",
check_rewrite_location_uri("https://localhost/", "http://localhost:3001/",
"localhost:3001", "https", 443);
check_rewrite_location_uri("http://localhost/",
"http://localhost:3001/",
check_rewrite_location_uri("http://localhost/", "http://localhost:3001/",
"localhost:3001", "http", 80);
check_rewrite_location_uri("http://localhost:443/",
"http://localhost:3001/",
check_rewrite_location_uri("http://localhost:443/", "http://localhost:3001/",
"localhost:3001", "http", 443);
check_rewrite_location_uri("https://localhost:80/",
"http://localhost:3001/",
check_rewrite_location_uri("https://localhost:80/", "http://localhost:3001/",
"localhost:3001", "https", 80);
check_rewrite_location_uri("",
"http://localhost:3001/",
"127.0.0.1", "https", 3000);
check_rewrite_location_uri("", "http://localhost:3001/", "127.0.0.1", "https",
3000);
check_rewrite_location_uri("https://localhost:3000/",
"http://localhost:3001/",
"localhost", "https", 3000);
check_rewrite_location_uri("",
"https://localhost:3001/",
"localhost", "https", 3000);
check_rewrite_location_uri("https://localhost:3000/",
"http://localhost/",
"http://localhost:3001/", "localhost", "https",
3000);
check_rewrite_location_uri("", "https://localhost:3001/", "localhost",
"https", 3000);
check_rewrite_location_uri("https://localhost:3000/", "http://localhost/",
"localhost", "https", 3000);
}
void test_http2_parse_http_status_code(void)
{
void test_http2_parse_http_status_code(void) {
CU_ASSERT(200 == http2::parse_http_status_code("200"));
CU_ASSERT(102 == http2::parse_http_status_code("102"));
CU_ASSERT(-1 == http2::parse_http_status_code("099"));

View File

@ -40,7 +40,7 @@ struct header {
std::string value;
};
typedef std::function<void(const uint8_t*, std::size_t)> data_cb;
typedef std::function<void(const uint8_t *, std::size_t)> data_cb;
typedef std::function<void(void)> void_cb;
// Callback function to generate response body. The implementation of
@ -53,8 +53,8 @@ typedef std::function<void(void)> void_cb;
// callback until application calls response::resume(). This is
// useful when there is no data to send at the moment but there will
// be more to come in near future.
typedef std::function<std::pair<ssize_t, bool>
(uint8_t *buf, std::size_t len)> read_cb;
typedef std::function<std::pair<ssize_t, bool>(uint8_t *buf, std::size_t len)>
read_cb;
class channel_impl;
@ -71,12 +71,13 @@ public:
void post(void_cb cb);
// Application must not call this directly.
channel_impl& impl();
channel_impl &impl();
private:
std::unique_ptr<channel_impl> impl_;
};
typedef std::function<void(channel&)> thread_cb;
typedef std::function<void(channel &)> thread_cb;
namespace server {
@ -90,25 +91,25 @@ public:
// Returns request headers. The pusedo headers, which start with
// colon (;), are exluced from this list.
const std::vector<header>& headers() const;
const std::vector<header> &headers() const;
// Returns method (e.g., GET).
const std::string& method() const;
const std::string &method() const;
// Returns scheme (e.g., https).
const std::string& scheme() const;
const std::string &scheme() const;
// Returns authority (e.g., example.org). This could be empty
// string. In this case, check host().
const std::string& authority() const;
const std::string &authority() const;
// Returns host (e.g., example.org). If host header field is not
// present, this value is copied from authority().
const std::string& host() const;
const std::string &host() const;
// Returns path (e.g., /index.html).
const std::string& path() const;
const std::string &path() const;
// Sets callback when chunk of request body is received.
void on_data(data_cb cb);
@ -141,7 +142,8 @@ public:
bool run_task(thread_cb start);
// Application must not call this directly.
request_impl& impl();
request_impl &impl();
private:
std::unique_ptr<request_impl> impl_;
};
@ -173,15 +175,16 @@ public:
bool started() const;
// Application must not call this directly.
response_impl& impl();
response_impl &impl();
private:
std::unique_ptr<response_impl> impl_;
};
// This is so called request callback. Called every time request is
// received.
typedef std::function<void(const std::shared_ptr<request>&,
const std::shared_ptr<response>&)> request_cb;
typedef std::function<void(const std::shared_ptr<request> &,
const std::shared_ptr<response> &)> request_cb;
class http2_impl;
@ -192,8 +195,7 @@ public:
// Starts listening connection on given address and port. The
// incoming requests are handled by given callback |cb|.
void listen(const std::string& address, uint16_t port,
request_cb cb);
void listen(const std::string &address, uint16_t port, request_cb cb);
// Sets number of native threads to handle incoming HTTP request.
// It defaults to 1.
@ -212,6 +214,7 @@ public:
// Sets the maximum length to which the queue of pending
// connections.
void backlog(int backlog);
private:
std::unique_ptr<http2_impl> impl_;
};
@ -220,7 +223,7 @@ private:
// Convenient function to create function to read file denoted by
// |path|. This can be passed to response::end().
read_cb file_reader(const std::string& path);
read_cb file_reader(const std::string &path);
// Like file_reader(const std::string&), but it takes opened file
// descriptor. The passed descriptor will be closed when returned
@ -231,10 +234,10 @@ read_cb file_reader_from_fd(int fd);
// vector. Returns true if path is safe. The |path| must start with
// "/" otherwise returns false. This function should be called after
// percent-decode was performed.
bool check_path(const std::string& path);
bool check_path(const std::string &path);
// Performs percent-decode against string |s|.
std::string percent_decode(const std::string& s);
std::string percent_decode(const std::string &s);
// Returns HTTP date representation of current posix time |t|.
std::string http_date(int64_t t);

View File

@ -23,7 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif // HAVE_CONFIG_H
#include <unistd.h>
@ -45,57 +45,48 @@ extern "C" {
#include "nghttp2_frame.h"
#include "comp_helper.h"
}
typedef struct {
int dump_header_table;
} inflate_config;
typedef struct { int dump_header_table; } inflate_config;
static inflate_config config;
static uint8_t to_ud(char c)
{
if(c >= 'A' && c <= 'Z') {
static uint8_t to_ud(char c) {
if (c >= 'A' && c <= 'Z') {
return c - 'A' + 10;
} else if(c >= 'a' && c <= 'z') {
} else if (c >= 'a' && c <= 'z') {
return c - 'a' + 10;
} else {
return c - '0';
}
}
static void decode_hex(uint8_t *dest, const char *src, size_t len)
{
static void decode_hex(uint8_t *dest, const char *src, size_t len) {
size_t i;
for(i = 0; i < len; i += 2) {
for (i = 0; i < len; i += 2) {
*dest++ = to_ud(src[i]) << 4 | to_ud(src[i + 1]);
}
}
static void to_json(nghttp2_hd_inflater *inflater,
json_t *headers, json_t *wire, int seq,
size_t old_settings_table_size)
{
static void to_json(nghttp2_hd_inflater *inflater, json_t *headers,
json_t *wire, int seq, size_t old_settings_table_size) {
auto obj = json_object();
json_object_set_new(obj, "seq", json_integer(seq));
json_object_set(obj, "wire", wire);
json_object_set(obj, "headers", headers);
if(old_settings_table_size != inflater->settings_hd_table_bufsize_max) {
if (old_settings_table_size != inflater->settings_hd_table_bufsize_max) {
json_object_set_new(obj, "header_table_size",
json_integer(inflater->settings_hd_table_bufsize_max));
}
if(config.dump_header_table) {
json_object_set_new(obj, "header_table",
dump_header_table(&inflater->ctx));
if (config.dump_header_table) {
json_object_set_new(obj, "header_table", dump_header_table(&inflater->ctx));
}
json_dumpf(obj, stdout, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
json_decref(obj);
printf("\n");
}
static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
{
static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq) {
ssize_t rv;
nghttp2_nv nv;
int inflate_flags;
@ -103,15 +94,15 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
auto wire = json_object_get(obj, "wire");
if(wire == nullptr) {
if (wire == nullptr) {
fprintf(stderr, "'wire' key is missing at %d\n", seq);
return -1;
}
auto table_size = json_object_get(obj, "header_table_size");
if(table_size) {
if(!json_is_integer(table_size)) {
if (table_size) {
if (!json_is_integer(table_size)) {
fprintf(stderr,
"The value of 'header_table_size key' is not integer at %d\n",
seq);
@ -119,7 +110,7 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
}
rv = nghttp2_hd_inflate_change_table_size(inflater,
json_integer_value(table_size));
if(rv != 0) {
if (rv != 0) {
fprintf(stderr,
"nghttp2_hd_change_table_size() failed with error %s at %d\n",
nghttp2_strerror(rv), seq);
@ -129,7 +120,7 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
auto inputlen = strlen(json_string_value(wire));
if(inputlen & 1) {
if (inputlen & 1) {
fprintf(stderr, "Badly formatted output value at %d\n", seq);
exit(EXIT_FAILURE);
}
@ -142,20 +133,20 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
auto headers = json_array();
auto p = buf.data();
for(;;) {
for (;;) {
inflate_flags = 0;
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, p, buflen, 1);
if(rv < 0) {
if (rv < 0) {
fprintf(stderr, "inflate failed with error code %zd at %d\n", rv, seq);
exit(EXIT_FAILURE);
}
p += rv;
buflen -= rv;
if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
json_array_append_new(headers, dump_header(nv.name, nv.namelen,
nv.value, nv.valuelen));
if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
json_array_append_new(
headers, dump_header(nv.name, nv.namelen, nv.value, nv.valuelen));
}
if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
break;
}
}
@ -167,26 +158,25 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
return 0;
}
static int perform(void)
{
static int perform(void) {
nghttp2_hd_inflater inflater;
json_error_t error;
auto json = json_loadf(stdin, 0, &error);
if(json == nullptr) {
if (json == nullptr) {
fprintf(stderr, "JSON loading failed\n");
exit(EXIT_FAILURE);
}
auto cases = json_object_get(json, "cases");
if(cases == nullptr) {
if (cases == nullptr) {
fprintf(stderr, "Missing 'cases' key in root object\n");
exit(EXIT_FAILURE);
}
if(!json_is_array(cases)) {
if (!json_is_array(cases)) {
fprintf(stderr, "'cases' must be JSON array\n");
exit(EXIT_FAILURE);
}
@ -195,17 +185,16 @@ static int perform(void)
output_json_header();
auto len = json_array_size(cases);
for(size_t i = 0; i < len; ++i) {
for (size_t i = 0; i < len; ++i) {
auto obj = json_array_get(cases, i);
if(!json_is_object(obj)) {
fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n",
i);
if (!json_is_object(obj)) {
fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n", i);
continue;
}
if(inflate_hd(obj, &inflater, i) != 0) {
if (inflate_hd(obj, &inflater, i) != 0) {
continue;
}
if(i + 1 < len) {
if (i + 1 < len) {
printf(",\n");
}
}
@ -216,8 +205,7 @@ static int perform(void)
return 0;
}
static void print_help(void)
{
static void print_help(void) {
std::cout << R"(HPACK HTTP/2 header decoder
Usage: inflatehd [OPTIONS] < INPUT
@ -248,25 +236,22 @@ The output of this program can be used as input for deflatehd.
OPTIONS:
-d, --dump-header-table
Output dynamic header table.)"
<< std::endl;;
Output dynamic header table.)" << std::endl;
;
}
static struct option long_options[] = {
{"dump-header-table", no_argument, nullptr, 'd'},
{nullptr, 0, nullptr, 0 }
};
{"dump-header-table", no_argument, nullptr, 'd'}, {nullptr, 0, nullptr, 0}};
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
config.dump_header_table = 0;
while(1) {
while (1) {
int option_index = 0;
int c = getopt_long(argc, argv, "dh", long_options, &option_index);
if(c == -1) {
if (c == -1) {
break;
}
switch(c) {
switch (c) {
case 'h':
print_help();
exit(EXIT_SUCCESS);

View File

@ -32,32 +32,19 @@ namespace nghttp2 {
namespace util {
EvbufferBuffer::EvbufferBuffer()
: evbuffer_(nullptr),
bucket_(nullptr),
buf_(nullptr),
bufmax_(0),
buflen_(0),
limit_(0),
writelen_(0)
{}
: evbuffer_(nullptr), bucket_(nullptr), buf_(nullptr), bufmax_(0),
buflen_(0), limit_(0), writelen_(0) {}
EvbufferBuffer::EvbufferBuffer(evbuffer *evbuffer, uint8_t *buf, size_t bufmax,
ssize_t limit)
: evbuffer_(evbuffer),
bucket_(limit == -1 ? nullptr : evbuffer_new()),
buf_(buf),
bufmax_(bufmax),
buflen_(0),
limit_(limit),
writelen_(0)
{}
: evbuffer_(evbuffer), bucket_(limit == -1 ? nullptr : evbuffer_new()),
buf_(buf), bufmax_(bufmax), buflen_(0), limit_(limit), writelen_(0) {}
void EvbufferBuffer::reset(evbuffer *evbuffer, uint8_t *buf, size_t bufmax,
ssize_t limit)
{
ssize_t limit) {
evbuffer_ = evbuffer;
buf_ = buf;
if(limit != -1 && !bucket_) {
if (limit != -1 && !bucket_) {
bucket_ = evbuffer_new();
}
bufmax_ = bufmax;
@ -66,25 +53,23 @@ void EvbufferBuffer::reset(evbuffer *evbuffer, uint8_t *buf, size_t bufmax,
writelen_ = 0;
}
EvbufferBuffer::~EvbufferBuffer()
{
if(bucket_) {
EvbufferBuffer::~EvbufferBuffer() {
if (bucket_) {
evbuffer_free(bucket_);
}
}
int EvbufferBuffer::write_buffer()
{
for(auto pos = buf_, end = buf_ + buflen_; pos < end;) {
int EvbufferBuffer::write_buffer() {
for (auto pos = buf_, end = buf_ + buflen_; pos < end;) {
// To avoid merging chunks in evbuffer, we first add to temporal
// buffer bucket_ and then move its chain to evbuffer_.
auto nwrite = std::min(end - pos, limit_);
auto rv = evbuffer_add(bucket_, pos, nwrite);
if(rv == -1) {
if (rv == -1) {
return -1;
}
rv = evbuffer_add_buffer(evbuffer_, bucket_);
if(rv == -1) {
if (rv == -1) {
return -1;
}
pos += nwrite;
@ -92,16 +77,15 @@ int EvbufferBuffer::write_buffer()
return 0;
}
int EvbufferBuffer::flush()
{
int EvbufferBuffer::flush() {
int rv;
if(buflen_ > 0) {
if(limit_ == -1) {
if (buflen_ > 0) {
if (limit_ == -1) {
rv = evbuffer_add(evbuffer_, buf_, buflen_);
} else {
rv = write_buffer();
}
if(rv == -1) {
if (rv == -1) {
return -1;
}
writelen_ += buflen_;
@ -110,29 +94,28 @@ int EvbufferBuffer::flush()
return 0;
}
int EvbufferBuffer::add(const uint8_t *data, size_t datalen)
{
int EvbufferBuffer::add(const uint8_t *data, size_t datalen) {
int rv;
if(buflen_ + datalen > bufmax_) {
if(buflen_ > 0) {
if(limit_ == -1) {
if (buflen_ + datalen > bufmax_) {
if (buflen_ > 0) {
if (limit_ == -1) {
rv = evbuffer_add(evbuffer_, buf_, buflen_);
} else {
rv = write_buffer();
}
if(rv == -1) {
if (rv == -1) {
return -1;
}
writelen_ += buflen_;
buflen_ = 0;
}
if(datalen > bufmax_) {
if(limit_ == -1) {
if (datalen > bufmax_) {
if (limit_ == -1) {
rv = evbuffer_add(evbuffer_, data, datalen);
} else {
rv = write_buffer();
}
if(rv == -1) {
if (rv == -1) {
return -1;
}
writelen_ += buflen_;
@ -144,28 +127,20 @@ int EvbufferBuffer::add(const uint8_t *data, size_t datalen)
return 0;
}
size_t EvbufferBuffer::get_buflen() const
{
return buflen_;
}
size_t EvbufferBuffer::get_buflen() const { return buflen_; }
size_t EvbufferBuffer::get_writelen() const
{
return writelen_;
}
size_t EvbufferBuffer::get_writelen() const { return writelen_; }
void bev_enable_unless(bufferevent *bev, int events)
{
if((bufferevent_get_enabled(bev) & events) == events) {
void bev_enable_unless(bufferevent *bev, int events) {
if ((bufferevent_get_enabled(bev) & events) == events) {
return;
}
bufferevent_enable(bev, events);
}
void bev_disable_unless(bufferevent *bev, int events)
{
if((bufferevent_get_enabled(bev) & events) == 0) {
void bev_disable_unless(bufferevent *bev, int events) {
if ((bufferevent_get_enabled(bev) & events) == 0) {
return;
}

View File

@ -51,6 +51,7 @@ public:
// Returns the number of written bytes to evbuffer_ so far. reset()
// resets this value to 0.
size_t get_writelen() const;
private:
evbuffer *evbuffer_;
evbuffer *bucket_;

File diff suppressed because it is too large Load Diff

View File

@ -26,13 +26,13 @@
#define NGHTTP2_CONFIG_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif // HAVE_CONFIG_H
// gcc 4.6 has std::chrono::monotonic_clock, which was renamed as
// std::chrono::steady_clock in C++11 standard.
#ifndef HAVE_STEADY_CLOCK
# define steady_clock monotonic_clock
#define steady_clock monotonic_clock
#endif // !HAVE_STEADY_CLOCK
#endif // NGHTTP2_CONFIG_H

View File

@ -26,11 +26,10 @@
#include <assert.h>
int nghttp2_gzip_inflate_new(nghttp2_gzip **inflater_ptr)
{
int nghttp2_gzip_inflate_new(nghttp2_gzip **inflater_ptr) {
int rv;
*inflater_ptr = malloc(sizeof(nghttp2_gzip));
if(*inflater_ptr == NULL) {
if (*inflater_ptr == NULL) {
return -1;
}
(*inflater_ptr)->finished = 0;
@ -40,31 +39,29 @@ int nghttp2_gzip_inflate_new(nghttp2_gzip **inflater_ptr)
(*inflater_ptr)->zst.zfree = Z_NULL;
(*inflater_ptr)->zst.opaque = Z_NULL;
rv = inflateInit2(&(*inflater_ptr)->zst, 47);
if(rv != Z_OK) {
if (rv != Z_OK) {
free(*inflater_ptr);
return -1;
}
return 0;
}
void nghttp2_gzip_inflate_del(nghttp2_gzip *inflater)
{
if(inflater != NULL) {
void nghttp2_gzip_inflate_del(nghttp2_gzip *inflater) {
if (inflater != NULL) {
inflateEnd(&inflater->zst);
free(inflater);
}
}
int nghttp2_gzip_inflate(nghttp2_gzip *inflater,
uint8_t *out, size_t *outlen_ptr,
const uint8_t *in, size_t *inlen_ptr)
{
int nghttp2_gzip_inflate(nghttp2_gzip *inflater, uint8_t *out,
size_t *outlen_ptr, const uint8_t *in,
size_t *inlen_ptr) {
int rv;
if(inflater->finished) {
if (inflater->finished) {
return -1;
}
inflater->zst.avail_in = (unsigned int)*inlen_ptr;
inflater->zst.next_in = (unsigned char*)in;
inflater->zst.next_in = (unsigned char *)in;
inflater->zst.avail_out = (unsigned int)*outlen_ptr;
inflater->zst.next_out = out;
@ -72,7 +69,7 @@ int nghttp2_gzip_inflate(nghttp2_gzip *inflater,
*inlen_ptr -= inflater->zst.avail_in;
*outlen_ptr -= inflater->zst.avail_out;
switch(rv) {
switch (rv) {
case Z_STREAM_END:
inflater->finished = 1;
case Z_OK:
@ -90,7 +87,6 @@ int nghttp2_gzip_inflate(nghttp2_gzip *inflater,
}
}
int nghttp2_gzip_inflate_finished(nghttp2_gzip *inflater)
{
int nghttp2_gzip_inflate_finished(nghttp2_gzip *inflater) {
return inflater->finished;
}

View File

@ -25,13 +25,13 @@
#ifndef NGHTTP2_GZIP_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <zlib.h>
#include <nghttp2/nghttp2.h>
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@ -102,9 +102,9 @@ void nghttp2_gzip_inflate_del(nghttp2_gzip *inflater);
* ....
* }
*/
int nghttp2_gzip_inflate(nghttp2_gzip *inflater,
uint8_t *out, size_t *outlen_ptr,
const uint8_t *in, size_t *inlen_ptr);
int nghttp2_gzip_inflate(nghttp2_gzip *inflater, uint8_t *out,
size_t *outlen_ptr, const uint8_t *in,
size_t *inlen_ptr);
/**
* @function

View File

@ -33,9 +33,8 @@
#include "nghttp2_gzip.h"
static ssize_t deflate_data(uint8_t *out, size_t outlen,
const uint8_t *in, size_t inlen)
{
static ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
size_t inlen) {
int rv;
z_stream zst;
zst.next_in = Z_NULL;
@ -47,7 +46,7 @@ static ssize_t deflate_data(uint8_t *out, size_t outlen,
assert(rv == Z_OK);
zst.avail_in = (unsigned int)inlen;
zst.next_in = (uint8_t*)in;
zst.next_in = (uint8_t *)in;
zst.avail_out = (unsigned int)outlen;
zst.next_out = out;
rv = deflate(&zst, Z_SYNC_FLUSH);
@ -55,35 +54,34 @@ static ssize_t deflate_data(uint8_t *out, size_t outlen,
deflateEnd(&zst);
return outlen-zst.avail_out;
return outlen - zst.avail_out;
}
static const char input[] =
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND "
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND "
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE "
"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION "
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION "
"WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.";
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND "
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND "
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE "
"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION "
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION "
"WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.";
void test_nghttp2_gzip_inflate(void)
{
void test_nghttp2_gzip_inflate(void) {
nghttp2_gzip *inflater;
uint8_t in[4096], out[4096], *inptr;
size_t inlen = sizeof(in);
size_t inproclen, outproclen;
const char *inputptr = input;
inlen = deflate_data(in, inlen, (const uint8_t*)input, sizeof(input)-1);
inlen = deflate_data(in, inlen, (const uint8_t *)input, sizeof(input) - 1);
CU_ASSERT(0 == nghttp2_gzip_inflate_new(&inflater));
/* First 16 bytes */
inptr = in;
inproclen = inlen;
outproclen = 16;
CU_ASSERT(0 == nghttp2_gzip_inflate(inflater, out, &outproclen,
inptr, &inproclen));
CU_ASSERT(
0 == nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
CU_ASSERT(16 == outproclen);
CU_ASSERT(inproclen > 0);
CU_ASSERT(0 == memcmp(inputptr, out, outproclen));
@ -93,8 +91,8 @@ void test_nghttp2_gzip_inflate(void)
inproclen = inlen;
inputptr += outproclen;
outproclen = 32;
CU_ASSERT(0 == nghttp2_gzip_inflate(inflater, out, &outproclen,
inptr, &inproclen));
CU_ASSERT(
0 == nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
CU_ASSERT(32 == outproclen);
CU_ASSERT(inproclen > 0);
CU_ASSERT(0 == memcmp(inputptr, out, outproclen));
@ -104,9 +102,9 @@ void test_nghttp2_gzip_inflate(void)
inproclen = inlen;
inputptr += outproclen;
outproclen = sizeof(out);
CU_ASSERT(0 == nghttp2_gzip_inflate(inflater, out, &outproclen,
inptr, &inproclen));
CU_ASSERT(sizeof(input)-49 == outproclen);
CU_ASSERT(
0 == nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
CU_ASSERT(sizeof(input) - 49 == outproclen);
CU_ASSERT(inproclen > 0);
CU_ASSERT(0 == memcmp(inputptr, out, outproclen));

View File

@ -25,7 +25,7 @@
#ifndef NGHTTP2_GZIP_TEST_H
#define NGHTTP2_GZIP_TEST_H
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -48,22 +48,21 @@
namespace nghttp2 {
namespace {
int parse_push_config(Config& config, const char *optarg)
{
int parse_push_config(Config &config, const char *optarg) {
const char *eq = strchr(optarg, '=');
if(eq == NULL) {
if (eq == NULL) {
return -1;
}
auto paths = std::vector<std::string>();
auto optarg_end = optarg + strlen(optarg);
const char *i = eq + 1;
for(;;) {
for (;;) {
const char *j = strchr(i, ',');
if(j == NULL) {
if (j == NULL) {
j = optarg_end;
}
paths.emplace_back(i, j);
if(j == optarg_end) {
if (j == optarg_end) {
break;
}
i = j;
@ -75,15 +74,13 @@ int parse_push_config(Config& config, const char *optarg)
} // namespace
namespace {
void print_version(std::ostream& out)
{
void print_version(std::ostream &out) {
out << "nghttpd nghttp2/" NGHTTP2_VERSION << std::endl;
}
} // namespace
namespace {
void print_usage(std::ostream& out)
{
void print_usage(std::ostream &out) {
out << "Usage: nghttpd [OPTION]... <PORT> <PRIVATE_KEY> <CERT>\n"
<< " or: nghttpd --no-tls [OPTION]... <PORT>\n"
<< "HTTP/2 experimental server" << std::endl;
@ -91,8 +88,7 @@ void print_usage(std::ostream& out)
} // namespace
namespace {
void print_help(std::ostream& out)
{
void print_help(std::ostream &out) {
print_usage(out);
out << R"(
<PORT> Specify listening port number.
@ -142,43 +138,40 @@ Options:
received, rather than complete request is
received.
--version Display version information and exit.
-h, --help Display this help and exit.)"
<< std::endl;
-h, --help Display this help and exit.)" << std::endl;
}
} // namespace
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
Config config;
bool color = false;
while(1) {
while (1) {
static int flag = 0;
static option long_options[] = {
{"daemon", no_argument, nullptr, 'D'},
{"htdocs", required_argument, nullptr, 'd'},
{"help", no_argument, nullptr, 'h'},
{"verbose", no_argument, nullptr, 'v'},
{"verify-client", no_argument, nullptr, 'V'},
{"header-table-size", required_argument, nullptr, 'c'},
{"push", required_argument, nullptr, 'p'},
{"padding", required_argument, nullptr, 'b'},
{"workers", required_argument, nullptr, 'n'},
{"error-gzip", no_argument, nullptr, 'e'},
{"no-tls", no_argument, &flag, 1},
{"color", no_argument, &flag, 2},
{"version", no_argument, &flag, 3},
{"dh-param-file", required_argument, &flag, 4},
{"early-response", no_argument, &flag, 5},
{nullptr, 0, nullptr, 0}
};
{"daemon", no_argument, nullptr, 'D'},
{"htdocs", required_argument, nullptr, 'd'},
{"help", no_argument, nullptr, 'h'},
{"verbose", no_argument, nullptr, 'v'},
{"verify-client", no_argument, nullptr, 'V'},
{"header-table-size", required_argument, nullptr, 'c'},
{"push", required_argument, nullptr, 'p'},
{"padding", required_argument, nullptr, 'b'},
{"workers", required_argument, nullptr, 'n'},
{"error-gzip", no_argument, nullptr, 'e'},
{"no-tls", no_argument, &flag, 1},
{"color", no_argument, &flag, 2},
{"version", no_argument, &flag, 3},
{"dh-param-file", required_argument, &flag, 4},
{"early-response", no_argument, &flag, 5},
{nullptr, 0, nullptr, 0}};
int option_index = 0;
int c = getopt_long(argc, argv, "DVb:c:d:ehn:p:v", long_options,
&option_index);
int c =
getopt_long(argc, argv, "DVb:c:d:ehn:p:v", long_options, &option_index);
char *end;
if(c == -1) {
if (c == -1) {
break;
}
switch(c) {
switch (c) {
case 'D':
config.daemon = true;
break;
@ -196,12 +189,12 @@ int main(int argc, char **argv)
break;
case 'n':
#ifdef NOTHREADS
std::cerr << "-n: WARNING: Threading disabled at build time, " <<
"no threads created." << std::endl;
std::cerr << "-n: WARNING: Threading disabled at build time, "
<< "no threads created." << std::endl;
#else
errno = 0;
config.num_worker = strtoul(optarg, &end, 10);
if(errno == ERANGE || *end != '\0' || config.num_worker == 0) {
if (errno == ERANGE || *end != '\0' || config.num_worker == 0) {
std::cerr << "-n: Bad option value: " << optarg << std::endl;
exit(EXIT_FAILURE);
}
@ -216,13 +209,13 @@ int main(int argc, char **argv)
case 'c':
errno = 0;
config.header_table_size = strtol(optarg, &end, 10);
if(errno == ERANGE || *end != '\0') {
if (errno == ERANGE || *end != '\0') {
std::cerr << "-c: Bad option value: " << optarg << std::endl;
exit(EXIT_FAILURE);
}
break;
case 'p':
if(parse_push_config(config, optarg) != 0) {
if (parse_push_config(config, optarg) != 0) {
std::cerr << "-p: Bad option value: " << optarg << std::endl;
}
break;
@ -230,7 +223,7 @@ int main(int argc, char **argv)
util::show_candidates(argv[optind - 1], long_options);
exit(EXIT_FAILURE);
case 0:
switch(flag) {
switch (flag) {
case 1:
// no-tls option
config.no_tls = true;
@ -257,7 +250,7 @@ int main(int argc, char **argv)
break;
}
}
if(argc - optind < (config.no_tls ? 1 : 3)) {
if (argc - optind < (config.no_tls ? 1 : 3)) {
print_usage(std::cerr);
std::cerr << "Too few arguments" << std::endl;
exit(EXIT_FAILURE);
@ -265,23 +258,23 @@ int main(int argc, char **argv)
config.port = strtol(argv[optind++], nullptr, 10);
if(!config.no_tls) {
if (!config.no_tls) {
config.private_key_file = argv[optind++];
config.cert_file = argv[optind++];
}
if(config.daemon) {
if(config.htdocs.empty()) {
if (config.daemon) {
if (config.htdocs.empty()) {
print_usage(std::cerr);
std::cerr << "-d option must be specified when -D is used." << std::endl;
exit(EXIT_FAILURE);
}
if(daemon(0, 0) == -1) {
if (daemon(0, 0) == -1) {
perror("daemon");
exit(EXIT_FAILURE);
}
}
if(config.htdocs.empty()) {
if (config.htdocs.empty()) {
config.htdocs = "./";
}
@ -308,7 +301,4 @@ int main(int argc, char **argv)
} // namespace nghttp2
int main(int argc, char **argv)
{
return nghttp2::main(argc, argv);
}
int main(int argc, char **argv) { return nghttp2::main(argc, argv); }

View File

@ -23,7 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
@ -39,39 +39,31 @@
#include "util_test.h"
#include "nghttp2_gzip_test.h"
static int init_suite1(void)
{
return 0;
}
static int init_suite1(void) { return 0; }
static int clean_suite1(void)
{
return 0;
}
static int clean_suite1(void) { return 0; }
int main(int argc, char *argv[]) {
CU_pSuite pSuite = NULL;
unsigned int num_tests_failed;
int main(int argc, char* argv[])
{
CU_pSuite pSuite = NULL;
unsigned int num_tests_failed;
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();
// initialize the CUnit test registry
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
// initialize the CUnit test registry
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
// add a suite to the registry
pSuite = CU_add_suite("shrpx_TestSuite", init_suite1, clean_suite1);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
// add a suite to the registry
pSuite = CU_add_suite("shrpx_TestSuite", init_suite1, clean_suite1);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
// add the tests to the suite
if(!CU_add_test(pSuite, "ssl_create_lookup_tree",
// add the tests to the suite
if (!CU_add_test(pSuite, "ssl_create_lookup_tree",
shrpx::test_shrpx_ssl_create_lookup_tree) ||
!CU_add_test(pSuite, "ssl_cert_lookup_tree_add_cert_from_file",
shrpx::test_shrpx_ssl_cert_lookup_tree_add_cert_from_file) ||
@ -80,16 +72,13 @@ int main(int argc, char* argv[])
shrpx::test_http2_check_http2_headers) ||
!CU_add_test(pSuite, "http2_get_unique_header",
shrpx::test_http2_get_unique_header) ||
!CU_add_test(pSuite, "http2_get_header",
shrpx::test_http2_get_header) ||
!CU_add_test(pSuite, "http2_value_lws",
shrpx::test_http2_value_lws) ||
!CU_add_test(pSuite, "http2_get_header", shrpx::test_http2_get_header) ||
!CU_add_test(pSuite, "http2_value_lws", shrpx::test_http2_value_lws) ||
!CU_add_test(pSuite, "http2_copy_norm_headers_to_nva",
shrpx::test_http2_copy_norm_headers_to_nva) ||
!CU_add_test(pSuite, "http2_build_http1_headers_from_norm_headers",
shrpx::test_http2_build_http1_headers_from_norm_headers) ||
!CU_add_test(pSuite, "http2_lws",
shrpx::test_http2_lws) ||
!CU_add_test(pSuite, "http2_lws", shrpx::test_http2_lws) ||
!CU_add_test(pSuite, "http2_rewrite_location_uri",
shrpx::test_http2_rewrite_location_uri) ||
!CU_add_test(pSuite, "http2_parse_http_status_code",
@ -106,8 +95,9 @@ int main(int argc, char* argv[])
shrpx::test_downstream_crumble_request_cookie) ||
!CU_add_test(pSuite, "downstream_assemble_request_cookie",
shrpx::test_downstream_assemble_request_cookie) ||
!CU_add_test(pSuite, "downstream_rewrite_norm_location_response_header",
shrpx::test_downstream_rewrite_norm_location_response_header) ||
!CU_add_test(
pSuite, "downstream_rewrite_norm_location_response_header",
shrpx::test_downstream_rewrite_norm_location_response_header) ||
!CU_add_test(pSuite, "config_parse_config_str_list",
shrpx::test_shrpx_config_parse_config_str_list) ||
!CU_add_test(pSuite, "config_parse_header",
@ -118,8 +108,7 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "util_strieq", shrpx::test_util_strieq) ||
!CU_add_test(pSuite, "util_inp_strlower",
shrpx::test_util_inp_strlower) ||
!CU_add_test(pSuite, "util_to_base64",
shrpx::test_util_to_base64) ||
!CU_add_test(pSuite, "util_to_base64", shrpx::test_util_to_base64) ||
!CU_add_test(pSuite, "util_percent_encode_token",
shrpx::test_util_percent_encode_token) ||
!CU_add_test(pSuite, "util_quote_string",
@ -127,19 +116,19 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "util_utox", shrpx::test_util_utox) ||
!CU_add_test(pSuite, "util_http_date", shrpx::test_util_http_date) ||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate)) {
CU_cleanup_registry();
return CU_get_error();
}
CU_cleanup_registry();
return CU_get_error();
}
// Run all tests using the CUnit Basic interface
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
num_tests_failed = CU_get_number_of_tests_failed();
CU_cleanup_registry();
if(CU_get_error() == CUE_SUCCESS) {
return num_tests_failed;
} else {
printf("CUnit Error: %s\n", CU_get_error_msg());
return CU_get_error();
}
// Run all tests using the CUnit Basic interface
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
num_tests_failed = CU_get_number_of_tests_failed();
CU_cleanup_registry();
if (CU_get_error() == CUE_SUCCESS) {
return num_tests_failed;
} else {
printf("CUnit Error: %s\n", CU_get_error_msg());
return CU_get_error();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
#define SHRPX_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif // HAVE_CONFIG_H
#include <sys/types.h>

View File

@ -49,91 +49,87 @@ using namespace nghttp2;
namespace shrpx {
namespace {
void upstream_readcb(bufferevent *bev, void *arg)
{
auto handler = static_cast<ClientHandler*>(arg);
void upstream_readcb(bufferevent *bev, void *arg) {
auto handler = static_cast<ClientHandler *>(arg);
auto upstream = handler->get_upstream();
if(upstream) {
if (upstream) {
upstream->reset_timeouts();
}
int rv = handler->on_read();
if(rv != 0) {
if (rv != 0) {
delete handler;
}
}
} // namespace
namespace {
void upstream_writecb(bufferevent *bev, void *arg)
{
auto handler = static_cast<ClientHandler*>(arg);
void upstream_writecb(bufferevent *bev, void *arg) {
auto handler = static_cast<ClientHandler *>(arg);
auto upstream = handler->get_upstream();
if(upstream) {
if (upstream) {
upstream->reset_timeouts();
}
handler->update_last_write_time();
// We actually depend on write low-water mark == 0.
if(handler->get_outbuf_length() > 0) {
if (handler->get_outbuf_length() > 0) {
// Possibly because of deferred callback, we may get this callback
// when the output buffer is not empty.
return;
}
if(handler->get_should_close_after_write()) {
if (handler->get_should_close_after_write()) {
delete handler;
return;
}
if(!upstream) {
if (!upstream) {
return;
}
int rv = upstream->on_write();
if(rv != 0) {
if (rv != 0) {
delete handler;
}
}
} // namespace
namespace {
void upstream_eventcb(bufferevent *bev, short events, void *arg)
{
auto handler = static_cast<ClientHandler*>(arg);
void upstream_eventcb(bufferevent *bev, short events, void *arg) {
auto handler = static_cast<ClientHandler *>(arg);
bool finish = false;
if(events & BEV_EVENT_EOF) {
if(LOG_ENABLED(INFO)) {
if (events & BEV_EVENT_EOF) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, handler) << "EOF";
}
finish = true;
}
if(events & BEV_EVENT_ERROR) {
if(LOG_ENABLED(INFO)) {
CLOG(INFO, handler) << "Network error: "
<< evutil_socket_error_to_string
(EVUTIL_SOCKET_ERROR());
if (events & BEV_EVENT_ERROR) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, handler) << "Network error: " << evutil_socket_error_to_string(
EVUTIL_SOCKET_ERROR());
}
finish = true;
}
if(events & BEV_EVENT_TIMEOUT) {
if(LOG_ENABLED(INFO)) {
if (events & BEV_EVENT_TIMEOUT) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, handler) << "Time out";
}
finish = true;
}
if(finish) {
if (finish) {
delete handler;
} else {
if(events & BEV_EVENT_CONNECTED) {
if (events & BEV_EVENT_CONNECTED) {
handler->set_tls_handshake(true);
if(LOG_ENABLED(INFO)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, handler) << "SSL/TLS handshake completed";
}
if(handler->validate_next_proto() != 0) {
if (handler->validate_next_proto() != 0) {
delete handler;
return;
}
if(LOG_ENABLED(INFO)) {
if(SSL_session_reused(handler->get_ssl())) {
if (LOG_ENABLED(INFO)) {
if (SSL_session_reused(handler->get_ssl())) {
CLOG(INFO, handler) << "SSL/TLS session reused";
}
}
@ -143,22 +139,20 @@ void upstream_eventcb(bufferevent *bev, short events, void *arg)
} // namespace
namespace {
void upstream_http2_connhd_readcb(bufferevent *bev, void *arg)
{
void upstream_http2_connhd_readcb(bufferevent *bev, void *arg) {
// This callback assumes upstream is Http2Upstream.
auto handler = static_cast<ClientHandler*>(arg);
if(handler->on_http2_connhd_read() != 0) {
auto handler = static_cast<ClientHandler *>(arg);
if (handler->on_http2_connhd_read() != 0) {
delete handler;
}
}
} // namespace
namespace {
void upstream_http1_connhd_readcb(bufferevent *bev, void *arg)
{
void upstream_http1_connhd_readcb(bufferevent *bev, void *arg) {
// This callback assumes upstream is HttpsUpstream.
auto handler = static_cast<ClientHandler*>(arg);
if(handler->on_http1_connhd_read() != 0) {
auto handler = static_cast<ClientHandler *>(arg);
if (handler->on_http1_connhd_read() != 0) {
delete handler;
}
}
@ -166,38 +160,26 @@ void upstream_http1_connhd_readcb(bufferevent *bev, void *arg)
ClientHandler::ClientHandler(bufferevent *bev,
bufferevent_rate_limit_group *rate_limit_group,
int fd, SSL *ssl,
const char *ipaddr,
const char *port,
WorkerStat *worker_stat,
int fd, SSL *ssl, const char *ipaddr,
const char *port, WorkerStat *worker_stat,
DownstreamConnectionPool *dconn_pool)
: ipaddr_(ipaddr),
port_(port),
dconn_pool_(dconn_pool),
bev_(bev),
http2session_(nullptr),
ssl_(ssl),
reneg_shutdown_timerev_(nullptr),
worker_stat_(worker_stat),
last_write_time_(0),
warmup_writelen_(0),
left_connhd_len_(NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN),
fd_(fd),
should_close_after_write_(false),
tls_handshake_(false),
tls_renegotiation_(false)
{
: ipaddr_(ipaddr), port_(port), dconn_pool_(dconn_pool), bev_(bev),
http2session_(nullptr), ssl_(ssl), reneg_shutdown_timerev_(nullptr),
worker_stat_(worker_stat), last_write_time_(0), warmup_writelen_(0),
left_connhd_len_(NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN), fd_(fd),
should_close_after_write_(false), tls_handshake_(false),
tls_renegotiation_(false) {
int rv;
++worker_stat->num_connections;
rv = bufferevent_set_rate_limit(bev_, get_config()->rate_limit_cfg);
if(rv == -1) {
if (rv == -1) {
CLOG(FATAL, this) << "bufferevent_set_rate_limit() failed";
}
rv = bufferevent_add_to_rate_limit_group(bev_, rate_limit_group);
if(rv == -1) {
if (rv == -1) {
CLOG(FATAL, this) << "bufferevent_add_to_rate_limit_group() failed";
}
@ -205,8 +187,8 @@ ClientHandler::ClientHandler(bufferevent *bev,
bufferevent_setwatermark(bev_, EV_READ, 0, SHRPX_READ_WATERMARK);
set_upstream_timeouts(&get_config()->upstream_read_timeout,
&get_config()->upstream_write_timeout);
if(ssl_) {
SSL_set_app_data(ssl_, reinterpret_cast<char*>(this));
if (ssl_) {
SSL_set_app_data(ssl_, reinterpret_cast<char *>(this));
set_bev_cb(nullptr, upstream_writecb, upstream_eventcb);
} else {
// For non-TLS version, first create HttpsUpstream. It may be
@ -218,13 +200,12 @@ ClientHandler::ClientHandler(bufferevent *bev,
}
}
ClientHandler::~ClientHandler()
{
if(LOG_ENABLED(INFO)) {
ClientHandler::~ClientHandler() {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Deleting";
}
if(upstream_) {
if (upstream_) {
upstream_->on_handler_delete();
}
@ -232,15 +213,15 @@ ClientHandler::~ClientHandler()
// TODO If backend is http/2, and it is in CONNECTED state, signal
// it and make it loopbreak when output is zero.
if(worker_config->graceful_shutdown && worker_stat_->num_connections == 0) {
if (worker_config->graceful_shutdown && worker_stat_->num_connections == 0) {
event_base_loopbreak(get_evbase());
}
if(reneg_shutdown_timerev_) {
if (reneg_shutdown_timerev_) {
event_free(reneg_shutdown_timerev_);
}
if(ssl_) {
if (ssl_) {
SSL_set_app_data(ssl_, nullptr);
SSL_set_shutdown(ssl_, SSL_RECEIVED_SHUTDOWN);
SSL_shutdown(ssl_);
@ -251,47 +232,37 @@ ClientHandler::~ClientHandler()
util::bev_disable_unless(bev_, EV_READ | EV_WRITE);
bufferevent_free(bev_);
if(ssl_) {
if (ssl_) {
SSL_free(ssl_);
}
shutdown(fd_, SHUT_WR);
close(fd_);
if(LOG_ENABLED(INFO)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Deleted";
}
}
Upstream* ClientHandler::get_upstream()
{
return upstream_.get();
}
Upstream *ClientHandler::get_upstream() { return upstream_.get(); }
bufferevent* ClientHandler::get_bev() const
{
return bev_;
}
bufferevent *ClientHandler::get_bev() const { return bev_; }
event_base* ClientHandler::get_evbase() const
{
event_base *ClientHandler::get_evbase() const {
return bufferevent_get_base(bev_);
}
void ClientHandler::set_bev_cb
(bufferevent_data_cb readcb, bufferevent_data_cb writecb,
bufferevent_event_cb eventcb)
{
void ClientHandler::set_bev_cb(bufferevent_data_cb readcb,
bufferevent_data_cb writecb,
bufferevent_event_cb eventcb) {
bufferevent_setcb(bev_, readcb, writecb, eventcb, this);
}
void ClientHandler::set_upstream_timeouts(const timeval *read_timeout,
const timeval *write_timeout)
{
const timeval *write_timeout) {
bufferevent_set_timeouts(bev_, read_timeout, write_timeout);
}
int ClientHandler::validate_next_proto()
{
int ClientHandler::validate_next_proto() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
int rv;
@ -299,27 +270,27 @@ int ClientHandler::validate_next_proto()
// First set callback for catch all cases
set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb);
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
for(int i = 0; i < 2; ++i) {
if(next_proto) {
if(LOG_ENABLED(INFO)) {
std::string proto(next_proto, next_proto+next_proto_len);
for (int i = 0; i < 2; ++i) {
if (next_proto) {
if (LOG_ENABLED(INFO)) {
std::string proto(next_proto, next_proto + next_proto_len);
CLOG(INFO, this) << "The negotiated next protocol: " << proto;
}
if(!ssl::in_proto_list(get_config()->npn_list,
next_proto, next_proto_len)) {
if (!ssl::in_proto_list(get_config()->npn_list, next_proto,
next_proto_len)) {
break;
}
if(util::check_h2_is_selected(next_proto, next_proto_len)) {
if (util::check_h2_is_selected(next_proto, next_proto_len)) {
set_bev_cb(upstream_http2_connhd_readcb, upstream_writecb,
upstream_eventcb);
auto http2_upstream = util::make_unique<Http2Upstream>(this);
if(!ssl::check_http2_requirement(ssl_)) {
if (!ssl::check_http2_requirement(ssl_)) {
rv = http2_upstream->terminate_session(NGHTTP2_INADEQUATE_SECURITY);
if(rv != 0) {
if (rv != 0) {
return -1;
}
}
@ -330,7 +301,7 @@ int ClientHandler::validate_next_proto()
// At this point, input buffer is already filled with some
// bytes. The read callback is not called until new data
// come. So consume input buffer here.
if(on_http2_connhd_read() != 0) {
if (on_http2_connhd_read() != 0) {
return -1;
}
@ -338,10 +309,10 @@ int ClientHandler::validate_next_proto()
} else {
#ifdef HAVE_SPDYLAY
uint16_t version = spdylay_npn_get_version(next_proto, next_proto_len);
if(version) {
if (version) {
upstream_ = util::make_unique<SpdyUpstream>(version, this);
switch(version) {
switch (version) {
case SPDYLAY_PROTO_SPDY2:
alpn_ = "spdy/2";
break;
@ -358,21 +329,21 @@ int ClientHandler::validate_next_proto()
// At this point, input buffer is already filled with some
// bytes. The read callback is not called until new data
// come. So consume input buffer here.
if(upstream_->on_read() != 0) {
if (upstream_->on_read() != 0) {
return -1;
}
return 0;
}
#endif // HAVE_SPDYLAY
if(next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) {
if (next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) {
upstream_ = util::make_unique<HttpsUpstream>(this);
alpn_ = "http/1.1";
// At this point, input buffer is already filled with some
// bytes. The read callback is not called until new data
// come. So consume input buffer here.
if(upstream_->on_read() != 0) {
if (upstream_->on_read() != 0) {
return -1;
}
@ -383,12 +354,12 @@ int ClientHandler::validate_next_proto()
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len);
#else // OPENSSL_VERSION_NUMBER < 0x10002000L
#else // OPENSSL_VERSION_NUMBER < 0x10002000L
break;
#endif // OPENSSL_VERSION_NUMBER < 0x10002000L
}
if(!next_proto) {
if(LOG_ENABLED(INFO)) {
if (!next_proto) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1";
}
upstream_ = util::make_unique<HttpsUpstream>(this);
@ -397,44 +368,37 @@ int ClientHandler::validate_next_proto()
// At this point, input buffer is already filled with some bytes.
// The read callback is not called until new data come. So consume
// input buffer here.
if(upstream_->on_read() != 0) {
if (upstream_->on_read() != 0) {
return -1;
}
return 0;
}
if(LOG_ENABLED(INFO)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "The negotiated protocol is not supported";
}
return -1;
}
int ClientHandler::on_read()
{
return upstream_->on_read();
}
int ClientHandler::on_read() { return upstream_->on_read(); }
int ClientHandler::on_event()
{
return upstream_->on_event();
}
int ClientHandler::on_event() { return upstream_->on_event(); }
int ClientHandler::on_http2_connhd_read()
{
int ClientHandler::on_http2_connhd_read() {
// This callback assumes upstream is Http2Upstream.
uint8_t data[NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN];
auto input = bufferevent_get_input(bev_);
auto readlen = evbuffer_remove(input, data, left_connhd_len_);
if(readlen == -1) {
if (readlen == -1) {
return -1;
}
if(memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE +
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_,
data, readlen) != 0) {
if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE +
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_,
data, readlen) != 0) {
// There is no downgrade path here. Just drop the connection.
if(LOG_ENABLED(INFO)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "invalid client connection header";
}
@ -443,7 +407,7 @@ int ClientHandler::on_http2_connhd_read()
left_connhd_len_ -= readlen;
if(left_connhd_len_ > 0) {
if (left_connhd_len_ > 0) {
return 0;
}
@ -451,27 +415,26 @@ int ClientHandler::on_http2_connhd_read()
// Run on_read to process data left in buffer since they are not
// notified further
if(on_read() != 0) {
if (on_read() != 0) {
return -1;
}
return 0;
}
int ClientHandler::on_http1_connhd_read()
{
int ClientHandler::on_http1_connhd_read() {
uint8_t data[NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN];
auto input = bufferevent_get_input(bev_);
auto readlen = evbuffer_copyout(input, data, left_connhd_len_);
if(readlen == -1) {
if (readlen == -1) {
return -1;
}
if(memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE +
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_,
data, readlen) != 0) {
if(LOG_ENABLED(INFO)) {
if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE +
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_,
data, readlen) != 0) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "This is HTTP/1.1 connection, "
<< "but may be upgraded to HTTP/2 later.";
}
@ -480,24 +443,24 @@ int ClientHandler::on_http1_connhd_read()
left_connhd_len_ = NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN;
set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb);
if(on_read() != 0) {
if (on_read() != 0) {
return -1;
}
return 0;
}
if(evbuffer_drain(input, readlen) == -1) {
if (evbuffer_drain(input, readlen) == -1) {
return -1;
}
left_connhd_len_ -= readlen;
if(left_connhd_len_ > 0) {
if (left_connhd_len_ > 0) {
return 0;
}
if(LOG_ENABLED(INFO)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "direct HTTP/2 connection";
}
@ -506,41 +469,34 @@ int ClientHandler::on_http1_connhd_read()
// Run on_read to process data left in buffer since they are not
// notified further
if(on_read() != 0) {
if (on_read() != 0) {
return -1;
}
return 0;
}
const std::string& ClientHandler::get_ipaddr() const
{
return ipaddr_;
}
const std::string &ClientHandler::get_ipaddr() const { return ipaddr_; }
bool ClientHandler::get_should_close_after_write() const
{
bool ClientHandler::get_should_close_after_write() const {
return should_close_after_write_;
}
void ClientHandler::set_should_close_after_write(bool f)
{
void ClientHandler::set_should_close_after_write(bool f) {
should_close_after_write_ = f;
}
void ClientHandler::pool_downstream_connection
(std::unique_ptr<DownstreamConnection> dconn)
{
if(LOG_ENABLED(INFO)) {
void ClientHandler::pool_downstream_connection(
std::unique_ptr<DownstreamConnection> dconn) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Pooling downstream connection DCONN:" << dconn.get();
}
dconn->set_client_handler(nullptr);
dconn_pool_->add_downstream_connection(std::move(dconn));
}
void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn)
{
if(LOG_ENABLED(INFO)) {
void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Removing downstream connection DCONN:" << dconn
<< " from pool";
}
@ -548,19 +504,18 @@ void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn)
}
std::unique_ptr<DownstreamConnection>
ClientHandler::get_downstream_connection()
{
ClientHandler::get_downstream_connection() {
auto dconn = dconn_pool_->pop_downstream_connection();
if(!dconn) {
if(LOG_ENABLED(INFO)) {
if (!dconn) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Downstream connection pool is empty."
<< " Create new one";
}
if(http2session_) {
dconn = util::make_unique<Http2DownstreamConnection>
(dconn_pool_, http2session_);
if (http2session_) {
dconn = util::make_unique<Http2DownstreamConnection>(dconn_pool_,
http2session_);
} else {
dconn = util::make_unique<HttpDownstreamConnection>(dconn_pool_);
}
@ -570,7 +525,7 @@ ClientHandler::get_downstream_connection()
dconn->set_client_handler(this);
if(LOG_ENABLED(INFO)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get()
<< " from pool";
}
@ -578,51 +533,39 @@ ClientHandler::get_downstream_connection()
return dconn;
}
size_t ClientHandler::get_outbuf_length()
{
size_t ClientHandler::get_outbuf_length() {
return evbuffer_get_length(bufferevent_get_output(bev_));
}
SSL* ClientHandler::get_ssl() const
{
return ssl_;
}
SSL *ClientHandler::get_ssl() const { return ssl_; }
void ClientHandler::set_http2_session(Http2Session *http2session)
{
void ClientHandler::set_http2_session(Http2Session *http2session) {
http2session_ = http2session;
}
Http2Session* ClientHandler::get_http2_session() const
{
return http2session_;
}
Http2Session *ClientHandler::get_http2_session() const { return http2session_; }
void ClientHandler::set_http1_connect_blocker
(ConnectBlocker *http1_connect_blocker)
{
void ClientHandler::set_http1_connect_blocker(
ConnectBlocker *http1_connect_blocker) {
http1_connect_blocker_ = http1_connect_blocker;
}
ConnectBlocker* ClientHandler::get_http1_connect_blocker() const
{
ConnectBlocker *ClientHandler::get_http1_connect_blocker() const {
return http1_connect_blocker_;
}
void ClientHandler::direct_http2_upgrade()
{
upstream_= util::make_unique<Http2Upstream>(this);
void ClientHandler::direct_http2_upgrade() {
upstream_ = util::make_unique<Http2Upstream>(this);
// TODO We don't know exact h2 draft version in direct upgrade. We
// just use library default for now.
alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID;
set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb);
}
int ClientHandler::perform_http2_upgrade(HttpsUpstream *http)
{
int ClientHandler::perform_http2_upgrade(HttpsUpstream *http) {
int rv;
auto upstream = util::make_unique<Http2Upstream>(this);
if(upstream->upgrade_upstream(http) != 0) {
if (upstream->upgrade_upstream(http) != 0) {
return -1;
}
// http pointer is now owned by upstream.
@ -633,47 +576,36 @@ int ClientHandler::perform_http2_upgrade(HttpsUpstream *http)
alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID;
set_bev_cb(upstream_http2_connhd_readcb, upstream_writecb, upstream_eventcb);
static char res[] = "HTTP/1.1 101 Switching Protocols\r\n"
"Connection: Upgrade\r\n"
"Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n"
"\r\n";
"Connection: Upgrade\r\n"
"Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n"
"\r\n";
rv = bufferevent_write(bev_, res, sizeof(res) - 1);
if(rv != 0) {
if (rv != 0) {
CLOG(FATAL, this) << "bufferevent_write() faild";
return -1;
}
return 0;
}
bool ClientHandler::get_http2_upgrade_allowed() const
{
return !ssl_;
}
bool ClientHandler::get_http2_upgrade_allowed() const { return !ssl_; }
std::string ClientHandler::get_upstream_scheme() const
{
if(ssl_) {
std::string ClientHandler::get_upstream_scheme() const {
if (ssl_) {
return "https";
} else {
return "http";
}
}
void ClientHandler::set_tls_handshake(bool f)
{
tls_handshake_ = f;
}
void ClientHandler::set_tls_handshake(bool f) { tls_handshake_ = f; }
bool ClientHandler::get_tls_handshake() const
{
return tls_handshake_;
}
bool ClientHandler::get_tls_handshake() const { return tls_handshake_; }
namespace {
void shutdown_cb(evutil_socket_t fd, short what, void *arg)
{
auto handler = static_cast<ClientHandler*>(arg);
void shutdown_cb(evutil_socket_t fd, short what, void *arg) {
auto handler = static_cast<ClientHandler *>(arg);
if(LOG_ENABLED(INFO)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, handler) << "Close connection due to TLS renegotiation";
}
@ -681,10 +613,9 @@ void shutdown_cb(evutil_socket_t fd, short what, void *arg)
}
} // namespace
void ClientHandler::set_tls_renegotiation(bool f)
{
if(tls_renegotiation_ == false) {
if(LOG_ENABLED(INFO)) {
void ClientHandler::set_tls_renegotiation(bool f) {
if (tls_renegotiation_ == false) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "TLS renegotiation detected. "
<< "Start shutdown timer now.";
}
@ -700,26 +631,22 @@ void ClientHandler::set_tls_renegotiation(bool f)
tls_renegotiation_ = f;
}
bool ClientHandler::get_tls_renegotiation() const
{
return tls_renegotiation_;
}
bool ClientHandler::get_tls_renegotiation() const { return tls_renegotiation_; }
namespace {
const size_t SHRPX_SMALL_WRITE_LIMIT = 1300;
const size_t SHRPX_WARMUP_THRESHOLD = 1 << 20;
} // namespace
ssize_t ClientHandler::get_write_limit()
{
if(!ssl_) {
ssize_t ClientHandler::get_write_limit() {
if (!ssl_) {
return -1;
}
timeval tv;
if(event_base_gettimeofday_cached(get_evbase(), &tv) == 0) {
if (event_base_gettimeofday_cached(get_evbase(), &tv) == 0) {
auto now = util::to_time64(tv);
if(now - last_write_time_ > 1000000) {
if (now - last_write_time_ > 1000000) {
// Time out, use small record size
warmup_writelen_ = 0;
return SHRPX_SMALL_WRITE_LIMIT;
@ -729,74 +656,62 @@ ssize_t ClientHandler::get_write_limit()
// If event_base_gettimeofday_cached() failed, we just skip timer
// checking. Don't know how to treat this.
if(warmup_writelen_ >= SHRPX_WARMUP_THRESHOLD) {
if (warmup_writelen_ >= SHRPX_WARMUP_THRESHOLD) {
return -1;
}
return SHRPX_SMALL_WRITE_LIMIT;
}
void ClientHandler::update_warmup_writelen(size_t n)
{
if(warmup_writelen_ < SHRPX_WARMUP_THRESHOLD) {
void ClientHandler::update_warmup_writelen(size_t n) {
if (warmup_writelen_ < SHRPX_WARMUP_THRESHOLD) {
warmup_writelen_ += n;
}
}
void ClientHandler::update_last_write_time()
{
void ClientHandler::update_last_write_time() {
timeval tv;
if(event_base_gettimeofday_cached(get_evbase(), &tv) == 0) {
if (event_base_gettimeofday_cached(get_evbase(), &tv) == 0) {
last_write_time_ = util::to_time64(tv);
}
}
void ClientHandler::write_accesslog(Downstream *downstream)
{
void ClientHandler::write_accesslog(Downstream *downstream) {
LogSpec lgsp = {
downstream,
ipaddr_.c_str(),
downstream->get_request_method().c_str(),
downstream, ipaddr_.c_str(), downstream->get_request_method().c_str(),
downstream->get_request_path().empty() ?
downstream->get_request_http2_authority().c_str() :
downstream->get_request_path().c_str(),
downstream->get_request_path().empty()
? downstream->get_request_http2_authority().c_str()
: downstream->get_request_path().c_str(),
alpn_.c_str(),
alpn_.c_str(),
downstream->get_request_start_time(),
std::chrono::high_resolution_clock::now(),
downstream->get_request_start_time(),
std::chrono::high_resolution_clock::now(),
downstream->get_request_major(),
downstream->get_request_minor(),
downstream->get_response_http_status(),
downstream->get_response_sent_bodylen(),
port_.c_str(),
get_config()->port,
get_config()->pid,
downstream->get_request_major(), downstream->get_request_minor(),
downstream->get_response_http_status(),
downstream->get_response_sent_bodylen(), port_.c_str(),
get_config()->port, get_config()->pid,
};
upstream_accesslog(get_config()->accesslog_format, &lgsp);
}
void ClientHandler::write_accesslog(int major, int minor,
unsigned int status,
int64_t body_bytes_sent)
{
void ClientHandler::write_accesslog(int major, int minor, unsigned int status,
int64_t body_bytes_sent) {
LogSpec lgsp = {
nullptr,
ipaddr_.c_str(),
"-", // method
"-", // path,
alpn_.c_str(),
std::chrono::high_resolution_clock::now(), //request_start_time TODO is there a better value?
std::chrono::high_resolution_clock::now(), //time_now
major, minor, // major, minor
status,
body_bytes_sent,
port_.c_str(),
get_config()->port,
get_config()->pid,
nullptr, ipaddr_.c_str(),
"-", // method
"-", // path,
alpn_.c_str(),
std::chrono::high_resolution_clock::now(), // request_start_time TODO is
// there a better value?
std::chrono::high_resolution_clock::now(), // time_now
major, minor, // major, minor
status, body_bytes_sent,
port_.c_str(), get_config()->port,
get_config()->pid,
};
upstream_accesslog(get_config()->accesslog_format, &lgsp);

View File

@ -47,35 +47,34 @@ struct WorkerStat;
class ClientHandler {
public:
ClientHandler(bufferevent *bev,
bufferevent_rate_limit_group *rate_limit_group,
int fd, SSL *ssl, const char *ipaddr, const char *port,
WorkerStat *worker_stat,
DownstreamConnectionPool *dconn_pool);
bufferevent_rate_limit_group *rate_limit_group, int fd,
SSL *ssl, const char *ipaddr, const char *port,
WorkerStat *worker_stat, DownstreamConnectionPool *dconn_pool);
~ClientHandler();
int on_read();
int on_event();
bufferevent* get_bev() const;
event_base* get_evbase() const;
bufferevent *get_bev() const;
event_base *get_evbase() const;
void set_bev_cb(bufferevent_data_cb readcb, bufferevent_data_cb writecb,
bufferevent_event_cb eventcb);
void set_upstream_timeouts(const timeval *read_timeout,
const timeval *write_timeout);
int validate_next_proto();
const std::string& get_ipaddr() const;
const std::string& get_port() const;
const std::string &get_ipaddr() const;
const std::string &get_port() const;
bool get_should_close_after_write() const;
void set_should_close_after_write(bool f);
Upstream* get_upstream();
Upstream *get_upstream();
void pool_downstream_connection(std::unique_ptr<DownstreamConnection> dconn);
void remove_downstream_connection(DownstreamConnection *dconn);
std::unique_ptr<DownstreamConnection> get_downstream_connection();
size_t get_outbuf_length();
SSL* get_ssl() const;
SSL *get_ssl() const;
void set_http2_session(Http2Session *http2session);
Http2Session* get_http2_session() const;
Http2Session *get_http2_session() const;
void set_http1_connect_blocker(ConnectBlocker *http1_connect_blocker);
ConnectBlocker* get_http1_connect_blocker() const;
ConnectBlocker *get_http1_connect_blocker() const;
// Call this function when HTTP/2 connection header is received at
// the start of the connection.
void direct_http2_upgrade();
@ -115,6 +114,7 @@ public:
// corresponding Downstream object is not available.
void write_accesslog(int major, int minor, unsigned int status,
int64_t body_bytes_sent);
private:
std::unique_ptr<Upstream> upstream_;
std::string ipaddr_;

File diff suppressed because it is too large Load Diff

View File

@ -133,21 +133,12 @@ union sockaddr_union {
sockaddr_in in;
};
enum shrpx_proto {
PROTO_HTTP2,
PROTO_HTTP
};
enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP };
struct AltSvc {
AltSvc()
: protocol_id(nullptr),
host(nullptr),
origin(nullptr),
protocol_id_len(0),
host_len(0),
origin_len(0),
port(0)
{}
: protocol_id(nullptr), host(nullptr), origin(nullptr),
protocol_id_len(0), host_len(0), origin_len(0), port(0) {}
char *protocol_id;
char *host;
@ -208,10 +199,10 @@ struct Config {
// list of supported NPN/ALPN protocol strings in the order of
// preference. The each element of this list is a NULL-terminated
// string.
std::vector<char*> npn_list;
std::vector<char *> npn_list;
// list of supported SSL/TLS protocol strings. The each element of
// this list is a NULL-terminated string.
std::vector<char*> tls_proto_list;
std::vector<char *> tls_proto_list;
// Path to file containing CA certificate solely used for client
// certificate validation
std::unique_ptr<char[]> verify_client_cacert;
@ -285,8 +276,8 @@ struct Config {
bool no_location_rewrite;
};
const Config* get_config();
Config* mod_config();
const Config *get_config();
Config *mod_config();
void create_config();
// Parses option name |opt| and value |optarg|. The results are
@ -310,12 +301,12 @@ std::string read_passwd_from_file(const char *filename);
// |s| and the caller must leave it as is after this call. This
// function copies |s| and first element in the return value points to
// it. It is caller's responsibility to deallocate its memory.
std::vector<char*> parse_config_str_list(const char *s);
std::vector<char *> parse_config_str_list(const char *s);
// Clears all elements of |list|, which is returned by
// parse_config_str_list(). If list is not empty, list[0] is freed by
// free(2). After this call, list.empty() must be true.
void clear_config_str_list(std::vector<char*>& list);
void clear_config_str_list(std::vector<char *> &list);
// Parses header field in |optarg|. We expect header field is formed
// like "NAME: VALUE". We require that NAME is non empty string. ":"
@ -333,15 +324,15 @@ std::unique_ptr<char[]> strcopy(const char *val);
std::unique_ptr<char[]> strcopy(const char *val, size_t n);
// Returns a copy of val.c_str().
std::unique_ptr<char[]> strcopy(const std::string& val);
std::unique_ptr<char[]> strcopy(const std::string &val);
// Returns string for syslog |facility|.
const char* str_syslog_facility(int facility);
const char *str_syslog_facility(int facility);
// Returns integer value of syslog |facility| string.
int int_syslog_facility(const char *strfacility);
FILE* open_file_for_write(const char *filename);
FILE *open_file_for_write(const char *filename);
} // namespace shrpx

View File

@ -30,8 +30,7 @@
namespace shrpx {
void test_shrpx_config_parse_config_str_list(void)
{
void test_shrpx_config_parse_config_str_list(void) {
auto res = parse_config_str_list("a");
CU_ASSERT(1 == res.size());
CU_ASSERT(0 == strcmp("a", res[0]));
@ -64,8 +63,7 @@ void test_shrpx_config_parse_config_str_list(void)
clear_config_str_list(res);
}
void test_shrpx_config_parse_header(void)
{
void test_shrpx_config_parse_header(void) {
auto p = parse_header("a: b");
CU_ASSERT("a" == p.first);
CU_ASSERT("b" == p.second);
@ -90,8 +88,7 @@ void test_shrpx_config_parse_header(void)
CU_ASSERT("bravo charlie" == p.second);
}
void test_shrpx_config_parse_log_format(void)
{
void test_shrpx_config_parse_log_format(void) {
auto res = parse_log_format("$remote_addr - $remote_user [$time_local] "
"\"$request\" $status $body_bytes_sent "
"\"$http_referer\" \"$http_user_agent\"");

View File

@ -30,50 +30,39 @@ namespace {
const int INITIAL_SLEEP = 2;
} // namespace
ConnectBlocker::ConnectBlocker()
: timerev_(nullptr),
sleep_(INITIAL_SLEEP)
{}
ConnectBlocker::ConnectBlocker() : timerev_(nullptr), sleep_(INITIAL_SLEEP) {}
ConnectBlocker::~ConnectBlocker()
{
if(timerev_) {
ConnectBlocker::~ConnectBlocker() {
if (timerev_) {
event_free(timerev_);
}
}
namespace {
void connect_blocker_cb(evutil_socket_t sig, short events, void *arg)
{
if(LOG_ENABLED(INFO)) {
void connect_blocker_cb(evutil_socket_t sig, short events, void *arg) {
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "unblock downstream connection";
}
}
} // namespace
int ConnectBlocker::init(event_base *evbase)
{
int ConnectBlocker::init(event_base *evbase) {
timerev_ = evtimer_new(evbase, connect_blocker_cb, this);
if(timerev_ == nullptr) {
if (timerev_ == nullptr) {
return -1;
}
return 0;
}
bool ConnectBlocker::blocked() const
{
bool ConnectBlocker::blocked() const {
return evtimer_pending(timerev_, nullptr);
}
void ConnectBlocker::on_success()
{
sleep_ = INITIAL_SLEEP;
}
void ConnectBlocker::on_success() { sleep_ = INITIAL_SLEEP; }
void ConnectBlocker::on_failure()
{
void ConnectBlocker::on_failure() {
int rv;
sleep_ = std::min(128, sleep_ * 2);
@ -84,7 +73,7 @@ void ConnectBlocker::on_failure()
rv = evtimer_add(timerev_, &t);
if(rv == -1) {
if (rv == -1) {
LOG(ERROR) << "evtimer_add for ConnectBlocker timerev_ failed";
}
}

View File

@ -45,6 +45,7 @@ public:
// Call this function if connect operation failed. This will start
// timer and blocks connection establishment for sleep_ seconds.
void on_failure();
private:
event *timerev_;
int sleep_;

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,7 @@ public:
Downstream(Upstream *upstream, int32_t stream_id, int32_t priority);
~Downstream();
void reset_upstream(Upstream *upstream);
Upstream* get_upstream() const;
Upstream *get_upstream() const;
void set_stream_id(int32_t stream_id);
int32_t get_stream_id() const;
void set_priority(int32_t pri);
@ -66,12 +66,11 @@ public:
void set_downstream_stream_id(int32_t stream_id);
int32_t get_downstream_stream_id() const;
int attach_downstream_connection
(std::unique_ptr<DownstreamConnection> dconn);
int attach_downstream_connection(std::unique_ptr<DownstreamConnection> dconn);
void detach_downstream_connection();
// Releases dconn_, without freeing it.
void release_downstream_connection();
DownstreamConnection* get_downstream_connection();
DownstreamConnection *get_downstream_connection();
// Returns dconn_ and nullifies dconn_.
std::unique_ptr<DownstreamConnection> pop_downstream_connection();
@ -93,12 +92,12 @@ public:
// Returns true if the request is HTTP Upgrade for HTTP/2
bool get_http2_upgrade_request() const;
// Returns the value of HTTP2-Settings request header field.
const std::string& get_http2_settings() const;
const std::string &get_http2_settings() const;
// downstream request API
const Headers& get_request_headers() const;
const Headers &get_request_headers() const;
void crumble_request_cookie();
void assemble_request_cookie();
const std::string& get_assembled_request_cookie() const;
const std::string &get_assembled_request_cookie() const;
// Makes key lowercase and sort headers by name using <
void normalize_request_headers();
// Returns iterator pointing to the request header with the name
@ -106,14 +105,13 @@ public:
// occurrence from the beginning. If no such header is found,
// returns std::end(get_request_headers()). This function must be
// called after calling normalize_request_headers().
Headers::const_iterator get_norm_request_header
(const std::string& name) const;
Headers::const_iterator
get_norm_request_header(const std::string &name) const;
// Returns iterator pointing to the request header with the name
// |name|. This function acts like get_norm_request_header(), but
// if request_headers_ was not normalized, use linear search to find
// the header. Otherwise, get_norm_request_header() is used.
Headers::const_iterator get_request_header
(const std::string& name) const;
Headers::const_iterator get_request_header(const std::string &name) const;
bool get_request_headers_normalized() const;
void add_request_header(std::string name, std::string value);
void set_last_request_header_value(std::string value);
@ -131,19 +129,21 @@ public:
size_t get_request_headers_sum() const;
void set_request_method(std::string method);
const std::string& get_request_method() const;
const std::string &get_request_method() const;
void set_request_path(std::string path);
void set_request_start_time(std::chrono::high_resolution_clock::time_point time);
const std::chrono::high_resolution_clock::time_point& get_request_start_time() const;
void
set_request_start_time(std::chrono::high_resolution_clock::time_point time);
const std::chrono::high_resolution_clock::time_point &
get_request_start_time() const;
void append_request_path(const char *data, size_t len);
// Returns request path. For HTTP/1.1, this is request-target. For
// HTTP/2, this is :path header field value.
const std::string& get_request_path() const;
const std::string &get_request_path() const;
// Returns HTTP/2 :scheme header field value.
const std::string& get_request_http2_scheme() const;
const std::string &get_request_http2_scheme() const;
void set_request_http2_scheme(std::string scheme);
// Returns HTTP/2 :authority header field value.
const std::string& get_request_http2_authority() const;
const std::string &get_request_http2_authority() const;
void set_request_http2_authority(std::string authority);
void set_request_major(int major);
void set_request_minor(int minor);
@ -175,7 +175,7 @@ public:
void set_request_state(int state);
int get_request_state() const;
// downstream response API
const Headers& get_response_headers() const;
const Headers &get_response_headers() const;
// Makes key lowercase and sort headers by name using <
void normalize_response_headers();
// Returns iterator pointing to the response header with the name
@ -183,14 +183,13 @@ public:
// occurrence from the beginning. If no such header is found,
// returns std::end(get_response_headers()). This function must be
// called after calling normalize_response_headers().
Headers::const_iterator get_norm_response_header
(const std::string& name) const;
Headers::const_iterator
get_norm_response_header(const std::string &name) const;
// Rewrites the location response header field. This function must
// be called after calling normalize_response_headers() and
// normalize_request_headers().
void rewrite_norm_location_response_header
(const std::string& upstream_scheme,
uint16_t upstream_port);
void rewrite_norm_location_response_header(const std::string &upstream_scheme,
uint16_t upstream_port);
void add_response_header(std::string name, std::string value);
void set_last_response_header_value(std::string value);
@ -220,7 +219,7 @@ public:
void set_response_state(int state);
int get_response_state() const;
int init_response_body_buf();
evbuffer* get_response_body_buf();
evbuffer *get_response_body_buf();
void add_response_bodylen(size_t amount);
int64_t get_response_bodylen() const;
void add_response_sent_bodylen(size_t amount);
@ -282,6 +281,7 @@ public:
// Returns true if accesslog can be written for this downstream.
bool accesslog_ready() const;
private:
Headers request_headers_;
Headers response_headers_;

View File

@ -30,33 +30,22 @@
namespace shrpx {
DownstreamConnection::DownstreamConnection
(DownstreamConnectionPool *dconn_pool)
: dconn_pool_(dconn_pool),
client_handler_(nullptr),
downstream_(nullptr)
{}
DownstreamConnection::DownstreamConnection(DownstreamConnectionPool *dconn_pool)
: dconn_pool_(dconn_pool), client_handler_(nullptr), downstream_(nullptr) {}
DownstreamConnection::~DownstreamConnection()
{}
DownstreamConnection::~DownstreamConnection() {}
void DownstreamConnection::set_client_handler(ClientHandler *handler)
{
void DownstreamConnection::set_client_handler(ClientHandler *handler) {
client_handler_ = handler;
}
ClientHandler* DownstreamConnection::get_client_handler()
{
ClientHandler *DownstreamConnection::get_client_handler() {
return client_handler_;
}
Downstream* DownstreamConnection::get_downstream()
{
return downstream_;
}
Downstream *DownstreamConnection::get_downstream() { return downstream_; }
DownstreamConnectionPool* DownstreamConnection::get_dconn_pool() const
{
DownstreamConnectionPool *DownstreamConnection::get_dconn_pool() const {
return dconn_pool_;
}

View File

@ -61,9 +61,10 @@ public:
virtual int on_priority_change(int32_t pri) = 0;
void set_client_handler(ClientHandler *client_handler);
ClientHandler* get_client_handler();
Downstream* get_downstream();
DownstreamConnectionPool* get_dconn_pool() const;
ClientHandler *get_client_handler();
Downstream *get_downstream();
DownstreamConnectionPool *get_dconn_pool() const;
protected:
DownstreamConnectionPool *dconn_pool_;
ClientHandler *client_handler_;

View File

@ -27,26 +27,22 @@
namespace shrpx {
DownstreamConnectionPool::DownstreamConnectionPool()
{}
DownstreamConnectionPool::DownstreamConnectionPool() {}
DownstreamConnectionPool::~DownstreamConnectionPool()
{
for(auto dconn : pool_) {
DownstreamConnectionPool::~DownstreamConnectionPool() {
for (auto dconn : pool_) {
delete dconn;
}
}
void DownstreamConnectionPool::add_downstream_connection
(std::unique_ptr<DownstreamConnection> dconn)
{
void DownstreamConnectionPool::add_downstream_connection(
std::unique_ptr<DownstreamConnection> dconn) {
pool_.insert(dconn.release());
}
std::unique_ptr<DownstreamConnection>
DownstreamConnectionPool::pop_downstream_connection()
{
if(pool_.empty()) {
DownstreamConnectionPool::pop_downstream_connection() {
if (pool_.empty()) {
return nullptr;
}
@ -55,9 +51,8 @@ DownstreamConnectionPool::pop_downstream_connection()
return dconn;
}
void DownstreamConnectionPool::remove_downstream_connection
(DownstreamConnection *dconn)
{
void DownstreamConnectionPool::remove_downstream_connection(
DownstreamConnection *dconn) {
pool_.erase(dconn);
delete dconn;
}

View File

@ -42,8 +42,9 @@ public:
void add_downstream_connection(std::unique_ptr<DownstreamConnection> dconn);
std::unique_ptr<DownstreamConnection> pop_downstream_connection();
void remove_downstream_connection(DownstreamConnection *dconn);
private:
std::set<DownstreamConnection*> pool_;
std::set<DownstreamConnection *> pool_;
};
} // namespace shrpx

Some files were not shown because too many files have changed in this diff Show More