diff --git a/channels/chan_websocket.c b/channels/chan_websocket.c index 6b8acc42bd..3d2bb80ca4 100644 --- a/channels/chan_websocket.c +++ b/channels/chan_websocket.c @@ -469,9 +469,7 @@ static struct ast_frame *dequeue_frame(struct websocket_pvt *instance) AST_LIST_UNLOCK); /* - * If the queue is paused, don't read a frame. Processing - * will continue down the function and a silence frame will - * be sent in its place. + * If the queue is paused, don't read a frame. */ if (instance->queue_paused) { return NULL; @@ -493,10 +491,9 @@ static struct ast_frame *dequeue_frame(struct websocket_pvt *instance) queued_frame = AST_LIST_REMOVE_HEAD(&instance->frame_queue, frame_list); /* - * If there are no frames in the queue, we need to - * return NULL so we can send a silence frame. We also need - * to send the QUEUE_DRAINED notification if we were requested - * to do so. + * If there are no frames in the queue, we need to return NULL. + * We also need to send the QUEUE_DRAINED notification if we + * were requested to do so. */ if (!queued_frame) { if (instance->report_queue_drained) { @@ -550,8 +547,7 @@ static struct ast_frame *dequeue_frame(struct websocket_pvt *instance) /* * If, after reading all control frames, there are no frames - * left in the queue, we need to return NULL so we can send - * a silence frame. + * left in the queue, we need to return NULL. */ if (!queued_frame) { return NULL; @@ -561,6 +557,30 @@ static struct ast_frame *dequeue_frame(struct websocket_pvt *instance) return queued_frame; } + +static struct ast_frame *create_frame_from_buffer(struct websocket_pvt *instance, + char *buffer, size_t len) +{ + struct ast_frame fr = { 0, }; + struct ast_frame *duped_frame = NULL; + + AST_FRAME_SET_BUFFER(&fr, buffer, 0, len); + fr.frametype = AST_FRAME_VOICE; + fr.subclass.format = instance->native_format; + if (instance->native_codec->samples_count) { + fr.samples = instance->native_codec->samples_count(&fr); + } + + duped_frame = ast_frisolate(&fr); + if (!duped_frame) { + ast_log(LOG_WARNING, "%s: Failed to isolate frame\n", + ast_channel_name(instance->channel)); + return NULL; + } + + return duped_frame; +} + /*! * \internal * @@ -600,34 +620,34 @@ static struct ast_frame *webchan_read(struct ast_channel *ast) } native_frame = dequeue_frame(instance); - - /* - * No frame when the timer fires means we have to return a null frame in its place. - */ if (!native_frame) { - ast_debug(4, "%s: WebSocket read timer fired with no frame available. Returning NULL frame.\n", + if (instance->leftover_len > 0) { + native_frame = create_frame_from_buffer(instance, instance->leftover_data, instance->leftover_len); + if (native_frame) { + ast_debug(4, "%s: WebSocket read timer fired with no frame available but with %d bytes in leftover_data. Returning partial frame.\n", + ast_channel_name(ast), (int)instance->leftover_len); + instance->leftover_len = 0; + return native_frame; + } + } + ast_debug(4, "%s: WebSocket read timer fired with no frame available and no data in leftover_data. Returning NULL frame.\n", ast_channel_name(ast)); return &ast_null_frame; } + ast_debug(5, "%s: WebSocket read timer fired. Dequeued %d byte frame. Left in buffer: %d\n", + ast_channel_name(ast), native_frame->datalen, (int)instance->leftover_len); + return native_frame; } static int queue_frame_from_buffer(struct websocket_pvt *instance, char *buffer, size_t len) { - struct ast_frame fr = { 0, }; struct ast_frame *duped_frame = NULL; - AST_FRAME_SET_BUFFER(&fr, buffer, 0, len); - fr.frametype = AST_FRAME_VOICE; - fr.subclass.format = instance->native_format; - fr.samples = instance->native_codec->samples_count(&fr); - - duped_frame = ast_frisolate(&fr); + duped_frame = create_frame_from_buffer(instance, buffer, len); if (!duped_frame) { - ast_log(LOG_WARNING, "%s: Failed to isolate frame\n", - ast_channel_name(instance->channel)); return -1; }