diff --git a/main/http.c b/main/http.c index e2982a73b5e0e94ffaeb82ddaf00511f09913acf..1009afcc24412c0cead6edbc24935b9c1f54ca2d 100644 --- a/main/http.c +++ b/main/http.c @@ -444,7 +444,9 @@ void ast_http_send(struct ast_tcptls_session_instance *ser, /* send content */ if (method != AST_HTTP_HEAD || status_code >= 400) { if (out) { - fprintf(ser->f, "%s", ast_str_buffer(out)); + if (fwrite(ast_str_buffer(out), content_length, 1, ser->f) != 1) { + ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno)); + } } if (fd) { @@ -466,8 +468,7 @@ void ast_http_send(struct ast_tcptls_session_instance *ser, ast_free(out); } - fclose(ser->f); - ser->f = 0; + ast_tcptls_close_session_file(ser); return; } diff --git a/main/manager.c b/main/manager.c index 328878251443561fbdcf609f7badfb0e12a9a906..5e74fb5a899294f04f47f25e99454c4f09ed91f2 100644 --- a/main/manager.c +++ b/main/manager.c @@ -1769,6 +1769,15 @@ static void session_destructor(void *obj) } if (session->f != NULL) { + /* + * Issuing shutdown() is necessary here to avoid a race + * condition where the last data written may not appear + * in the the TCP stream. See ASTERISK-23548 + */ + fflush(session->f); + if (session->fd != -1) { + shutdown(session->fd, SHUT_RDWR); + } fclose(session->f); } if (eqe) { @@ -6740,12 +6749,21 @@ static void process_output(struct mansession *s, struct ast_str **out, struct as } if (s->f) { + /* + * Issuing shutdown() is necessary here to avoid a race + * condition where the last data written may not appear + * in the the TCP stream. See ASTERISK-23548 + */ + if (s->fd != -1) { + shutdown(s->fd, SHUT_RDWR); + } if (fclose(s->f)) { ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno)); } s->f = NULL; s->fd = -1; } else if (s->fd != -1) { + shutdown(s->fd, SHUT_RDWR); if (close(s->fd)) { ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); } diff --git a/main/tcptls.c b/main/tcptls.c index e07f1f1a05e94e966980914083efab3cbe82afa3..417178c8f71d651221b4dc27f22662f939596d68 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -625,12 +625,22 @@ error: void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session) { if (tcptls_session->f) { + /* + * Issuing shutdown() is necessary here to avoid a race + * condition where the last data written may not appear + * in the TCP stream. See ASTERISK-23548 + */ + fflush(tcptls_session->f); + if (tcptls_session->fd != -1) { + shutdown(tcptls_session->fd, SHUT_RDWR); + } if (fclose(tcptls_session->f)) { ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno)); } tcptls_session->f = NULL; tcptls_session->fd = -1; } else if (tcptls_session->fd != -1) { + shutdown(tcptls_session->fd, SHUT_RDWR); if (close(tcptls_session->fd)) { ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); }