diff options
-rw-r--r-- | main/http.c | 7 | ||||
-rw-r--r-- | main/manager.c | 18 | ||||
-rw-r--r-- | main/tcptls.c | 10 |
3 files changed, 32 insertions, 3 deletions
diff --git a/main/http.c b/main/http.c index e2982a73b..1009afcc2 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 328878251..5e74fb5a8 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 e07f1f1a0..417178c8f 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)); } |