summaryrefslogtreecommitdiff
path: root/res/res_http_websocket.c
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2015-08-03 11:06:07 -0500
committerMark Michelson <mmichelson@digium.com>2015-08-03 11:23:29 -0500
commit35a98161df088b4714850a00b179a90646ef4214 (patch)
treecb74f3d6f1ce7556b3b7536c882e195f57bdba35 /res/res_http_websocket.c
parent8eef7392c4b7c6ac4e34d165f065a74fefcb827f (diff)
res_http_websocket: Avoid passing strlen() to ast_websocket_write().
We have seen a rash of test failures on a 32-bit build agent. Commit 48698a5e21d7307f61b5fb2bd39fd593bc1423ca solved an obvious problem where we were not encoding a 64-bit value correctly over the wire. This commit, however, did not solve the test failures. In the failing tests, ARI is attempting to send a 537 byte text frame over a websocket. When sending a frame this small, 16 bits are all that is required in order to encode the payload length on the websocket frame. However, ast_websocket_write() thinks that the payload length is greater than 65535 and therefore writes out a 64 bit payload length. Inspecting this payload length, the lower 32 bits are exactly what we would expect it to be, 537 in hex. The upper 32 bits, are junk values that are not expected to be there. In the failure, we are passing the result of strlen() to a function that expects a uint64_t parameter to be passed in. strlen() returns a size_t, which on this 32-bit machine is 32 bits wide. Normally, passing a 32-bit unsigned value to somewhere where a 64-bit unsigned value is expected would cause no problems. In fact, in manual runs of failing tests, this works just fine. However, ast_websocket_write() uses the Asterisk optional API, which means that rather than a simple function call, there are a series of macros that are used for its declaration and implementation. These macros may be causing some sort of error to occur when converting from a 32 bit quantity to a 64 bit quantity. This commit changes the logic by making existing ast_websocket_write() calls use ast_websocket_write_string() instead. Within ast_websocket_write_string(), the 64-bit converted strlen is saved in a local variable, and that variable is passed to ast_websocket_write() instead. Note that this commit message is full of speculation rather than certainty. This is because the observed test failures, while always present in automated test runs, never occur when tests are manually attempted on the same test agent. The idea behind this commit is to fix a theoretical issue by performing changes that should, at the least, cause no harm. If it turns out that this change does not fix the failing tests, then this commit should be reverted. Change-Id: I4458dd87d785ca322b89c152b223a540a3d23e67
Diffstat (limited to 'res/res_http_websocket.c')
-rw-r--r--res/res_http_websocket.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c
index 1ecfd964c..33905452f 100644
--- a/res/res_http_websocket.c
+++ b/res/res_http_websocket.c
@@ -1370,8 +1370,17 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read_string)
int AST_OPTIONAL_API_NAME(ast_websocket_write_string)
(struct ast_websocket *ws, const char *buf)
{
+ uint64_t len = strlen(buf);
+
+ /* We do not pass strlen(buf) to ast_websocket_write() directly because the
+ * size_t returned by strlen() may not require the same storage size
+ * as the uint64_t that ast_websocket_write() uses. This normally
+ * would not cause a problem, but since ast_websocket_write() uses
+ * the optional API, this function call goes through a series of macros
+ * that may cause a 32-bit to 64-bit conversion to go awry.
+ */
return ast_websocket_write(ws, AST_WEBSOCKET_OPCODE_TEXT,
- (char *)buf, strlen(buf));
+ (char *)buf, len);
}
static int load_module(void)