📄 http_resp.c
字号:
} } /* clip the buffer */ http_trans_buf_clip(a_conn, l_start_body + 4); ec: a_resp->header_state = http_resp_header_start; return l_return;}inthttp_resp_read_body(http_resp *a_resp, http_req *a_req, http_trans_conn *a_conn){ int l_return = 0; char *l_content_length = NULL; char *l_transfer_encoding = NULL; char *l_connection = NULL; /* check to see if we have to jump in anywhere. */ if (a_conn->sync == HTTP_TRANS_ASYNC) { if (a_resp->body_state == http_resp_body_read_content_length) goto http_resp_body_read_content_length_jump; if (a_resp->body_state == http_resp_body_read_chunked) goto http_resp_body_read_chunked_jump; if (a_resp->body_state == http_resp_body_read_standard) goto http_resp_body_read_standard_jump; } /* check to make sure that things are ok. */ if ((!a_resp) || (!a_conn)) return -1; /* check to see if there should be an entity body. */ /* check to see if there's a content length */ l_content_length = http_hdr_get_value(a_resp->headers, http_hdr_Content_Length); /* check to see if there's a transfer encoding */ l_transfer_encoding = http_hdr_get_value(a_resp->headers, http_hdr_Transfer_Encoding); /* check to see if the connection header is set */ l_connection = http_hdr_get_value(a_resp->headers, http_hdr_Connection); /* if there's a content length, do your stuff */ if (l_content_length && (a_req->type != http_req_type_head)) { if (string_is_number(l_content_length) == 0) { a_conn->errstr = "Content length in http response was not a number"; return -1; } a_resp->content_length = atoi(l_content_length); /* set the state */ a_resp->body_state = http_resp_body_read_content_length; http_resp_body_read_content_length_jump: l_return = read_body_content_length(a_resp, a_req, a_conn); } else if (l_content_length) { /* this happens in a head request with content length. */ return HTTP_TRANS_DONE; } else if (l_transfer_encoding) { /* check to see if it's using chunked transfer encoding */ if (!strcasecmp(l_transfer_encoding, "chunked")) { /* set the state */ a_resp->body_state = http_resp_body_read_chunked; http_resp_body_read_chunked_jump: l_return = read_body_chunked(a_resp, a_req, a_conn); } else { /* what kind of encoding? */ a_conn->errstr = "Unknown encoding type in http response"; return -1; } } else { a_resp->body_state = http_resp_body_read_standard; /* set the state */ http_resp_body_read_standard_jump: l_return = read_body_standard(a_resp, a_req, a_conn); /* after that the connection gets closed */ if (l_return == HTTP_TRANS_DONE) { close(a_conn->sock); a_conn->sock = -1; } } /* check to see if the connection should be closed */ if (l_connection && (l_return != HTTP_TRANS_NOT_DONE)) { if (!strcasecmp(l_connection, "close")) { close (a_conn->sock); a_conn->sock = -1; } } if (l_return == HTTP_TRANS_DONE) a_resp->body_state = http_resp_body_start; return l_return;}static intstring_is_number(char *a_string){ int i = 0; if (strlen(a_string) < 1) return 0; while (a_string[i]) { if (isdigit(a_string[i]) == 0) return 0; i++; } return 1;}static intread_chunk(http_trans_conn *a_conn){ char *l_end_chunk_hdr = NULL; int l_len = 0; int i = 0; int j = 0; char *l_ptr = NULL; int l_left_to_read = 0; int l_rv = 0; if (a_conn->chunk_len == 0) { /* check to make sure that the pattern is in the buffer */ do { if ((l_end_chunk_hdr = http_trans_buf_has_patt(a_conn->io_buf, a_conn->io_buf_alloc, "\r\n", 2)) == NULL) { l_rv = http_trans_read_into_buf(a_conn); if (l_rv == HTTP_TRANS_ERR) return HTTP_TRANS_ERR; /* check to see if the remote end hung up. */ if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0)) return HTTP_TRANS_ERR; if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE)) return HTTP_TRANS_NOT_DONE; } } while (l_end_chunk_hdr == NULL); /* set the begining at the start of the buffer */ l_ptr = a_conn->io_buf; /* eat the hex value of the chunk */ while ((l_ptr < l_end_chunk_hdr) && (((tolower(*l_ptr) <= 'f') && (tolower(*l_ptr) >= 'a')) || ((*l_ptr <= '9') && (*l_ptr >= '0')))) l_ptr++; /* get the length of the hex number */ l_len = l_ptr - a_conn->io_buf; if (l_len == 0) { a_conn->chunk_len = -1; return HTTP_TRANS_ERR; } /* walk the size adding the values as you go along. */ for (i=0, j=l_len-1; i < l_len; i++, j--) { if ((tolower(a_conn->io_buf[i]) <= 'f') && (tolower(a_conn->io_buf[i]) >= 'a')) a_conn->chunk_len += (tolower(a_conn->io_buf[i]) - 0x57) << (4*j); else a_conn->chunk_len += (tolower(a_conn->io_buf[i]) - 0x30) << (4*j); } /* reset the pointer past the end of the header */ http_trans_buf_clip(a_conn, l_end_chunk_hdr + 2); } /* check to see if it's the last chunk. If not then add it.*/ if (a_conn->chunk_len != 0) { /* figure out how much we need to read */ /* the + 2 is for the \r\n that always follows a chunk. */ l_left_to_read = a_conn->chunk_len - a_conn->io_buf_alloc + 2; /* check to make sure that we actually need to read anything in. */ if (l_left_to_read > 0) { /* set the vars in the struct */ a_conn->io_buf_io_left = l_left_to_read; a_conn->io_buf_io_done = 0; /* append it */ do { l_rv = http_trans_read_into_buf(a_conn); if (l_rv == HTTP_TRANS_ERR) return HTTP_TRANS_ERR; /* check and see if the server hung up. */ if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0)) return HTTP_TRANS_ERR; if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE)) return HTTP_TRANS_NOT_DONE; } while (l_rv == HTTP_TRANS_NOT_DONE); } } if (a_conn->io_buf_alloc >= a_conn->chunk_len + 2) return HTTP_TRANS_DONE; /* we only get here if there was an error. */ if (a_conn->chunk_len == 0) return HTTP_TRANS_DONE; return HTTP_TRANS_ERR;}static intread_body_chunked(http_resp *a_resp, http_req *a_req, http_trans_conn *a_conn){ int l_rv = 0; int l_done = 0; do { /* read a chunk */ l_rv = read_chunk(a_conn); if (l_rv == HTTP_TRANS_ERR) return HTTP_TRANS_ERR; if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE)) return HTTP_TRANS_NOT_DONE; /* see if it's the first time */ if (a_conn->chunk_len > 0) { if (a_resp->body == NULL) { a_resp->body = malloc(a_conn->chunk_len); memcpy(a_resp->body, a_conn->io_buf, a_conn->chunk_len); a_resp->body_len = a_conn->chunk_len; } /* append it to the body */ else { a_resp->body = realloc(a_resp->body, (a_resp->body_len + a_conn->chunk_len)); memcpy(&a_resp->body[a_resp->body_len], a_conn->io_buf, a_conn->chunk_len); a_resp->body_len += a_conn->chunk_len; } } /* make sure there's at least 2 bytes in the buffer. This happens when a read was 3 bytes as in 0\r\n and there is still 2 bytes ( \r\n ) in the read queue. */ if ((a_conn->chunk_len == 0) && (a_conn->io_buf_alloc < 2)) { a_conn->io_buf_io_left = ( 2 - a_conn->io_buf_alloc ); a_conn->io_buf_io_done = 0; do { l_rv = http_trans_read_into_buf(a_conn); } while (l_rv == HTTP_TRANS_NOT_DONE); /* check for an error */ if (l_rv == HTTP_TRANS_ERR) return HTTP_TRANS_ERR; } if (a_conn->chunk_len == 0) l_done = 1; else { /* clip the buffer */ http_trans_buf_clip(a_conn, &a_conn->io_buf[a_conn->chunk_len + 2]); } a_conn->chunk_len = 0; } while (l_done == 0); return HTTP_TRANS_DONE;}static voidflush_response_body(http_resp *a_resp, http_trans_conn *a_conn){ if (a_resp->body != NULL) { free(a_resp->body); } a_resp->flushed_length += a_resp->body_len; a_resp->body_len = a_conn->io_buf_alloc; a_resp->body = malloc(a_conn->io_buf_alloc + 1); memset(a_resp->body, 0, a_conn->io_buf_alloc + 1); memcpy(a_resp->body, a_conn->io_buf, a_conn->io_buf_alloc); /* clean the buffer */ http_trans_buf_reset(a_conn);}voidhttp_resp_flush(http_resp *a_resp, http_trans_conn *a_conn){ flush_response_body(a_resp, a_conn);}static intread_body_content_length(http_resp *a_resp, http_req *a_req, http_trans_conn *a_conn){ int l_len = 0; int l_left_to_read = 0; int l_rv = 0; l_len = a_resp->content_length; if (l_len == 0) return HTTP_TRANS_DONE; /* find out how much more we have to read */ l_left_to_read = l_len - a_conn->io_buf_alloc - a_resp->flushed_length - a_resp->body_len; /* set the variables */ a_conn->io_buf_io_left = l_left_to_read; a_conn->io_buf_io_done = 0; if (l_left_to_read > 0) { /* append the rest of the body to the buffer */ do { l_rv = http_trans_read_into_buf(a_conn); if ((l_rv == HTTP_TRANS_NOT_DONE) && (a_conn->sync == HTTP_TRANS_ASYNC)) return HTTP_TRANS_NOT_DONE; if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0)) return HTTP_TRANS_ERR; } while(l_rv == HTTP_TRANS_NOT_DONE); if (l_rv == HTTP_TRANS_ERR) return HTTP_TRANS_ERR; } /* write it into the body */ flush_response_body (a_resp, a_conn); return HTTP_TRANS_DONE;}static intread_body_standard(http_resp *a_resp, http_req *a_req, http_trans_conn *a_conn){ int l_rv = 0; /* anything without a content length or chunked encoding */ do { l_rv = http_trans_read_into_buf(a_conn); if (a_conn->sync == HTTP_TRANS_ASYNC) { if ((l_rv == HTTP_TRANS_NOT_DONE) || (a_conn->last_read != 0)) return HTTP_TRANS_NOT_DONE; } } while ((l_rv == HTTP_TRANS_NOT_DONE) || (a_conn->last_read > 0)); if (l_rv == HTTP_TRANS_ERR) return HTTP_TRANS_ERR; flush_response_body(a_resp, a_conn); return HTTP_TRANS_DONE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -