Increase WebSocket frame size and improve large read handling

Some WebSocket applications, like [chan_respoke][], require a larger
frame size than the default 8k; this patch bumps the default to 16k.
This patch also fixes some problems exacerbated by large frames.

The sanity counter was decremented on every fread attempt in
ws_safe_read(), regardless of whether data was read from the socket or
not. For large frames, this could result in loss of sanity prior to
reading the entire frame. (16k frame / 1448 bytes per segment = 12
segments).

This patch changes the sanity counter so that it only decrements when
fread() doesn't read any bytes. This more closely matches the original
intention of ws_safe_read(), given that the error message is
"Websocket seems unresponsive".

This patch also properly logs EOF conditions, so disconnects are no
longer confused with unresponsive connections.

 [chan_respoke]: https://github.com/respoke/chan_respoke

Review: https://reviewboard.asterisk.org/r/4431/


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@432236 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/61/61/1
David M. Lee 10 years ago
parent 789d4379b6
commit 551b35e822

@ -48,7 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define MAX_PROTOCOL_BUCKETS 7
/*! \brief Size of the pre-determined buffer for WebSocket frames */
#define MAXIMUM_FRAME_SIZE 8192
#define MAXIMUM_FRAME_SIZE 16384
/*! \brief Default reconstruction size for multi-frame payload reconstruction. If exceeded the next frame will start a
* payload.
@ -361,18 +361,35 @@ int AST_OPTIONAL_API_NAME(ast_websocket_set_timeout)(struct ast_websocket *sessi
*/
static inline int ws_safe_read(struct ast_websocket *session, char *buf, int len, enum ast_websocket_opcode *opcode)
{
int sanity;
size_t rlen;
int xlen = len;
char *rbuf = buf;
for (sanity = 10; sanity; sanity--) {
int sanity = 10;
for (;;) {
clearerr(session->f);
rlen = fread(rbuf, 1, xlen, session->f);
if (!rlen && ferror(session->f) && errno != EAGAIN) {
ast_log(LOG_ERROR, "Error reading from web socket: %s\n", strerror(errno));
*opcode = AST_WEBSOCKET_OPCODE_CLOSE;
session->closing = 1;
return -1;
if (!rlen) {
if (feof(session->f)) {
ast_log(LOG_WARNING, "Web socket closed abruptly\n");
*opcode = AST_WEBSOCKET_OPCODE_CLOSE;
session->closing = 1;
return -1;
}
if (ferror(session->f) && errno != EAGAIN) {
ast_log(LOG_ERROR, "Error reading from web socket: %s\n", strerror(errno));
*opcode = AST_WEBSOCKET_OPCODE_CLOSE;
session->closing = 1;
return -1;
}
if (!--sanity) {
ast_log(LOG_WARNING, "Websocket seems unresponsive, disconnecting ...\n");
*opcode = AST_WEBSOCKET_OPCODE_CLOSE;
session->closing = 1;
return -1;
}
}
xlen = xlen - rlen;
rbuf = rbuf + rlen;
@ -386,12 +403,6 @@ static inline int ws_safe_read(struct ast_websocket *session, char *buf, int len
return -1;
}
}
if (!sanity) {
ast_log(LOG_WARNING, "Websocket seems unresponsive, disconnecting ...\n");
*opcode = AST_WEBSOCKET_OPCODE_CLOSE;
session->closing = 1;
return -1;
}
return 0;
}

Loading…
Cancel
Save