diff options
author | Joshua Colp <jcolp@digium.com> | 2015-12-30 18:43:34 -0600 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2015-12-30 18:43:34 -0600 |
commit | 4e5250d5c29a4a43531522efb6de234759e8dbfb (patch) | |
tree | 70dca47003439f9e3392d287c8d07d4af3004231 | |
parent | 410c5ee0fc5f1ba8bc25ca6e2cdc11527f36b1b7 (diff) | |
parent | 3bddcc0219bbe18ae925e1d41301fa9001530804 (diff) |
Merge "res_http_websocket.c: prevent avoidable disconnections caused by write errors"
-rw-r--r-- | include/asterisk/http_websocket.h | 4 | ||||
-rw-r--r-- | res/res_http_websocket.c | 33 |
2 files changed, 19 insertions, 18 deletions
diff --git a/include/asterisk/http_websocket.h b/include/asterisk/http_websocket.h index 23492ff95..cd49dbe48 100644 --- a/include/asterisk/http_websocket.h +++ b/include/asterisk/http_websocket.h @@ -266,12 +266,12 @@ AST_OPTIONAL_API(int, ast_websocket_read_string, * \param session Pointer to the WebSocket session * \param opcode WebSocket operation code to place in the frame * \param payload Optional pointer to a payload to add to the frame - * \param actual_length Length of the payload (0 if no payload) + * \param payload_size Length of the payload (0 if no payload) * * \retval 0 if successfully written * \retval -1 if error occurred */ -AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length), { errno = ENOSYS; return -1;}); +AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t payload_size), { errno = ENOSYS; return -1;}); /*! * \brief Construct and transmit a WebSocket frame containing string data. diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c index c40aae6d2..265457854 100644 --- a/res/res_http_websocket.c +++ b/res/res_http_websocket.c @@ -332,18 +332,19 @@ static const char *websocket_opcode2str(enum ast_websocket_opcode opcode) } /*! \brief Write function for websocket traffic */ -int AST_OPTIONAL_API_NAME(ast_websocket_write)(struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length) +int AST_OPTIONAL_API_NAME(ast_websocket_write)(struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t payload_size) { size_t header_size = 2; /* The minimum size of a websocket frame is 2 bytes */ char *frame; uint64_t length; + uint64_t frame_size; ast_debug(3, "Writing websocket %s frame, length %" PRIu64 "\n", - websocket_opcode2str(opcode), actual_length); + websocket_opcode2str(opcode), payload_size); - if (actual_length < 126) { - length = actual_length; - } else if (actual_length < (1 << 16)) { + if (payload_size < 126) { + length = payload_size; + } else if (payload_size < (1 << 16)) { length = 126; /* We need an additional 2 bytes to store the extended length */ header_size += 2; @@ -353,37 +354,37 @@ int AST_OPTIONAL_API_NAME(ast_websocket_write)(struct ast_websocket *session, en header_size += 8; } - frame = ast_alloca(header_size); - memset(frame, 0, header_size); + frame_size = header_size + payload_size; + + frame = ast_alloca(frame_size + 1); + memset(frame, 0, frame_size + 1); frame[0] = opcode | 0x80; frame[1] = length; /* Use the additional available bytes to store the length */ if (length == 126) { - put_unaligned_uint16(&frame[2], htons(actual_length)); + put_unaligned_uint16(&frame[2], htons(payload_size)); } else if (length == 127) { - put_unaligned_uint64(&frame[2], htonll(actual_length)); + put_unaligned_uint64(&frame[2], htonll(payload_size)); } + memcpy(&frame[header_size], payload, payload_size); + ao2_lock(session); if (session->closing) { ao2_unlock(session); return -1; } - if (ast_careful_fwrite(session->f, session->fd, frame, header_size, session->timeout)) { - ao2_unlock(session); - /* 1011 - server terminating connection due to not being able to fulfill the request */ - ast_websocket_close(session, 1011); - return -1; - } - if (ast_careful_fwrite(session->f, session->fd, payload, actual_length, session->timeout)) { + if (ast_careful_fwrite(session->f, session->fd, frame, frame_size, session->timeout)) { ao2_unlock(session); /* 1011 - server terminating connection due to not being able to fulfill the request */ + ast_debug(1, "Closing WS with 1011 because we can't fulfill a write request\n"); ast_websocket_close(session, 1011); return -1; } + fflush(session->f); ao2_unlock(session); |