Implement internal abstraction for iostreams

fopencookie/funclose is a non-standard API and should not be used
in portable software. Additionally, the way FILE's fd is used in
non-blocking mode is undefined behaviour and cannot be relied on.

This introduces internal abstraction for io streams, that allows
implementing the desired virtualization of read/write operations
with necessary timeout handling.

ASTERISK-24515 #close
ASTERISK-24517 #close

Change-Id: Id916aef418b665ced6a7489aef74908b6e376e85
This commit is contained in:
Timo Teräs
2016-06-02 22:10:06 +03:00
parent 0cc14597b2
commit 070a51bf7c
13 changed files with 1002 additions and 1103 deletions

View File

@@ -211,7 +211,7 @@ static int find_sequence(char * inbuf, int inlen, char * matchbuf, int matchlen)
* This function has two modes. The first to find a boundary marker. The
* second is to find the filename immediately after the boundary.
*/
static int readmimefile(FILE *fin, FILE *fout, char *boundary, int contentlen)
static int readmimefile(struct ast_iostream *in, FILE *fout, char *boundary, int contentlen)
{
int find_filename = 0;
char buf[4096];
@@ -222,7 +222,7 @@ static int readmimefile(FILE *fin, FILE *fout, char *boundary, int contentlen)
int boundary_len;
char * path_end, * path_start, * filespec;
if (NULL == fin || NULL == fout || NULL == boundary || 0 >= contentlen) {
if (NULL == in || NULL == fout || NULL == boundary || 0 >= contentlen) {
return -1;
}
@@ -236,8 +236,8 @@ static int readmimefile(FILE *fin, FILE *fout, char *boundary, int contentlen)
}
if (0 < num_to_read) {
if (fread(&(buf[char_in_buf]), 1, num_to_read, fin) < num_to_read) {
ast_log(LOG_WARNING, "fread() failed: %s\n", strerror(errno));
if (ast_iostream_read(in, &(buf[char_in_buf]), num_to_read) < num_to_read) {
ast_log(LOG_WARNING, "read failed: %s\n", strerror(errno));
num_to_read = 0;
}
contentlen -= num_to_read;
@@ -378,7 +378,7 @@ static int http_post_callback(struct ast_tcptls_session_instance *ser, const str
*/
ast_http_body_read_status(ser, 0);
if (0 > readmimefile(ser->f, f, boundary_marker, content_len)) {
if (0 > readmimefile(ser->stream, f, boundary_marker, content_len)) {
ast_debug(1, "Cannot find boundary marker in POST request.\n");
fclose(f);
ast_http_error(ser, 400, "Bad Request", "Cannot find boundary marker in POST request.");