*/
AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), { errno = ENOSYS; return -1;});
+/*!
+ * \brief Wait for the WebSocket session to be ready to be read.
+ * \since 16.8.0
+ * \since 17.2.0
+ *
+ * \param session Pointer to the WebSocket session
+ * \param timeout the number of milliseconds to wait
+ *
+ * \retval -1 if error occurred
+ * \retval 0 if the timeout expired
+ * \retval 1 if the WebSocket session is ready for reading
+ */
+AST_OPTIONAL_API(int, ast_websocket_wait_for_input, (struct ast_websocket *session, int timeout), { errno = ENOSYS; return -1; });
+
/*!
* \brief Get the remote address for a WebSocket connected session.
*
*/
int ast_iostream_get_fd(struct ast_iostream *stream);
+/*!
+ * \brief Wait for input on the iostream's file descriptor
+ * \since 16.8.0
+ * \since 17.2.0
+ *
+ * \param stream A pointer to an iostream
+ * \param timeout the number of milliseconds to wait
+ *
+ * \retval -1 if error occurred
+ * \retval 0 if the timeout expired
+ * \retval 1 if the stream is ready for reading
+ */
+int ast_iostream_wait_for_input(struct ast_iostream *stream, int timeout);
+
/*!
* \brief Make an iostream non-blocking.
*
return stream->fd;
}
+int ast_iostream_wait_for_input(struct ast_iostream *stream, int timeout)
+{
+#if defined(DO_SSL)
+ /* Because SSL is read in blocks, it's possible that the last time we read we
+ got more than we asked for and it is now buffered inside OpenSSL. If that
+ is the case, calling ast_wait_for_input() will block until the fd is ready
+ for reading again, which might never happen. */
+ if (stream->ssl && SSL_pending(stream->ssl)) {
+ return 1;
+ }
+#endif
+ return ast_wait_for_input(stream->fd, timeout);
+}
+
void ast_iostream_nonblock(struct ast_iostream *stream)
{
ast_fd_set_flags(stream->fd, O_NONBLOCK);
return session->closing ? -1 : ast_iostream_get_fd(session->stream);
}
+int AST_OPTIONAL_API_NAME(ast_websocket_wait_for_input)(struct ast_websocket *session, int timeout)
+{
+ return session->closing ? -1 : ast_iostream_wait_for_input(session->stream, timeout);
+}
+
struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_remote_address)(struct ast_websocket *session)
{
return &session->remote_address;
break;
}
}
- if (ast_wait_for_input(ast_iostream_get_fd(session->stream), 1000) < 0) {
- ast_log(LOG_ERROR, "ast_wait_for_input returned err: %s\n", strerror(errno));
+ if (ast_iostream_wait_for_input(session->stream, 1000) < 0) {
+ ast_log(LOG_ERROR, "ast_iostream_wait_for_input returned err: %s\n", strerror(errno));
*opcode = AST_WEBSOCKET_OPCODE_CLOSE;
session->closing = 1;
ao2_unlock(session);
goto end;
}
- while ((res = ast_wait_for_input(ast_websocket_fd(session), -1)) > 0) {
+ while ((res = ast_websocket_wait_for_input(session, -1)) > 0) {
char *payload;
uint64_t payload_len;
enum ast_websocket_opcode opcode;
transport = create_data.transport;
read_data.transport = transport;
- while (ast_wait_for_input(ast_websocket_fd(session), -1) > 0) {
+ while (ast_websocket_wait_for_input(session, -1) > 0) {
enum ast_websocket_opcode opcode;
int fragmented;