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
29 changes: 29 additions & 0 deletions src/bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,15 @@ int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length
chunks[1].iov_base = (char *)payload;
chunks[1].iov_len = payload_length;

#ifdef MSG_NOSIGNAL
/* Match bsd_send: a disconnected peer must not terminate the process. */
struct msghdr message = {0};
message.msg_iov = chunks;
message.msg_iovlen = 2;
return sendmsg(fd, &message, MSG_NOSIGNAL);
#else
return writev(fd, chunks, 2);
#endif
}
#else
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
Expand All @@ -433,6 +441,27 @@ int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length
}
#endif

int bsd_write3(LIBUS_SOCKET_DESCRIPTOR fd, const char *prefix, int prefix_length, const char *data, int data_length, const char *suffix, int suffix_length) {
#ifndef _WIN32
struct iovec chunks[3] = {{(char *) prefix, (size_t) prefix_length},
{(char *) data, (size_t) data_length},
{(char *) suffix, (size_t) suffix_length}};
#ifdef MSG_NOSIGNAL
struct msghdr message = {0};
message.msg_iov = chunks;
message.msg_iovlen = 3;
return sendmsg(fd, &message, MSG_NOSIGNAL);
#else
return writev(fd, chunks, 3);
#endif
#else
int written = bsd_send(fd, prefix, prefix_length, 1);
if (written != prefix_length) return written;
int more = bsd_write2(fd, data, data_length, suffix, suffix_length);
return written + (more < 0 ? 0 : more);
#endif
}

int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {

// MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
Expand Down
1 change: 1 addition & 0 deletions src/internal/networking/bsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd
int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
int bsd_write3(LIBUS_SOCKET_DESCRIPTOR fd, const char *prefix, int prefix_length, const char *data, int data_length, const char *suffix, int suffix_length);
int bsd_would_block();

// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
Expand Down
3 changes: 3 additions & 0 deletions src/libusockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length
/* Special path for non-SSL sockets. Used to send header and payload in one go. Works like us_socket_write. */
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length);

/* Same non-SSL semantics as write2, with three buffers. Their combined length must fit in an int. */
int us_socket_write3(int ssl, struct us_socket_t *s, const char *prefix, int prefix_length, const char *data, int data_length, const char *suffix, int suffix_length);

/* Set a low precision, high performance timer on a socket. A socket can only have one single active timer
* at any given point in time. Will remove any such pre set timer */
void us_socket_timeout(int ssl, struct us_socket_t *s, unsigned int seconds);
Expand Down
13 changes: 13 additions & 0 deletions src/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,25 @@ int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int hea

int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length);
if (written != header_length + payload_length) {
s->context->loop->data.last_write_failed = 1;
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
}

return written < 0 ? 0 : written;
}

int us_socket_write3(int ssl, struct us_socket_t *s, const char *prefix, int prefix_length, const char *data, int data_length, const char *suffix, int suffix_length) {
if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
return 0;
}
int written = bsd_write3(us_poll_fd(&s->p), prefix, prefix_length, data, data_length, suffix, suffix_length);
if (written != prefix_length + data_length + suffix_length) {
s->context->loop->data.last_write_failed = 1;
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
}
return written < 0 ? 0 : written;
}

int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more) {
#ifndef LIBUS_NO_SSL
if (ssl) {
Expand Down