Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions src/mgtransport.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ int mg_raw_transport_init(int sockfd, mg_raw_transport **transport,
if (!ttransport) {
return MG_ERROR_OOM;
}
ttransport->recv_buf_capacity = 65536;
ttransport->recv_buf = mg_allocator_malloc(allocator, ttransport->recv_buf_capacity);
if (!ttransport->recv_buf) {
mg_allocator_free(allocator, ttransport);
return MG_ERROR_OOM;
}
ttransport->recv_buf_len = 0;
ttransport->recv_buf_pos = 0;
ttransport->sockfd = sockfd;
ttransport->send = mg_raw_transport_send;
ttransport->recv = mg_raw_transport_recv;
Expand Down Expand Up @@ -95,21 +103,31 @@ int mg_raw_transport_send(struct mg_transport *transport, const char *buf,

int mg_raw_transport_recv(struct mg_transport *transport, char *buf,
size_t len) {
int sockfd = ((mg_raw_transport *)transport)->sockfd;
mg_raw_transport *raw = (mg_raw_transport *)transport;
size_t total_received = 0;
while (total_received < len) {
ssize_t received_now =
mg_socket_receive(sockfd, buf + total_received, len - total_received);
if (received_now == 0) {
// Server closed the connection.
fprintf(stderr, "mg_raw_transport_recv: connection closed by server\n");
return -1;
}
if (received_now == -1) {
perror("mg_raw_transport_recv");
return -1;
if (raw->recv_buf_pos < raw->recv_buf_len) {
size_t from_buf = len - total_received;
if (from_buf > raw->recv_buf_len - raw->recv_buf_pos) {
from_buf = raw->recv_buf_len - raw->recv_buf_pos;
}
memcpy(buf + total_received, raw->recv_buf + raw->recv_buf_pos, from_buf);
total_received += from_buf;
raw->recv_buf_pos += from_buf;
} else {
ssize_t received_now = mg_socket_receive(raw->sockfd, raw->recv_buf,
raw->recv_buf_capacity);
if (received_now == 0) {
fprintf(stderr, "mg_raw_transport_recv: connection closed by server\n");
return -1;
}
if (received_now == -1) {
perror("mg_raw_transport_recv");
return -1;
}
raw->recv_buf_len = (size_t)received_now;
raw->recv_buf_pos = 0;
}
total_received += (size_t)received_now;
}
return 0;
}
Expand All @@ -119,6 +137,10 @@ void mg_raw_transport_destroy(struct mg_transport *transport) {
if (mg_socket_close(self->sockfd) != 0) {
abort();
}
if (self->recv_buf) {
mg_allocator_free(self->allocator, self->recv_buf);
self->recv_buf = NULL;
}
mg_allocator_free(self->allocator, transport);
}

Expand Down
5 changes: 5 additions & 0 deletions src/mgtransport.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ typedef struct mg_raw_transport {
void (*suspend_until_ready_to_read)(struct mg_transport *);
void (*suspend_until_ready_to_write)(struct mg_transport *);
int sockfd;
/* Buffered read: reduce recv() syscalls by reading in larger chunks */
char *recv_buf;
size_t recv_buf_capacity;
size_t recv_buf_len;
size_t recv_buf_pos;
mg_allocator *allocator;
} mg_raw_transport;

Expand Down
Loading