Browse Source

[core] move con throttling to connections-glue.c

move write throttling code from network.c:network_write_chunkqueue()
to connections-glue.c:connection_write_chunkqueue() and fix the code
to use TCP_CORK only on TCP sockets.
personal/stbuehler/mod-csrf
Glenn Strauss 5 years ago
parent
commit
82feb70588
  1. 76
      src/connections-glue.c
  2. 2
      src/connections.c
  3. 1
      src/connections.h
  4. 65
      src/network.c
  5. 2
      src/network.h

76
src/connections-glue.c

@ -1,5 +1,6 @@
#include "first.h"
#include "sys-socket.h"
#include "base.h"
#include "connections.h"
#include "log.h"
@ -263,6 +264,81 @@ static handler_t connection_handle_read_post_chunked(server *srv, connection *co
return HANDLER_GO_ON;
}
static off_t connection_write_throttle(server *srv, connection *con, off_t max_bytes) {
UNUSED(srv);
if (con->conf.global_kbytes_per_second) {
off_t limit = con->conf.global_kbytes_per_second * 1024 - *(con->conf.global_bytes_per_second_cnt_ptr);
if (limit <= 0) {
/* we reached the global traffic limit */
con->traffic_limit_reached = 1;
return 0;
} else {
if (max_bytes > limit) max_bytes = limit;
}
}
if (con->conf.kbytes_per_second) {
off_t limit = con->conf.kbytes_per_second * 1024 - con->bytes_written_cur_second;
if (limit <= 0) {
/* we reached the traffic limit */
con->traffic_limit_reached = 1;
return 0;
} else {
if (max_bytes > limit) max_bytes = limit;
}
}
return max_bytes;
}
int connection_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
int ret = -1;
off_t written = 0;
#ifdef TCP_CORK
int corked = 0;
#endif
max_bytes = connection_write_throttle(srv, con, max_bytes);
if (0 == max_bytes) return 1;
written = cq->bytes_out;
#ifdef TCP_CORK
/* Linux: put a cork into the socket as we want to combine the write() calls
* but only if we really have multiple chunks, and only if TCP socket
*/
if (cq->first && cq->first->next) {
const int sa_family = con->srv_socket->addr.plain.sa_family;
if (sa_family == AF_INET || sa_family == AF_INET6) {
corked = 1;
(void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
}
}
#endif
ret = con->network_write(srv, con, cq, max_bytes);
if (ret >= 0) {
chunkqueue_remove_finished_chunks(cq);
ret = chunkqueue_is_empty(cq) ? 0 : 1;
}
#ifdef TCP_CORK
if (corked) {
corked = 0;
(void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
}
#endif
written = cq->bytes_out - written;
con->bytes_written += written;
con->bytes_written_cur_second += written;
*(con->conf.global_bytes_per_second_cnt_ptr) += written;
return ret;
}
handler_t connection_handle_read_post_state(server *srv, connection *con) {
chunkqueue *cq = con->read_queue;
chunkqueue *dst_cq = con->request_content_queue;

2
src/connections.c

@ -476,7 +476,7 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
}
static int connection_handle_write(server *srv, connection *con) {
switch(network_write_chunkqueue(srv, con, con->write_queue, MAX_WRITE_LIMIT)) {
switch(connection_write_chunkqueue(srv, con, con->write_queue, MAX_WRITE_LIMIT)) {
case 0:
con->write_request_ts = srv->cur_ts;
if (con->file_finished) {

1
src/connections.h

@ -18,6 +18,7 @@ const char * connection_get_short_state(connection_state_t state);
int connection_state_machine(server *srv, connection *con);
handler_t connection_handle_read_post_state(server *srv, connection *con);
handler_t connection_handle_read_post_error(server *srv, connection *con, int http_status);
int connection_write_chunkqueue(server *srv, connection *con, chunkqueue *c, off_t max_bytes);
void connection_response_reset(server *srv, connection *con);
#endif

65
src/network.c

@ -591,68 +591,3 @@ int network_register_fdevents(server *srv) {
}
return 0;
}
int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
int ret = -1;
off_t written = 0;
#ifdef TCP_CORK
int corked = 0;
#endif
if (con->conf.global_kbytes_per_second) {
off_t limit = con->conf.global_kbytes_per_second * 1024 - *(con->conf.global_bytes_per_second_cnt_ptr);
if (limit <= 0) {
/* we reached the global traffic limit */
con->traffic_limit_reached = 1;
return 1;
} else {
if (max_bytes > limit) max_bytes = limit;
}
}
if (con->conf.kbytes_per_second) {
off_t limit = con->conf.kbytes_per_second * 1024 - con->bytes_written_cur_second;
if (limit <= 0) {
/* we reached the traffic limit */
con->traffic_limit_reached = 1;
return 1;
} else {
if (max_bytes > limit) max_bytes = limit;
}
}
written = cq->bytes_out;
#ifdef TCP_CORK
/* Linux: put a cork into the socket as we want to combine the write() calls
* but only if we really have multiple chunks
*/
if (cq->first && cq->first->next) {
corked = 1;
(void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
}
#endif
ret = con->network_write(srv, con, cq, max_bytes);
if (ret >= 0) {
chunkqueue_remove_finished_chunks(cq);
ret = chunkqueue_is_empty(cq) ? 0 : 1;
}
#ifdef TCP_CORK
if (corked) {
corked = 0;
(void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
}
#endif
written = cq->bytes_out - written;
con->bytes_written += written;
con->bytes_written_cur_second += written;
*(con->conf.global_bytes_per_second_cnt_ptr) += written;
return ret;
}

2
src/network.h

@ -6,8 +6,6 @@
void network_accept_tcp_nagle_disable(int fd);
int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c, off_t max_bytes);
int network_init(server *srv);
int network_close(server *srv);

Loading…
Cancel
Save