lnk commit front code
This commit is contained in:
332
include/oss_sdk/aos_http_io.c
Normal file
332
include/oss_sdk/aos_http_io.c
Normal file
@@ -0,0 +1,332 @@
|
||||
#include "aos_log.h"
|
||||
#include "aos_http_io.h"
|
||||
#include "aos_define.h"
|
||||
#include <apr_thread_mutex.h>
|
||||
#include <apr_file_io.h>
|
||||
|
||||
aos_pool_t *aos_global_pool = NULL;
|
||||
apr_file_t *aos_stderr_file = NULL;
|
||||
|
||||
aos_http_request_options_t *aos_default_http_request_options = NULL;
|
||||
aos_http_transport_options_t *aos_default_http_transport_options = NULL;
|
||||
|
||||
aos_http_transport_create_pt aos_http_transport_create = aos_curl_http_transport_create;
|
||||
aos_http_transport_perform_pt aos_http_transport_perform = aos_curl_http_transport_perform;
|
||||
|
||||
static apr_thread_mutex_t* requestStackMutexG = NULL;
|
||||
static CURL *requestStackG[AOS_REQUEST_STACK_SIZE];
|
||||
static int requestStackCountG;
|
||||
static char aos_user_agent[256];
|
||||
|
||||
|
||||
static aos_http_transport_options_t *aos_http_transport_options_create(aos_pool_t *p);
|
||||
|
||||
CURL *aos_request_get()
|
||||
{
|
||||
CURL *request = NULL;
|
||||
|
||||
apr_thread_mutex_lock(requestStackMutexG);
|
||||
if (requestStackCountG > 0) {
|
||||
request = requestStackG[--requestStackCountG];
|
||||
}
|
||||
apr_thread_mutex_unlock(requestStackMutexG);
|
||||
|
||||
// If we got one, deinitialize it for re-use
|
||||
if (request) {
|
||||
curl_easy_reset(request);
|
||||
}
|
||||
else {
|
||||
request = curl_easy_init();
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
void request_release(CURL *request)
|
||||
{
|
||||
apr_thread_mutex_lock(requestStackMutexG);
|
||||
|
||||
// If the request stack is full, destroy this one
|
||||
// else put this one at the front of the request stack; we do this because
|
||||
// we want the most-recently-used curl handle to be re-used on the next
|
||||
// request, to maximize our chances of re-using a TCP connection before it
|
||||
// times out
|
||||
if (requestStackCountG == AOS_REQUEST_STACK_SIZE) {
|
||||
apr_thread_mutex_unlock(requestStackMutexG);
|
||||
curl_easy_cleanup(request);
|
||||
}
|
||||
else {
|
||||
requestStackG[requestStackCountG++] = request;
|
||||
apr_thread_mutex_unlock(requestStackMutexG);
|
||||
}
|
||||
}
|
||||
|
||||
void aos_set_default_request_options(aos_http_request_options_t *op)
|
||||
{
|
||||
aos_default_http_request_options = op;
|
||||
}
|
||||
|
||||
void aos_set_default_transport_options(aos_http_transport_options_t *op)
|
||||
{
|
||||
aos_default_http_transport_options = op;
|
||||
}
|
||||
|
||||
aos_http_request_options_t *aos_http_request_options_create(aos_pool_t *p)
|
||||
{
|
||||
aos_http_request_options_t *options;
|
||||
|
||||
options = (aos_http_request_options_t *)aos_pcalloc(p, sizeof(aos_http_request_options_t));
|
||||
options->speed_limit = AOS_MIN_SPEED_LIMIT;
|
||||
options->speed_time = AOS_MIN_SPEED_TIME;
|
||||
options->connect_timeout = AOS_CONNECT_TIMEOUT;
|
||||
options->dns_cache_timeout = AOS_DNS_CACHE_TIMOUT;
|
||||
options->max_memory_size = AOS_MAX_MEMORY_SIZE;
|
||||
options->enable_crc = AOS_TRUE;
|
||||
options->proxy_auth = NULL;
|
||||
options->proxy_host = NULL;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
aos_http_transport_options_t *aos_http_transport_options_create(aos_pool_t *p)
|
||||
{
|
||||
return (aos_http_transport_options_t *)aos_pcalloc(p, sizeof(aos_http_transport_options_t));
|
||||
}
|
||||
|
||||
aos_http_controller_t *aos_http_controller_create(aos_pool_t *p, int owner)
|
||||
{
|
||||
int s;
|
||||
aos_http_controller_t *ctl;
|
||||
|
||||
if(p == NULL) {
|
||||
if ((s = aos_pool_create(&p, NULL)) != APR_SUCCESS) {
|
||||
aos_fatal_log("aos_pool_create failure.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ctl = (aos_http_controller_t *)aos_pcalloc(p, sizeof(aos_http_controller_ex_t));
|
||||
ctl->pool = p;
|
||||
ctl->owner = owner;
|
||||
ctl->options = aos_default_http_request_options;
|
||||
|
||||
return ctl;
|
||||
}
|
||||
|
||||
aos_http_request_t *aos_http_request_create(aos_pool_t *p)
|
||||
{
|
||||
aos_http_request_t *req;
|
||||
|
||||
req = (aos_http_request_t *)aos_pcalloc(p, sizeof(aos_http_request_t));
|
||||
req->method = HTTP_GET;
|
||||
req->headers = aos_table_make(p, 5);
|
||||
req->query_params = aos_table_make(p, 3);
|
||||
aos_list_init(&req->body);
|
||||
req->type = BODY_IN_MEMORY;
|
||||
req->body_len = 0;
|
||||
req->pool = p;
|
||||
req->read_body = aos_read_http_body_memory;
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
aos_http_response_t *aos_http_response_create(aos_pool_t *p)
|
||||
{
|
||||
aos_http_response_t *resp;
|
||||
|
||||
resp = (aos_http_response_t *)aos_pcalloc(p, sizeof(aos_http_response_t));
|
||||
resp->status = -1;
|
||||
resp->headers = aos_table_make(p, 10);
|
||||
aos_list_init(&resp->body);
|
||||
resp->type = BODY_IN_MEMORY;
|
||||
resp->body_len = 0;
|
||||
resp->pool = p;
|
||||
resp->write_body = aos_write_http_body_memory;
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
int aos_read_http_body_memory(aos_http_request_t *req, char *buffer, int len)
|
||||
{
|
||||
int wsize;
|
||||
int bytes = 0;
|
||||
aos_buf_t *b;
|
||||
aos_buf_t *n;
|
||||
|
||||
aos_list_for_each_entry_safe(aos_buf_t, b, n, &req->body, node) {
|
||||
wsize = aos_buf_size(b);
|
||||
if (wsize == 0) {
|
||||
aos_list_del(&b->node);
|
||||
continue;
|
||||
}
|
||||
wsize = aos_min(len - bytes, wsize);
|
||||
if (wsize == 0) {
|
||||
break;
|
||||
}
|
||||
memcpy(buffer + bytes, b->pos, wsize);
|
||||
b->pos += wsize;
|
||||
bytes += wsize;
|
||||
if (b->pos == b->last) {
|
||||
aos_list_del(&b->node);
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int aos_read_http_body_file(aos_http_request_t *req, char *buffer, int len)
|
||||
{
|
||||
int s;
|
||||
char buf[256];
|
||||
apr_size_t nbytes = len;
|
||||
apr_size_t bytes_left;
|
||||
|
||||
if (req->file_buf == NULL || req->file_buf->file == NULL) {
|
||||
aos_error_log("request body arg invalid file_buf NULL.");
|
||||
return AOSE_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (req->file_buf->file_pos >= req->file_buf->file_last) {
|
||||
aos_debug_log("file read finish.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes_left = (apr_size_t)(req->file_buf->file_last - req->file_buf->file_pos);
|
||||
if (nbytes > bytes_left) {
|
||||
nbytes = bytes_left;
|
||||
}
|
||||
|
||||
if ((s = apr_file_read(req->file_buf->file, buffer, &nbytes)) != APR_SUCCESS) {
|
||||
aos_error_log("apr_file_read filure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
|
||||
return AOSE_FILE_READ_ERROR;
|
||||
}
|
||||
req->file_buf->file_pos += nbytes;
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int aos_write_http_body_memory(aos_http_response_t *resp, const char *buffer, int len)
|
||||
{
|
||||
aos_buf_t *b;
|
||||
|
||||
b = aos_create_buf(resp->pool, len);
|
||||
memcpy(b->pos, buffer, len);
|
||||
b->last += len;
|
||||
aos_list_add_tail(&b->node, &resp->body);
|
||||
resp->body_len += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int aos_write_http_body_file(aos_http_response_t *resp, const char *buffer, int len)
|
||||
{
|
||||
int elen;
|
||||
int s;
|
||||
char buf[256];
|
||||
apr_size_t nbytes = len;
|
||||
|
||||
if (resp->file_buf == NULL) {
|
||||
resp->file_buf = aos_create_file_buf(resp->pool);
|
||||
}
|
||||
|
||||
if (resp->file_buf->file == NULL) {
|
||||
if (resp->file_path == NULL) {
|
||||
aos_error_log("resp body file arg NULL.");
|
||||
return AOSE_INVALID_ARGUMENT;
|
||||
}
|
||||
aos_trace_log("open file %s.", resp->file_path);
|
||||
if ((elen = aos_open_file_for_write(resp->pool, resp->file_path, resp->file_buf)) != AOSE_OK) {
|
||||
return elen;
|
||||
}
|
||||
}
|
||||
|
||||
assert(resp->file_buf->file != NULL);
|
||||
if ((s = apr_file_write(resp->file_buf->file, buffer, &nbytes)) != APR_SUCCESS) {
|
||||
aos_error_log("apr_file_write fialure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
|
||||
return AOSE_FILE_WRITE_ERROR;
|
||||
}
|
||||
|
||||
resp->file_buf->file_last += nbytes;
|
||||
resp->body_len += nbytes;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int aos_http_io_initialize(const char *user_agent_info, int flags)
|
||||
{
|
||||
CURLcode ecode;
|
||||
int s;
|
||||
char buf[256];
|
||||
aos_http_request_options_t *req_options;
|
||||
aos_http_transport_options_t *trans_options;
|
||||
|
||||
if ((ecode = curl_global_init(CURL_GLOBAL_ALL &
|
||||
~((flags & AOS_INIT_WINSOCK) ? 0: CURL_GLOBAL_WIN32))) != CURLE_OK)
|
||||
{
|
||||
aos_error_log("curl_global_init failure, code:%d %s.\n", ecode, curl_easy_strerror(ecode));
|
||||
return AOSE_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if ((s = apr_initialize()) != APR_SUCCESS) {
|
||||
aos_error_log("apr_initialize failue.\n");
|
||||
return AOSE_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (!user_agent_info || !*user_agent_info) {
|
||||
user_agent_info = "Unknown";
|
||||
}
|
||||
|
||||
if ((s = aos_pool_create(&aos_global_pool, NULL)) != APR_SUCCESS) {
|
||||
aos_error_log("aos_pool_create failure, code:%d %s.\n", s, apr_strerror(s, buf, sizeof(buf)));
|
||||
return AOSE_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if ((s = apr_thread_mutex_create(&requestStackMutexG, APR_THREAD_MUTEX_DEFAULT, aos_global_pool)) != APR_SUCCESS) {
|
||||
aos_error_log("apr_thread_mutex_create failure, code:%d %s.\n", s, apr_strerror(s, buf, sizeof(buf)));
|
||||
return AOSE_INTERNAL_ERROR;
|
||||
}
|
||||
requestStackCountG = 0;
|
||||
|
||||
apr_snprintf(aos_user_agent, sizeof(aos_user_agent)-1, "%s(Compatible %s)",
|
||||
AOS_VER, user_agent_info);
|
||||
|
||||
req_options = aos_http_request_options_create(aos_global_pool);
|
||||
trans_options = aos_http_transport_options_create(aos_global_pool);
|
||||
trans_options->user_agent = aos_user_agent;
|
||||
|
||||
aos_set_default_request_options(req_options);
|
||||
aos_set_default_transport_options(trans_options);
|
||||
|
||||
return AOSE_OK;
|
||||
}
|
||||
|
||||
void aos_http_io_deinitialize()
|
||||
{
|
||||
apr_thread_mutex_destroy(requestStackMutexG);
|
||||
|
||||
while (requestStackCountG--) {
|
||||
curl_easy_cleanup(requestStackG[requestStackCountG]);
|
||||
}
|
||||
|
||||
if (aos_stderr_file != NULL) {
|
||||
apr_file_close(aos_stderr_file);
|
||||
aos_stderr_file = NULL;
|
||||
}
|
||||
if (aos_global_pool != NULL) {
|
||||
aos_pool_destroy(aos_global_pool);
|
||||
aos_global_pool = NULL;
|
||||
}
|
||||
apr_terminate();
|
||||
}
|
||||
|
||||
int aos_http_send_request(aos_http_controller_t *ctl, aos_http_request_t *req, aos_http_response_t *resp)
|
||||
{
|
||||
aos_http_transport_t *t;
|
||||
|
||||
t = aos_http_transport_create(ctl->pool);
|
||||
t->req = req;
|
||||
t->resp = resp;
|
||||
t->controller = (aos_http_controller_ex_t *)ctl;
|
||||
|
||||
return aos_http_transport_perform(t);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user