lnk commit front code

This commit is contained in:
lnk
2025-01-16 16:17:01 +08:00
commit 1776a2bf0d
587 changed files with 257079 additions and 0 deletions

187
include/oss_sdk/aos_buf.c Normal file
View File

@@ -0,0 +1,187 @@
#include "aos_buf.h"
#include "aos_log.h"
#include <apr_file_io.h>
aos_buf_t *aos_create_buf(aos_pool_t *p, int size)
{
aos_buf_t* b;
b = aos_palloc(p, sizeof(aos_buf_t) + size);
if (b == NULL) {
return NULL;
}
b->pos = (uint8_t *)b + sizeof(aos_buf_t);
b->start = b->pos;
b->last = b->start;
b->end = b->last + size;
aos_list_init(&b->node);
return b;
}
aos_buf_t *aos_buf_pack(aos_pool_t *p, const void *data, int size)
{
aos_buf_t* b;
b = aos_palloc(p, sizeof(aos_buf_t));
if (b == NULL) {
return NULL;
}
b->pos = (uint8_t *)data;
b->start = b->pos;
b->last = b->start + size;
b->end = b->last;
aos_list_init(&b->node);
return b;
}
int64_t aos_buf_list_len(aos_list_t *list)
{
aos_buf_t *b;
int64_t len = 0;
aos_list_for_each_entry(aos_buf_t, b, list, node) {
len += aos_buf_size(b);
}
return len;
}
char *aos_buf_list_content(aos_pool_t *p, aos_list_t *list)
{
int64_t body_len;
char *buf;
int64_t pos = 0;
int64_t size = 0;
aos_buf_t *content;
body_len = aos_buf_list_len(list);
buf = aos_pcalloc(p, (size_t)(body_len + 1));
buf[body_len] = '\0';
aos_list_for_each_entry(aos_buf_t, content, list, node) {
size = aos_buf_size(content);
memcpy(buf + pos, content->pos, (size_t)(size));
pos += size;
}
return buf;
}
aos_file_buf_t *aos_create_file_buf(aos_pool_t *p)
{
return (aos_file_buf_t*)aos_pcalloc(p, sizeof(aos_file_buf_t));
}
int aos_open_file_for_read(aos_pool_t *p, const char *path, aos_file_buf_t *fb)
{
int s;
char buf[256];
apr_finfo_t finfo;
if ((s = apr_file_open(&fb->file, path, APR_READ, APR_UREAD | APR_GREAD, p)) != APR_SUCCESS) {
aos_error_log("apr_file_open failure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
assert(fb->file == NULL);
return AOSE_OPEN_FILE_ERROR;
}
if ((s = apr_file_info_get(&finfo, APR_FINFO_NORM, fb->file)) != APR_SUCCESS) {
apr_file_close(fb->file);
aos_error_log("apr_file_open failure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
return AOSE_FILE_INFO_ERROR;
}
fb->file_pos = 0;
fb->file_last = finfo.size;
fb->owner = 1;
return AOSE_OK;
}
int aos_open_file_for_all_read(aos_pool_t *p, const char *path, aos_file_buf_t *fb)
{
return aos_open_file_for_read(p, path, fb);
}
int aos_open_file_for_range_read(aos_pool_t *p, const char *path,
int64_t file_pos, int64_t file_last, aos_file_buf_t *fb)
{
int s;
s = aos_open_file_for_read(p, path, fb);
if (s == AOSE_OK) {
if (file_pos > fb->file_pos) {
if (file_pos > fb->file_last) {
aos_warn_log("read range beyond file size, read start:%" APR_INT64_T_FMT ", file size:%" APR_INT64_T_FMT "\n",
file_pos, fb->file_last);
file_pos = fb->file_last;
}
fb->file_pos = file_pos;
}
if (file_last < fb->file_last) {
fb->file_last = file_last;
}
apr_file_seek(fb->file, APR_SET, (apr_off_t *)&fb->file_pos);
}
return s;
}
int aos_open_file_for_write(aos_pool_t *p, const char *path, aos_file_buf_t *fb)
{
int s;
char buf[256];
if ((s = apr_file_open(&fb->file, path, APR_CREATE | APR_WRITE | APR_TRUNCATE,
APR_UREAD | APR_UWRITE | APR_GREAD, p)) != APR_SUCCESS) {
aos_error_log("apr_file_open failure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
assert(fb->file == NULL);
return AOSE_OPEN_FILE_ERROR;
}
fb->owner = 1;
return AOSE_OK;
}
int aos_open_file_for_write_notrunc(aos_pool_t *p, const char *path, aos_file_buf_t *fb)
{
int s;
char buf[256];
if ((s = apr_file_open(&fb->file, path, APR_CREATE | APR_WRITE,
APR_UREAD | APR_UWRITE | APR_GREAD, p)) != APR_SUCCESS) {
aos_error_log("apr_file_open failure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
assert(fb->file == NULL);
return AOSE_OPEN_FILE_ERROR;
}
fb->owner = 1;
return AOSE_OK;
}
void aos_buf_append_string(aos_pool_t *p, aos_buf_t *b, const char *str, int len)
{
int size;
int nsize;
int remain;
char *buf;
if (len <= 0) return;
remain = b->end - b->last;
if (remain > len + 128) {
memcpy(b->last, str, len);
b->last += len;
} else {
size = aos_buf_size(b);
nsize = (size + len) * 2;
buf = aos_palloc(p, nsize);
memcpy(buf, b->pos, size);
memcpy(buf+size, str, len);
b->start = (uint8_t *)buf;
b->end = (uint8_t *)buf + nsize;
b->pos = (uint8_t *)buf;
b->last = (uint8_t *)buf + size + len;
}
}

67
include/oss_sdk/aos_buf.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef LIBAOS_BUF_H
#define LIBAOS_BUF_H
#include "aos_define.h"
#include "aos_list.h"
AOS_CPP_START
typedef struct {
aos_list_t node;
uint8_t *pos;
uint8_t *last;
uint8_t *start;
uint8_t *end;
} aos_buf_t;
typedef struct {
aos_list_t node;
int64_t file_pos;
int64_t file_last;
apr_file_t *file;
uint32_t owner:1;
} aos_file_buf_t;
aos_buf_t *aos_create_buf(aos_pool_t *p, int size);
#define aos_buf_size(b) (b->last - b->pos)
aos_file_buf_t *aos_create_file_buf(aos_pool_t *p);
aos_buf_t *aos_buf_pack(aos_pool_t *p, const void *data, int size);
int64_t aos_buf_list_len(aos_list_t *list);
char *aos_buf_list_content(aos_pool_t *p, aos_list_t *list);
void aos_buf_append_string(aos_pool_t *p, aos_buf_t *b, const char *str, int len);
/**
* @param fb file_pos, file_last equal file_size.
* @return AOSE_OK success, other failure.
*/
int aos_open_file_for_read(aos_pool_t *p, const char *path, aos_file_buf_t *fb);
int aos_open_file_for_all_read(aos_pool_t *p, const char *path, aos_file_buf_t *fb);
int aos_open_file_for_range_read(aos_pool_t *p, const char *path,
int64_t file_pos, int64_t file_last,
aos_file_buf_t *fb);
/**
* create the file if not there, truncate if file exists.
* @param fb not check file_pos, file_last.
* @return AOSE_OK success, other failure.
*/
int aos_open_file_for_write(aos_pool_t *p, const char *path, aos_file_buf_t *fb);
/**
* create the file if not there.
* @param fb not check file_pos, file_last.
* @return AOSE_OK success, other failure.
*/
int aos_open_file_for_write_notrunc(aos_pool_t *p, const char *path, aos_file_buf_t *fb);
AOS_CPP_END
#endif

288
include/oss_sdk/aos_crc64.c Normal file
View File

@@ -0,0 +1,288 @@
/* aos_crc64.c -- compute CRC-64
* Copyright (C) 2013 Mark Adler
* Version 1.4 16 Dec 2013 Mark Adler
*/
/*
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler
madler@alumni.caltech.edu
*/
/* Compute CRC-64 in the manner of xz, using the ECMA-182 polynomial,
bit-reversed, with one's complement pre and post processing. Provide a
means to combine separately computed CRC-64's. */
/* Version history:
1.0 13 Dec 2013 First version
1.1 13 Dec 2013 Fix comments in test code
1.2 14 Dec 2013 Determine endianess at run time
1.3 15 Dec 2013 Add eight-byte processing for big endian as well
Make use of the pthread library optional
1.4 16 Dec 2013 Make once variable volatile for limited thread protection
*/
#include "aos_crc64.h"
/* 64-bit CRC polynomial with these coefficients, but reversed:
64, 62, 57, 55, 54, 53, 52, 47, 46, 45, 40, 39, 38, 37, 35, 33, 32,
31, 29, 27, 24, 23, 22, 21, 19, 17, 13, 12, 10, 9, 7, 4, 1, 0 */
#define POLY UINT64_C(0xc96c5795d7870f42)
/* Tables for CRC calculation -- filled in by initialization functions that are
called once. These could be replaced by constant tables generated in the
same way. There are two tables, one for each endianess. Since these are
static, i.e. local, one should be compiled out of existence if the compiler
can evaluate the endianess check in crc64() at compile time. */
static uint64_t crc64_little_table[8][256];
static uint64_t crc64_big_table[8][256];
/* Fill in the CRC-64 constants table. */
static void crc64_init(uint64_t table[][256])
{
unsigned n, k;
uint64_t crc;
/* generate CRC-64's for all single byte sequences */
for (n = 0; n < 256; n++) {
crc = n;
for (k = 0; k < 8; k++)
crc = crc & 1 ? POLY ^ (crc >> 1) : crc >> 1;
table[0][n] = crc;
}
/* generate CRC-64's for those followed by 1 to 7 zeros */
for (n = 0; n < 256; n++) {
crc = table[0][n];
for (k = 1; k < 8; k++) {
crc = table[0][crc & 0xff] ^ (crc >> 8);
table[k][n] = crc;
}
}
}
/* This function is called once to initialize the CRC-64 table for use on a
little-endian architecture. */
static void crc64_little_init(void)
{
crc64_init(crc64_little_table);
}
/* Reverse the bytes in a 64-bit word. */
static APR_INLINE uint64_t rev8(uint64_t a)
{
uint64_t m;
m = UINT64_C(0xff00ff00ff00ff);
a = ((a >> 8) & m) | (a & m) << 8;
m = UINT64_C(0xffff0000ffff);
a = ((a >> 16) & m) | (a & m) << 16;
return a >> 32 | a << 32;
}
/* This function is called once to initialize the CRC-64 table for use on a
big-endian architecture. */
static void crc64_big_init(void)
{
unsigned k, n;
crc64_init(crc64_big_table);
for (k = 0; k < 8; k++)
for (n = 0; n < 256; n++)
crc64_big_table[k][n] = rev8(crc64_big_table[k][n]);
}
/* Run the init() function exactly once. If pthread.h is not included, then
this macro will use a simple static state variable for the purpose, which is
not thread-safe. The init function must be of the type void init(void). */
#ifdef PTHREAD_ONCE_INIT
# define ONCE(init) \
do { \
static pthread_once_t once = PTHREAD_ONCE_INIT; \
pthread_once(&once, init); \
} while (0)
#else
# define ONCE(init) \
do { \
static volatile int once = 1; \
if (once) { \
if (once++ == 1) { \
init(); \
once = 0; \
} \
else \
while (once) \
; \
} \
} while (0)
#endif
/* Calculate a CRC-64 eight bytes at a time on a little-endian architecture. */
static APR_INLINE uint64_t crc64_little(uint64_t crc, void *buf, size_t len)
{
unsigned char *next = buf;
ONCE(crc64_little_init);
crc = ~crc;
while (len && ((uintptr_t)next & 7) != 0) {
crc = crc64_little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
while (len >= 8) {
crc ^= *(uint64_t *)next;
crc = crc64_little_table[7][crc & 0xff] ^
crc64_little_table[6][(crc >> 8) & 0xff] ^
crc64_little_table[5][(crc >> 16) & 0xff] ^
crc64_little_table[4][(crc >> 24) & 0xff] ^
crc64_little_table[3][(crc >> 32) & 0xff] ^
crc64_little_table[2][(crc >> 40) & 0xff] ^
crc64_little_table[1][(crc >> 48) & 0xff] ^
crc64_little_table[0][crc >> 56];
next += 8;
len -= 8;
}
while (len) {
crc = crc64_little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
return ~crc;
}
/* Calculate a CRC-64 eight bytes at a time on a big-endian architecture. */
static APR_INLINE uint64_t crc64_big(uint64_t crc, void *buf, size_t len)
{
unsigned char *next = buf;
ONCE(crc64_big_init);
crc = ~rev8(crc);
while (len && ((uintptr_t)next & 7) != 0) {
crc = crc64_big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
len--;
}
while (len >= 8) {
crc ^= *(uint64_t *)next;
crc = crc64_big_table[0][crc & 0xff] ^
crc64_big_table[1][(crc >> 8) & 0xff] ^
crc64_big_table[2][(crc >> 16) & 0xff] ^
crc64_big_table[3][(crc >> 24) & 0xff] ^
crc64_big_table[4][(crc >> 32) & 0xff] ^
crc64_big_table[5][(crc >> 40) & 0xff] ^
crc64_big_table[6][(crc >> 48) & 0xff] ^
crc64_big_table[7][crc >> 56];
next += 8;
len -= 8;
}
while (len) {
crc = crc64_big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
len--;
}
return ~rev8(crc);
}
/* Return the CRC-64 of buf[0..len-1] with initial crc, processing eight bytes
at a time. This selects one of two routines depending on the endianess of
the architecture. A good optimizing compiler will determine the endianess
at compile time if it can, and get rid of the unused code and table. If the
endianess can be changed at run time, then this code will handle that as
well, initializing and using two tables, if called upon to do so. */
uint64_t aos_crc64(uint64_t crc, void *buf, size_t len)
{
uint64_t n = 1;
return *(char *)&n ? crc64_little(crc, buf, len) :
crc64_big(crc, buf, len);
}
#define GF2_DIM 64 /* dimension of GF(2) vectors (length of CRC) */
static uint64_t gf2_matrix_times(uint64_t *mat, uint64_t vec)
{
uint64_t sum;
sum = 0;
while (vec) {
if (vec & 1)
sum ^= *mat;
vec >>= 1;
mat++;
}
return sum;
}
static void gf2_matrix_square(uint64_t *square, uint64_t *mat)
{
unsigned n;
for (n = 0; n < GF2_DIM; n++)
square[n] = gf2_matrix_times(mat, mat[n]);
}
/* Return the CRC-64 of two sequential blocks, where crc1 is the CRC-64 of the
first block, crc2 is the CRC-64 of the second block, and len2 is the length
of the second block. */
uint64_t aos_crc64_combine(uint64_t crc1, uint64_t crc2, uintmax_t len2)
{
unsigned n;
uint64_t row;
uint64_t even[GF2_DIM]; /* even-power-of-two zeros operator */
uint64_t odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case */
if (len2 == 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = POLY; /* CRC-64 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
row <<= 1;
}
/* put operator for two zero bits in even */
gf2_matrix_square(even, odd);
/* put operator for four zero bits in odd */
gf2_matrix_square(odd, even);
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte, eight zero bits, in even) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square(even, odd);
if (len2 & 1)
crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
/* if no more bits set, then done */
if (len2 == 0)
break;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square(odd, even);
if (len2 & 1)
crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
/* if no more bits set, then done */
} while (len2 != 0);
/* return combined crc */
crc1 ^= crc2;
return crc1;
}

View File

@@ -0,0 +1,13 @@
#ifndef LIBAOS_CRC_H
#define LIBAOS_CRC_H
#include "aos_define.h"
AOS_CPP_START
uint64_t aos_crc64(uint64_t crc, void *buf, size_t len);
uint64_t aos_crc64_combine(uint64_t crc1, uint64_t crc2, uintmax_t len2);
AOS_CPP_END
#endif

View File

@@ -0,0 +1,152 @@
#ifndef LIBAOS_DEFINE_H
#define LIBAOS_DEFINE_H
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <apr_time.h>
#include <apr_strings.h>
#include <apr_pools.h>
#include <apr_tables.h>
#include <apr_file_io.h>
#include <curl/curl.h>
#ifdef __cplusplus
# define AOS_CPP_START extern "C" {
# define AOS_CPP_END }
#else
# define AOS_CPP_START
# define AOS_CPP_END
#endif
typedef enum {
HTTP_GET,
HTTP_HEAD,
HTTP_PUT,
HTTP_POST,
HTTP_DELETE
} http_method_e;
typedef enum {
AOSE_OK = 0,
AOSE_OUT_MEMORY = -1000,
AOSE_OVER_MEMORY = -999,
AOSE_FAILED_CONNECT = -998,
AOSE_ABORT_CALLBACK = -997,
AOSE_INTERNAL_ERROR = -996,
AOSE_REQUEST_TIMEOUT = -995,
AOSE_INVALID_ARGUMENT = -994,
AOSE_INVALID_OPERATION = -993,
AOSE_CONNECTION_FAILED = -992,
AOSE_FAILED_INITIALIZE = -991,
AOSE_NAME_LOOKUP_ERROR = -990,
AOSE_FAILED_VERIFICATION = -989,
AOSE_WRITE_BODY_ERROR = -988,
AOSE_READ_BODY_ERROR = -987,
AOSE_SERVICE_ERROR = -986,
AOSE_OPEN_FILE_ERROR = -985,
AOSE_FILE_SEEK_ERROR = -984,
AOSE_FILE_INFO_ERROR = -983,
AOSE_FILE_READ_ERROR = -982,
AOSE_FILE_WRITE_ERROR = -981,
AOSE_XML_PARSE_ERROR = -980,
AOSE_UTF8_ENCODE_ERROR = -979,
AOSE_CRC_INCONSISTENT_ERROR = -978,
AOSE_FILE_FLUSH_ERROR = -977,
AOSE_FILE_TRUNC_ERROR = -976,
AOSE_UNKNOWN_ERROR = -100
} aos_error_code_e;
typedef apr_pool_t aos_pool_t;
typedef apr_table_t aos_table_t;
typedef apr_table_entry_t aos_table_entry_t;
typedef apr_array_header_t aos_array_header_t;
#define aos_table_elts(t) apr_table_elts(t)
#define aos_is_empty_table(t) apr_is_empty_table(t)
#define aos_table_make(p, n) apr_table_make(p, n)
#define aos_table_add_int(t, key, value) do { \
char value_str[64]; \
apr_snprintf(value_str, sizeof(value_str), "%d", value);\
apr_table_add(t, key, value_str); \
} while(0)
#define aos_table_add_int64(t, key, value) do { \
char value_str[64]; \
apr_snprintf(value_str, sizeof(value_str), "%" APR_INT64_T_FMT, value);\
apr_table_add(t, key, value_str); \
} while(0)
#define aos_table_set_int64(t, key, value) do { \
char value_str[64]; \
apr_snprintf(value_str, sizeof(value_str), "%" APR_INT64_T_FMT, value);\
apr_table_set(t, key, value_str); \
} while(0)
#define aos_pool_create(n, p) apr_pool_create(n, p)
#define aos_pool_destroy(p) apr_pool_destroy(p)
#define aos_palloc(p, s) apr_palloc(p, s)
#define aos_pcalloc(p, s) apr_pcalloc(p, s)
#define AOS_INIT_WINSOCK 1
#define AOS_MD5_STRING_LEN 32
#define AOS_MAX_URI_LEN 2048
#define AOS_MAX_HEADER_LEN 8192
#define AOS_MAX_QUERY_ARG_LEN 1024
#define AOS_MAX_GMT_TIME_LEN 128
#define AOS_MAX_XML_NODE_VALUE_LEN 1024
#define AOS_MAX_INT64_STRING_LEN 64
#define AOS_MAX_UINT64_STRING_LEN 64
#define AOS_CONNECT_TIMEOUT 10
#define AOS_DNS_CACHE_TIMOUT 60
#define AOS_MIN_SPEED_LIMIT 1024
#define AOS_MIN_SPEED_TIME 15
#define AOS_MAX_MEMORY_SIZE 1024*1024*1024L
#define AOS_MAX_PART_SIZE 512*1024*1024L
#define AOS_DEFAULT_PART_SIZE 1024*1024L
#define AOS_REQUEST_STACK_SIZE 32
#define aos_abs(value) (((value) >= 0) ? (value) : - (value))
#define aos_max(val1, val2) (((val1) < (val2)) ? (val2) : (val1))
#define aos_min(val1, val2) (((val1) > (val2)) ? (val2) : (val1))
#define LF (char) 10
#define CR (char) 13
#define CRLF "\x0d\x0a"
#define AOS_VERSION "3.5.0"
#define AOS_VER "aliyun-sdk-c/" AOS_VERSION
#define AOS_HTTP_PREFIX "http://"
#define AOS_HTTPS_PREFIX "https://"
#define AOS_RTMP_PREFIX "rtmp://"
#define AOS_TEMP_FILE_SUFFIX ".tmp"
#define AOS_FALSE 0
#define AOS_TRUE 1
# ifndef WIN32
# ifndef __LONG_LONG_MAX__
# define __LONG_LONG_MAX__ 9223372036854775807LL
# endif
# ifndef LLONG_MIN
# define LLONG_MIN (-LLONG_MAX-1)
# endif
# ifndef LLONG_MAX
# define LLONG_MAX __LONG_LONG_MAX__
# endif
# ifndef ULLONG_MAX
# define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
# endif
# endif
#endif

View File

@@ -0,0 +1,50 @@
#include "aos_fstack.h"
aos_array_header_t *aos_fstack_create(aos_pool_t *p, int size)
{
return apr_array_make(p, size, sizeof(aos_fstack_item_t));
}
void aos_fstack_push(aos_array_header_t *fstack, void *data, aos_func_u func, int order)
{
aos_fstack_item_t *item;
item = (aos_fstack_item_t*)apr_array_push(fstack);
item->data = data;
item->func = func;
item->order = order;
}
aos_fstack_item_t *aos_fstack_pop(aos_array_header_t *fstack)
{
aos_fstack_item_t *item;
item = (aos_fstack_item_t*)apr_array_pop(fstack);
if (item == NULL) {
return NULL;
}
switch (item->order) {
case 1:
item->func.func1(item->data);
break;
case 2:
item->func.func2();
break;
case 3:
item->func.func3(item->data);
break;
case 4:
item->func.func4();
break;
default:
break;
}
return item;
}
void aos_fstack_destory(aos_array_header_t *fstack)
{
while (aos_fstack_pop(fstack) != NULL);
}

View File

@@ -0,0 +1,36 @@
#ifndef LIBAOS_FSTACK_H
#define LIBAOS_FSTACK_H
#include "aos_define.h"
AOS_CPP_START
typedef void (*aos_func1_pt)(void*);
typedef void (*aos_func2_pt)();
typedef int (*aos_func3_pt)(void*);
typedef int (*aos_func4_pt)();
typedef union aos_func_u {
aos_func1_pt func1;
aos_func2_pt func2;
aos_func3_pt func3;
aos_func4_pt func4;
} aos_func_u;
typedef struct aos_fstack_item_t {
void *data;
aos_func_u func;
int order;
} aos_fstack_item_t;
aos_array_header_t *aos_fstack_create(aos_pool_t *p, int size);
aos_fstack_item_t *aos_fstack_pop(aos_array_header_t *fstack);
void aos_fstack_destory(aos_array_header_t *fstack);
void aos_fstack_push(aos_array_header_t *fstack, void *data, aos_func_u func, int order);
AOS_CPP_END
#endif

View 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);
}

View File

@@ -0,0 +1,55 @@
#ifndef LIBAOS_HTTP_IO_H
#define LIBAOS_HTTP_IO_H
#include "aos_transport.h"
#include "oss_define.h"
AOS_CPP_START
aos_http_controller_t *aos_http_controller_create(aos_pool_t *p, int owner);
/* http io error message*/
static APR_INLINE const char *aos_http_controller_get_reason(aos_http_controller_t *ctl)
{
aos_http_controller_ex_t *ctle = (aos_http_controller_ex_t *)ctl;
return ctle->reason;
}
CURL *aos_request_get();
void request_release(CURL *request);
int aos_http_io_initialize(const char *user_agent_info, int flag);
void aos_http_io_deinitialize();
int aos_http_send_request(aos_http_controller_t *ctl, aos_http_request_t *req, aos_http_response_t *resp);
void aos_set_default_request_options(aos_http_request_options_t *op);
void aos_set_default_transport_options(aos_http_transport_options_t *op);
aos_http_request_options_t *aos_http_request_options_create(aos_pool_t *p);
aos_http_request_t *aos_http_request_create(aos_pool_t *p);
aos_http_response_t *aos_http_response_create(aos_pool_t *p);
int aos_read_http_body_memory(aos_http_request_t *req, char *buffer, int len);
int aos_write_http_body_memory(aos_http_response_t *resp, const char *buffer, int len);
int aos_read_http_body_file(aos_http_request_t *req, char *buffer, int len);
int aos_write_http_body_file(aos_http_response_t *resp, const char *buffer, int len);
typedef aos_http_transport_t *(*aos_http_transport_create_pt)(aos_pool_t *p);
typedef int (*aos_http_transport_perform_pt)(aos_http_transport_t *t);
extern aos_pool_t *aos_global_pool;
extern apr_file_t *aos_stderr_file;
extern aos_http_request_options_t *aos_default_http_request_options;
extern aos_http_transport_options_t *aos_default_http_transport_options;
extern aos_http_transport_create_pt aos_http_transport_create;
extern aos_http_transport_perform_pt aos_http_transport_perform;
AOS_CPP_END
#endif

101
include/oss_sdk/aos_list.h Normal file
View File

@@ -0,0 +1,101 @@
#ifndef LIBAOS_LIST_H
#define LIBAOS_LIST_H
#include <apr_general.h>
// from kernel list
typedef struct aos_list_s aos_list_t;
struct aos_list_s {
aos_list_t *next, *prev;
};
#define aos_list_head_init(name) {&(name), &(name)}
#define aos_list_init(ptr) do { \
(ptr)->next = (ptr); \
(ptr)->prev = (ptr); \
} while (0)
static APR_INLINE void __aos_list_add(aos_list_t *list, aos_list_t *prev, aos_list_t *next)
{
next->prev = list;
list->next = next;
list->prev = prev;
prev->next = list;
}
// list head to add it before
static APR_INLINE void aos_list_add_tail(aos_list_t *list, aos_list_t *head)
{
__aos_list_add(list, head->prev, head);
}
static APR_INLINE void __aos_list_del(aos_list_t *prev, aos_list_t *next)
{
next->prev = prev;
prev->next = next;
}
// deletes entry from list
static APR_INLINE void aos_list_del(aos_list_t *entry)
{
__aos_list_del(entry->prev, entry->next);
aos_list_init(entry);
}
// tests whether a list is empty
static APR_INLINE int aos_list_empty(const aos_list_t *head)
{
return (head->next == head);
}
// move list to new_list
static APR_INLINE void aos_list_movelist(aos_list_t *list, aos_list_t *new_list)
{
if (!aos_list_empty(list)) {
new_list->prev = list->prev;
new_list->next = list->next;
new_list->prev->next = new_list;
new_list->next->prev = new_list;
aos_list_init(list);
} else {
aos_list_init(new_list);
}
}
// get last
#define aos_list_get_last(list, type, member) \
aos_list_empty(list) ? NULL : aos_list_entry((list)->prev, type, member)
// get first
#define aos_list_get_first(list, type, member) \
aos_list_empty(list) ? NULL : aos_list_entry((list)->next, type, member)
#define aos_list_entry(ptr, type, member) \
(type *)( (char *)ptr - APR_OFFSETOF(type, member) )
// traversing
#define aos_list_for_each_entry(postp, pos, head, member) \
for (pos = aos_list_entry((head)->next, postp, member); \
&pos->member != (head); \
pos = aos_list_entry(pos->member.next, postp, member))
#define aos_list_for_each_entry_reverse(postp, pos, head, member) \
for (pos = aos_list_entry((head)->prev, postp, member); \
&pos->member != (head); \
pos = aos_list_entry(pos->member.prev, postp, member))
#define aos_list_for_each_entry_safe(postp, pos, n, head, member) \
for (pos = aos_list_entry((head)->next, postp, member), \
n = aos_list_entry(pos->member.next, postp, member); \
&pos->member != (head); \
pos = n, n = aos_list_entry(n->member.next, postp, member))
#define aos_list_for_each_entry_safe_reverse(postp, pos, n, head, member) \
for (pos = aos_list_entry((head)->prev, postp, member), \
n = aos_list_entry(pos->member.prev, postp, member); \
&pos->member != (head); \
pos = n, n = aos_list_entry(n->member.prev, postp, member))
#endif

73
include/oss_sdk/aos_log.c Normal file
View File

@@ -0,0 +1,73 @@
#include "aos_log.h"
#include "apr_portable.h"
aos_log_print_pt aos_log_print = aos_log_print_default;
aos_log_format_pt aos_log_format = aos_log_format_default;
aos_log_level_e aos_log_level = AOS_LOG_WARN;
extern apr_file_t *aos_stderr_file;
void aos_log_set_print(aos_log_print_pt p)
{
aos_log_print = p;
}
void aos_log_set_format(aos_log_format_pt p)
{
aos_log_format = p;
}
void aos_log_set_level(aos_log_level_e level)
{
aos_log_level = level;
}
void aos_log_set_output(apr_file_t *output)
{
aos_stderr_file = output;
}
void aos_log_print_default(const char *message, int len)
{
if (aos_stderr_file == NULL) {
fprintf(stderr, "%s", message);
} else {
apr_size_t bnytes = len;
apr_file_write(aos_stderr_file, message, &bnytes);
}
}
void aos_log_format_default(int level,
const char *file,
int line,
const char *function,
const char *fmt, ...)
{
int len;
apr_time_t t;
int s;
apr_time_exp_t tm;
va_list args;
char buffer[4096];
t = apr_time_now();
if ((s = apr_time_exp_lt(&tm, t)) != APR_SUCCESS) {
return;
}
len = apr_snprintf(buffer, 4090, "[%04d-%02d-%02d %02d:%02d:%02d.%03d] %" APR_INT64_T_FMT " %s:%d ",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
(int64_t)apr_os_thread_current(), file, line);
va_start(args, fmt);
len += vsnprintf(buffer + len, 4090 - len, fmt, args);
va_end(args);
while (buffer[len -1] == '\n') len--;
buffer[len++] = '\n';
buffer[len] = '\0';
aos_log_print(buffer, len);
}

78
include/oss_sdk/aos_log.h Normal file
View File

@@ -0,0 +1,78 @@
#ifndef LIBAOS_LOG_H
#define LIBAOS_LOG_H
#include "aos_define.h"
AOS_CPP_START
typedef void (*aos_log_print_pt)(const char *message, int len);
typedef void (*aos_log_format_pt)(int level,
const char *file,
int line,
const char *function,
const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 5, 6)));
void aos_log_set_print(aos_log_print_pt p);
void aos_log_set_format(aos_log_format_pt p);
typedef enum {
AOS_LOG_OFF = 1,
AOS_LOG_FATAL,
AOS_LOG_ERROR,
AOS_LOG_WARN,
AOS_LOG_INFO,
AOS_LOG_DEBUG,
AOS_LOG_TRACE,
AOS_LOG_ALL
} aos_log_level_e;
#ifdef WIN32
#define aos_fatal_log(format, ...) if(aos_log_level>=AOS_LOG_FATAL) \
aos_log_format(AOS_LOG_FATAL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define aos_error_log(format, ...) if(aos_log_level>=AOS_LOG_ERROR) \
aos_log_format(AOS_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define aos_warn_log(format, ...) if(aos_log_level>=AOS_LOG_WARN) \
aos_log_format(AOS_LOG_WARN, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define aos_info_log(format, ...) if(aos_log_level>=AOS_LOG_INFO) \
aos_log_format(AOS_LOG_INFO, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define aos_debug_log(format, ...) if(aos_log_level>=AOS_LOG_DEBUG) \
aos_log_format(AOS_LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define aos_trace_log(format, ...) if(aos_log_level>=AOS_LOG_TRACE) \
aos_log_format(AOS_LOG_TRACE, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#else
#define aos_fatal_log(format, args...) if(aos_log_level>=AOS_LOG_FATAL) \
aos_log_format(AOS_LOG_FATAL, __FILE__, __LINE__, __FUNCTION__, format, ## args)
#define aos_error_log(format, args...) if(aos_log_level>=AOS_LOG_ERROR) \
aos_log_format(AOS_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, format, ## args)
#define aos_warn_log(format, args...) if(aos_log_level>=AOS_LOG_WARN) \
aos_log_format(AOS_LOG_WARN, __FILE__, __LINE__, __FUNCTION__, format, ## args)
#define aos_info_log(format, args...) if(aos_log_level>=AOS_LOG_INFO) \
aos_log_format(AOS_LOG_INFO, __FILE__, __LINE__, __FUNCTION__, format, ## args)
#define aos_debug_log(format, args...) if(aos_log_level>=AOS_LOG_DEBUG) \
aos_log_format(AOS_LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, format, ## args)
#define aos_trace_log(format, args...) if(aos_log_level>=AOS_LOG_TRACE) \
aos_log_format(AOS_LOG_TRACE, __FILE__, __LINE__, __FUNCTION__, format, ## args)
#endif
void aos_log_set_level(aos_log_level_e level);
void aos_log_set_output(apr_file_t *output);
void aos_log_print_default(const char *message, int len);
void aos_log_format_default(int level,
const char *file,
int line,
const char *function,
const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 5, 6)));
extern aos_log_level_e aos_log_level;
extern aos_log_format_pt aos_log_format;
extern aos_log_format_pt aos_log_format;
AOS_CPP_END
#endif

View File

@@ -0,0 +1,108 @@
#include "aos_log.h"
#include "aos_util.h"
#include "aos_status.h"
const char AOS_XML_PARSE_ERROR_CODE[] = "ParseXmlError";
const char AOS_OPEN_FILE_ERROR_CODE[] = "OpenFileFail";
const char AOS_WRITE_FILE_ERROR_CODE[] = "WriteFileFail";
const char AOS_RENAME_FILE_ERROR_CODE[] = "RenameFileFail";
const char AOS_HTTP_IO_ERROR_CODE[] = "HttpIoError";
const char AOS_UNKNOWN_ERROR_CODE[] = "UnknownError";
const char AOS_CLIENT_ERROR_CODE[] = "ClientError";
const char AOS_SERVER_ERROR_CODE[] = "ServerError";
const char AOS_UTF8_ENCODE_ERROR_CODE[] = "Utf8EncodeFail";
const char AOS_URL_ENCODE_ERROR_CODE[] = "UrlEncodeFail";
const char AOS_INCONSISTENT_ERROR_CODE[] = "InconsistentError";
const char AOS_CREATE_QUEUE_ERROR_CODE[] = "CreateQueueFail";
const char AOS_CREATE_THREAD_POOL_ERROR_CODE[] = "CreateThreadPoolFail";
aos_status_t *aos_status_create(aos_pool_t *p)
{
return (aos_status_t *)aos_pcalloc(p, sizeof(aos_status_t));
}
aos_status_t *aos_status_dup(aos_pool_t *p, aos_status_t *src)
{
aos_status_t *dst = aos_status_create(p);
dst->code = src->code;
dst->error_code = apr_pstrdup(p, src->error_code);
dst->error_msg = apr_pstrdup(p, src->error_msg);
return dst;
}
int aos_should_retry(aos_status_t *s) {
int aos_error_code = 0;
// HTTP Error
if (s == NULL || s->code / 100 == 2) {
return AOS_FALSE;
}
// OSS Error
if (s->code / 100 == 5) {
return AOS_TRUE;
}
// Curl Error
if (s->code != AOSE_OK) {
if (s->code == AOSE_CONNECTION_FAILED || s->code == AOSE_REQUEST_TIMEOUT ||
s->code == AOSE_FAILED_CONNECT || s->code == AOSE_SERVICE_ERROR) {
return AOS_TRUE;
}
}
return AOS_FALSE;
}
aos_status_t *aos_status_parse_from_body(aos_pool_t *p, aos_list_t *bc, int code, aos_status_t *s)
{
int res;
mxml_node_t *root, *node;
mxml_node_t *code_node, *message_node;
char *node_content;
if (s == NULL) {
s = aos_status_create(p);
}
s->code = code;
if (aos_http_is_ok(code)) {
return s;
}
if (aos_list_empty(bc)) {
s->error_code = (char *)AOS_UNKNOWN_ERROR_CODE;
return s;
}
if ((res = aos_parse_xml_body(bc, &root)) != AOSE_OK) {
s->error_code = (char *)AOS_UNKNOWN_ERROR_CODE;
return s;
}
node = mxmlFindElement(root, root, "Error",NULL, NULL,MXML_DESCEND);
if (NULL == node) {
char *xml_content = aos_buf_list_content(p, bc);
aos_error_log("Xml format invalid, root node name is not Error.\n");
aos_error_log("Xml Content:%s\n", xml_content);
s->error_code = (char *)AOS_UNKNOWN_ERROR_CODE;
mxmlDelete(root);
return s;
}
code_node = mxmlFindElement(node, root, "Code",NULL, NULL,MXML_DESCEND);
if (NULL != code_node) {
node_content = code_node->child->value.opaque;
s->error_code = apr_pstrdup(p, (char *)node_content);
}
message_node = mxmlFindElement(node, root, "Message",NULL, NULL,MXML_DESCEND);
if (NULL != message_node) {
node_content = message_node->child->value.opaque;
s->error_msg = apr_pstrdup(p, (char *)node_content);
}
mxmlDelete(root);
return s;
}

View File

@@ -0,0 +1,60 @@
#ifndef LIBAOS_STATUS_H
#define LIBAOS_STATUS_H
#include "aos_define.h"
#include "aos_list.h"
AOS_CPP_START
typedef struct aos_status_s aos_status_t;
struct aos_status_s {
int code; // > 0 http code
char *error_code; // can't modify
char *error_msg; // can't modify
char *req_id; // can't modify
};
static APR_INLINE int aos_status_is_ok(aos_status_t *s)
{
return s->code > 0 && s->code / 100 == 2;
}
static APR_INLINE int aos_http_is_ok(int st)
{
return st / 100 == 2;
}
#define aos_status_set(s, c, ec, es) \
(s)->code = c; (s)->error_code = (char *)ec; (s)->error_msg = (char *)es
/**
* @brief determine whether the request should be retried
* @param[in] s the return status of api, such as oss_put_object_from_buffer
* @return int AOS_FALSE indicates no retries, AOS_TRUE retry
*/
int aos_should_retry(aos_status_t *s);
aos_status_t *aos_status_create(aos_pool_t *p);
aos_status_t *aos_status_dup(aos_pool_t *p, aos_status_t *src);
aos_status_t *aos_status_parse_from_body(aos_pool_t *p, aos_list_t *bc, int code, aos_status_t *s);
extern const char AOS_XML_PARSE_ERROR_CODE[];
extern const char AOS_OPEN_FILE_ERROR_CODE[];
extern const char AOS_WRITE_FILE_ERROR_CODE[];
extern const char AOS_RENAME_FILE_ERROR_CODE[];
extern const char AOS_HTTP_IO_ERROR_CODE[];
extern const char AOS_UNKNOWN_ERROR_CODE[];
extern const char AOS_CLIENT_ERROR_CODE[];
extern const char AOS_SERVER_ERROR_CODE[];
extern const char AOS_UTF8_ENCODE_ERROR_CODE[];
extern const char AOS_URL_ENCODE_ERROR_CODE[];
extern const char AOS_INCONSISTENT_ERROR_CODE[];
extern const char AOS_CREATE_QUEUE_ERROR_CODE[];
extern const char AOS_CREATE_THREAD_POOL_ERROR_CODE[];
AOS_CPP_END
#endif

View File

@@ -0,0 +1,54 @@
#include "aos_string.h"
typedef int (*aos_is_char_pt)(char c);
static void aos_strip_str_func(aos_string_t *str, aos_is_char_pt func);
char *aos_pstrdup(aos_pool_t *p, const aos_string_t *s)
{
return apr_pstrndup(p, s->data, s->len);
}
static void aos_strip_str_func(aos_string_t *str, aos_is_char_pt func)
{
char *data = str->data;
int len = str->len;
int offset = 0;
if (len == 0) return;
while (len > 0 && func(data[len - 1])) {
--len;
}
for (; offset < len && func(data[offset]); ++offset) {
// empty;
}
str->data = data + offset;
str->len = len - offset;
}
void aos_unquote_str(aos_string_t *str)
{
aos_strip_str_func(str, aos_is_quote);
}
void aos_strip_space(aos_string_t *str)
{
aos_strip_str_func(str, aos_is_space);
}
void aos_trip_space_and_cntrl(aos_string_t *str)
{
aos_strip_str_func(str, aos_is_space_or_cntrl);
}
int aos_ends_with(const aos_string_t *str, const aos_string_t *suffix)
{
if (!str || !suffix) {
return 0;
}
return (str->len >= suffix->len) && strncmp(str->data + str->len - suffix->len, suffix->data, suffix->len) == 0;
}

View File

@@ -0,0 +1,75 @@
#ifndef LIBAOS_STRING_H
#define LIBAOS_STRING_H
#include "aos_define.h"
AOS_CPP_START
typedef struct {
int len;
char *data;
} aos_string_t;
#define aos_string(str) { sizeof(str) - 1, (char *) str }
#define aos_null_string { 0, NULL }
#define aos_str_set(str, text) \
(str)->len = strlen(text); (str)->data = (char *) text
#define aos_str_null(str) (str)->len = 0; (str)->data = NULL
#define aos_tolower(c) (char) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
#define aos_toupper(c) (char) ((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)
static APR_INLINE void aos_string_tolower(aos_string_t *str)
{
int i = 0;
while (i < str->len) {
str->data[i] = aos_tolower(str->data[i]);
++i;
}
}
static APR_INLINE char *aos_strlchr(char *p, char *last, char c)
{
while (p < last) {
if (*p == c) {
return p;
}
p++;
}
return NULL;
}
static APR_INLINE int aos_is_quote(char c)
{
return c == '\"';
}
static APR_INLINE int aos_is_space(char c)
{
return ((c == ' ') || (c == '\t'));
}
static APR_INLINE int aos_is_space_or_cntrl(char c)
{
return c <= ' ';
}
static APR_INLINE int aos_is_null_string(aos_string_t *str)
{
if (str == NULL || str->data == NULL || str->len == 0) {
return AOS_TRUE;
}
return AOS_FALSE;
}
void aos_strip_space(aos_string_t *str);
void aos_trip_space_and_cntrl(aos_string_t *str);
void aos_unquote_str(aos_string_t *str);
char *aos_pstrdup(aos_pool_t *p, const aos_string_t *s);
int aos_ends_with(const aos_string_t *str, const aos_string_t *suffix);
AOS_CPP_END
#endif

View File

@@ -0,0 +1,463 @@
#include "aos_log.h"
#include "aos_util.h"
#include "aos_string.h"
#include "aos_http_io.h"
#include "aos_transport.h"
#include "aos_crc64.h"
static int aos_curl_code_to_status(CURLcode code);
static void aos_init_curl_headers(aos_curl_http_transport_t *t);
static void aos_transport_cleanup(aos_http_transport_t *t);
static int aos_init_curl_url(aos_curl_http_transport_t *t);
static void aos_curl_transport_headers_done(aos_curl_http_transport_t *t);
static int aos_curl_transport_setup(aos_curl_http_transport_t *t);
static void aos_curl_transport_finish(aos_curl_http_transport_t *t);
static void aos_move_transport_state(aos_curl_http_transport_t *t, aos_transport_state_e s);
static size_t aos_curl_default_header_callback(char *buffer, size_t size, size_t nitems, void *userdata);
static size_t aos_curl_default_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
static size_t aos_curl_default_read_callback(char *buffer, size_t size, size_t nitems, void *instream);
static void aos_init_curl_headers(aos_curl_http_transport_t *t)
{
int pos;
char *header;
const aos_array_header_t *tarr;
const aos_table_entry_t *telts;
union aos_func_u func;
if (t->req->method == HTTP_PUT || t->req->method == HTTP_POST) {
header = apr_psprintf(t->pool, "Content-Length: %" APR_INT64_T_FMT, t->req->body_len);
t->headers = curl_slist_append(t->headers, header);
}
tarr = aos_table_elts(t->req->headers);
telts = (aos_table_entry_t*)tarr->elts;
for (pos = 0; pos < tarr->nelts; ++pos) {
header = apr_psprintf(t->pool, "%s: %s", telts[pos].key, telts[pos].val);
t->headers = curl_slist_append(t->headers, header);
}
func.func1 = (aos_func1_pt)curl_slist_free_all;
aos_fstack_push(t->cleanup, t->headers, func, 1);
}
static int aos_init_curl_url(aos_curl_http_transport_t *t)
{
int rs;
const char *proto;
aos_string_t querystr;
char uristr[3*AOS_MAX_URI_LEN+1];
uristr[0] = '\0';
aos_str_null(&querystr);
if ((rs = aos_url_encode(uristr, t->req->uri, AOS_MAX_URI_LEN)) != AOSE_OK) {
t->controller->error_code = rs;
t->controller->reason = "uri invalid argument.";
return rs;
}
if ((rs = aos_query_params_to_string(t->pool, t->req->query_params, &querystr)) != AOSE_OK) {
t->controller->error_code = rs;
t->controller->reason = "query params invalid argument.";
return rs;
}
proto = strlen(t->req->proto) != 0 ? t->req->proto : AOS_HTTP_PREFIX;
if (querystr.len == 0) {
t->url = apr_psprintf(t->pool, "%s%s/%s",
proto,
t->req->host,
uristr);
} else {
t->url = apr_psprintf(t->pool, "%s%s/%s%.*s",
proto,
t->req->host,
uristr,
querystr.len,
querystr.data);
}
aos_debug_log("url:%s.", t->url);
return AOSE_OK;
}
static void aos_transport_cleanup(aos_http_transport_t *t)
{
int s;
char buf[256];
if (t->req->file_buf != NULL && t->req->file_buf->owner) {
aos_trace_log("close request body file.");
if ((s = apr_file_close(t->req->file_buf->file)) != APR_SUCCESS) {
aos_warn_log("apr_file_close failure, %s.", apr_strerror(s, buf, sizeof(buf)));
}
t->req->file_buf = NULL;
}
if (t->resp->file_buf != NULL && t->resp->file_buf->owner) {
aos_trace_log("close response body file.");
if ((s = apr_file_close(t->resp->file_buf->file)) != APR_SUCCESS) {
aos_warn_log("apr_file_close failure, %s.", apr_strerror(s, buf, sizeof(buf)));
}
t->resp->file_buf = NULL;
}
}
aos_http_transport_t *aos_curl_http_transport_create(aos_pool_t *p)
{
aos_func_u func;
aos_curl_http_transport_t *t;
t = (aos_curl_http_transport_t *)aos_pcalloc(p, sizeof(aos_curl_http_transport_t));
t->pool = p;
t->options = aos_default_http_transport_options;
t->cleanup = aos_fstack_create(p, 5);
func.func1 = (aos_func1_pt)aos_transport_cleanup;
aos_fstack_push(t->cleanup, t, func, 1);
t->curl = aos_request_get();
func.func1 = (aos_func1_pt)request_release;
aos_fstack_push(t->cleanup, t->curl, func, 1);
t->header_callback = aos_curl_default_header_callback;
t->read_callback = aos_curl_default_read_callback;
t->write_callback = aos_curl_default_write_callback;
return (aos_http_transport_t *)t;
}
static void aos_move_transport_state(aos_curl_http_transport_t *t, aos_transport_state_e s)
{
if (t->state < s) {
t->state = s;
}
}
void aos_curl_response_headers_parse(aos_pool_t *p, aos_table_t *headers, char *buffer, int len)
{
char *pos;
aos_string_t str;
aos_string_t key;
aos_string_t value;
str.data = buffer;
str.len = len;
aos_trip_space_and_cntrl(&str);
pos = aos_strlchr(str.data, str.data + str.len, ':');
if (pos == NULL) {
return;
}
key.data = str.data;
key.len = pos - str.data;
pos += 1;
value.len = str.data + str.len - pos;
value.data = pos;
aos_strip_space(&value);
apr_table_addn(headers, aos_pstrdup(p, &key), aos_pstrdup(p, &value));
}
size_t aos_curl_default_header_callback(char *buffer, size_t size, size_t nitems, void *userdata)
{
int len;
aos_curl_http_transport_t *t;
t = (aos_curl_http_transport_t *)(userdata);
len = size * nitems;
if (t->controller->first_byte_time == 0) {
t->controller->first_byte_time = apr_time_now();
}
aos_curl_response_headers_parse(t->pool, t->resp->headers, buffer, len);
aos_move_transport_state(t, TRANS_STATE_HEADER);
return len;
}
static void aos_curl_transport_headers_done(aos_curl_http_transport_t *t)
{
long http_code;
CURLcode code;
const char *value;
if (t->controller->error_code != AOSE_OK) {
aos_debug_log("has error %d.", t->controller->error_code);
return;
}
if (t->resp->status > 0) {
aos_trace_log("http response status %d.", t->resp->status);
return;
}
t->resp->status = 0;
if ((code = curl_easy_getinfo(t->curl, CURLINFO_RESPONSE_CODE, &http_code)) != CURLE_OK) {
t->controller->reason = apr_pstrdup(t->pool, curl_easy_strerror(code));
t->controller->error_code = AOSE_INTERNAL_ERROR;
return;
} else {
t->resp->status = http_code;
}
value = apr_table_get(t->resp->headers, "Content-Length");
if (value != NULL) {
t->resp->content_length = aos_atoi64(value);
}
}
size_t aos_curl_default_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
int len;
int bytes;
aos_curl_http_transport_t *t;
t = (aos_curl_http_transport_t *)(userdata);
len = size * nmemb;
if (t->controller->first_byte_time == 0) {
t->controller->first_byte_time = apr_time_now();
}
aos_curl_transport_headers_done(t);
if (t->controller->error_code != AOSE_OK) {
aos_debug_log("write callback abort");
return 0;
}
// On HTTP error, we expect to parse an HTTP error response
if (t->resp->status < 200 || t->resp->status > 299) {
bytes = aos_write_http_body_memory(t->resp, ptr, len);
assert(bytes == len);
aos_move_transport_state(t, TRANS_STATE_BODY_IN);
return bytes;
}
if (t->resp->type == BODY_IN_MEMORY && t->resp->body_len >= (int64_t)t->controller->options->max_memory_size) {
t->controller->reason = apr_psprintf(t->pool,
"receive body too big, current body size: %" APR_INT64_T_FMT ", max memory size: %" APR_INT64_T_FMT,
t->resp->body_len, t->controller->options->max_memory_size);
t->controller->error_code = AOSE_OVER_MEMORY;
aos_error_log("error reason:%s, ", t->controller->reason);
return 0;
}
if ((bytes = t->resp->write_body(t->resp, ptr, len)) < 0) {
aos_debug_log("write body failure, %d.", bytes);
t->controller->error_code = AOSE_WRITE_BODY_ERROR;
t->controller->reason = "write body failure.";
return 0;
}
if (bytes >= 0) {
// progress callback
if (NULL != t->resp->progress_callback) {
t->resp->progress_callback(t->resp->body_len, t->resp->content_length);
}
// crc
if (t->controller->options->enable_crc) {
t->resp->crc64 = aos_crc64(t->resp->crc64, ptr, bytes);
}
}
aos_move_transport_state(t, TRANS_STATE_BODY_IN);
return bytes;
}
size_t aos_curl_default_read_callback(char *buffer, size_t size, size_t nitems, void *instream)
{
int len;
int bytes;
aos_curl_http_transport_t *t;
t = (aos_curl_http_transport_t *)(instream);
len = size * nitems;
if (t->controller->error_code != AOSE_OK) {
aos_debug_log("abort read callback.");
return CURL_READFUNC_ABORT;
}
if ((bytes = t->req->read_body(t->req, buffer, len)) < 0) {
aos_debug_log("read body failure, %d.", bytes);
t->controller->error_code = AOSE_READ_BODY_ERROR;
t->controller->reason = "read body failure.";
return CURL_READFUNC_ABORT;
}
if (bytes >= 0) {
// progress callback
t->req->consumed_bytes += bytes;
if (NULL != t->req->progress_callback) {
t->req->progress_callback(t->req->consumed_bytes, t->req->body_len);
}
// crc
if (t->controller->options->enable_crc) {
t->req->crc64 = aos_crc64(t->req->crc64, buffer, bytes);
}
}
aos_move_transport_state(t, TRANS_STATE_BODY_OUT);
return bytes;
}
static int aos_curl_code_to_status(CURLcode code)
{
switch (code) {
case CURLE_OUT_OF_MEMORY:
return AOSE_OUT_MEMORY;
case CURLE_COULDNT_RESOLVE_PROXY:
case CURLE_COULDNT_RESOLVE_HOST:
return AOSE_NAME_LOOKUP_ERROR;
case CURLE_COULDNT_CONNECT:
return AOSE_FAILED_CONNECT;
case CURLE_WRITE_ERROR:
case CURLE_OPERATION_TIMEDOUT:
return AOSE_CONNECTION_FAILED;
case CURLE_PARTIAL_FILE:
return AOSE_OK;
case CURLE_SSL_CACERT:
return AOSE_FAILED_VERIFICATION;
default:
return AOSE_INTERNAL_ERROR;
}
}
static void aos_curl_transport_finish(aos_curl_http_transport_t *t)
{
aos_curl_transport_headers_done(t);
if (t->cleanup != NULL) {
aos_fstack_destory(t->cleanup);
t->cleanup = NULL;
}
}
int aos_curl_transport_setup(aos_curl_http_transport_t *t)
{
CURLcode code;
#define curl_easy_setopt_safe(opt, val) \
if ((code = curl_easy_setopt(t->curl, opt, val)) != CURLE_OK) { \
t->controller->reason = apr_pstrdup(t->pool, curl_easy_strerror(code)); \
t->controller->error_code = AOSE_FAILED_INITIALIZE; \
aos_error_log("curl_easy_setopt failed, code:%d %s.", code, t->controller->reason); \
return AOSE_FAILED_INITIALIZE; \
}
curl_easy_setopt_safe(CURLOPT_PRIVATE, t);
curl_easy_setopt_safe(CURLOPT_HEADERDATA, t);
curl_easy_setopt_safe(CURLOPT_HEADERFUNCTION, t->header_callback);
curl_easy_setopt_safe(CURLOPT_READDATA, t);
curl_easy_setopt_safe(CURLOPT_READFUNCTION, t->read_callback);
curl_easy_setopt_safe(CURLOPT_WRITEDATA, t);
curl_easy_setopt_safe(CURLOPT_WRITEFUNCTION, t->write_callback);
curl_easy_setopt_safe(CURLOPT_FILETIME, 1);
curl_easy_setopt_safe(CURLOPT_NOSIGNAL, 1);
curl_easy_setopt_safe(CURLOPT_NOPROGRESS, 1);
curl_easy_setopt_safe(CURLOPT_TCP_NODELAY, 1);
curl_easy_setopt_safe(CURLOPT_NETRC, CURL_NETRC_IGNORED);
// transport options
curl_easy_setopt_safe(CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt_safe(CURLOPT_USERAGENT, t->options->user_agent);
// request options
curl_easy_setopt_safe(CURLOPT_DNS_CACHE_TIMEOUT, t->controller->options->dns_cache_timeout);
curl_easy_setopt_safe(CURLOPT_CONNECTTIMEOUT, t->controller->options->connect_timeout);
curl_easy_setopt_safe(CURLOPT_LOW_SPEED_LIMIT, t->controller->options->speed_limit);
curl_easy_setopt_safe(CURLOPT_LOW_SPEED_TIME, t->controller->options->speed_time);
aos_init_curl_headers(t);
curl_easy_setopt_safe(CURLOPT_HTTPHEADER, t->headers);
if (t->controller->options->proxy_host != NULL) {
// proxy
curl_easy_setopt_safe(CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_easy_setopt_safe(CURLOPT_PROXY, t->controller->options->proxy_host);
// authorize
if (t->controller->options->proxy_auth != NULL) {
curl_easy_setopt_safe(CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_easy_setopt_safe(CURLOPT_PROXYUSERPWD, t->controller->options->proxy_auth);
}
}
if (NULL == t->req->signed_url) {
if (aos_init_curl_url(t) != AOSE_OK) {
return t->controller->error_code;
}
}
else {
t->url = t->req->signed_url;
}
curl_easy_setopt_safe(CURLOPT_URL, t->url);
switch (t->req->method) {
case HTTP_HEAD:
curl_easy_setopt_safe(CURLOPT_NOBODY, 1);
break;
case HTTP_PUT:
curl_easy_setopt_safe(CURLOPT_UPLOAD, 1);
break;
case HTTP_POST:
curl_easy_setopt_safe(CURLOPT_POST, 1);
break;
case HTTP_DELETE:
curl_easy_setopt_safe(CURLOPT_CUSTOMREQUEST, "DELETE");
break;
default: // HTTP_GET
break;
}
#undef curl_easy_setopt_safe
t->state = TRANS_STATE_INIT;
return AOSE_OK;
}
int aos_curl_http_transport_perform(aos_http_transport_t *t_)
{
int ecode;
CURLcode code;
aos_curl_http_transport_t *t = (aos_curl_http_transport_t *)(t_);
ecode = aos_curl_transport_setup(t);
if (ecode != AOSE_OK) {
return ecode;
}
t->controller->start_time = apr_time_now();
code = curl_easy_perform(t->curl);
t->controller->finish_time = apr_time_now();
aos_move_transport_state(t, TRANS_STATE_DONE);
if ((code != CURLE_OK) && (t->controller->error_code == AOSE_OK)) {
ecode = aos_curl_code_to_status(code);
if (ecode != AOSE_OK) {
t->controller->error_code = ecode;
t->controller->reason = apr_pstrdup(t->pool, curl_easy_strerror(code));
aos_error_log("transport failure curl code:%d error:%s", code, t->controller->reason);
}
}
aos_curl_transport_finish(t);
return t->controller->error_code;
}

View File

@@ -0,0 +1,152 @@
#ifndef LIBAOS_TRANSPORT_H
#define LIBAOS_TRANSPORT_H
#include "aos_define.h"
#include "aos_buf.h"
AOS_CPP_START
typedef struct aos_http_request_s aos_http_request_t;
typedef struct aos_http_response_s aos_http_response_t;
typedef struct aos_http_transport_s aos_http_transport_t;
typedef struct aos_http_controller_s aos_http_controller_t;
typedef struct aos_http_request_options_s aos_http_request_options_t;
typedef struct aos_http_transport_options_s aos_http_transport_options_t;
typedef struct aos_curl_http_transport_s aos_curl_http_transport_t;
typedef int (*aos_read_http_body_pt)(aos_http_request_t *req, char *buffer, int len);
typedef int (*aos_write_http_body_pt)(aos_http_response_t *resp, const char *buffer, int len);
typedef void (*oss_progress_callback)(int64_t consumed_bytes, int64_t total_bytes);
void aos_curl_response_headers_parse(aos_pool_t *p, aos_table_t *headers, char *buffer, int len);
aos_http_transport_t *aos_curl_http_transport_create(aos_pool_t *p);
int aos_curl_http_transport_perform(aos_http_transport_t *t);
struct aos_http_request_options_s {
int speed_limit;
int speed_time;
int dns_cache_timeout;
int connect_timeout;
int64_t max_memory_size;
int enable_crc;
char *proxy_host;
char *proxy_auth;
};
struct aos_http_transport_options_s {
char *user_agent;
char *cacerts_path;
uint32_t ssl_verification_disabled:1;
};
#define AOS_HTTP_BASE_CONTROLLER_DEFINE \
aos_http_request_options_t *options; \
aos_pool_t *pool; \
int64_t start_time; \
int64_t first_byte_time; \
int64_t finish_time; \
uint32_t owner:1; \
void *user_data;
struct aos_http_controller_s {
AOS_HTTP_BASE_CONTROLLER_DEFINE
};
typedef struct aos_http_controller_ex_s {
AOS_HTTP_BASE_CONTROLLER_DEFINE
// private
int error_code;
char *reason; // can't modify
} aos_http_controller_ex_t;
typedef enum {
BODY_IN_MEMORY = 0,
BODY_IN_FILE,
BODY_IN_CALLBACK
} aos_http_body_type_e;
struct aos_http_request_s {
char *host;
char *proto;
char *signed_url;
http_method_e method;
char *uri;
char *resource;
aos_table_t *headers;
aos_table_t *query_params;
aos_list_t body;
int64_t body_len;
char *file_path;
aos_file_buf_t *file_buf;
aos_pool_t *pool;
void *user_data;
aos_read_http_body_pt read_body;
aos_http_body_type_e type;
oss_progress_callback progress_callback;
uint64_t crc64;
int64_t consumed_bytes;
};
struct aos_http_response_s {
int status;
aos_table_t *headers;
aos_list_t body;
int64_t body_len;
char *file_path;
aos_file_buf_t* file_buf;
int64_t content_length;
aos_pool_t *pool;
void *user_data;
aos_write_http_body_pt write_body;
aos_http_body_type_e type;
oss_progress_callback progress_callback;
uint64_t crc64;
};
typedef enum {
TRANS_STATE_INIT,
TRANS_STATE_HEADER,
TRANS_STATE_BODY_IN,
TRANS_STATE_BODY_OUT,
TRANS_STATE_ABORT,
TRANS_STATE_DONE
} aos_transport_state_e;
#define AOS_HTTP_BASE_TRANSPORT_DEFINE \
aos_http_request_t *req; \
aos_http_response_t *resp; \
aos_pool_t *pool; \
aos_transport_state_e state; \
aos_array_header_t *cleanup; \
aos_http_transport_options_t *options; \
aos_http_controller_ex_t *controller;
struct aos_http_transport_s {
AOS_HTTP_BASE_TRANSPORT_DEFINE
};
struct aos_curl_http_transport_s {
AOS_HTTP_BASE_TRANSPORT_DEFINE
CURL *curl;
char *url;
struct curl_slist *headers;
curl_read_callback header_callback;
curl_read_callback read_callback;
curl_write_callback write_callback;
};
AOS_CPP_END
#endif

523
include/oss_sdk/aos_util.c Normal file
View File

@@ -0,0 +1,523 @@
#include "aos_util.h"
#include "aos_log.h"
static const char *g_s_wday[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char *g_s_mon[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static const char g_s_gmt_format[] = "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT";
int aos_parse_xml_body(aos_list_t *bc, mxml_node_t **root)
{
aos_buf_t *b;
size_t len;
*root = NULL;
len = (size_t)aos_buf_list_len(bc);
{
int nsize = 0;
char *buffer = (char*)malloc(sizeof(char)*(len+1));
memset(buffer, 0, len + 1);
aos_list_for_each_entry(aos_buf_t, b, bc, node) {
memcpy(buffer + nsize, (char *)b->pos, aos_buf_size(b));
nsize += aos_buf_size(b);
}
*root = mxmlLoadString(NULL, buffer, MXML_OPAQUE_CALLBACK);
free(buffer);
if (NULL == *root) {
return AOSE_INTERNAL_ERROR;
}
}
return AOSE_OK;
}
int aos_convert_to_gmt_time(char* date, const char* format, apr_time_exp_t *tm)
{
int size = apr_snprintf(date, AOS_MAX_GMT_TIME_LEN, format,
g_s_wday[tm->tm_wday], tm->tm_mday, g_s_mon[tm->tm_mon], 1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
if (size >= 0 && size < AOS_MAX_GMT_TIME_LEN) {
return AOSE_OK;
} else {
return AOSE_INTERNAL_ERROR;
}
}
int aos_get_gmt_str_time(char datestr[AOS_MAX_GMT_TIME_LEN])
{
int s;
apr_time_t now;
char buf[128];
apr_time_exp_t result;
now = apr_time_now();
if ((s = apr_time_exp_gmt(&result, now)) != APR_SUCCESS) {
aos_error_log("apr_time_exp_gmt fialure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
return AOSE_INTERNAL_ERROR;
}
if ((s = aos_convert_to_gmt_time(datestr, g_s_gmt_format, &result))
!= AOSE_OK) {
aos_error_log("aos_convert_to_GMT failure, code:%d.", s);
}
return s;
}
int aos_url_encode(char *dest, const char *src, int maxSrcSize)
{
static const char *hex = "0123456789ABCDEF";
int len = 0;
unsigned char c;
while (*src) {
if (++len > maxSrcSize) {
*dest = 0;
return AOSE_INVALID_ARGUMENT;
}
c = *src;
if (isalnum(c) || (c == '-') || (c == '_') || (c == '.') || (c == '~')) {
*dest++ = c;
} else if (*src == ' ') {
*dest++ = '%';
*dest++ = '2';
*dest++ = '0';
} else {
*dest++ = '%';
*dest++ = hex[c >> 4];
*dest++ = hex[c & 15];
}
src++;
}
*dest = 0;
return AOSE_OK;
}
int aos_query_params_to_string(aos_pool_t *p, aos_table_t *query_params, aos_string_t *querystr)
{
int rs;
int pos;
int len;
char sep = '?';
char ebuf[AOS_MAX_QUERY_ARG_LEN*3+1];
char abuf[AOS_MAX_QUERY_ARG_LEN*6+128];
int max_len;
const aos_array_header_t *tarr;
const aos_table_entry_t *telts;
aos_buf_t *querybuf;
if (apr_is_empty_table(query_params)) {
return AOSE_OK;
}
max_len = sizeof(abuf)-1;
querybuf = aos_create_buf(p, 256);
aos_str_null(querystr);
tarr = aos_table_elts(query_params);
telts = (aos_table_entry_t*)tarr->elts;
for (pos = 0; pos < tarr->nelts; ++pos) {
if ((rs = aos_url_encode(ebuf, telts[pos].key, AOS_MAX_QUERY_ARG_LEN)) != AOSE_OK) {
aos_error_log("query params args too big, key:%s.", telts[pos].key);
return AOSE_INVALID_ARGUMENT;
}
len = apr_snprintf(abuf, max_len, "%c%s", sep, ebuf);
if (telts[pos].val != NULL && *telts[pos].val != '\0') {
if ((rs = aos_url_encode(ebuf, telts[pos].val, AOS_MAX_QUERY_ARG_LEN)) != AOSE_OK) {
aos_error_log("query params args too big, value:%s.", telts[pos].val);
return AOSE_INVALID_ARGUMENT;
}
len += apr_snprintf(abuf+len, max_len-len, "=%s", ebuf);
if (len >= AOS_MAX_QUERY_ARG_LEN) {
aos_error_log("query params args too big, %s.", abuf);
return AOSE_INVALID_ARGUMENT;
}
}
aos_buf_append_string(p, querybuf, abuf, len);
sep = '&';
}
// result
querystr->data = (char *)querybuf->pos;
querystr->len = aos_buf_size(querybuf);
return AOSE_OK;
}
void aos_gnome_sort(const char **headers, int size)
{
const char *tmp;
int i = 0, last_highest = 0;
while (i < size) {
if ((i == 0) || apr_strnatcasecmp(headers[i-1], headers[i]) < 0) {
i = ++last_highest;
} else {
tmp = headers[i];
headers[i] = headers[i - 1];
headers[--i] = tmp;
}
}
}
const char* aos_http_method_to_string(http_method_e method)
{
switch (method) {
case HTTP_GET:
return "GET";
case HTTP_HEAD:
return "HEAD";
case HTTP_PUT:
return "PUT";
case HTTP_POST:
return "POST";
case HTTP_DELETE:
return "DELETE";
default:
return "UNKNOWN";
}
}
int aos_base64_encode(const unsigned char *in, int inLen, char *out)
{
static const char *ENC =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *original_out = out;
while (inLen) {
// first 6 bits of char 1
*out++ = ENC[*in >> 2];
if (!--inLen) {
// last 2 bits of char 1, 4 bits of 0
*out++ = ENC[(*in & 0x3) << 4];
*out++ = '=';
*out++ = '=';
break;
}
// last 2 bits of char 1, first 4 bits of char 2
*out++ = ENC[((*in & 0x3) << 4) | (*(in + 1) >> 4)];
in++;
if (!--inLen) {
// last 4 bits of char 2, 2 bits of 0
*out++ = ENC[(*in & 0xF) << 2];
*out++ = '=';
break;
}
// last 4 bits of char 2, first 2 bits of char 3
*out++ = ENC[((*in & 0xF) << 2) | (*(in + 1) >> 6)];
in++;
// last 6 bits of char 3
*out++ = ENC[*in & 0x3F];
in++, inLen--;
}
return (out - original_out);
}
// HMAC-SHA-1:
//
// K - is key padded with zeros to 512 bits
// m - is message
// OPAD - 0x5c5c5c...
// IPAD - 0x363636...
//
// HMAC(K,m) = SHA1((K ^ OPAD) . SHA1((K ^ IPAD) . m))
void HMAC_SHA1(unsigned char hmac[20], const unsigned char *key, int key_len,
const unsigned char *message, int message_len)
{
unsigned char kopad[64], kipad[64];
int i;
unsigned char digest[APR_SHA1_DIGESTSIZE];
apr_sha1_ctx_t context;
if (key_len > 64) {
key_len = 64;
}
for (i = 0; i < key_len; i++) {
kopad[i] = key[i] ^ 0x5c;
kipad[i] = key[i] ^ 0x36;
}
for ( ; i < 64; i++) {
kopad[i] = 0 ^ 0x5c;
kipad[i] = 0 ^ 0x36;
}
apr_sha1_init(&context);
apr_sha1_update(&context, (const char *)kipad, 64);
apr_sha1_update(&context, (const char *)message, (unsigned int)message_len);
apr_sha1_final(digest, &context);
apr_sha1_init(&context);
apr_sha1_update(&context, (const char *)kopad, 64);
apr_sha1_update(&context, (const char *)digest, 20);
apr_sha1_final(hmac, &context);
}
unsigned char* aos_md5(aos_pool_t* pool, const char *in, apr_size_t in_len) {
unsigned char* out;
apr_md5_ctx_t context;
//APR_MD5_DIGESTSIZE: The MD5 digest size, value is 16
out = aos_palloc(pool, APR_MD5_DIGESTSIZE + 1);
if (!out) {
return NULL;
}
if (0 != apr_md5_init(&context)) {
return NULL;
}
if (0 != apr_md5_update(&context, in, in_len)) {
return NULL;
}
if (0 != apr_md5_final(out, &context)) {
return NULL;
}
out[APR_MD5_DIGESTSIZE] = '\0';
return out;
};
int aos_url_decode(const char *in, char *out)
{
static const char tbl[256] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1
};
char c, v1, v2;
if(in != NULL) {
while((c=*in++) != '\0') {
if(c == '%') {
if(!(v1=*in++) || (v1=tbl[(unsigned char)v1])<0 ||
!(v2=*in++) || (v2=tbl[(unsigned char)v2])<0) {
*out = '\0';
return -1;
}
c = (v1<<4)|v2;
} else if (c == '+') {
c = ' ';
}
*out++ = c;
}
}
*out = '\0';
return 0;
}
/*
* Convert a string to a long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long long aos_strtoll(const char *nptr, char **endptr, int base)
{
const char *s;
/* LONGLONG */
long long int acc, cutoff;
int c;
int neg, any, cutlim;
/* endptr may be NULL */
#ifdef __GNUC__
/* This outrageous construct just to shut up a GCC warning. */
(void) &acc; (void) &cutoff;
#endif
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
do {
c = (unsigned char) *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for long longs is
* [-9223372036854775808..9223372036854775807] and the input base
* is 10, cutoff will be set to 922337203685477580 and cutlim to
* either 7 (neg==0) or 8 (neg==1), meaning that if we have
* accumulated a value > 922337203685477580, or equal but the
* next digit is > 7 (or 8), the number is too big, and we will
* return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? LLONG_MIN : LLONG_MAX;
cutlim = (int)(cutoff % base);
cutoff /= base;
if (neg) {
if (cutlim > 0) {
cutlim -= base;
cutoff += 1;
}
cutlim = -cutlim;
}
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (neg) {
if (acc < cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = LLONG_MIN;
errno = ERANGE;
} else {
any = 1;
acc *= base;
acc -= c;
}
} else {
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = LLONG_MAX;
errno = ERANGE;
} else {
any = 1;
acc *= base;
acc += c;
}
}
}
if (endptr != 0)
/* LINTED interface specification */
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
int64_t aos_atoi64(const char *nptr)
{
return aos_strtoull(nptr, NULL, 10);
}
unsigned long long aos_strtoull(const char *nptr, char **endptr, int base)
{
const char *s;
unsigned long long acc, cutoff;
int c;
int neg, any, cutlim;
/*
* See strtoq for comments as to the logic used.
*/
s = nptr;
do {
c = (unsigned char) *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = ULLONG_MAX / (unsigned long long)base;
cutlim = ULLONG_MAX % (unsigned long long)base;
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = ULLONG_MAX;
errno = ERANGE;
} else {
any = 1;
acc *= (unsigned long long)base;
acc += c;
}
}
if (neg && any > 0)
#ifdef WIN32
#pragma warning(disable : 4146)
#endif
acc = -acc;
#ifdef WIN32
#pragma warning(default : 4146)
#endif
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
uint64_t aos_atoui64(const char *nptr)
{
return aos_strtoull(nptr, NULL, 10);
}

View File

@@ -0,0 +1,84 @@
#ifndef LIBAOS_UTIL_H
#define LIBAOS_UTIL_H
#include "aos_buf.h"
#include "aos_string.h"
#include "aos_define.h"
#include "aos_fstack.h"
#include <mxml.h>
#include <apr_md5.h>
#include <apr_sha1.h>
AOS_CPP_START
int aos_parse_xml_body(aos_list_t *bc, mxml_node_t **root);
void aos_gnome_sort(const char **headers, int size);
int aos_convert_to_gmt_time(char* date, const char* format, apr_time_exp_t *tm);
int aos_get_gmt_str_time(char datestr[AOS_MAX_GMT_TIME_LEN]);
/**
* URL-encodes a string from [src] into [dest]. [dest] must have at least
* 3x the number of characters that [source] has. At most [maxSrcSize] bytes
* from [src] are encoded; if more are present in [src], 0 is returned from
* urlEncode, else nonzero is returned.
*/
int aos_url_encode(char *dest, const char *src, int maxSrcSize);
const char* aos_http_method_to_string(http_method_e method);
/**
* encode query string, check query args < AOS_MAX_QUERY_ARG_LEN
* result string "?a&b=x"
*/
int aos_query_params_to_string(aos_pool_t *p, aos_table_t *query_params, aos_string_t *querystr);
/**
* base64 encode bytes. The output buffer must have at least
* ((4 * (inLen + 1)) / 3) bytes in it. Returns the number of bytes written
* to [out].
*/
int aos_base64_encode(const unsigned char *in, int inLen, char *out);
/**
* Compute HMAC-SHA-1 with key [key] and message [message], storing result
* in [hmac]
*/
void HMAC_SHA1(unsigned char hmac[20], const unsigned char *key, int key_len,
const unsigned char *message, int message_len);
unsigned char* aos_md5(aos_pool_t* pool, const char* in, apr_size_t in_len);
int aos_url_decode(const char *in, char *out);
/*
* Convert a string to a long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long long aos_strtoll(const char *nptr, char **endptr, int base);
/*
* @brief Convert a string to int64_t.
**/
int64_t aos_atoi64(const char *nptr);
/*
* @brief Convert a string to an unsigned long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
**/
unsigned long long aos_strtoull(const char *nptr, char **endptr, int base);
/*
* @brief Convert a string to uint64_t.
**/
uint64_t aos_atoui64(const char *nptr);
AOS_CPP_END
#endif

332
include/oss_sdk/mxml.h Normal file
View File

@@ -0,0 +1,332 @@
/*
* "$Id: mxml.h 451 2014-01-04 21:50:06Z msweet $"
*
* Header file for Mini-XML, a small XML-like file parsing library.
*
* Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
* law. Distribution and use rights are outlined in the file "COPYING"
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
* http://www.msweet.org/projects.php/Mini-XML
*/
/*
* Prevent multiple inclusion...
*/
#ifndef _mxml_h_
# define _mxml_h_
/*
* Include necessary headers...
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
# include <errno.h>
/*
* Constants...
*/
# define MXML_MAJOR_VERSION 2 /* Major version number */
# define MXML_MINOR_VERSION 8 /* Minor version number */
# define MXML_TAB 8 /* Tabs every N columns */
# define MXML_NO_CALLBACK 0 /* Don't use a type callback */
# define MXML_INTEGER_CALLBACK mxml_integer_cb
/* Treat all data as integers */
# define MXML_OPAQUE_CALLBACK mxml_opaque_cb
/* Treat all data as opaque */
# define MXML_REAL_CALLBACK mxml_real_cb
/* Treat all data as real numbers */
# define MXML_TEXT_CALLBACK 0 /* Treat all data as text */
# define MXML_IGNORE_CALLBACK mxml_ignore_cb
/* Ignore all non-element content */
# define MXML_NO_PARENT 0 /* No parent for the node */
# define MXML_DESCEND 1 /* Descend when finding/walking */
# define MXML_NO_DESCEND 0 /* Don't descend when finding/walking */
# define MXML_DESCEND_FIRST -1 /* Descend for first find */
# define MXML_WS_BEFORE_OPEN 0 /* Callback for before open tag */
# define MXML_WS_AFTER_OPEN 1 /* Callback for after open tag */
# define MXML_WS_BEFORE_CLOSE 2 /* Callback for before close tag */
# define MXML_WS_AFTER_CLOSE 3 /* Callback for after close tag */
# define MXML_ADD_BEFORE 0 /* Add node before specified node */
# define MXML_ADD_AFTER 1 /* Add node after specified node */
# define MXML_ADD_TO_PARENT NULL /* Add node relative to parent */
/*
* Data types...
*/
typedef enum mxml_sax_event_e /**** SAX event type. ****/
{
MXML_SAX_CDATA, /* CDATA node */
MXML_SAX_COMMENT, /* Comment node */
MXML_SAX_DATA, /* Data node */
MXML_SAX_DIRECTIVE, /* Processing directive node */
MXML_SAX_ELEMENT_CLOSE, /* Element closed */
MXML_SAX_ELEMENT_OPEN /* Element opened */
} mxml_sax_event_t;
typedef enum mxml_type_e /**** The XML node type. ****/
{
MXML_IGNORE = -1, /* Ignore/throw away node @since Mini-XML 2.3@ */
MXML_ELEMENT, /* XML element with attributes */
MXML_INTEGER, /* Integer value */
MXML_OPAQUE, /* Opaque string */
MXML_REAL, /* Real value */
MXML_TEXT, /* Text fragment */
MXML_CUSTOM /* Custom data @since Mini-XML 2.1@ */
} mxml_type_t;
typedef void (*mxml_custom_destroy_cb_t)(void *);
/**** Custom data destructor ****/
typedef void (*mxml_error_cb_t)(const char *);
/**** Error callback function ****/
typedef struct mxml_attr_s /**** An XML element attribute value. @private@ ****/
{
char *name; /* Attribute name */
char *value; /* Attribute value */
} mxml_attr_t;
typedef struct mxml_element_s /**** An XML element value. @private@ ****/
{
char *name; /* Name of element */
int num_attrs; /* Number of attributes */
mxml_attr_t *attrs; /* Attributes */
} mxml_element_t;
typedef struct mxml_text_s /**** An XML text value. @private@ ****/
{
int whitespace; /* Leading whitespace? */
char *string; /* Fragment string */
} mxml_text_t;
typedef struct mxml_custom_s /**** An XML custom value. @private@ ****/
{
void *data; /* Pointer to (allocated) custom data */
mxml_custom_destroy_cb_t destroy; /* Pointer to destructor function */
} mxml_custom_t;
typedef union mxml_value_u /**** An XML node value. @private@ ****/
{
mxml_element_t element; /* Element */
int integer; /* Integer number */
char *opaque; /* Opaque string */
double real; /* Real number */
mxml_text_t text; /* Text fragment */
mxml_custom_t custom; /* Custom data @since Mini-XML 2.1@ */
} mxml_value_t;
struct mxml_node_s /**** An XML node. @private@ ****/
{
mxml_type_t type; /* Node type */
struct mxml_node_s *next; /* Next node under same parent */
struct mxml_node_s *prev; /* Previous node under same parent */
struct mxml_node_s *parent; /* Parent node */
struct mxml_node_s *child; /* First child node */
struct mxml_node_s *last_child; /* Last child node */
mxml_value_t value; /* Node value */
int ref_count; /* Use count */
void *user_data; /* User data */
};
typedef struct mxml_node_s mxml_node_t; /**** An XML node. ****/
struct mxml_index_s /**** An XML node index. @private@ ****/
{
char *attr; /* Attribute used for indexing or NULL */
int num_nodes; /* Number of nodes in index */
int alloc_nodes; /* Allocated nodes in index */
int cur_node; /* Current node */
mxml_node_t **nodes; /* Node array */
};
typedef struct mxml_index_s mxml_index_t;
/**** An XML node index. ****/
typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
/**** Custom data load callback function ****/
typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
/**** Custom data save callback function ****/
typedef int (*mxml_entity_cb_t)(const char *);
/**** Entity callback function */
typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *);
/**** Load callback function ****/
typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int);
/**** Save callback function ****/
typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
/**** SAX callback function ****/
/*
* C++ support...
*/
# ifdef __cplusplus
extern "C" {
# endif /* __cplusplus */
/*
* Prototypes...
*/
extern void mxmlAdd(mxml_node_t *parent, int where,
mxml_node_t *child, mxml_node_t *node);
extern void mxmlDelete(mxml_node_t *node);
extern void mxmlElementDeleteAttr(mxml_node_t *node,
const char *name);
extern const char *mxmlElementGetAttr(mxml_node_t *node, const char *name);
extern void mxmlElementSetAttr(mxml_node_t *node, const char *name,
const char *value);
extern void mxmlElementSetAttrf(mxml_node_t *node, const char *name,
const char *format, ...)
# ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 3, 4)))
# endif /* __GNUC__ */
;
extern int mxmlEntityAddCallback(mxml_entity_cb_t cb);
extern const char *mxmlEntityGetName(int val);
extern int mxmlEntityGetValue(const char *name);
extern void mxmlEntityRemoveCallback(mxml_entity_cb_t cb);
extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top,
const char *name, const char *attr,
const char *value, int descend);
extern mxml_node_t *mxmlFindPath(mxml_node_t *node, const char *path);
extern const char *mxmlGetCDATA(mxml_node_t *node);
extern const void *mxmlGetCustom(mxml_node_t *node);
extern const char *mxmlGetElement(mxml_node_t *node);
extern mxml_node_t *mxmlGetFirstChild(mxml_node_t *node);
extern int mxmlGetInteger(mxml_node_t *node);
extern mxml_node_t *mxmlGetLastChild(mxml_node_t *node);
extern mxml_node_t *mxmlGetNextSibling(mxml_node_t *node);
extern const char *mxmlGetOpaque(mxml_node_t *node);
extern mxml_node_t *mxmlGetParent(mxml_node_t *node);
extern mxml_node_t *mxmlGetPrevSibling(mxml_node_t *node);
extern double mxmlGetReal(mxml_node_t *node);
extern int mxmlGetRefCount(mxml_node_t *node);
extern const char *mxmlGetText(mxml_node_t *node, int *whitespace);
extern mxml_type_t mxmlGetType(mxml_node_t *node);
extern void *mxmlGetUserData(mxml_node_t *node);
extern void mxmlIndexDelete(mxml_index_t *ind);
extern mxml_node_t *mxmlIndexEnum(mxml_index_t *ind);
extern mxml_node_t *mxmlIndexFind(mxml_index_t *ind,
const char *element,
const char *value);
extern int mxmlIndexGetCount(mxml_index_t *ind);
extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element,
const char *attr);
extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind);
extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, int fd,
mxml_type_t (*cb)(mxml_node_t *));
extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp,
mxml_type_t (*cb)(mxml_node_t *));
extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s,
mxml_type_t (*cb)(mxml_node_t *));
extern mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string);
extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data,
mxml_custom_destroy_cb_t destroy);
extern mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name);
extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, int integer);
extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real);
extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace,
const char *string);
extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace,
const char *format, ...)
# ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 3, 4)))
# endif /* __GNUC__ */
;
extern mxml_node_t *mxmlNewXML(const char *version);
extern int mxmlRelease(mxml_node_t *node);
extern void mxmlRemove(mxml_node_t *node);
extern int mxmlRetain(mxml_node_t *node);
extern char *mxmlSaveAllocString(mxml_node_t *node,
mxml_save_cb_t cb);
extern int mxmlSaveFd(mxml_node_t *node, int fd,
mxml_save_cb_t cb);
extern int mxmlSaveFile(mxml_node_t *node, FILE *fp,
mxml_save_cb_t cb);
extern int mxmlSaveString(mxml_node_t *node, char *buffer,
int bufsize, mxml_save_cb_t cb);
extern mxml_node_t *mxmlSAXLoadFd(mxml_node_t *top, int fd,
mxml_type_t (*cb)(mxml_node_t *),
mxml_sax_cb_t sax, void *sax_data);
extern mxml_node_t *mxmlSAXLoadFile(mxml_node_t *top, FILE *fp,
mxml_type_t (*cb)(mxml_node_t *),
mxml_sax_cb_t sax, void *sax_data);
extern mxml_node_t *mxmlSAXLoadString(mxml_node_t *top, const char *s,
mxml_type_t (*cb)(mxml_node_t *),
mxml_sax_cb_t sax, void *sax_data);
extern int mxmlSetCDATA(mxml_node_t *node, const char *data);
extern int mxmlSetCustom(mxml_node_t *node, void *data,
mxml_custom_destroy_cb_t destroy);
extern void mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
mxml_custom_save_cb_t save);
extern int mxmlSetElement(mxml_node_t *node, const char *name);
extern void mxmlSetErrorCallback(mxml_error_cb_t cb);
extern int mxmlSetInteger(mxml_node_t *node, int integer);
extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque);
extern int mxmlSetReal(mxml_node_t *node, double real);
extern int mxmlSetText(mxml_node_t *node, int whitespace,
const char *string);
extern int mxmlSetTextf(mxml_node_t *node, int whitespace,
const char *format, ...)
# ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 3, 4)))
# endif /* __GNUC__ */
;
extern int mxmlSetUserData(mxml_node_t *node, void *data);
extern void mxmlSetWrapMargin(int column);
extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
int descend);
extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
int descend);
/*
* Semi-private functions...
*/
extern void mxml_error(const char *format, ...);
extern mxml_type_t mxml_ignore_cb(mxml_node_t *node);
extern mxml_type_t mxml_integer_cb(mxml_node_t *node);
extern mxml_type_t mxml_opaque_cb(mxml_node_t *node);
extern mxml_type_t mxml_real_cb(mxml_node_t *node);
/*
* C++ support...
*/
# ifdef __cplusplus
}
# endif /* __cplusplus */
#endif /* !_mxml_h_ */
/*
* End of "$Id: mxml.h 451 2014-01-04 21:50:06Z msweet $".
*/

957
include/oss_sdk/oss_api.h Normal file
View File

@@ -0,0 +1,957 @@
#ifndef LIBOSS_API_H
#define LIBOSS_API_H
#include "aos_util.h"
#include "aos_string.h"
#include "aos_status.h"
#include "oss_define.h"
#include "oss_util.h"
OSS_CPP_START
/*
* @brief create oss bucket
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] oss_acl the oss bucket acl
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_create_bucket(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_acl_e oss_acl,
aos_table_t **resp_headers);
/*
* @brief delete oss bucket
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_delete_bucket(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_table_t **resp_headers);
/*
* @brief put oss bucket acl
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] oss_acl the oss bucket acl
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_put_bucket_acl(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_acl_e oss_acl,
aos_table_t **resp_headers);
/*
* @brief get oss bucket acl
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[out] oss_acl the oss bucket acl
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_bucket_acl(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_string_t *oss_acl,
aos_table_t **resp_headers);
/*
* @brief put oss bucket lifecycle
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] lifecycle_rule_list the oss bucket lifecycle list
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_put_bucket_lifecycle(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_list_t *lifecycle_rule_list,
aos_table_t **resp_headers);
/*
* @brief get oss bucket lifecycle
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[out] lifecycle_rule_list the oss bucket lifecycle list
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_bucket_lifecycle(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_list_t *lifecycle_rule_list,
aos_table_t **resp_headers);
/*
* @brief delete oss bucket lifecycle
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_delete_bucket_lifecycle(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_table_t **resp_headers);
/*
* @brief list oss objects
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] params input params for list object request,
including prefix, marker, delimiter, max_ret
* @param[out] params output params for list object response,
including truncated, next_marker, obje list
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_list_object(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_list_object_params_t *params,
aos_table_t **resp_headers);
/*
* @brief put oss object from buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] buffer the buffer containing object content
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_put_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief put oss object from file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] filename the filename to put
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_put_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *filename,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief put oss object from buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] buffer the buffer containing object content
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] progress_callback the progress callback function
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_put_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief put oss object from file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] filename the filename to put
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] progress_callback the progress callback function
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_put_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *filename,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief get oss object to buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[out] buffer the buffer containing object content
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_object_to_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_list_t *buffer,
aos_table_t **resp_headers);
/*
* @brief get oss object to buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] progress_callback the progress callback function
* @param[out] buffer the buffer containing object content
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_get_object_to_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_list_t *buffer,
oss_progress_callback progress_callback,
aos_table_t **resp_headers);
/*
* @brief get oss object to file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] filename the filename storing object content
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_object_to_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_string_t *filename,
aos_table_t **resp_headers);
/*
* @brief get oss object to file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] filename the filename storing object content
* @param[in] progress_callback the progress callback function
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_get_object_to_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_string_t *filename,
oss_progress_callback progress_callback,
aos_table_t **resp_headers);
/*
* @brief head oss object
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers containing object meta
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_head_object(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief delete oss object
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_delete_object(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t **resp_headers);
/*
* @brief delete oss objects
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object_list the oss object list name
* @param[in] is_quiet is quiet or verbose
* @param[out] resp_headers oss server response headers
* @param[out] deleted_object_list deleted object list
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_delete_objects(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_list_t *object_list,
int is_quiet,
aos_table_t **resp_headers,
aos_list_t *deleted_object_list);
/*
* @brief delete oss objects by prefix
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] prefix prefix of delete objects
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_delete_objects_by_prefix(oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *prefix);
/*
* @brief copy oss objects
* @param[in] options the oss request options
* @param[in] source_bucket the oss source bucket name
* @param[in] object_list the oss source object list name
* @param[in] dest_bucket the oss dest bucket name
* @param[in] dest_list the oss dest object list name
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_copy_object(const oss_request_options_t *options,
const aos_string_t *source_bucket,
const aos_string_t *source_object,
const aos_string_t *dest_bucket,
const aos_string_t *dest_object,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief append oss object from buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] position the start position append
* @param[in] buffer the buffer containing object content
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_append_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief append oss object from buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] position the start position append
* @param[in] init_crc the initial crc value
* @param[in] buffer the buffer containing object content
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] progress_callback the progress callback function
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_append_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
uint64_t init_crc,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief append oss object from file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] position the start position append
* @param[in] append_file the file containing appending content
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_append_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
const aos_string_t *append_file,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief append oss object from file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] position the start position append
* @param[in] init_crc the initial crc value
* @param[in] append_file the file containing appending content
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] progress_callback the progress callback function
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_append_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
uint64_t init_crc,
const aos_string_t *append_file,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief gen signed url for oss object api
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] expires the end expire time for signed url
* @param[in] req the aos http request
* @return signed url, non-NULL success, NULL failure
*/
char *oss_gen_signed_url(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t expires,
aos_http_request_t *req);
/*
* @brief oss put object from buffer using signed url
* @param[in] options the oss request options
* @param[in] signed_url the signed url for put object
* @param[in] buffer the buffer containing object content
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_put_object_from_buffer_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief oss put object from file using signed url
* @param[in] options the oss request options
* @param[in] signed_url the signed url for put object
* @param[in] filename the filename containing object content
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_put_object_from_file_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_string_t *filename,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief oss get object to buffer using signed url
* @param[in] options the oss request options
* @param[in] signed_url the signed url for put object
* @param[in] buffer the buffer containing object content
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_object_to_buffer_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_table_t *headers,
aos_table_t *params,
aos_list_t *buffer,
aos_table_t **resp_headers);
/*
* @brief oss get object to file using signed url
* @param[in] options the oss request options
* @param[in] signed_url the signed url for put object
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] filename the filename containing object content
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_object_to_file_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_table_t *headers,
aos_table_t *params,
aos_string_t *filename,
aos_table_t **resp_headers);
/*
* @brief oss head object using signed url
* @param[in] options the oss request options
* @param[in] signed_url the signed url for put object
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_head_object_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief oss init multipart upload
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_init_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_string_t *upload_id,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief oss upload part from buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] part_num the upload part number
* @param[in] buffer the buffer containing upload part content
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_upload_part_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
aos_list_t *buffer,
aos_table_t **resp_headers);
/*
* @brief oss upload part from buffer
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] part_num the upload part number
* @param[in] buffer the buffer containing upload part content
* @param[in] progress_callback the progress callback function
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_upload_part_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
aos_list_t *buffer,
oss_progress_callback progress_callback,
aos_table_t *headers,
aos_table_t *params,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief oss upload part from file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] part_num the upload part number
* @param[in] upload_file the file containing upload part content
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_upload_part_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
oss_upload_file_t *upload_file,
aos_table_t **resp_headers);
/*
* @brief oss upload part from file
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] part_num the upload part number
* @param[in] upload_file the file containing upload part content
* @param[in] progress_callback the progress callback function
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_upload_part_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
oss_upload_file_t *upload_file,
oss_progress_callback progress_callback,
aos_table_t *headers,
aos_table_t *params,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief oss abort multipart upload
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_abort_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_string_t *upload_id,
aos_table_t **resp_headers);
/*
* @brief oss complete multipart upload
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] part_list the uploaded part list to complete
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_complete_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
aos_list_t *part_list,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief oss complete multipart upload
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] part_list the uploaded part list to complete
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_do_complete_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
aos_list_t *part_list,
aos_table_t *headers,
aos_table_t *params,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief oss list upload part with specific upload_id for object
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] params the input list upload part parameters,
incluing part_number_marker, max_ret
* @param[out] params the output params,
including next_part_number_marker, part_list, truncated
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_list_upload_part(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
oss_list_upload_part_params_t *params,
aos_table_t **resp_headers);
/*
* @brief oss list multipart upload for bucket
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] params the input list multipart upload parameters
* @param[out] params the output params including next_key_marker, next_upload_id_markert, upload_list etc
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_list_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_list_multipart_upload_params_t *params,
aos_table_t **resp_headers);
/*
* @brief oss copy large object using upload part copy
* @param[in] options the oss request options
* @param[in] paramsthe upload part copy parameters
* @param[in] headers the headers for request
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_upload_part_copy(const oss_request_options_t *options,
oss_upload_part_copy_params_t *params,
aos_table_t *headers,
aos_table_t **resp_headers);
/*
* @brief oss upload file using multipart upload
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] upload_id the upload id to upload if has
* @param[in] filename the filename containing object content
* @param[in] part_size the part size for multipart upload
* @param[in] headers the headers for request
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_upload_file(oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_string_t *upload_id,
aos_string_t *filename,
int64_t part_size,
aos_table_t *headers);
/*
* @brief oss upload file with mulit-thread and resumable
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] filepath the filename containing object content
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] clt_params the control params of upload
* @param[in] progress_callback the progress callback function
* @param[out] resp_headers oss server response headers
* @param[out] resp_body oss server response body
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_resumable_upload_file(oss_request_options_t *options,
aos_string_t *bucket,
aos_string_t *object,
aos_string_t *filepath,
aos_table_t *headers,
aos_table_t *params,
oss_resumable_clt_params_t *clt_params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body);
/*
* @brief oss upload file with mulit-thread and resumable
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] object the oss object name
* @param[in] filepath download object to the file
* @param[in] headers the headers for request
* @param[in] params the params for request
* @param[in] clt_params the control params of upload
* @param[in] progress_callback the progress callback function
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_resumable_download_file(oss_request_options_t *options,
aos_string_t *bucket,
aos_string_t *object,
aos_string_t *filepath,
aos_table_t *headers,
aos_table_t *params,
oss_resumable_clt_params_t *clt_params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers);
/*
* @brief oss create live channel
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] config the oss live channel configuration
* @param[in] publish_url_list the publish url list
* @param[in] play_url_list the play url list
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_create_live_channel(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_live_channel_configuration_t *config,
aos_list_t *publish_url_list,
aos_list_t *play_url_list,
aos_table_t **resp_headers);
/*
* @brief oss set live channel status
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] live_channel the oss live channel name
* @param[in] live_channel_status the oss live channel status, enabled or disabled
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_put_live_channel_status(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
const aos_string_t *live_channel_status,
aos_table_t **resp_headers);
/*
* @brief oss get live channel information
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] live_channel the oss live channel name
* @param[out] info the oss live channel information
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_live_channel_info(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
oss_live_channel_configuration_t *info,
aos_table_t **resp_headers);
/*
* @brief oss get live channel stat
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] live_channel the oss live channel name
* @param[out] stat the oss live channel stat
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_live_channel_stat(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
oss_live_channel_stat_t *stat,
aos_table_t **resp_headers);
/*
* @brief delete oss live channel
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] live_channel the oss live channel name
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_delete_live_channel(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
aos_table_t **resp_headers);
/*
* @brief list oss live channels
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] params input params for list live channel request,
including prefix, marker, max_key
* @param[out] params output params for list object response,
including truncated, next_marker, live channel list
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_list_live_channel(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_list_live_channel_params_t *params,
aos_table_t **resp_headers);
/*
* @brief oss get live record history of live channel
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] live_channel the oss live channel name
* @param[out] live_record_list the oss live records of live channel
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_get_live_channel_history(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
aos_list_t *live_record_list,
aos_table_t **resp_headers);
/*
* @brief generate vod play list for a period of time
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] live_channel the oss live channel name
* @param[in] play_list_name the oss live channel play list name
* @param[in] start_time the start epoch time of play list, such as 1459922368
* @param[in] end_time the end epoch time of play list, such as 1459922563
* @param[out] resp_headers oss server response headers
* @return aos_status_t, code is 2xx success, other failure
*/
aos_status_t *oss_gen_vod_play_list(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
const aos_string_t *play_list_name,
const int64_t start_time,
const int64_t end_time,
aos_table_t **resp_headers);
/*
* @brief gen signed url for put rtmp stream
* @param[in] options the oss request options
* @param[in] bucket the oss bucket name
* @param[in] live_channel the oss live channel name
* @param[in] play_list_name the oss live channel play list name
* @param[in] expires the end expire time for signed url
* @return signed url, non-NULL success, NULL failure
*/
char *oss_gen_rtmp_signed_url(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
const aos_string_t *play_list_name,
const int64_t expires);
OSS_CPP_END
#endif

570
include/oss_sdk/oss_auth.c Normal file
View File

@@ -0,0 +1,570 @@
#include "oss_auth.h"
#include "aos_log.h"
#include "oss_util.h"
static const char *g_s_oss_sub_resource_list[] = {
"acl",
"uploadId",
"uploads",
"partNumber",
"response-content-type",
"response-content-language",
"response-expires",
"response-cache-control",
"response-content-disposition",
"response-content-encoding",
"append",
"position",
"lifecycle",
"delete",
"live",
"status",
"comp",
"vod",
"startTime",
"endTime",
"x-oss-process",
"security-token",
NULL,
};
static int is_oss_sub_resource(const char *str);
static int is_oss_canonicalized_header(const char *str);
static int oss_get_canonicalized_headers(aos_pool_t *p,
const aos_table_t *headers, aos_buf_t *signbuf);
static int oss_get_canonicalized_resource(aos_pool_t *p,
const aos_table_t *params, aos_buf_t *signbuf);
static int oss_get_canonicalized_params(aos_pool_t *p,
const aos_table_t *params, aos_buf_t *signbuf);
static int is_oss_sub_resource(const char *str)
{
int i = 0;
for ( ; g_s_oss_sub_resource_list[i]; i++) {
if (apr_strnatcmp(g_s_oss_sub_resource_list[i], str) == 0) {
return 1;
}
}
return 0;
}
static int is_oss_canonicalized_header(const char *str)
{
size_t len = strlen(OSS_CANNONICALIZED_HEADER_PREFIX);
return strncasecmp(str, OSS_CANNONICALIZED_HEADER_PREFIX, len) == 0;
}
static int oss_get_canonicalized_headers(aos_pool_t *p,
const aos_table_t *headers,
aos_buf_t *signbuf)
{
int pos;
int meta_count = 0;
int i;
int len;
const aos_array_header_t *tarr;
const aos_table_entry_t *telts;
char **meta_headers;
const char *value;
aos_string_t tmp_str;
char *tmpbuf = (char*)malloc(AOS_MAX_HEADER_LEN + 1);
if (NULL == tmpbuf) {
aos_error_log("malloc %d memory failed.", AOS_MAX_HEADER_LEN + 1);
return AOSE_OVER_MEMORY;
}
if (apr_is_empty_table(headers)) {
free(tmpbuf);
return AOSE_OK;
}
// sort user meta header
tarr = aos_table_elts(headers);
telts = (aos_table_entry_t*)tarr->elts;
meta_headers = aos_pcalloc(p, tarr->nelts * sizeof(char*));
for (pos = 0; pos < tarr->nelts; ++pos) {
if (is_oss_canonicalized_header(telts[pos].key)) {
aos_string_t key = aos_string(telts[pos].key);
aos_string_tolower(&key);
meta_headers[meta_count++] = key.data;
}
}
if (meta_count == 0) {
free(tmpbuf);
return AOSE_OK;
}
aos_gnome_sort((const char **)meta_headers, meta_count);
// sign string
for (i = 0; i < meta_count; ++i) {
value = apr_table_get(headers, meta_headers[i]);
aos_str_set(&tmp_str, value);
aos_strip_space(&tmp_str);
len = apr_snprintf(tmpbuf, AOS_MAX_HEADER_LEN + 1, "%s:%.*s",
meta_headers[i], tmp_str.len, tmp_str.data);
if (len > AOS_MAX_HEADER_LEN) {
free(tmpbuf);
aos_error_log("user meta header too many, %d > %d.",
len, AOS_MAX_HEADER_LEN);
return AOSE_INVALID_ARGUMENT;
}
tmp_str.data = tmpbuf;
tmp_str.len = len;
aos_buf_append_string(p, signbuf, tmpbuf, len);
aos_buf_append_string(p, signbuf, "\n", sizeof("\n")-1);
}
free(tmpbuf);
return AOSE_OK;
}
static int oss_get_canonicalized_resource(aos_pool_t *p,
const aos_table_t *params,
aos_buf_t *signbuf)
{
int pos;
int subres_count = 0;
int i;
int len;
char sep;
const char *value;
char tmpbuf[AOS_MAX_QUERY_ARG_LEN+1];
char **subres_headers;
const aos_array_header_t *tarr;
const aos_table_entry_t *telts;
if (apr_is_empty_table(params)) {
return AOSE_OK;
}
// sort sub resource param
tarr = aos_table_elts(params);
telts = (aos_table_entry_t*)tarr->elts;
subres_headers = aos_pcalloc(p, tarr->nelts * sizeof(char*));
for (pos = 0; pos < tarr->nelts; ++pos) {
if (is_oss_sub_resource(telts[pos].key)) {
subres_headers[subres_count++] = telts[pos].key;
}
}
if (subres_count == 0) {
return AOSE_OK;
}
aos_gnome_sort((const char **)subres_headers, subres_count);
// sign string
sep = '?';
for (i = 0; i < subres_count; ++i) {
value = apr_table_get(params, subres_headers[i]);
if (value != NULL && *value != '\0') {
len = apr_snprintf(tmpbuf, sizeof(tmpbuf), "%c%s=%s",
sep, subres_headers[i], value);
} else {
len = apr_snprintf(tmpbuf, sizeof(tmpbuf), "%c%s",
sep, subres_headers[i]);
}
if (len >= AOS_MAX_QUERY_ARG_LEN) {
aos_error_log("http query params too long, %s.", tmpbuf);
return AOSE_INVALID_ARGUMENT;
}
aos_buf_append_string(p, signbuf, tmpbuf, len);
sep = '&';
}
return AOSE_OK;
}
int oss_get_string_to_sign(aos_pool_t *p,
http_method_e method,
const aos_string_t *canon_res,
const aos_table_t *headers,
const aos_table_t *params,
aos_string_t *signstr)
{
int res;
aos_buf_t *signbuf;
const char *value;
aos_str_null(signstr);
signbuf = aos_create_buf(p, 1024);
#define signbuf_append_from_headers(KEY) do { \
if ((value = apr_table_get(headers, KEY)) != NULL) { \
aos_buf_append_string(p, signbuf, value, strlen(value)); \
} \
aos_buf_append_string(p, signbuf, "\n", sizeof("\n")-1); \
} while (0)
#define signbuf_append(VALUE, LEN) do { \
aos_buf_append_string(p, signbuf, VALUE, LEN); \
aos_buf_append_string(p, signbuf, "\n", sizeof("\n")-1); \
} while (0)
value = aos_http_method_to_string(method);
signbuf_append(value, strlen(value));
signbuf_append_from_headers(OSS_CONTENT_MD5);
signbuf_append_from_headers(OSS_CONTENT_TYPE);
// date
if ((value = apr_table_get(headers, OSS_CANNONICALIZED_HEADER_DATE)) == NULL) {
value = apr_table_get(headers, OSS_DATE);
}
if (NULL == value || *value == '\0') {
aos_error_log("http header date is empty.");
return AOSE_INVALID_ARGUMENT;
}
signbuf_append(value, strlen(value));
// user meta headers
if ((res = oss_get_canonicalized_headers(p, headers, signbuf)) != AOSE_OK) {
return res;
}
// canonicalized resource
aos_buf_append_string(p, signbuf, canon_res->data, canon_res->len);
if (params != NULL && (res = oss_get_canonicalized_resource(p, params, signbuf)) != AOSE_OK) {
return res;
}
// result
signstr->data = (char *)signbuf->pos;
signstr->len = aos_buf_size(signbuf);
return AOSE_OK;
}
void oss_sign_headers(aos_pool_t *p,
const aos_string_t *signstr,
const aos_string_t *access_key_id,
const aos_string_t *access_key_secret,
aos_table_t *headers)
{
int b64Len;
char *value;
unsigned char hmac[20];
char b64[((20 + 1) * 4) / 3];
HMAC_SHA1(hmac, (unsigned char *)access_key_secret->data, access_key_secret->len,
(unsigned char *)signstr->data, signstr->len);
// Now base-64 encode the results
b64Len = aos_base64_encode(hmac, 20, b64);
value = apr_psprintf(p, "OSS %.*s:%.*s", access_key_id->len, access_key_id->data, b64Len, b64);
apr_table_addn(headers, OSS_AUTHORIZATION, value);
return;
}
int oss_get_signed_headers(aos_pool_t *p,
const aos_string_t *access_key_id,
const aos_string_t *access_key_secret,
const aos_string_t* canon_res,
aos_http_request_t *req)
{
int res;
aos_string_t signstr;
res = oss_get_string_to_sign(p, req->method, canon_res,
req->headers, req->query_params, &signstr);
if (res != AOSE_OK) {
return res;
}
aos_debug_log("signstr:%.*s.", signstr.len, signstr.data);
oss_sign_headers(p, &signstr, access_key_id, access_key_secret, req->headers);
return AOSE_OK;
}
int oss_sign_request(aos_http_request_t *req,
const oss_config_t *config)
{
aos_string_t canon_res;
char canon_buf[AOS_MAX_URI_LEN];
char datestr[AOS_MAX_GMT_TIME_LEN];
const char *value;
int res = AOSE_OK;
int len = 0;
len = strlen(req->resource);
if (len >= AOS_MAX_URI_LEN - 1) {
aos_error_log("http resource too long, %s.", req->resource);
return AOSE_INVALID_ARGUMENT;
}
canon_res.data = canon_buf;
canon_res.len = apr_snprintf(canon_buf, sizeof(canon_buf), "/%s", req->resource);
if ((value = apr_table_get(req->headers, OSS_CANNONICALIZED_HEADER_DATE)) == NULL) {
aos_get_gmt_str_time(datestr);
apr_table_set(req->headers, OSS_DATE, datestr);
}
res = oss_get_signed_headers(req->pool, &config->access_key_id,
&config->access_key_secret, &canon_res, req);
return res;
}
int get_oss_request_signature(const oss_request_options_t *options,
aos_http_request_t *req,
const aos_string_t *expires,
aos_string_t *signature)
{
aos_string_t canon_res;
char canon_buf[AOS_MAX_URI_LEN];
const char *value;
aos_string_t signstr;
int res = AOSE_OK;
int b64Len;
unsigned char hmac[20];
char b64[((20 + 1) * 4) / 3];
canon_res.data = canon_buf;
canon_res.len = apr_snprintf(canon_buf, sizeof(canon_buf), "/%s", req->resource);
apr_table_set(req->headers, OSS_DATE, expires->data);
if ((res = oss_get_string_to_sign(options->pool, req->method, &canon_res,
req->headers, req->query_params, &signstr))!= AOSE_OK) {
return res;
}
HMAC_SHA1(hmac, (unsigned char *)options->config->access_key_secret.data,
options->config->access_key_secret.len,
(unsigned char *)signstr.data, signstr.len);
b64Len = aos_base64_encode(hmac, 20, b64);
value = apr_psprintf(options->pool, "%.*s", b64Len, b64);
aos_str_set(signature, value);
return res;
}
int oss_get_signed_url(const oss_request_options_t *options,
aos_http_request_t *req,
const aos_string_t *expires,
aos_string_t *signed_url)
{
char *signed_url_str;
aos_string_t querystr;
char uristr[3*AOS_MAX_URI_LEN+1];
int res = AOSE_OK;
aos_string_t signature;
const char *proto;
if (options->config->sts_token.data != NULL) {
apr_table_set(req->query_params, OSS_SECURITY_TOKEN, options->config->sts_token.data);
}
res = get_oss_request_signature(options, req, expires, &signature);
if (res != AOSE_OK) {
return res;
}
apr_table_set(req->query_params, OSS_ACCESSKEYID, options->config->access_key_id.data);
apr_table_set(req->query_params, OSS_EXPIRES, expires->data);
apr_table_set(req->query_params, OSS_SIGNATURE, signature.data);
uristr[0] = '\0';
aos_str_null(&querystr);
res = aos_url_encode(uristr, req->uri, AOS_MAX_URI_LEN);
if (res != AOSE_OK) {
return res;
}
res = aos_query_params_to_string(options->pool, req->query_params, &querystr);
if (res != AOSE_OK) {
return res;
}
proto = strlen(req->proto) != 0 ? req->proto : AOS_HTTP_PREFIX;
signed_url_str = apr_psprintf(options->pool, "%s%s/%s%.*s",
proto, req->host, uristr,
querystr.len, querystr.data);
aos_str_set(signed_url, signed_url_str);
return res;
}
int oss_get_rtmp_signed_url(const oss_request_options_t *options,
aos_http_request_t *req,
const aos_string_t *expires,
const aos_string_t *play_list_name,
aos_table_t *params,
aos_string_t *signed_url)
{
char *signed_url_str;
aos_string_t querystr;
char uristr[3*AOS_MAX_URI_LEN+1];
int res = AOSE_OK;
aos_string_t signature;
int pos = 0;
const aos_array_header_t *tarr;
const aos_table_entry_t *telts;
if (NULL != params) {
tarr = aos_table_elts(params);
telts = (aos_table_entry_t*)tarr->elts;
for (pos = 0; pos < tarr->nelts; ++pos) {
apr_table_set(req->query_params, telts[pos].key, telts[pos].val);
}
}
apr_table_set(req->query_params, OSS_PLAY_LIST_NAME, play_list_name->data);
res = get_oss_rtmp_request_signature(options, req, expires,&signature);
if (res != AOSE_OK) {
return res;
}
apr_table_set(req->query_params, OSS_ACCESSKEYID,
options->config->access_key_id.data);
apr_table_set(req->query_params, OSS_EXPIRES, expires->data);
apr_table_set(req->query_params, OSS_SIGNATURE, signature.data);
uristr[0] = '\0';
aos_str_null(&querystr);
res = aos_url_encode(uristr, req->uri, AOS_MAX_URI_LEN);
if (res != AOSE_OK) {
return res;
}
res = aos_query_params_to_string(options->pool, req->query_params, &querystr);
if (res != AOSE_OK) {
return res;
}
signed_url_str = apr_psprintf(options->pool, "%s%s/%s%.*s",
req->proto, req->host, uristr,
querystr.len, querystr.data);
aos_str_set(signed_url, signed_url_str);
return res;
}
int get_oss_rtmp_request_signature(const oss_request_options_t *options,
aos_http_request_t *req,
const aos_string_t *expires,
aos_string_t *signature)
{
aos_string_t canon_res;
char canon_buf[AOS_MAX_URI_LEN];
const char *value;
aos_string_t signstr;
int res = AOSE_OK;
int b64Len;
unsigned char hmac[20];
char b64[((20 + 1) * 4) / 3];
canon_res.data = canon_buf;
canon_res.len = apr_snprintf(canon_buf, sizeof(canon_buf), "/%s", req->resource);
if ((res = oss_get_rtmp_string_to_sign(options->pool, expires, &canon_res,
req->query_params, &signstr))!= AOSE_OK) {
return res;
}
HMAC_SHA1(hmac, (unsigned char *)options->config->access_key_secret.data,
options->config->access_key_secret.len,
(unsigned char *)signstr.data, signstr.len);
b64Len = aos_base64_encode(hmac, 20, b64);
value = apr_psprintf(options->pool, "%.*s", b64Len, b64);
aos_str_set(signature, value);
return res;
}
int oss_get_rtmp_string_to_sign(aos_pool_t *p,
const aos_string_t *expires,
const aos_string_t *canon_res,
const aos_table_t *params,
aos_string_t *signstr)
{
int res;
aos_buf_t *signbuf;
aos_str_null(signstr);
signbuf = aos_create_buf(p, 1024);
// expires
aos_buf_append_string(p, signbuf, expires->data, expires->len);
aos_buf_append_string(p, signbuf, "\n", sizeof("\n")-1);
// canonicalized params
if ((res = oss_get_canonicalized_params(p, params, signbuf)) != AOSE_OK) {
return res;
}
// canonicalized resource
aos_buf_append_string(p, signbuf, canon_res->data, canon_res->len);
// result
signstr->data = (char *)signbuf->pos;
signstr->len = aos_buf_size(signbuf);
return AOSE_OK;
}
static int oss_get_canonicalized_params(aos_pool_t *p,
const aos_table_t *params,
aos_buf_t *signbuf)
{
int pos;
int meta_count = 0;
int i;
int len;
const aos_array_header_t *tarr;
const aos_table_entry_t *telts;
char **meta_headers;
const char *value;
aos_string_t tmp_str;
char *tmpbuf = (char*)malloc(AOS_MAX_HEADER_LEN + 1);
if (NULL == tmpbuf) {
aos_error_log("malloc %d memory failed.", AOS_MAX_HEADER_LEN + 1);
return AOSE_OVER_MEMORY;
}
if (apr_is_empty_table(params)) {
free(tmpbuf);
return AOSE_OK;
}
// sort user meta header
tarr = aos_table_elts(params);
telts = (aos_table_entry_t*)tarr->elts;
meta_headers = aos_pcalloc(p, tarr->nelts * sizeof(char*));
for (pos = 0; pos < tarr->nelts; ++pos) {
aos_string_t key = aos_string(telts[pos].key);
meta_headers[meta_count++] = key.data;
}
if (meta_count == 0) {
free(tmpbuf);
return AOSE_OK;
}
aos_gnome_sort((const char **)meta_headers, meta_count);
// sign string
for (i = 0; i < meta_count; ++i) {
value = apr_table_get(params, meta_headers[i]);
aos_str_set(&tmp_str, value);
aos_strip_space(&tmp_str);
len = apr_snprintf(tmpbuf, AOS_MAX_HEADER_LEN + 1, "%s:%.*s",
meta_headers[i], tmp_str.len, tmp_str.data);
if (len > AOS_MAX_HEADER_LEN) {
free(tmpbuf);
aos_error_log("rtmp parameters too many, %d > %d.",
len, AOS_MAX_HEADER_LEN);
return AOSE_INVALID_ARGUMENT;
}
tmp_str.data = tmpbuf;
tmp_str.len = len;
aos_buf_append_string(p, signbuf, tmpbuf, len);
aos_buf_append_string(p, signbuf, "\n", sizeof("\n")-1);
}
free(tmpbuf);
return AOSE_OK;
}

View File

@@ -0,0 +1,76 @@
#ifndef LIB_OSS_AUTH_H
#define LIB_OSS_AUTH_H
#include "aos_util.h"
#include "aos_string.h"
#include "aos_http_io.h"
#include "oss_define.h"
OSS_CPP_START
/**
* @brief sign oss headers
**/
void oss_sign_headers(aos_pool_t *p,
const aos_string_t *signstr,
const aos_string_t *access_key_id,
const aos_string_t *access_key_secret,
aos_table_t *headers);
/**
* @brief get string to signature
**/
int oss_get_string_to_sign(aos_pool_t *p,
http_method_e method,
const aos_string_t *canon_res,
const aos_table_t *headers,
const aos_table_t *params,
aos_string_t *signstr);
/**
* @brief get signed oss request headers
**/
int oss_get_signed_headers(aos_pool_t *p, const aos_string_t *access_key_id,
const aos_string_t *access_key_secret,
const aos_string_t* canon_res, aos_http_request_t *req);
/**
* @brief sign oss request
**/
int oss_sign_request(aos_http_request_t *req, const oss_config_t *config);
/**
* @brief generate oss request Signature
**/
int get_oss_request_signature(const oss_request_options_t *options, aos_http_request_t *req,
const aos_string_t *expires, aos_string_t *signature);
/**
* @brief get oss signed url
**/
int oss_get_signed_url(const oss_request_options_t *options, aos_http_request_t *req,
const aos_string_t *expires, aos_string_t *auth_url);
/**
* @brief get rtmp string to signature
**/
int oss_get_rtmp_string_to_sign(aos_pool_t *p, const aos_string_t *expires,
const aos_string_t *canon_res, const aos_table_t *params,
aos_string_t *signstr);
/**
* @brief generate oss rtmp request signature
**/
int get_oss_rtmp_request_signature(const oss_request_options_t *options, aos_http_request_t *req,
const aos_string_t *expires, aos_string_t *signature);
/**
* @brief get oss rtmp signed url
**/
int oss_get_rtmp_signed_url(const oss_request_options_t *options, aos_http_request_t *req,
const aos_string_t *expires, const aos_string_t *play_list_name, aos_table_t *params,
aos_string_t *signed_url);
OSS_CPP_END
#endif

View File

@@ -0,0 +1,406 @@
#include "aos_log.h"
#include "aos_define.h"
#include "aos_util.h"
#include "aos_string.h"
#include "aos_status.h"
#include "oss_auth.h"
#include "oss_util.h"
#include "oss_xml.h"
#include "oss_api.h"
aos_status_t *oss_create_bucket(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_acl_e oss_acl,
aos_table_t **resp_headers)
{
const char *oss_acl_str = NULL;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *headers = NULL;
aos_table_t *query_params = NULL;
query_params = aos_table_create_if_null(options, query_params, 0);
//init headers
headers = aos_table_create_if_null(options, headers, 1);
oss_acl_str = get_oss_acl_str(oss_acl);
if (oss_acl_str) {
apr_table_set(headers, OSS_CANNONICALIZED_HEADER_ACL, oss_acl_str);
}
oss_init_bucket_request(options, bucket, HTTP_PUT, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_delete_bucket(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
headers = aos_table_create_if_null(options, headers, 0);
query_params = aos_table_create_if_null(options, query_params, 0);
oss_init_bucket_request(options, bucket, HTTP_DELETE, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_put_bucket_acl(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_acl_e oss_acl,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
const char *oss_acl_str = NULL;
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_ACL, "");
headers = aos_table_create_if_null(options, headers, 1);
oss_acl_str = get_oss_acl_str(oss_acl);
if (oss_acl_str) {
apr_table_set(headers, OSS_CANNONICALIZED_HEADER_ACL, oss_acl_str);
}
oss_init_bucket_request(options, bucket, HTTP_PUT, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_get_bucket_acl(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_string_t *oss_acl,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
int res;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_ACL, "");
headers = aos_table_create_if_null(options, headers, 0);
oss_init_bucket_request(options, bucket, HTTP_GET, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
res = oss_acl_parse_from_body(options->pool, &resp->body, oss_acl);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_list_object(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_list_object_params_t *params,
aos_table_t **resp_headers)
{
int res;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 4);
apr_table_add(query_params, OSS_PREFIX, params->prefix.data);
apr_table_add(query_params, OSS_DELIMITER, params->delimiter.data);
apr_table_add(query_params, OSS_MARKER, params->marker.data);
aos_table_add_int(query_params, OSS_MAX_KEYS, params->max_ret);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_bucket_request(options, bucket, HTTP_GET, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
res = oss_list_objects_parse_from_body(options->pool, &resp->body,
&params->object_list, &params->common_prefix_list,
&params->next_marker, &params->truncated);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_put_bucket_lifecycle(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_list_t *lifecycle_rule_list,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
apr_table_t *query_params = NULL;
aos_table_t *headers = NULL;
aos_list_t body;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_LIFECYCLE, "");
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_bucket_request(options, bucket, HTTP_PUT, &req,
query_params, headers, &resp);
build_lifecycle_body(options->pool, lifecycle_rule_list, &body);
oss_write_request_body_from_buffer(&body, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_get_bucket_lifecycle(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_list_t *lifecycle_rule_list,
aos_table_t **resp_headers)
{
int res;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_LIFECYCLE, "");
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_bucket_request(options, bucket, HTTP_GET, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
res = oss_lifecycle_rules_parse_from_body(options->pool,
&resp->body, lifecycle_rule_list);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_delete_bucket_lifecycle(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_LIFECYCLE, "");
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_bucket_request(options, bucket, HTTP_DELETE, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_delete_objects(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_list_t *object_list,
int is_quiet,
aos_table_t **resp_headers,
aos_list_t *deleted_object_list)
{
int res;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *headers = NULL;
aos_table_t *query_params = NULL;
aos_list_t body;
unsigned char *md5 = NULL;
char *buf = NULL;
int64_t body_len;
char *b64_value = NULL;
int b64_buf_len = (20 + 1) * 4 / 3;
int b64_len;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_DELETE, "");
//init headers
headers = aos_table_create_if_null(options, headers, 1);
apr_table_set(headers, OSS_CONTENT_TYPE, OSS_MULTIPART_CONTENT_TYPE);
oss_init_bucket_request(options, bucket, HTTP_POST, &req,
query_params, headers, &resp);
build_delete_objects_body(options->pool, object_list, is_quiet, &body);
//add Content-MD5
body_len = aos_buf_list_len(&body);
buf = aos_buf_list_content(options->pool, &body);
md5 = aos_md5(options->pool, buf, (apr_size_t)body_len);
b64_value = aos_pcalloc(options->pool, b64_buf_len);
b64_len = aos_base64_encode(md5, 20, b64_value);
b64_value[b64_len] = '\0';
apr_table_addn(headers, OSS_CONTENT_MD5, b64_value);
oss_write_request_body_from_buffer(&body, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (is_quiet) {
return s;
}
if (!aos_status_is_ok(s)) {
return s;
}
res = oss_delete_objects_parse_from_body(options->pool, &resp->body,
deleted_object_list);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_delete_objects_by_prefix(oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *prefix)
{
aos_pool_t *subpool = NULL;
aos_pool_t *parent_pool = NULL;
int is_quiet = 1;
aos_status_t *s = NULL;
aos_status_t *ret = NULL;
oss_list_object_params_t *params = NULL;
int list_object_count = 0;
parent_pool = options->pool;
params = oss_create_list_object_params(parent_pool);
if (prefix->data == NULL) {
aos_str_set(&params->prefix, "");
} else {
aos_str_set(&params->prefix, prefix->data);
}
while (params->truncated) {
aos_table_t *list_object_resp_headers = NULL;
aos_list_t object_list;
aos_list_t deleted_object_list;
oss_list_object_content_t *list_content = NULL;
aos_table_t *delete_objects_resp_headers = NULL;
char *key = NULL;
aos_pool_create(&subpool, parent_pool);
options->pool = subpool;
list_object_count = 0;
aos_list_init(&object_list);
s = oss_list_object(options, bucket, params, &list_object_resp_headers);
if (!aos_status_is_ok(s)) {
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}
aos_list_for_each_entry(oss_list_object_content_t, list_content, &params->object_list, node) {
oss_object_key_t *object_key = oss_create_oss_object_key(parent_pool);
key = apr_psprintf(parent_pool, "%.*s", list_content->key.len,
list_content->key.data);
aos_str_set(&object_key->key, key);
aos_list_add_tail(&object_key->node, &object_list);
list_object_count += 1;
}
if (list_object_count == 0)
{
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}
aos_pool_destroy(subpool);
aos_list_init(&deleted_object_list);
aos_pool_create(&subpool, parent_pool);
options->pool = subpool;
s = oss_delete_objects(options, bucket, &object_list, is_quiet,
&delete_objects_resp_headers, &deleted_object_list);
if (!aos_status_is_ok(s)) {
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}
if (!params->truncated) {
ret = aos_status_dup(parent_pool, s);
}
aos_pool_destroy(subpool);
aos_list_init(&params->object_list);
if (params->next_marker.data) {
aos_str_set(&params->marker, params->next_marker.data);
}
}
options->pool = parent_pool;
return ret;
}

View File

@@ -0,0 +1,66 @@
#include "oss_define.h"
const char OSS_CANNONICALIZED_HEADER_PREFIX[] = "x-oss-";
const char OSS_CANNONICALIZED_HEADER_DATE[] = "x-oss-date";
const char OSS_CANNONICALIZED_HEADER_ACL[] = "x-oss-acl";
const char OSS_CANNONICALIZED_HEADER_COPY_SOURCE[] = "x-oss-copy-source";
const char OSS_CONTENT_MD5[] = "Content-MD5";
const char OSS_CONTENT_TYPE[] = "Content-Type";
const char OSS_CONTENT_LENGTH[] = "Content-Length";
const char OSS_DATE[] = "Date";
const char OSS_AUTHORIZATION[] = "Authorization";
const char OSS_ACCESSKEYID[] = "OSSAccessKeyId";
const char OSS_EXPECT[] = "Expect";
const char OSS_EXPIRES[] = "Expires";
const char OSS_SIGNATURE[] = "Signature";
const char OSS_ACL[] = "acl";
const char OSS_PREFIX[] = "prefix";
const char OSS_DELIMITER[] = "delimiter";
const char OSS_MARKER[] = "marker";
const char OSS_MAX_KEYS[] = "max-keys";
const char OSS_UPLOADS[] = "uploads";
const char OSS_UPLOAD_ID[] = "uploadId";
const char OSS_MAX_PARTS[] = "max-parts";
const char OSS_PART_NUMBER_MARKER[] = "part-number-marker";
const char OSS_KEY_MARKER[] = "key-marker";
const char OSS_UPLOAD_ID_MARKER[] = "upload-id-marker";
const char OSS_MAX_UPLOADS[] = "max-uploads";
const char OSS_PARTNUMBER[] = "partNumber";
const char OSS_APPEND[] = "append";
const char OSS_POSITION[] = "position";
const char OSS_MULTIPART_CONTENT_TYPE[] = "application/x-www-form-urlencoded";
const char OSS_COPY_SOURCE[] = "x-oss-copy-source";
const char OSS_COPY_SOURCE_RANGE[] = "x-oss-copy-source-range";
const char OSS_SECURITY_TOKEN[] = "security-token";
const char OSS_STS_SECURITY_TOKEN[] = "x-oss-security-token";
const char OSS_OBJECT_TYPE[] = "x-oss-object-type";
const char OSS_NEXT_APPEND_POSITION[] = "x-oss-next-append-position";
const char OSS_HASH_CRC64_ECMA[] = "x-oss-hash-crc64ecma";
const char OSS_CALLBACK[] = "x-oss-callback";
const char OSS_CALLBACK_VAR[] = "x-oss-callback-var";
const char OSS_PROCESS[] = "x-oss-process";
const char OSS_LIFECYCLE[] = "lifecycle";
const char OSS_DELETE[] = "delete";
const char OSS_YES[] = "yes";
const char OSS_OBJECT_TYPE_NORMAL[] = "Normal";
const char OSS_OBJECT_TYPE_APPENDABLE[] = "Appendable";
const char OSS_LIVE_CHANNEL[] = "live";
const char OSS_LIVE_CHANNEL_STATUS[] = "status";
const char OSS_COMP[] = "comp";
const char OSS_LIVE_CHANNEL_STAT[] = "stat";
const char OSS_LIVE_CHANNEL_HISTORY[] = "history";
const char OSS_LIVE_CHANNEL_VOD[] = "vod";
const char OSS_LIVE_CHANNEL_START_TIME[] = "startTime";
const char OSS_LIVE_CHANNEL_END_TIME[] = "endTime";
const char OSS_PLAY_LIST_NAME[] = "playlistName";
const char LIVE_CHANNEL_STATUS_DISABLED[] = "disabled";
const char LIVE_CHANNEL_STATUS_ENABLED[] = "enabled";
const char LIVE_CHANNEL_STATUS_IDLE[] = "idle";
const char LIVE_CHANNEL_STATUS_LIVE[] = "live";
const char LIVE_CHANNEL_DEFAULT_TYPE[] = "HLS";
const char LIVE_CHANNEL_DEFAULT_PLAYLIST[] = "playlist.m3u8";
const int LIVE_CHANNEL_DEFAULT_FRAG_DURATION = 5;
const int LIVE_CHANNEL_DEFAULT_FRAG_COUNT = 3;
const int OSS_MAX_PART_NUM = 10000;
const int OSS_PER_RET_NUM = 1000;
const int MAX_SUFFIX_LEN = 1024;

View File

@@ -0,0 +1,318 @@
#ifndef LIBOSS_DEFINE_H
#define LIBOSS_DEFINE_H
#include "aos_string.h"
#include "aos_list.h"
#include "aos_transport.h"
#ifdef __cplusplus
# define OSS_CPP_START extern "C" {
# define OSS_CPP_END }
#else
# define OSS_CPP_START
# define OSS_CPP_END
#endif
#define aos_xml_error_status_set(STATUS, RES) do { \
aos_status_set(STATUS, RES, AOS_XML_PARSE_ERROR_CODE, NULL); \
} while(0)
#define aos_file_error_status_set(STATUS, RES) do { \
aos_status_set(STATUS, RES, AOS_OPEN_FILE_ERROR_CODE, NULL); \
} while(0)
#define aos_inconsistent_error_status_set(STATUS, RES) do { \
aos_status_set(STATUS, RES, AOS_INCONSISTENT_ERROR_CODE, NULL); \
} while(0)
extern const char OSS_CANNONICALIZED_HEADER_ACL[];
extern const char OSS_CANNONICALIZED_HEADER_SOURCE[];
extern const char OSS_CANNONICALIZED_HEADER_PREFIX[];
extern const char OSS_CANNONICALIZED_HEADER_DATE[];
extern const char OSS_CANNONICALIZED_HEADER_COPY_SOURCE[];
extern const char OSS_CONTENT_MD5[];
extern const char OSS_CONTENT_TYPE[];
extern const char OSS_CONTENT_LENGTH[];
extern const char OSS_DATE[];
extern const char OSS_AUTHORIZATION[];
extern const char OSS_ACCESSKEYID[];
extern const char OSS_EXPECT[];
extern const char OSS_EXPIRES[];
extern const char OSS_SIGNATURE[];
extern const char OSS_ACL[];
extern const char OSS_PREFIX[];
extern const char OSS_DELIMITER[];
extern const char OSS_MARKER[];
extern const char OSS_MAX_KEYS[];
extern const char OSS_UPLOADS[];
extern const char OSS_UPLOAD_ID[];
extern const char OSS_MAX_PARTS[];
extern const char OSS_KEY_MARKER[];
extern const char OSS_UPLOAD_ID_MARKER[];
extern const char OSS_MAX_UPLOADS[];
extern const char OSS_PARTNUMBER[];
extern const char OSS_PART_NUMBER_MARKER[];
extern const char OSS_APPEND[];
extern const char OSS_POSITION[];
extern const char OSS_MULTIPART_CONTENT_TYPE[];
extern const char OSS_COPY_SOURCE[];
extern const char OSS_COPY_SOURCE_RANGE[];
extern const char OSS_SECURITY_TOKEN[];
extern const char OSS_STS_SECURITY_TOKEN[];
extern const char OSS_OBJECT_TYPE[];
extern const char OSS_NEXT_APPEND_POSITION[];
extern const char OSS_HASH_CRC64_ECMA[];
extern const char OSS_CALLBACK[];
extern const char OSS_CALLBACK_VAR[];
extern const char OSS_PROCESS[];
extern const char OSS_LIFECYCLE[];
extern const char OSS_DELETE[];
extern const char OSS_YES[];
extern const char OSS_OBJECT_TYPE_NORMAL[];
extern const char OSS_OBJECT_TYPE_APPENDABLE[];
extern const char OSS_LIVE_CHANNEL[];
extern const char OSS_LIVE_CHANNEL_STATUS[];
extern const char OSS_COMP[];
extern const char OSS_LIVE_CHANNEL_STAT[];
extern const char OSS_LIVE_CHANNEL_HISTORY[];
extern const char OSS_LIVE_CHANNEL_VOD[];
extern const char OSS_LIVE_CHANNEL_START_TIME[];
extern const char OSS_LIVE_CHANNEL_END_TIME[];
extern const char OSS_PLAY_LIST_NAME[];
extern const char LIVE_CHANNEL_STATUS_DISABLED[];
extern const char LIVE_CHANNEL_STATUS_ENABLED[];
extern const char LIVE_CHANNEL_STATUS_IDLE[];
extern const char LIVE_CHANNEL_STATUS_LIVE[];
extern const char LIVE_CHANNEL_DEFAULT_TYPE[];
extern const char LIVE_CHANNEL_DEFAULT_PLAYLIST[];
extern const int LIVE_CHANNEL_DEFAULT_FRAG_DURATION;
extern const int LIVE_CHANNEL_DEFAULT_FRAG_COUNT;
extern const int OSS_MAX_PART_NUM;
extern const int OSS_PER_RET_NUM;
extern const int MAX_SUFFIX_LEN;
typedef struct oss_lib_curl_initializer_s oss_lib_curl_initializer_t;
/**
* oss_acl is an ACL that can be specified when an object is created or
* updated. Each canned ACL has a predefined value when expanded to a full
* set of OSS ACL Grants.
* Private canned ACL gives the owner FULL_CONTROL and no other permissions
* are issued
* Public Read canned ACL gives the owner FULL_CONTROL and all users Read
* permission
* Public Read Write canned ACL gives the owner FULL_CONTROL and all users
* Read and Write permission
**/
typedef enum {
OSS_ACL_PRIVATE = 0, /*< private */
OSS_ACL_PUBLIC_READ = 1, /*< public read */
OSS_ACL_PUBLIC_READ_WRITE = 2 /*< public read write */
} oss_acl_e;
typedef struct {
aos_string_t endpoint;
aos_string_t access_key_id;
aos_string_t access_key_secret;
aos_string_t sts_token;
int is_cname;
aos_string_t proxy_host;
int proxy_port;
aos_string_t proxy_user;
aos_string_t proxy_passwd;
} oss_config_t;
typedef struct {
oss_config_t *config;
aos_http_controller_t *ctl; /*< aos http controller, more see aos_transport.h */
aos_pool_t *pool;
} oss_request_options_t;
typedef struct {
aos_list_t node;
aos_string_t key;
aos_string_t last_modified;
aos_string_t etag;
aos_string_t size;
aos_string_t owner_id;
aos_string_t owner_display_name;
} oss_list_object_content_t;
typedef struct {
aos_list_t node;
aos_string_t prefix;
} oss_list_object_common_prefix_t;
typedef struct {
aos_list_t node;
aos_string_t key;
aos_string_t upload_id;
aos_string_t initiated;
} oss_list_multipart_upload_content_t;
typedef struct {
aos_list_t node;
aos_string_t part_number;
aos_string_t size;
aos_string_t etag;
aos_string_t last_modified;
} oss_list_part_content_t;
typedef struct {
aos_list_t node;
aos_string_t part_number;
aos_string_t etag;
} oss_complete_part_content_t;
typedef struct {
int part_num;
char *etag;
} oss_upload_part_t;
typedef struct {
aos_string_t prefix;
aos_string_t marker;
aos_string_t delimiter;
int max_ret;
int truncated;
aos_string_t next_marker;
aos_list_t object_list;
aos_list_t common_prefix_list;
} oss_list_object_params_t;
typedef struct {
aos_string_t part_number_marker;
int max_ret;
int truncated;
aos_string_t next_part_number_marker;
aos_list_t part_list;
} oss_list_upload_part_params_t;
typedef struct {
aos_string_t prefix;
aos_string_t key_marker;
aos_string_t upload_id_marker;
aos_string_t delimiter;
int max_ret;
int truncated;
aos_string_t next_key_marker;
aos_string_t next_upload_id_marker;
aos_list_t upload_list;
} oss_list_multipart_upload_params_t;
typedef struct {
aos_string_t source_bucket;
aos_string_t source_object;
aos_string_t dest_bucket;
aos_string_t dest_object;
aos_string_t upload_id;
int part_num;
int64_t range_start;
int64_t range_end;
} oss_upload_part_copy_params_t;
typedef struct {
aos_string_t filename; /**< file range read filename */
int64_t file_pos; /**< file range read start position */
int64_t file_last; /**< file range read last position */
} oss_upload_file_t;
typedef struct {
aos_list_t node;
aos_string_t id;
aos_string_t prefix;
aos_string_t status;
int days;
aos_string_t date;
} oss_lifecycle_rule_content_t;
typedef struct {
aos_list_t node;
aos_string_t key;
} oss_object_key_t;
typedef struct {
char *suffix;
char *type;
} oss_content_type_t;
typedef struct {
int64_t part_size; // bytes, default 1MB
int32_t thread_num; // default 1
int enable_checkpoint; // default disable, false
aos_string_t checkpoint_path; // dafault ./filepath.ucp or ./filepath.dcp
} oss_resumable_clt_params_t;
typedef struct {
aos_string_t type;
int32_t frag_duration;
int32_t frag_count;
aos_string_t play_list_name;
}oss_live_channel_target_t;
typedef struct {
aos_string_t name;
aos_string_t description;
aos_string_t status;
oss_live_channel_target_t target;
} oss_live_channel_configuration_t;
typedef struct {
aos_list_t node;
aos_string_t publish_url;
} oss_live_channel_publish_url_t;
typedef struct {
aos_list_t node;
aos_string_t play_url;
} oss_live_channel_play_url_t;
typedef struct {
int32_t width;
int32_t height;
int32_t frame_rate;
int32_t band_width;
aos_string_t codec;
} oss_video_stat_t;
typedef struct {
int32_t band_width;
int32_t sample_rate;
aos_string_t codec;
} oss_audio_stat_t;
typedef struct {
aos_string_t pushflow_status;
aos_string_t connected_time;
aos_string_t remote_addr;
oss_video_stat_t video_stat;
oss_audio_stat_t audio_stat;
} oss_live_channel_stat_t;
typedef struct {
aos_list_t node;
aos_string_t name;
aos_string_t description;
aos_string_t status;
aos_string_t last_modified;
aos_list_t publish_url_list;
aos_list_t play_url_list;
} oss_live_channel_content_t;
typedef struct {
aos_string_t prefix;
aos_string_t marker;
int max_keys;
int truncated;
aos_string_t next_marker;
aos_list_t live_channel_list;
} oss_list_live_channel_params_t;
typedef struct {
aos_list_t node;
aos_string_t start_time;
aos_string_t end_time;
aos_string_t remote_addr;
} oss_live_record_content_t;
#endif

336
include/oss_sdk/oss_live.c Normal file
View File

@@ -0,0 +1,336 @@
#include "aos_log.h"
#include "aos_define.h"
#include "aos_util.h"
#include "aos_string.h"
#include "aos_status.h"
#include "oss_auth.h"
#include "oss_util.h"
#include "oss_xml.h"
#include "oss_api.h"
aos_status_t *oss_create_live_channel(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_live_channel_configuration_t *config,
aos_list_t *publish_url_list,
aos_list_t *play_url_list,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
aos_list_t body;
//init params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_LIVE_CHANNEL, "");
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_live_channel_request(options, bucket, &config->name, HTTP_PUT,
&req, query_params, headers, &resp);
// build body
build_create_live_channel_body(options->pool, config, &body);
oss_write_request_body_from_buffer(&body, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
// parse result
res = oss_create_live_channel_parse_from_body(options->pool, &resp->body,
publish_url_list, play_url_list);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_put_live_channel_status(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
const aos_string_t *live_channel_status,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init params
query_params = aos_table_create_if_null(options, query_params, 2);
apr_table_add(query_params, OSS_LIVE_CHANNEL, "");
apr_table_add(query_params, OSS_LIVE_CHANNEL_STATUS, live_channel_status->data);
//init headers, forbid 'Expect' and 'Transfer-Encoding' of HTTP
headers = aos_table_create_if_null(options, headers, 2);
apr_table_set(headers, "Expect", "");
apr_table_set(headers, "Transfer-Encoding", "");
oss_init_live_channel_request(options, bucket, live_channel, HTTP_PUT,
&req, query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_get_live_channel_info(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
oss_live_channel_configuration_t *info,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_LIVE_CHANNEL, "");
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_live_channel_request(options, bucket, live_channel, HTTP_GET,
&req, query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
// parse result
res = oss_live_channel_info_parse_from_body(options->pool, &resp->body, info);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
aos_str_set(&info->name, aos_pstrdup(options->pool, live_channel));
return s;
}
aos_status_t *oss_get_live_channel_stat(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
oss_live_channel_stat_t *stat,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init params
query_params = aos_table_create_if_null(options, query_params, 2);
apr_table_add(query_params, OSS_LIVE_CHANNEL, "");
apr_table_add(query_params, OSS_COMP, OSS_LIVE_CHANNEL_STAT);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_live_channel_request(options, bucket, live_channel, HTTP_GET,
&req, query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
// parse result
res = oss_live_channel_stat_parse_from_body(options->pool, &resp->body, stat);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_delete_live_channel(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_LIVE_CHANNEL, "");
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_live_channel_request(options, bucket, live_channel, HTTP_DELETE,
&req, query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_list_live_channel(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_list_live_channel_params_t *params,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init params
query_params = aos_table_create_if_null(options, query_params, 4);
apr_table_add(query_params, OSS_LIVE_CHANNEL, "");
apr_table_add(query_params, OSS_PREFIX, params->prefix.data);
apr_table_add(query_params, OSS_MARKER, params->marker.data);
aos_table_add_int(query_params, OSS_MAX_KEYS, params->max_keys);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_bucket_request(options, bucket, HTTP_GET, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
// parse result
res = oss_list_live_channel_parse_from_body(options->pool, &resp->body,
&params->live_channel_list, &params->next_marker, &params->truncated);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_get_live_channel_history(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
aos_list_t *live_record_list,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init params
query_params = aos_table_create_if_null(options, query_params, 2);
apr_table_add(query_params, OSS_LIVE_CHANNEL, "");
apr_table_add(query_params, OSS_COMP, OSS_LIVE_CHANNEL_HISTORY);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_live_channel_request(options, bucket, live_channel, HTTP_GET,
&req, query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
// parse result
res = oss_live_channel_history_parse_from_body(options->pool, &resp->body, live_record_list);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_gen_vod_play_list(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
const aos_string_t *play_list_name,
const int64_t start_time,
const int64_t end_time,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
char *resource = NULL;
aos_string_t resource_str;
//init params
query_params = aos_table_create_if_null(options, query_params, 3);
apr_table_add(query_params, OSS_LIVE_CHANNEL_VOD, "");
apr_table_add(query_params, OSS_LIVE_CHANNEL_START_TIME,
apr_psprintf(options->pool, "%" APR_INT64_T_FMT, start_time));
apr_table_add(query_params, OSS_LIVE_CHANNEL_END_TIME,
apr_psprintf(options->pool, "%" APR_INT64_T_FMT, end_time));
//init headers
headers = aos_table_create_if_null(options, headers, 1);
apr_table_set(headers, OSS_CONTENT_TYPE, OSS_MULTIPART_CONTENT_TYPE);
resource = apr_psprintf(options->pool, "%s/%s", live_channel->data, play_list_name->data);
aos_str_set(&resource_str, resource);
oss_init_live_channel_request(options, bucket, &resource_str, HTTP_POST,
&req, query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
char *oss_gen_rtmp_signed_url(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
const aos_string_t *play_list_name,
const int64_t expires)
{
aos_string_t signed_url;
char *expires_str = NULL;
aos_string_t expires_time;
int res = AOSE_OK;
aos_http_request_t *req = NULL;
aos_table_t *params = NULL;
expires_str = apr_psprintf(options->pool, "%" APR_INT64_T_FMT, expires);
aos_str_set(&expires_time, expires_str);
req = aos_http_request_create(options->pool);
oss_get_rtmp_uri(options, bucket, live_channel, req);
res = oss_get_rtmp_signed_url(options, req, &expires_time, play_list_name,
params, &signed_url);
if (res != AOSE_OK) {
return NULL;
}
return signed_url.data;
}

View File

@@ -0,0 +1,556 @@
#include "aos_log.h"
#include "aos_define.h"
#include "aos_util.h"
#include "aos_string.h"
#include "aos_status.h"
#include "oss_auth.h"
#include "oss_util.h"
#include "oss_xml.h"
#include "oss_api.h"
aos_status_t *oss_init_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_string_t *upload_id,
aos_table_t *headers,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_UPLOADS, "");
//init headers
headers = aos_table_create_if_null(options, headers, 1);
set_content_type(NULL, object->data, headers);
oss_init_object_request(options, bucket, object, HTTP_POST,
&req, query_params, headers, NULL, 0, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
res = oss_upload_id_parse_from_body(options->pool, &resp->body, upload_id);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_abort_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_string_t *upload_id,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 1);
apr_table_add(query_params, OSS_UPLOAD_ID, upload_id->data);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_object_request(options, bucket, object, HTTP_DELETE,
&req, query_params, headers, NULL, 0, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_list_upload_part(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
oss_list_upload_part_params_t *params,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 3);
apr_table_add(query_params, OSS_UPLOAD_ID, upload_id->data);
aos_table_add_int(query_params, OSS_MAX_PARTS, params->max_ret);
apr_table_add(query_params, OSS_PART_NUMBER_MARKER,
params->part_number_marker.data);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_object_request(options, bucket, object, HTTP_GET,
&req, query_params, headers, NULL, 0, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
res = oss_list_parts_parse_from_body(options->pool, &resp->body,
&params->part_list, &params->next_part_number_marker,
&params->truncated);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_list_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
oss_list_multipart_upload_params_t *params,
aos_table_t **resp_headers)
{
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
aos_table_t *headers = NULL;
//init query_params
query_params = aos_table_create_if_null(options, query_params, 6);
apr_table_add(query_params, OSS_UPLOADS, "");
apr_table_add(query_params, OSS_PREFIX, params->prefix.data);
apr_table_add(query_params, OSS_DELIMITER, params->delimiter.data);
apr_table_add(query_params, OSS_KEY_MARKER, params->key_marker.data);
apr_table_add(query_params, OSS_UPLOAD_ID_MARKER, params->upload_id_marker.data);
aos_table_add_int(query_params, OSS_MAX_UPLOADS, params->max_ret);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_bucket_request(options, bucket, HTTP_GET, &req,
query_params, headers, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (!aos_status_is_ok(s)) {
return s;
}
res = oss_list_multipart_uploads_parse_from_body(options->pool, &resp->body,
&params->upload_list, &params->next_key_marker,
&params->next_upload_id_marker, &params->truncated);
if (res != AOSE_OK) {
aos_xml_error_status_set(s, res);
}
return s;
}
aos_status_t *oss_complete_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
aos_list_t *part_list,
aos_table_t *headers,
aos_table_t **resp_headers)
{
return oss_do_complete_multipart_upload(options, bucket, object, upload_id, part_list,
headers, NULL, resp_headers, NULL);
}
aos_status_t *oss_do_complete_multipart_upload(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
aos_list_t *part_list,
aos_table_t *headers,
aos_table_t *params,
aos_table_t **resp_headers,
aos_list_t *resp_body)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
apr_table_t *query_params = NULL;
aos_list_t body;
//init query_params
query_params = aos_table_create_if_null(options, params, 1);
apr_table_add(query_params, OSS_UPLOAD_ID, upload_id->data);
//init headers
headers = aos_table_create_if_null(options, headers, 1);
apr_table_set(headers, OSS_CONTENT_TYPE, OSS_MULTIPART_CONTENT_TYPE);
oss_init_object_request(options, bucket, object, HTTP_POST,
&req, query_params, headers, NULL, 0, &resp);
build_complete_multipart_upload_body(options->pool, part_list, &body);
oss_write_request_body_from_buffer(&body, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
oss_fill_read_response_body(resp, resp_body);
return s;
}
aos_status_t *oss_upload_part_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
aos_list_t *buffer,
aos_table_t **resp_headers)
{
return oss_do_upload_part_from_buffer(options, bucket, object, upload_id, part_num,
buffer, NULL, NULL, NULL, resp_headers, NULL);
}
aos_status_t *oss_do_upload_part_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
aos_list_t *buffer,
oss_progress_callback progress_callback,
aos_table_t *headers,
aos_table_t *params,
aos_table_t **resp_headers,
aos_list_t *resp_body)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
//init query_params
query_params = aos_table_create_if_null(options, params, 2);
apr_table_add(query_params, OSS_UPLOAD_ID, upload_id->data);
aos_table_add_int(query_params, OSS_PARTNUMBER, part_num);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_object_request(options, bucket, object, HTTP_PUT, &req, query_params,
headers, progress_callback, 0, &resp);
oss_write_request_body_from_buffer(buffer, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
oss_fill_read_response_body(resp, resp_body);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_upload_part_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
oss_upload_file_t *upload_file,
aos_table_t **resp_headers)
{
return oss_do_upload_part_from_file(options, bucket, object, upload_id, part_num,
upload_file, NULL, NULL, NULL, resp_headers, NULL);
}
aos_status_t *oss_do_upload_part_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
int part_num,
oss_upload_file_t *upload_file,
oss_progress_callback progress_callback,
aos_table_t *headers,
aos_table_t *params,
aos_table_t **resp_headers,
aos_list_t *resp_body)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
int res = AOSE_OK;
s = aos_status_create(options->pool);
//init query_params
query_params = aos_table_create_if_null(options, params, 2);
apr_table_add(query_params, OSS_UPLOAD_ID, upload_id->data);
aos_table_add_int(query_params, OSS_PARTNUMBER, part_num);
//init headers
headers = aos_table_create_if_null(options, headers, 0);
oss_init_object_request(options, bucket, object, HTTP_PUT, &req,
query_params, headers, progress_callback, 0, &resp);
res = oss_write_request_body_from_upload_file(options->pool, upload_file, req);
if (res != AOSE_OK) {
aos_file_error_status_set(s, res);
return s;
}
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
oss_fill_read_response_body(resp, resp_body);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_upload_part_copy(const oss_request_options_t *options,
oss_upload_part_copy_params_t *params,
aos_table_t *headers,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
char *copy_source = NULL;
char *copy_source_range = NULL;
s = aos_status_create(options->pool);
//init query_params
query_params = aos_table_create_if_null(options, query_params, 2);
apr_table_add(query_params, OSS_UPLOAD_ID, params->upload_id.data);
aos_table_add_int(query_params, OSS_PARTNUMBER, params->part_num);
//init headers
headers = aos_table_create_if_null(options, headers, 2);
copy_source = apr_psprintf(options->pool, "/%.*s/%.*s",
params->source_bucket.len, params->source_bucket.data,
params->source_object.len, params->source_object.data);
apr_table_add(headers, OSS_COPY_SOURCE, copy_source);
copy_source_range = apr_psprintf(options->pool,
"bytes=%" APR_INT64_T_FMT "-%" APR_INT64_T_FMT,
params->range_start, params->range_end);
apr_table_add(headers, OSS_COPY_SOURCE_RANGE, copy_source_range);
oss_init_object_request(options, &params->dest_bucket, &params->dest_object,
HTTP_PUT, &req, query_params, headers, NULL, 0, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_get_sorted_uploaded_part(oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *upload_id,
aos_list_t *complete_part_list,
int *part_count)
{
aos_pool_t *subpool = NULL;
aos_pool_t *parent_pool = NULL;
aos_status_t *s = NULL;
aos_status_t *ret = NULL;
oss_upload_part_t *part_arr = NULL;
int part_index = 0;
int index = 0;
int uploaded_part_count = 0;
oss_list_upload_part_params_t *params = NULL;
oss_list_part_content_t *part_content = NULL;
oss_complete_part_content_t *complete_content = NULL;
aos_table_t *list_part_resp_headers = NULL;
char *part_num_str = NULL;
parent_pool = options->pool;
part_arr = aos_palloc(parent_pool, OSS_MAX_PART_NUM * sizeof(oss_upload_part_t *));
params = oss_create_list_upload_part_params(parent_pool);
while (params->truncated) {
aos_pool_create(&subpool, parent_pool);
options->pool = subpool;
s = oss_list_upload_part(options, bucket, object,
upload_id, params, &list_part_resp_headers);
if (!aos_status_is_ok(s)) {
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}
if (!params->truncated) {
ret = aos_status_dup(parent_pool, s);
}
aos_list_for_each_entry(oss_list_part_content_t, part_content, &params->part_list, node) {
oss_upload_part_t upload_part;
upload_part.etag = part_content->etag.data;
upload_part.part_num = atoi(part_content->part_number.data);
part_arr[part_index++] = upload_part;
uploaded_part_count++;
}
aos_list_init(&params->part_list);
if (params->next_part_number_marker.data != NULL) {
aos_str_set(&params->part_number_marker,
params->next_part_number_marker.data);
}
//sort multipart upload part content
qsort(part_arr, uploaded_part_count, sizeof(part_arr[0]), part_sort_cmp);
for (index = 0; index < part_index; ++index) {
complete_content = oss_create_complete_part_content(parent_pool);
part_num_str = apr_psprintf(parent_pool, "%d", part_arr[index].part_num);
aos_str_set(&complete_content->part_number, part_num_str);
aos_str_set(&complete_content->etag, part_arr[index].etag);
aos_list_add_tail(&complete_content->node, complete_part_list);
}
part_index = 0;
aos_pool_destroy(subpool);
}
*part_count = uploaded_part_count;
options->pool = parent_pool;
return ret;
}
aos_status_t *oss_upload_file(oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_string_t *upload_id,
aos_string_t *filepath,
int64_t part_size,
aos_table_t *headers)
{
aos_pool_t *subpool = NULL;
aos_pool_t *parent_pool = NULL;
int64_t start_pos;
int64_t end_pos;
int part_num;
int part_count = 0;
int res = AOSE_OK;
aos_status_t *s = NULL;
aos_status_t *ret = NULL;
aos_file_buf_t *fb = NULL;
oss_upload_file_t *upload_file = NULL;
aos_table_t *upload_part_resp_headers = NULL;
char *part_num_str = NULL;
char *etag = NULL;
aos_list_t complete_part_list;
oss_complete_part_content_t *complete_content = NULL;
aos_table_t *complete_resp_headers = NULL;
aos_list_init(&complete_part_list);
parent_pool = options->pool;
//get upload_id and uploaded part
aos_pool_create(&subpool, options->pool);
options->pool = subpool;
if (NULL == upload_id->data) {
aos_table_t *init_multipart_headers = NULL;
aos_table_t *init_multipart_resp_headers = NULL;
init_multipart_headers = aos_table_make(subpool, 0);
s = oss_init_multipart_upload(options, bucket, object,
upload_id, init_multipart_headers, &init_multipart_resp_headers);
if (!aos_status_is_ok(s)) {
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}
} else {
s = oss_get_sorted_uploaded_part(options, bucket, object, upload_id,
&complete_part_list, &part_count);
if (!aos_status_is_ok(s)) {
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}
}
aos_pool_destroy(subpool);
//get part size
fb = aos_create_file_buf(parent_pool);
res = aos_open_file_for_read(parent_pool, filepath->data, fb);
if (res != AOSE_OK) {
s = aos_status_create(parent_pool);
aos_file_error_status_set(s, res);
options->pool = parent_pool;
return s;
}
oss_get_part_size(fb->file_last, &part_size);
//upload part from file
upload_file = oss_create_upload_file(parent_pool);
aos_str_set(&upload_file->filename, filepath->data);
start_pos = part_size * part_count;
end_pos = start_pos + part_size;
part_num = part_count + 1;
while (1) {
aos_pool_create(&subpool, parent_pool);
options->pool = subpool;
upload_file->file_pos = start_pos;
upload_file->file_last = end_pos;
s = oss_upload_part_from_file(options, bucket, object, upload_id,
part_num, upload_file, &upload_part_resp_headers);
if (!aos_status_is_ok(s)) {
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}
complete_content = oss_create_complete_part_content(parent_pool);
part_num_str = apr_psprintf(parent_pool, "%d", part_num);
aos_str_set(&complete_content->part_number, part_num_str);
etag = apr_pstrdup(parent_pool,
(char*)apr_table_get(upload_part_resp_headers, "ETag"));
aos_str_set(&complete_content->etag, etag);
aos_list_add_tail(&complete_content->node, &complete_part_list);
aos_pool_destroy(subpool);
if (end_pos >= fb->file_last) {
break;
}
start_pos += part_size;
end_pos += part_size;
if (end_pos > fb->file_last)
end_pos = fb->file_last;
part_num += 1;
}
//complete multipart
aos_pool_create(&subpool, parent_pool);
options->pool = subpool;
headers = aos_table_create_if_null(options, headers, 0);
s = oss_complete_multipart_upload(options, bucket, object, upload_id,
&complete_part_list, headers, &complete_resp_headers);
ret = aos_status_dup(parent_pool, s);
aos_pool_destroy(subpool);
options->pool = parent_pool;
return ret;
}

View File

@@ -0,0 +1,642 @@
#include "aos_log.h"
#include "aos_util.h"
#include "aos_string.h"
#include "aos_status.h"
#include "oss_auth.h"
#include "oss_util.h"
#include "oss_xml.h"
#include "oss_api.h"
char *oss_gen_signed_url(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t expires,
aos_http_request_t *req)
{
aos_string_t signed_url;
char *expires_str = NULL;
aos_string_t expires_time;
int res = AOSE_OK;
expires_str = apr_psprintf(options->pool, "%" APR_INT64_T_FMT, expires);
aos_str_set(&expires_time, expires_str);
oss_get_object_uri(options, bucket, object, req);
res = oss_get_signed_url(options, req, &expires_time, &signed_url);
if (res != AOSE_OK) {
return NULL;
}
return signed_url.data;
}
aos_status_t *oss_put_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t **resp_headers)
{
return oss_do_put_object_from_buffer(options, bucket, object, buffer,
headers, NULL, NULL, resp_headers, NULL);
}
aos_status_t *oss_do_put_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
headers = aos_table_create_if_null(options, headers, 2);
set_content_type(NULL, object->data, headers);
apr_table_add(headers, OSS_EXPECT, "");
query_params = aos_table_create_if_null(options, params, 0);
oss_init_object_request(options, bucket, object, HTTP_PUT,
&req, query_params, headers, progress_callback, 0, &resp);
oss_write_request_body_from_buffer(buffer, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_body(resp, resp_body);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_put_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *filename,
aos_table_t *headers,
aos_table_t **resp_headers)
{
return oss_do_put_object_from_file(options, bucket, object, filename,
headers, NULL, NULL, resp_headers, NULL);
}
aos_status_t *oss_do_put_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
const aos_string_t *filename,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
int res = AOSE_OK;
s = aos_status_create(options->pool);
headers = aos_table_create_if_null(options, headers, 2);
set_content_type(filename->data, object->data, headers);
apr_table_add(headers, OSS_EXPECT, "");
query_params = aos_table_create_if_null(options, params, 0);
oss_init_object_request(options, bucket, object, HTTP_PUT, &req,
query_params, headers, progress_callback, 0, &resp);
res = oss_write_request_body_from_file(options->pool, filename, req);
if (res != AOSE_OK) {
aos_file_error_status_set(s, res);
return s;
}
s = oss_process_request(options, req, resp);
oss_fill_read_response_body(resp, resp_body);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_get_object_to_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_list_t *buffer,
aos_table_t **resp_headers)
{
return oss_do_get_object_to_buffer(options, bucket, object, headers,
params, buffer, NULL, resp_headers);
}
aos_status_t *oss_do_get_object_to_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_list_t *buffer,
oss_progress_callback progress_callback,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
headers = aos_table_create_if_null(options, headers, 0);
params = aos_table_create_if_null(options, params, 0);
oss_init_object_request(options, bucket, object, HTTP_GET,
&req, params, headers, progress_callback, 0, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_body(resp, buffer);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp) &&
!has_range_or_process_in_request(req)) {
oss_check_crc_consistent(resp->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_get_object_to_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_string_t *filename,
aos_table_t **resp_headers)
{
return oss_do_get_object_to_file(options, bucket, object, headers,
params, filename, NULL, resp_headers);
}
aos_status_t *oss_do_get_object_to_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t *params,
aos_string_t *filename,
oss_progress_callback progress_callback,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
int res = AOSE_OK;
aos_string_t tmp_filename;
headers = aos_table_create_if_null(options, headers, 0);
params = aos_table_create_if_null(options, params, 0);
oss_get_temporary_file_name(options->pool, filename, &tmp_filename);
oss_init_object_request(options, bucket, object, HTTP_GET,
&req, params, headers, progress_callback, 0, &resp);
s = aos_status_create(options->pool);
res = oss_init_read_response_body_to_file(options->pool, &tmp_filename, resp);
if (res != AOSE_OK) {
aos_file_error_status_set(s, res);
return s;
}
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp) &&
!has_range_or_process_in_request(req)) {
oss_check_crc_consistent(resp->crc64, resp->headers, s);
}
oss_temp_file_rename(s, tmp_filename.data, filename->data, options->pool);
return s;
}
aos_status_t *oss_head_object(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t *headers,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
headers = aos_table_create_if_null(options, headers, 0);
query_params = aos_table_create_if_null(options, query_params, 0);
oss_init_object_request(options, bucket, object, HTTP_HEAD,
&req, query_params, headers, NULL, 0, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_delete_object(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *headers = NULL;
aos_table_t *query_params = NULL;
headers = aos_table_create_if_null(options, headers, 0);
query_params = aos_table_create_if_null(options, query_params, 0);
oss_init_object_request(options, bucket, object, HTTP_DELETE,
&req, query_params, headers, NULL, 0, &resp);
oss_get_object_uri(options, bucket, object, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_copy_object(const oss_request_options_t *options,
const aos_string_t *source_bucket,
const aos_string_t *source_object,
const aos_string_t *dest_bucket,
const aos_string_t *dest_object,
aos_table_t *headers,
aos_table_t **resp_headers)
{
char *copy_source = NULL;
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
char buffer[AOS_MAX_QUERY_ARG_LEN*3+1];
int res = -1;
s = aos_status_create(options->pool);
headers = aos_table_create_if_null(options, headers, 2);
query_params = aos_table_create_if_null(options, query_params, 0);
/* init headers */
res = aos_url_encode(buffer, source_object->data, AOS_MAX_QUERY_ARG_LEN);
if (res != AOSE_OK) {
aos_status_set(s, res, AOS_URL_ENCODE_ERROR_CODE, NULL);
return s;
}
copy_source = apr_psprintf(options->pool, "/%.*s/%s",
source_bucket->len, source_bucket->data, buffer);
apr_table_set(headers, OSS_CANNONICALIZED_HEADER_COPY_SOURCE, copy_source);
set_content_type(NULL, dest_object->data, headers);
oss_init_object_request(options, dest_bucket, dest_object, HTTP_PUT,
&req, query_params, headers, NULL, 0, &resp);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_append_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
/* init query_params */
query_params = aos_table_create_if_null(options, query_params, 2);
apr_table_add(query_params, OSS_APPEND, "");
aos_table_add_int64(query_params, OSS_POSITION, position);
/* init headers */
headers = aos_table_create_if_null(options, headers, 2);
set_content_type(NULL, object->data, headers);
apr_table_add(headers, OSS_EXPECT, "");
oss_init_object_request(options, bucket, object, HTTP_POST,
&req, query_params, headers, NULL, 0, &resp);
oss_write_request_body_from_buffer(buffer, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_do_append_object_from_buffer(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
uint64_t init_crc,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
/* init query_params */
query_params = aos_table_create_if_null(options, params, 2);
apr_table_add(query_params, OSS_APPEND, "");
aos_table_add_int64(query_params, OSS_POSITION, position);
/* init headers */
headers = aos_table_create_if_null(options, headers, 2);
set_content_type(NULL, object->data, headers);
apr_table_add(headers, OSS_EXPECT, "");
oss_init_object_request(options, bucket, object, HTTP_POST, &req, query_params,
headers, progress_callback, init_crc, &resp);
oss_write_request_body_from_buffer(buffer, req);
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
oss_fill_read_response_body(resp, resp_body);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_append_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
const aos_string_t *append_file,
aos_table_t *headers,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
int res = AOSE_OK;
/* init query_params */
query_params = aos_table_create_if_null(options, query_params, 2);
apr_table_add(query_params, OSS_APPEND, "");
aos_table_add_int64(query_params, OSS_POSITION, position);
/* init headers */
headers = aos_table_create_if_null(options, headers, 2);
set_content_type(append_file->data, object->data, headers);
apr_table_add(headers, OSS_EXPECT, "");
oss_init_object_request(options, bucket, object, HTTP_POST,
&req, query_params, headers, NULL, 0, &resp);
res = oss_write_request_body_from_file(options->pool, append_file, req);
s = aos_status_create(options->pool);
if (res != AOSE_OK) {
aos_file_error_status_set(s, res);
return s;
}
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}
aos_status_t *oss_do_append_object_from_file(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
int64_t position,
uint64_t init_crc,
const aos_string_t *append_file,
aos_table_t *headers,
aos_table_t *params,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
int res = AOSE_OK;
/* init query_params */
query_params = aos_table_create_if_null(options, params, 2);
apr_table_add(query_params, OSS_APPEND, "");
aos_table_add_int64(query_params, OSS_POSITION, position);
/* init headers */
headers = aos_table_create_if_null(options, headers, 2);
set_content_type(append_file->data, object->data, headers);
apr_table_add(headers, OSS_EXPECT, "");
oss_init_object_request(options, bucket, object, HTTP_POST, &req, query_params,
headers, progress_callback, init_crc, &resp);
res = oss_write_request_body_from_file(options->pool, append_file, req);
s = aos_status_create(options->pool);
if (res != AOSE_OK) {
aos_file_error_status_set(s, res);
return s;
}
s = oss_process_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
oss_fill_read_response_body(resp, resp_body);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_put_object_from_buffer_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_list_t *buffer,
aos_table_t *headers,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
/* init query_params */
headers = aos_table_create_if_null(options, headers, 0);
query_params = aos_table_create_if_null(options, query_params, 0);
oss_init_signed_url_request(options, signed_url, HTTP_PUT,
&req, query_params, headers, &resp);
oss_write_request_body_from_buffer(buffer, req);
s = oss_process_signed_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_put_object_from_file_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_string_t *filename,
aos_table_t *headers,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
int res = AOSE_OK;
s = aos_status_create(options->pool);
headers = aos_table_create_if_null(options, headers, 0);
query_params = aos_table_create_if_null(options, query_params, 0);
oss_init_signed_url_request(options, signed_url, HTTP_PUT,
&req, query_params, headers, &resp);
res = oss_write_request_body_from_file(options->pool, filename, req);
if (res != AOSE_OK) {
aos_file_error_status_set(s, res);
return s;
}
s = oss_process_signed_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp)) {
oss_check_crc_consistent(req->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_get_object_to_buffer_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_table_t *headers,
aos_table_t *params,
aos_list_t *buffer,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
headers = aos_table_create_if_null(options, headers, 0);
params = aos_table_create_if_null(options, params, 0);
oss_init_signed_url_request(options, signed_url, HTTP_GET,
&req, params, headers, &resp);
s = oss_process_signed_request(options, req, resp);
oss_fill_read_response_body(resp, buffer);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp) &&
!has_range_or_process_in_request(req)) {
oss_check_crc_consistent(resp->crc64, resp->headers, s);
}
return s;
}
aos_status_t *oss_get_object_to_file_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_table_t *headers,
aos_table_t *params,
aos_string_t *filename,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
int res = AOSE_OK;
aos_string_t tmp_filename;
s = aos_status_create(options->pool);
headers = aos_table_create_if_null(options, headers, 0);
params = aos_table_create_if_null(options, params, 0);
oss_get_temporary_file_name(options->pool, filename, &tmp_filename);
oss_init_signed_url_request(options, signed_url, HTTP_GET,
&req, params, headers, &resp);
res = oss_init_read_response_body_to_file(options->pool, filename, resp);
if (res != AOSE_OK) {
aos_file_error_status_set(s, res);
return s;
}
s = oss_process_signed_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
if (is_enable_crc(options) && has_crc_in_response(resp) &&
!has_range_or_process_in_request(req)) {
oss_check_crc_consistent(resp->crc64, resp->headers, s);
}
oss_temp_file_rename(s, tmp_filename.data, filename->data, options->pool);
return s;
}
aos_status_t *oss_head_object_by_url(const oss_request_options_t *options,
const aos_string_t *signed_url,
aos_table_t *headers,
aos_table_t **resp_headers)
{
aos_status_t *s = NULL;
aos_http_request_t *req = NULL;
aos_http_response_t *resp = NULL;
aos_table_t *query_params = NULL;
headers = aos_table_create_if_null(options, headers, 0);
query_params = aos_table_create_if_null(options, query_params, 0);
oss_init_signed_url_request(options, signed_url, HTTP_HEAD,
&req, query_params, headers, &resp);
s = oss_process_signed_request(options, req, resp);
oss_fill_read_response_header(resp, resp_headers);
return s;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,168 @@
#ifndef LIBOSS_RESUMABLE_H
#define LIBOSS_RESUMABLE_H
#include "aos_define.h"
#include "aos_string.h"
#include "aos_status.h"
#include "apr_atomic.h"
#include "apr_queue.h"
#include "apr_thread_pool.h"
#include "oss_define.h"
AOS_CPP_START
#define OSS_CP_UPLOAD 1
#define OSS_CP_DOWNLOAD 2
typedef struct {
int32_t index; // the index of part, start from 0
int64_t offset; // the offset point of part
int64_t size; // the size of part
int completed; // AOS_TRUE completed, AOS_FALSE uncompleted
aos_string_t etag; // the etag of part, for upload
uint64_t crc64;
} oss_checkpoint_part_t;
typedef struct {
aos_string_t md5; // the md5 of checkout content
int cp_type; // 1 upload, 2 download
apr_file_t *thefile; // the handle of checkpoint file
aos_string_t file_path; // local file path
int64_t file_size; // local file size, for upload
apr_time_t file_last_modified; // local file last modified time, for upload
aos_string_t file_md5; // the md5 of the local file content, for upload, reserved
aos_string_t object_name; // object name
int64_t object_size; // object size, for download
aos_string_t object_last_modified; // object last modified time, for download
aos_string_t object_etag; // object etag, for download
aos_string_t upload_id; // upload id
int part_num; // the total number of parts
int64_t part_size; // the part size, byte
oss_checkpoint_part_t *parts; // the parts of local or object, from 0
} oss_checkpoint_t;
typedef struct {
oss_checkpoint_part_t *part;
aos_status_t *s;
aos_string_t etag;
uint64_t crc64;
} oss_part_task_result_t;
typedef struct {
oss_request_options_t options;
aos_string_t *bucket;
aos_string_t *object;
aos_string_t *upload_id;
aos_string_t *filepath;
oss_checkpoint_part_t *part;
oss_part_task_result_t *result;
apr_uint32_t *launched; // the number of launched part tasks, use atomic
apr_uint32_t *failed; // the number of failed part tasks, use atomic
apr_uint32_t *completed; // the number of completed part tasks, use atomic
apr_queue_t *failed_parts; // the queue of failed parts tasks, thread safe
apr_queue_t *completed_parts; // the queue of completed parts tasks, thread safe
apr_queue_t *task_result_queue;
} oss_thread_params_t;
int32_t oss_get_thread_num(oss_resumable_clt_params_t *clt_params);
void oss_get_upload_checkpoint_path(oss_resumable_clt_params_t *clt_params, const aos_string_t *filepath,
aos_pool_t *pool, aos_string_t *checkpoint_path);
void oss_get_download_checkpoint_path(oss_resumable_clt_params_t *clt_params, const aos_string_t *filepath,
aos_pool_t *pool, aos_string_t *checkpoint_path);
int oss_get_file_info(const aos_string_t *filepath, aos_pool_t *pool, apr_finfo_t *finfo);
int oss_does_file_exist(const aos_string_t *filepath, aos_pool_t *pool);
int oss_open_checkpoint_file(aos_pool_t *pool, aos_string_t *checkpoint_path, oss_checkpoint_t *checkpoint);
int oss_open_checkpoint_file(aos_pool_t *pool, aos_string_t *checkpoint_path, oss_checkpoint_t *checkpoint);
int oss_get_part_num(int64_t file_size, int64_t part_size);
void oss_build_parts(int64_t file_size, int64_t part_size, oss_checkpoint_part_t *parts);
void oss_build_thread_params(oss_thread_params_t *thr_params, int part_num,
aos_pool_t *parent_pool, oss_request_options_t *options,
aos_string_t *bucket, aos_string_t *object, aos_string_t *filepath,
aos_string_t *upload_id, oss_checkpoint_part_t *parts,
oss_part_task_result_t *result);
void oss_destroy_thread_pool(oss_thread_params_t *thr_params, int part_num);
void oss_set_task_tracker(oss_thread_params_t *thr_params, int part_num,
apr_uint32_t *launched, apr_uint32_t *failed, apr_uint32_t *completed,
apr_queue_t *failed_parts, apr_queue_t *completed_parts);
int oss_verify_checkpoint_md5(aos_pool_t *pool, const oss_checkpoint_t *checkpoint);
void oss_build_upload_checkpoint(aos_pool_t *pool, oss_checkpoint_t *checkpoint, aos_string_t *file_path,
apr_finfo_t *finfo, aos_string_t *upload_id, int64_t part_size);
void oss_build_download_checkpoint(aos_pool_t *pool, oss_checkpoint_t *checkpoint, aos_string_t *file_path,
const char *object_name, int64_t object_size, const char *object_last_modified,
const char *object_etag, int64_t part_size);
int oss_dump_checkpoint(aos_pool_t *pool, const oss_checkpoint_t *checkpoint);
int oss_load_checkpoint(aos_pool_t *pool, const aos_string_t *filepath, oss_checkpoint_t *checkpoint);
int oss_is_upload_checkpoint_valid(aos_pool_t *pool, oss_checkpoint_t *checkpoint, apr_finfo_t *finfo);
void oss_update_checkpoint(aos_pool_t *pool, oss_checkpoint_t *checkpoint, int32_t part_index,
aos_string_t *etag, uint64_t crc64);
void oss_get_checkpoint_todo_parts(oss_checkpoint_t *checkpoint, int *part_num, oss_checkpoint_part_t *parts);
void *APR_THREAD_FUNC upload_part(apr_thread_t *thd, void *data);
aos_status_t *oss_resumable_upload_file_without_cp(oss_request_options_t *options,
aos_string_t *bucket,
aos_string_t *object,
aos_string_t *filepath,
aos_table_t *headers,
aos_table_t *params,
int32_t thread_num,
int64_t part_size,
apr_finfo_t *finfo,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body);
aos_status_t *oss_resumable_upload_file_with_cp(oss_request_options_t *options,
aos_string_t *bucket,
aos_string_t *object,
aos_string_t *filepath,
aos_table_t *headers,
aos_table_t *params,
int32_t thread_num,
int64_t part_size,
aos_string_t *checkpoint_path,
apr_finfo_t *finfo,
oss_progress_callback progress_callback,
aos_table_t **resp_headers,
aos_list_t *resp_body);
aos_status_t *oss_resumable_download_file_internal(oss_request_options_t *options,
aos_string_t *bucket,
aos_string_t *object,
aos_string_t *filepath,
aos_table_t *headers,
aos_table_t *params,
int32_t thread_num,
int64_t part_size,
aos_string_t *checkpoint_path,
oss_progress_callback progress_callback,
aos_table_t **resp_headers);
AOS_CPP_END
#endif

926
include/oss_sdk/oss_util.c Normal file
View File

@@ -0,0 +1,926 @@
#include "aos_string.h"
#include "aos_util.h"
#include "aos_log.h"
#include "aos_status.h"
#include "oss_auth.h"
#include "oss_util.h"
#ifndef WIN32
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#endif
static char *default_content_type = "application/octet-stream";
static oss_content_type_t file_type[] = {
{"html", "text/html"},
{"htm", "text/html"},
{"shtml", "text/html"},
{"css", "text/css"},
{"xml", "text/xml"},
{"gif", "image/gif"},
{"jpeg", "image/jpeg"},
{"jpg", "image/jpeg"},
{"js", "application/x-javascript"},
{"atom", "application/atom+xml"},
{"rss", "application/rss+xml"},
{"mml", "text/mathml"},
{"txt", "text/plain"},
{"jad", "text/vnd.sun.j2me.app-descriptor"},
{"wml", "text/vnd.wap.wml"},
{"htc", "text/x-component"},
{"png", "image/png"},
{"tif", "image/tiff"},
{"tiff", "image/tiff"},
{"wbmp", "image/vnd.wap.wbmp"},
{"ico", "image/x-icon"},
{"jng", "image/x-jng"},
{"bmp", "image/x-ms-bmp"},
{"svg", "image/svg+xml"},
{"svgz", "image/svg+xml"},
{"webp", "image/webp"},
{"jar", "application/java-archive"},
{"war", "application/java-archive"},
{"ear", "application/java-archive"},
{"hqx", "application/mac-binhex40"},
{"doc ", "application/msword"},
{"pdf", "application/pdf"},
{"ps", "application/postscript"},
{"eps", "application/postscript"},
{"ai", "application/postscript"},
{"rtf", "application/rtf"},
{"xls", "application/vnd.ms-excel"},
{"ppt", "application/vnd.ms-powerpoint"},
{"wmlc", "application/vnd.wap.wmlc"},
{"kml", "application/vnd.google-earth.kml+xml"},
{"kmz", "application/vnd.google-earth.kmz"},
{"7z", "application/x-7z-compressed"},
{"cco", "application/x-cocoa"},
{"jardiff", "application/x-java-archive-diff"},
{"jnlp", "application/x-java-jnlp-file"},
{"run", "application/x-makeself"},
{"pl", "application/x-perl"},
{"pm", "application/x-perl"},
{"prc", "application/x-pilot"},
{"pdb", "application/x-pilot"},
{"rar", "application/x-rar-compressed"},
{"rpm", "application/x-redhat-package-manager"},
{"sea", "application/x-sea"},
{"swf", "application/x-shockwave-flash"},
{"sit", "application/x-stuffit"},
{"tcl", "application/x-tcl"},
{"tk", "application/x-tcl"},
{"der", "application/x-x509-ca-cert"},
{"pem", "application/x-x509-ca-cert"},
{"crt", "application/x-x509-ca-cert"},
{"xpi", "application/x-xpinstall"},
{"xhtml", "application/xhtml+xml"},
{"zip", "application/zip"},
{"wgz", "application/x-nokia-widget"},
{"bin", "application/octet-stream"},
{"exe", "application/octet-stream"},
{"dll", "application/octet-stream"},
{"deb", "application/octet-stream"},
{"dmg", "application/octet-stream"},
{"eot", "application/octet-stream"},
{"iso", "application/octet-stream"},
{"img", "application/octet-stream"},
{"msi", "application/octet-stream"},
{"msp", "application/octet-stream"},
{"msm", "application/octet-stream"},
{"mid", "audio/midi"},
{"midi", "audio/midi"},
{"kar", "audio/midi"},
{"mp3", "audio/mpeg"},
{"ogg", "audio/ogg"},
{"m4a", "audio/x-m4a"},
{"ra", "audio/x-realaudio"},
{"3gpp", "video/3gpp"},
{"3gp", "video/3gpp"},
{"mp4", "video/mp4"},
{"mpeg", "video/mpeg"},
{"mpg", "video/mpeg"},
{"mov", "video/quicktime"},
{"webm", "video/webm"},
{"flv", "video/x-flv"},
{"m4v", "video/x-m4v"},
{"mng", "video/x-mng"},
{"asx", "video/x-ms-asf"},
{"asf", "video/x-ms-asf"},
{"wmv", "video/x-ms-wmv"},
{"avi", "video/x-msvideo"},
{"ts", "video/MP2T"},
{"m3u8", "application/x-mpegURL"},
{"apk", "application/vnd.android.package-archive"},
{NULL, NULL}
};
static int starts_with(const aos_string_t *str, const char *prefix) {
uint32_t i;
if(NULL != str && prefix && str->len > 0 && strlen(prefix)) {
for(i = 0; str->data[i] != '\0' && prefix[i] != '\0'; i++) {
if(prefix[i] != str->data[i]) return 0;
}
return 1;
}
return 0;
}
static void generate_proto(const oss_request_options_t *options,
aos_http_request_t *req)
{
const char *proto;
proto = starts_with(&options->config->endpoint, AOS_HTTP_PREFIX) ?
AOS_HTTP_PREFIX : "";
proto = starts_with(&options->config->endpoint, AOS_HTTPS_PREFIX) ?
AOS_HTTPS_PREFIX : proto;
req->proto = apr_psprintf(options->pool, "%.*s", (int)strlen(proto), proto);
}
static void generate_rtmp_proto(const oss_request_options_t *options,
aos_http_request_t *req)
{
const char *proto = AOS_RTMP_PREFIX;
req->proto = apr_psprintf(options->pool, "%.*s", (int)strlen(proto), proto);
}
int is_valid_ip(const char *str)
{
if (INADDR_NONE == inet_addr(str) || INADDR_ANY == inet_addr(str)) {
return 0;
}
return 1;
}
oss_config_t *oss_config_create(aos_pool_t *p)
{
return (oss_config_t *)aos_pcalloc(p, sizeof(oss_config_t));
}
void oss_config_resolve(aos_pool_t *pool, oss_config_t *config, aos_http_controller_t *ctl)
{
if(!aos_is_null_string(&config->proxy_host)) {
// proxy host:port
if (config->proxy_port == 0) {
ctl->options->proxy_host = apr_psprintf(pool, "%.*s", config->proxy_host.len, config->proxy_host.data);
} else {
ctl->options->proxy_host = apr_psprintf(pool, "%.*s:%d", config->proxy_host.len, config->proxy_host.data,
config->proxy_port);
}
// authorize user:passwd
if (!aos_is_null_string(&config->proxy_user) && !aos_is_null_string(&config->proxy_passwd)) {
ctl->options->proxy_auth = apr_psprintf(pool, "%.*s:%.*s", config->proxy_user.len,
config->proxy_user.data, config->proxy_passwd.len, config->proxy_passwd.data);
}
}
}
oss_request_options_t *oss_request_options_create(aos_pool_t *p)
{
int s;
oss_request_options_t *options;
if(p == NULL) {
if ((s = aos_pool_create(&p, NULL)) != APR_SUCCESS) {
aos_fatal_log("aos_pool_create failure.");
return NULL;
}
}
options = (oss_request_options_t *)aos_pcalloc(p, sizeof(oss_request_options_t));
options->pool = p;
return options;
}
void oss_get_object_uri(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_http_request_t *req)
{
int32_t proto_len;
const char *raw_endpoint_str;
aos_string_t raw_endpoint;
generate_proto(options, req);
proto_len = strlen(req->proto);
req->resource = apr_psprintf(options->pool, "%.*s/%.*s",
bucket->len, bucket->data,
object->len, object->data);
raw_endpoint_str = aos_pstrdup(options->pool,
&options->config->endpoint) + proto_len;
raw_endpoint.len = options->config->endpoint.len - proto_len;
raw_endpoint.data = options->config->endpoint.data + proto_len;
if (options->config->is_cname) {
req->host = apr_psprintf(options->pool, "%.*s",
raw_endpoint.len, raw_endpoint.data);
req->uri = object->data;
} else if (is_valid_ip(raw_endpoint_str)) {
req->host = apr_psprintf(options->pool, "%.*s",
raw_endpoint.len, raw_endpoint.data);
req->uri = apr_psprintf(options->pool, "%.*s/%.*s",
bucket->len, bucket->data,
object->len, object->data);
} else {
req->host = apr_psprintf(options->pool, "%.*s.%.*s",
bucket->len, bucket->data,
raw_endpoint.len, raw_endpoint.data);
req->uri = object->data;
}
}
void oss_get_bucket_uri(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_http_request_t *req)
{
int32_t proto_len;
const char *raw_endpoint_str;
aos_string_t raw_endpoint;
generate_proto(options, req);
proto_len = strlen(req->proto);
raw_endpoint_str = aos_pstrdup(options->pool,
&options->config->endpoint) + proto_len;
raw_endpoint.len = options->config->endpoint.len - proto_len;
raw_endpoint.data = options->config->endpoint.data + proto_len;
if (is_valid_ip(raw_endpoint_str)) {
req->resource = apr_psprintf(options->pool, "%.*s",
bucket->len, bucket->data);
} else {
req->resource = apr_psprintf(options->pool, "%.*s/",
bucket->len, bucket->data);
}
if (options->config->is_cname ||
is_valid_ip(raw_endpoint_str))
{
req->host = apr_psprintf(options->pool, "%.*s",
raw_endpoint.len, raw_endpoint.data);
req->uri = apr_psprintf(options->pool, "%.*s", bucket->len,
bucket->data);
} else {
req->host = apr_psprintf(options->pool, "%.*s.%.*s",
bucket->len, bucket->data,
raw_endpoint.len, raw_endpoint.data);
req->uri = apr_psprintf(options->pool, "%s", "");
}
}
void oss_get_rtmp_uri(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel_id,
aos_http_request_t *req)
{
int32_t proto_len = 0;
const char *raw_endpoint_str = NULL;
aos_string_t raw_endpoint;
generate_rtmp_proto(options, req);
proto_len = strlen(req->proto);
req->resource = apr_psprintf(options->pool, "%.*s/%.*s", bucket->len, bucket->data,
live_channel_id->len, live_channel_id->data);
raw_endpoint_str = aos_pstrdup(options->pool,
&options->config->endpoint) + proto_len;
raw_endpoint.len = options->config->endpoint.len - proto_len;
raw_endpoint.data = options->config->endpoint.data + proto_len;
if (options->config->is_cname) {
req->host = apr_psprintf(options->pool, "%.*s",
raw_endpoint.len, raw_endpoint.data);
req->uri = apr_psprintf(options->pool, "live/%.*s",
live_channel_id->len, live_channel_id->data);
} else if (is_valid_ip(raw_endpoint_str)) {
req->host = apr_psprintf(options->pool, "%.*s",
raw_endpoint.len, raw_endpoint.data);
req->uri = apr_psprintf(options->pool, "%.*s/live/%.*s",
bucket->len, bucket->data,
live_channel_id->len, live_channel_id->data);
} else {
req->host = apr_psprintf(options->pool, "%.*s.%.*s",
bucket->len, bucket->data,
raw_endpoint.len, raw_endpoint.data);
req->uri = apr_psprintf(options->pool, "live/%.*s",
live_channel_id->len, live_channel_id->data);
}
}
void oss_write_request_body_from_buffer(aos_list_t *buffer,
aos_http_request_t *req)
{
aos_list_movelist(buffer, &req->body);
req->body_len = aos_buf_list_len(&req->body);
}
int oss_write_request_body_from_file(aos_pool_t *p,
const aos_string_t *filename,
aos_http_request_t *req)
{
int res = AOSE_OK;
aos_file_buf_t *fb = aos_create_file_buf(p);
res = aos_open_file_for_all_read(p, filename->data, fb);
if (res != AOSE_OK) {
aos_error_log("Open read file fail, filename:%s\n", filename->data);
return res;
}
req->body_len = fb->file_last;
req->file_path = filename->data;
req->file_buf = fb;
req->type = BODY_IN_FILE;
req->read_body = aos_read_http_body_file;
return res;
}
int oss_write_request_body_from_upload_file(aos_pool_t *p,
oss_upload_file_t *upload_file,
aos_http_request_t *req)
{
int res = AOSE_OK;
aos_file_buf_t *fb = aos_create_file_buf(p);
res = aos_open_file_for_range_read(p, upload_file->filename.data,
upload_file->file_pos, upload_file->file_last, fb);
if (res != AOSE_OK) {
aos_error_log("Open read file fail, filename:%s\n",
upload_file->filename.data);
return res;
}
req->body_len = fb->file_last - fb->file_pos;
req->file_path = upload_file->filename.data;
req->file_buf = fb;
req->type = BODY_IN_FILE;
req->read_body = aos_read_http_body_file;
return res;
}
void oss_fill_read_response_body(aos_http_response_t *resp,
aos_list_t *buffer)
{
if (NULL != buffer) {
aos_list_movelist(&resp->body, buffer);
}
}
int oss_init_read_response_body_to_file(aos_pool_t *p,
const aos_string_t *filename,
aos_http_response_t *resp)
{
int res = AOSE_OK;
aos_file_buf_t *fb = aos_create_file_buf(p);
res = aos_open_file_for_write(p, filename->data, fb);
if (res != AOSE_OK) {
aos_error_log("Open write file fail, filename:%s\n", filename->data);
return res;
}
resp->file_path = filename->data;
resp->file_buf = fb;
resp->write_body = aos_write_http_body_file;
resp->type = BODY_IN_FILE;
return res;
}
int oss_init_read_response_body_to_fb(aos_file_buf_t *fb,
const aos_string_t *filename,
aos_http_response_t *resp)
{
int res = AOSE_OK;
resp->file_path = filename->data;
resp->file_buf = fb;
resp->write_body = aos_write_http_body_file;
resp->type = BODY_IN_FILE;
return res;
}
void oss_fill_read_response_header(aos_http_response_t *resp,
aos_table_t **headers)
{
if (NULL != headers && NULL != resp) {
*headers = resp->headers;
}
}
void *oss_create_api_result_content(aos_pool_t *p, size_t size)
{
void *result_content = aos_palloc(p, size);
if (NULL == result_content) {
return NULL;
}
aos_list_init((aos_list_t *)result_content);
return result_content;
}
oss_list_object_content_t *oss_create_list_object_content(aos_pool_t *p)
{
return (oss_list_object_content_t *)oss_create_api_result_content(
p, sizeof(oss_list_object_content_t));
}
oss_list_object_common_prefix_t *oss_create_list_object_common_prefix(aos_pool_t *p)
{
return (oss_list_object_common_prefix_t *)oss_create_api_result_content(
p, sizeof(oss_list_object_common_prefix_t));
}
oss_list_multipart_upload_content_t *oss_create_list_multipart_upload_content(aos_pool_t *p)
{
return (oss_list_multipart_upload_content_t*)oss_create_api_result_content(
p, sizeof(oss_list_multipart_upload_content_t));
}
oss_list_part_content_t *oss_create_list_part_content(aos_pool_t *p)
{
oss_list_part_content_t *list_part_content = NULL;
list_part_content = (oss_list_part_content_t*)oss_create_api_result_content(p,
sizeof(oss_list_part_content_t));
return list_part_content;
}
oss_complete_part_content_t *oss_create_complete_part_content(aos_pool_t *p)
{
oss_complete_part_content_t *complete_part_content = NULL;
complete_part_content = (oss_complete_part_content_t*)oss_create_api_result_content(
p, sizeof(oss_complete_part_content_t));
return complete_part_content;
}
oss_list_object_params_t *oss_create_list_object_params(aos_pool_t *p)
{
oss_list_object_params_t * params;
params = (oss_list_object_params_t *)aos_pcalloc(
p, sizeof(oss_list_object_params_t));
aos_list_init(&params->object_list);
aos_list_init(&params->common_prefix_list);
aos_str_set(&params->prefix, "");
aos_str_set(&params->marker, "");
aos_str_set(&params->delimiter, "");
params->truncated = 1;
params->max_ret = OSS_PER_RET_NUM;
return params;
}
oss_list_upload_part_params_t *oss_create_list_upload_part_params(aos_pool_t *p)
{
oss_list_upload_part_params_t *params;
params = (oss_list_upload_part_params_t *)aos_pcalloc(
p, sizeof(oss_list_upload_part_params_t));
aos_list_init(&params->part_list);
aos_str_set(&params->part_number_marker, "");
params->max_ret = OSS_PER_RET_NUM;
params->truncated = 1;
return params;
}
oss_list_multipart_upload_params_t *oss_create_list_multipart_upload_params(aos_pool_t *p)
{
oss_list_multipart_upload_params_t *params;
params = (oss_list_multipart_upload_params_t *)aos_pcalloc(
p, sizeof(oss_list_multipart_upload_params_t));
aos_list_init(&params->upload_list);
aos_str_set(&params->prefix, "");
aos_str_set(&params->key_marker, "");
aos_str_set(&params->upload_id_marker, "");
aos_str_set(&params->delimiter, "");
params->truncated = 1;
params->max_ret = OSS_PER_RET_NUM;
return params;
}
oss_upload_part_copy_params_t *oss_create_upload_part_copy_params(aos_pool_t *p)
{
return (oss_upload_part_copy_params_t *)aos_pcalloc(
p, sizeof(oss_upload_part_copy_params_t));
}
oss_lifecycle_rule_content_t *oss_create_lifecycle_rule_content(aos_pool_t *p)
{
oss_lifecycle_rule_content_t *rule;
rule = (oss_lifecycle_rule_content_t *)aos_pcalloc(
p, sizeof(oss_lifecycle_rule_content_t));
aos_str_set(&rule->id, "");
aos_str_set(&rule->prefix, "");
aos_str_set(&rule->status, "");
aos_str_set(&rule->date, "");
rule->days = INT_MAX;
return rule;
}
oss_upload_file_t *oss_create_upload_file(aos_pool_t *p)
{
return (oss_upload_file_t *)aos_pcalloc(p, sizeof(oss_upload_file_t));
}
oss_object_key_t *oss_create_oss_object_key(aos_pool_t *p)
{
return (oss_object_key_t *)aos_pcalloc(p, sizeof(oss_object_key_t));
}
oss_live_channel_publish_url_t *oss_create_live_channel_publish_url(aos_pool_t *p)
{
return (oss_live_channel_publish_url_t *)aos_pcalloc(p, sizeof(oss_live_channel_publish_url_t));
}
oss_live_channel_play_url_t *oss_create_live_channel_play_url(aos_pool_t *p)
{
return (oss_live_channel_play_url_t *)aos_pcalloc(p, sizeof(oss_live_channel_play_url_t));
}
oss_live_channel_content_t *oss_create_list_live_channel_content(aos_pool_t *p)
{
oss_live_channel_content_t *list_live_channel_content = NULL;
list_live_channel_content = (oss_live_channel_content_t*)oss_create_api_result_content(p,
sizeof(oss_live_channel_content_t));
aos_list_init(&list_live_channel_content->publish_url_list);
aos_list_init(&list_live_channel_content->play_url_list);
return list_live_channel_content;
}
oss_live_record_content_t *oss_create_live_record_content(aos_pool_t *p)
{
oss_live_record_content_t *live_record_content = NULL;
live_record_content = (oss_live_record_content_t*)oss_create_api_result_content(p,
sizeof(oss_live_record_content_t));
return live_record_content;
}
oss_live_channel_configuration_t *oss_create_live_channel_configuration_content(aos_pool_t *p)
{
oss_live_channel_configuration_t *config;
config = (oss_live_channel_configuration_t *)aos_pcalloc(
p, sizeof(oss_live_channel_configuration_t));
aos_str_set(&config->name, "");
aos_str_set(&config->description, "");
aos_str_set(&config->status, LIVE_CHANNEL_STATUS_ENABLED);
aos_str_set(&config->target.type, LIVE_CHANNEL_DEFAULT_TYPE);
aos_str_set(&config->target.play_list_name, LIVE_CHANNEL_DEFAULT_PLAYLIST);
config->target.frag_duration = LIVE_CHANNEL_DEFAULT_FRAG_DURATION;
config->target.frag_count = LIVE_CHANNEL_DEFAULT_FRAG_COUNT;
return config;
}
oss_checkpoint_t *oss_create_checkpoint_content(aos_pool_t *p)
{
oss_checkpoint_t *cp;
cp = (oss_checkpoint_t *)aos_pcalloc(p, sizeof(oss_checkpoint_t));
cp->parts = (oss_checkpoint_part_t *)aos_pcalloc(p, sizeof(oss_checkpoint_part_t) * OSS_MAX_PART_NUM);
aos_str_set(&cp->md5, "");
aos_str_set(&cp->file_path, "");
aos_str_set(&cp->file_md5, "");
aos_str_set(&cp->object_name, "");
aos_str_set(&cp->object_last_modified, "");
aos_str_set(&cp->object_etag, "");
aos_str_set(&cp->upload_id, "");
return cp;
}
oss_resumable_clt_params_t *oss_create_resumable_clt_params_content(aos_pool_t *p, int64_t part_size, int32_t thread_num,
int enable_checkpoint, const char *checkpoint_path)
{
oss_resumable_clt_params_t *clt;
clt = (oss_resumable_clt_params_t *)aos_pcalloc(p, sizeof(oss_resumable_clt_params_t));
clt->part_size = part_size;
clt->thread_num = thread_num;
clt->enable_checkpoint = enable_checkpoint;
if (enable_checkpoint && NULL != checkpoint_path) {
aos_str_set(&clt->checkpoint_path, checkpoint_path);
}
return clt;
}
oss_list_live_channel_params_t *oss_create_list_live_channel_params(aos_pool_t *p)
{
oss_list_live_channel_params_t *params;
params = (oss_list_live_channel_params_t *)aos_pcalloc(
p, sizeof(oss_list_live_channel_params_t));
aos_list_init(&params->live_channel_list);
aos_str_set(&params->prefix, "");
aos_str_set(&params->marker, "");
params->truncated = 1;
params->max_keys = OSS_PER_RET_NUM;
return params;
}
const char *get_oss_acl_str(oss_acl_e oss_acl)
{
switch (oss_acl) {
case OSS_ACL_PRIVATE:
return "private";
case OSS_ACL_PUBLIC_READ:
return "public-read";
case OSS_ACL_PUBLIC_READ_WRITE:
return "public-read-write";
default:
return NULL;
}
}
void oss_init_request(const oss_request_options_t *options,
http_method_e method,
aos_http_request_t **req,
aos_table_t *params,
aos_table_t *headers,
aos_http_response_t **resp)
{
*req = aos_http_request_create(options->pool);
*resp = aos_http_response_create(options->pool);
(*req)->method = method;
init_sts_token_header();
(*req)->headers = headers;
(*req)->query_params = params;
}
void oss_init_bucket_request(const oss_request_options_t *options,
const aos_string_t *bucket,
http_method_e method,
aos_http_request_t **req,
aos_table_t *params,
aos_table_t *headers,
aos_http_response_t **resp)
{
oss_init_request(options, method, req, params, headers, resp);
oss_get_bucket_uri(options, bucket, *req);
}
void oss_init_object_request(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
http_method_e method,
aos_http_request_t **req,
aos_table_t *params,
aos_table_t *headers,
oss_progress_callback cb,
uint64_t init_crc,
aos_http_response_t **resp)
{
oss_init_request(options, method, req, params, headers, resp);
if (HTTP_GET == method) {
(*resp)->progress_callback = cb;
} else if (HTTP_PUT == method || HTTP_POST == method) {
(*req)->progress_callback = cb;
(*req)->crc64 = init_crc;
}
oss_get_object_uri(options, bucket, object, *req);
}
void oss_init_live_channel_request(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel,
http_method_e method,
aos_http_request_t **req,
aos_table_t *params,
aos_table_t *headers,
aos_http_response_t **resp)
{
oss_init_request(options, method, req, params, headers, resp);
oss_get_object_uri(options, bucket, live_channel, *req);
}
void oss_init_signed_url_request(const oss_request_options_t *options,
const aos_string_t *signed_url,
http_method_e method,
aos_http_request_t **req,
aos_table_t *params,
aos_table_t *headers,
aos_http_response_t **resp)
{
*req = aos_http_request_create(options->pool);
*resp = aos_http_response_create(options->pool);
(*req)->method = method;
(*req)->headers = headers;
(*req)->query_params = params;
(*req)->signed_url = signed_url->data;
}
aos_status_t *oss_send_request(aos_http_controller_t *ctl,
aos_http_request_t *req,
aos_http_response_t *resp)
{
aos_status_t *s;
const char *reason;
int res = AOSE_OK;
s = aos_status_create(ctl->pool);
res = aos_http_send_request(ctl, req, resp);
if (res != AOSE_OK) {
reason = aos_http_controller_get_reason(ctl);
aos_status_set(s, res, AOS_HTTP_IO_ERROR_CODE, reason);
} else if (!aos_http_is_ok(resp->status)) {
s = aos_status_parse_from_body(ctl->pool, &resp->body, resp->status, s);
} else {
s->code = resp->status;
}
s->req_id = (char*)(apr_table_get(resp->headers, "x-oss-request-id"));
if (s->req_id == NULL) {
s->req_id = (char*)(apr_table_get(resp->headers, "x-img-request-id"));
if (s->req_id == NULL) {
s->req_id = "";
}
}
return s;
}
aos_status_t *oss_process_request(const oss_request_options_t *options,
aos_http_request_t *req,
aos_http_response_t *resp)
{
int res = AOSE_OK;
aos_status_t *s;
s = aos_status_create(options->pool);
res = oss_sign_request(req, options->config);
if (res != AOSE_OK) {
aos_status_set(s, res, AOS_CLIENT_ERROR_CODE, NULL);
return s;
}
return oss_send_request(options->ctl, req, resp);
}
aos_status_t *oss_process_signed_request(const oss_request_options_t *options,
aos_http_request_t *req,
aos_http_response_t *resp)
{
return oss_send_request(options->ctl, req, resp);
}
void oss_get_part_size(int64_t filesize, int64_t *part_size)
{
if (filesize > (*part_size) * OSS_MAX_PART_NUM) {
*part_size = (filesize + OSS_MAX_PART_NUM -
filesize % OSS_MAX_PART_NUM) / OSS_MAX_PART_NUM;
aos_warn_log("Part number larger than max limit, "
"part size Changed to:%" APR_INT64_T_FMT "\n",
*part_size);
}
}
int part_sort_cmp(const void *a, const void *b)
{
return (((oss_upload_part_t*)a)->part_num -
((oss_upload_part_t*)b)->part_num > 0 ? 1 : -1);
}
void oss_headers_add_range(apr_pool_t *pool, apr_table_t *headers, int64_t offset, int64_t size)
{
char *range;
range = apr_psprintf(pool, "bytes=%" APR_INT64_T_FMT "-%" APR_INT64_T_FMT,
offset, offset + size - 1);
apr_table_set(headers, "Range", range);
}
char *get_content_type_by_suffix(const char *suffix)
{
oss_content_type_t *content_type;
for (content_type = file_type; content_type->suffix; ++content_type) {
if (strcasecmp(content_type->suffix, suffix) == 0)
{
return content_type->type;
}
}
return default_content_type;
}
char *get_content_type(const char *name)
{
char *begin;
char *content_type = NULL;
begin = strrchr(name, '.');
if (begin) {
content_type = get_content_type_by_suffix(begin + 1);
}
return content_type;
}
void set_content_type(const char* file_name,
const char* key,
aos_table_t *headers)
{
char *user_content_type = NULL;
char *content_type = NULL;
const char *mime_key = NULL;
mime_key = file_name == NULL ? key : file_name;
user_content_type = (char*)apr_table_get(headers, OSS_CONTENT_TYPE);
if (NULL == user_content_type && mime_key != NULL) {
content_type = get_content_type(mime_key);
if (content_type) {
apr_table_set(headers, OSS_CONTENT_TYPE, content_type);
} else {
apr_table_set(headers, OSS_CONTENT_TYPE, default_content_type);
}
}
}
aos_table_t* aos_table_create_if_null(const oss_request_options_t *options,
aos_table_t *table,
int table_size)
{
if (table == NULL) {
table = aos_table_make(options->pool, table_size);
}
return table;
}
int is_enable_crc(const oss_request_options_t *options)
{
return options->ctl->options->enable_crc;
}
int has_crc_in_response(const aos_http_response_t *resp)
{
if (NULL != apr_table_get(resp->headers, OSS_HASH_CRC64_ECMA)) {
return AOS_TRUE;
}
return AOS_FALSE;
}
int has_range_or_process_in_request(const aos_http_request_t *req)
{
if (NULL != apr_table_get(req->headers, "Range") ||
NULL != apr_table_get(req->query_params, OSS_PROCESS)) {
return AOS_TRUE;
}
return AOS_FALSE;
}
static int check_crc(uint64_t crc, const apr_table_t *headers)
{
char * srv_crc = (char*)(apr_table_get(headers, OSS_HASH_CRC64_ECMA));
if (NULL != srv_crc && crc != aos_atoui64(srv_crc)) {
return AOSE_CRC_INCONSISTENT_ERROR;
}
return AOSE_OK;
}
int oss_check_crc_consistent(uint64_t crc, const apr_table_t *resp_headers, aos_status_t *s)
{
int res = check_crc(crc, resp_headers);
if (res != AOSE_OK) {
aos_inconsistent_error_status_set(s, res);
}
return res;
}
int oss_get_temporary_file_name(aos_pool_t *p, const aos_string_t *filename, aos_string_t *temp_file_name)
{
int len = filename->len + 1;
char *temp_file_name_ptr = NULL;
len += strlen(AOS_TEMP_FILE_SUFFIX);
temp_file_name_ptr = aos_pcalloc(p, len);
apr_snprintf(temp_file_name_ptr, len, "%.*s%s", filename->len, filename->data, AOS_TEMP_FILE_SUFFIX);
aos_str_set(temp_file_name, temp_file_name_ptr);
return len;
}
int oss_temp_file_rename(aos_status_t *s, const char *from_path, const char *to_path, apr_pool_t *pool)
{
int res = -1;
if (s != NULL) {
if (aos_status_is_ok(s)) {
res = apr_file_rename(from_path, to_path, pool);
} else {
res = apr_file_remove(from_path, pool);
}
}
return res;
}

298
include/oss_sdk/oss_util.h Normal file
View File

@@ -0,0 +1,298 @@
#ifndef LIBOSS_UTIL_H
#define LIBOSS_UTIL_H
#include "aos_string.h"
#include "aos_transport.h"
#include "aos_status.h"
#include "oss_define.h"
#include "oss_resumable.h"
OSS_CPP_START
#define init_sts_token_header() do { \
if (options->config->sts_token.data != NULL) {\
apr_table_set(headers, OSS_STS_SECURITY_TOKEN, options->config->sts_token.data);\
}\
} while(0)
/**
* @brief check hostname ends with specific oss domain suffix.
**/
int is_oss_domain(const aos_string_t *str);
/**
* @brief check hostname is ip.
**/
int is_valid_ip(const char *str);
/**
* @brief get oss acl str according oss_acl
* @param[in] oss_acl the oss bucket acl
* @return oss acl str
**/
const char *get_oss_acl_str(oss_acl_e oss_acl);
/**
* @brief create oss config including host, port, access_key_id, access_key_secret, is_oss_domain
**/
oss_config_t *oss_config_create(aos_pool_t *p);
/**
* @brief evaluate config to curl
**/
void oss_config_resolve(aos_pool_t *pool, oss_config_t *config, aos_http_controller_t *ctl);
/**
* @brief create oss request options
* @return oss request options
**/
oss_request_options_t *oss_request_options_create(aos_pool_t *p);
/**
* @brief init oss request
**/
void oss_init_request(const oss_request_options_t *options, http_method_e method,
aos_http_request_t **req, aos_table_t *params, aos_table_t *headers, aos_http_response_t **resp);
/**
* @brief init oss bucket request
**/
void oss_init_bucket_request(const oss_request_options_t *options, const aos_string_t *bucket,
http_method_e method, aos_http_request_t **req, aos_table_t *params, aos_table_t *headers,
aos_http_response_t **resp);
/**
* @brief init oss object request
**/
void oss_init_object_request(const oss_request_options_t *options, const aos_string_t *bucket,
const aos_string_t *object, http_method_e method, aos_http_request_t **req,
aos_table_t *params, aos_table_t *headers, oss_progress_callback cb, uint64_t initcrc,
aos_http_response_t **resp);
/**
* @brief init oss live channel request
**/
void oss_init_live_channel_request(const oss_request_options_t *options,
const aos_string_t *bucket, const aos_string_t *live_channel,
http_method_e method, aos_http_request_t **req, aos_table_t *params,
aos_table_t *headers, aos_http_response_t **resp);
/**
* @brief init oss request with signed_url
**/
void oss_init_signed_url_request(const oss_request_options_t *options, const aos_string_t *signed_url,
http_method_e method, aos_http_request_t **req,
aos_table_t *params, aos_table_t *headers, aos_http_response_t **resp);
/**
* @brief oss send request
**/
aos_status_t *oss_send_request(aos_http_controller_t *ctl, aos_http_request_t *req,
aos_http_response_t *resp);
/**
* @brief process oss request including sign request, send request, get response
**/
aos_status_t *oss_process_request(const oss_request_options_t *options,
aos_http_request_t *req, aos_http_response_t *resp);
/**
* @brief process oss request with signed_url including send request, get response
**/
aos_status_t *oss_process_signed_request(const oss_request_options_t *options,
aos_http_request_t *req, aos_http_response_t *resp);
/**
* @brief get object uri using third-level domain if hostname is oss domain, otherwise second-level domain
**/
void oss_get_object_uri(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *object,
aos_http_request_t *req);
/**
* @brief bucket uri using third-level domain if hostname is oss domain, otherwise second-level domain
**/
void oss_get_bucket_uri(const oss_request_options_t *options,
const aos_string_t *bucket,
aos_http_request_t *req);
/**
* @brief get rtmp uri using third-level domain if hostname is oss domain, otherwise second-level domain
**/
void oss_get_rtmp_uri(const oss_request_options_t *options,
const aos_string_t *bucket,
const aos_string_t *live_channel_id,
aos_http_request_t *req);
/**
* @brief write body content into oss request body from buffer
**/
void oss_write_request_body_from_buffer(aos_list_t *buffer, aos_http_request_t *req);
/**
* @brief write body content into oss request body from file
**/
int oss_write_request_body_from_file(aos_pool_t *p, const aos_string_t *filename, aos_http_request_t *req);
/**
* @brief write body content into oss request body from multipart upload file
**/
int oss_write_request_body_from_upload_file(aos_pool_t *p, oss_upload_file_t *upload_file, aos_http_request_t *req);
/**
* @brief read body content from oss response body to buffer
**/
void oss_fill_read_response_body(aos_http_response_t *resp, aos_list_t *buffer);
/**
* @brief read body content from oss response body to file
**/
int oss_init_read_response_body_to_file(aos_pool_t *p, const aos_string_t *filename, aos_http_response_t *resp);
/**
* @brief read body content from oss response body to file buffer
**/
int oss_init_read_response_body_to_fb(aos_file_buf_t *fb, const aos_string_t *filename, aos_http_response_t *resp);
/**
* @brief read response header if headers is not null
**/
void oss_fill_read_response_header(aos_http_response_t *resp, aos_table_t **headers);
/**
* @brief create oss api result content
* @return oss api result content
**/
void *oss_create_api_result_content(aos_pool_t *p, size_t size);
oss_list_object_content_t *oss_create_list_object_content(aos_pool_t *p);
oss_list_object_common_prefix_t *oss_create_list_object_common_prefix(aos_pool_t *p);
oss_list_part_content_t *oss_create_list_part_content(aos_pool_t *p);
oss_list_multipart_upload_content_t *oss_create_list_multipart_upload_content(aos_pool_t *p);
oss_complete_part_content_t *oss_create_complete_part_content(aos_pool_t *p);
/**
* @brief create oss api list parameters
* @return oss api list parameters
**/
oss_list_object_params_t *oss_create_list_object_params(aos_pool_t *p);
oss_list_upload_part_params_t *oss_create_list_upload_part_params(aos_pool_t *p);
oss_list_multipart_upload_params_t *oss_create_list_multipart_upload_params(aos_pool_t *p);
oss_list_live_channel_params_t *oss_create_list_live_channel_params(aos_pool_t *p);
/**
* @brief create upload part copy params
* @return upload part copy params struct for upload part copy
**/
oss_upload_part_copy_params_t *oss_create_upload_part_copy_params(aos_pool_t *p);
/**
* @brief create upload file struct for range multipart upload
* @return upload file struct for range multipart upload
**/
oss_upload_file_t *oss_create_upload_file(aos_pool_t *p);
/**
* @brief create lifecycle rule content
* @return lifecycle rule content
**/
oss_lifecycle_rule_content_t *oss_create_lifecycle_rule_content(aos_pool_t *p);
/**
* @brief create oss object content for delete objects
* @return oss object content
**/
oss_object_key_t *oss_create_oss_object_key(aos_pool_t *p);
/**
* @brief create oss live channel publish url content for delete objects
* @return oss live channel publish url content
**/
oss_live_channel_publish_url_t *oss_create_live_channel_publish_url(aos_pool_t *p);
/**
* @brief create oss live channel play url content for delete objects
* @return oss live channel play url content
**/
oss_live_channel_play_url_t *oss_create_live_channel_play_url(aos_pool_t *p);
/**
* @brief create oss list live channel content for delete objects
* @return oss list live channel content
**/
oss_live_channel_content_t *oss_create_list_live_channel_content(aos_pool_t *p);
/**
* @brief create oss live recored content for delete objects
* @return oss live record content
**/
oss_live_record_content_t *oss_create_live_record_content(aos_pool_t *p);
/**
* @brief create live channel configuration content
* @return live channel configuration content
**/
oss_live_channel_configuration_t *oss_create_live_channel_configuration_content(aos_pool_t *p);
/**
* @brief create oss checkpoint content
* @return oss checkpoint content
**/
oss_checkpoint_t *oss_create_checkpoint_content(aos_pool_t *p);
/**
* @brief create oss resumable clt params content
* @return oss checkpoint content
**/
oss_resumable_clt_params_t *oss_create_resumable_clt_params_content(aos_pool_t *p, int64_t part_size, int32_t thread_num,
int enable_checkpoint, const char *checkpoint_path);
/**
* @brief get part size for multipart upload
**/
void oss_get_part_size(int64_t filesize, int64_t *part_size);
/**
* @brief compare function for part sort
**/
int part_sort_cmp(const void *a, const void *b);
/**
* @brief add range in http request
**/
void oss_headers_add_range(apr_pool_t *pool, apr_table_t *headers, int64_t offset, int64_t size);
/**
* @brief set content type for object according to objectname
* @return oss content type
**/
char *get_content_type(const char *name);
char *get_content_type_by_suffix(const char *suffix);
/**
* @brief set content type for object according to filename
**/
void set_content_type(const char* filename, const char* key, aos_table_t *headers);
aos_table_t* aos_table_create_if_null(const oss_request_options_t *options,
aos_table_t *table, int table_size);
int is_enable_crc(const oss_request_options_t *options);
int has_crc_in_response(const aos_http_response_t *resp);
int has_range_or_process_in_request(const aos_http_request_t *req) ;
/**
* @brief check crc consistent between client and server
**/
int oss_check_crc_consistent(uint64_t crc, const apr_table_t *resp_headers, aos_status_t *s);
int oss_get_temporary_file_name(aos_pool_t *p, const aos_string_t *filename, aos_string_t *temp_file_name);
int oss_temp_file_rename(aos_status_t *s, const char *from_path, const char *to_path, apr_pool_t *pool);
OSS_CPP_END
#endif

1457
include/oss_sdk/oss_xml.c Normal file

File diff suppressed because it is too large Load Diff

188
include/oss_sdk/oss_xml.h Normal file
View File

@@ -0,0 +1,188 @@
#ifndef LIBOSS_XML_H
#define LIBOSS_XML_H
#include <mxml.h>
#include "aos_string.h"
#include "aos_transport.h"
#include "aos_status.h"
#include "oss_define.h"
#include "oss_resumable.h"
OSS_CPP_START
/**
* @brief functions for xml body parse
**/
int get_xmldoc(aos_list_t *bc, mxml_node_t **root);
char *get_xmlnode_value(aos_pool_t *p, mxml_node_t * root, const char *xml_path);
/**
* @brief build xml body for complete_multipart_upload
**/
char *build_complete_multipart_upload_xml(aos_pool_t *p, aos_list_t *bc);
/**
* @brief build body for complete multipart upload
**/
void build_complete_multipart_upload_body(aos_pool_t *p, aos_list_t *part_list, aos_list_t *body);
/**
* @brief build xml body for put lifecycle
**/
char *build_lifecycle_xml(aos_pool_t *p, aos_list_t *lifecycle_rule_list);
/**
* @brief build body for put lifecycle
**/
void build_lifecycle_body(aos_pool_t *p, aos_list_t *lifecycle_rule_list, aos_list_t *body);
/**
* @brief build xml body for delete objects
**/
char *build_objects_xml(aos_pool_t *p, aos_list_t *object_list, const char *quiet);
/**
* @brief build body for delete objects
**/
void build_delete_objects_body(aos_pool_t *p, aos_list_t *object_list, int is_quiet,
aos_list_t *body);
mxml_node_t *set_xmlnode_value_str(mxml_node_t *parent, const char *name, const aos_string_t *value);
mxml_node_t *set_xmlnode_value_int(mxml_node_t *parent, const char *name, int value);
mxml_node_t *set_xmlnode_value_int64(mxml_node_t *parent, const char *name, int64_t value);
mxml_node_t *set_xmlnode_value_uint64(mxml_node_t *parent, const char *name, uint64_t value);
int get_xmlnode_value_str(aos_pool_t *p, mxml_node_t *xml_node, const char *xml_path, aos_string_t *value);
int get_xmlnode_value_int(aos_pool_t *p, mxml_node_t *xml_node, const char *xml_path, int *value);
int get_xmlnode_value_int64(aos_pool_t *p, mxml_node_t *xml_node, const char *xml_path, int64_t *value);
int get_xmlnode_value_uint64(aos_pool_t *p, mxml_node_t *xml_node, const char *xml_path, uint64_t *value);
/**
* @brief build xml for checkpoint
**/
char *oss_build_checkpoint_xml(aos_pool_t *p, const oss_checkpoint_t *checkpoint);
/**
* @bried parse checkpoint from xml
**/
int oss_checkpoint_parse_from_body(aos_pool_t *p, const char *xml_body, oss_checkpoint_t *checkpoint);
/**
* @bried parse acl from xml body for get_bucket_acl
**/
int oss_acl_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_string_t *oss_acl);
/**
* @brief parse upload_id from xml body for init multipart upload
**/
int oss_upload_id_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_string_t *upload_id);
/**
* @brief parse objects from xml body for list objects
**/
void oss_list_objects_owner_parse(aos_pool_t *p, mxml_node_t *xml_node, oss_list_object_content_t *content);
void oss_list_objects_content_parse(aos_pool_t *p, mxml_node_t *xml_node, oss_list_object_content_t *content);
void oss_list_objects_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *object_list);
void oss_list_objects_prefix_parse(aos_pool_t *p, mxml_node_t *root,
oss_list_object_common_prefix_t *common_prefix);
void oss_list_objects_common_prefix_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *common_prefix_list);
int oss_list_objects_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_list_t *object_list,
aos_list_t *common_prefix_list, aos_string_t *marker, int *truncated);
/**
* @brief parse parts from xml body for list upload part
**/
void oss_list_parts_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *part_list);
void oss_list_parts_content_parse(aos_pool_t *p, mxml_node_t *xml_node, oss_list_part_content_t *content);
int oss_list_parts_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_list_t *part_list,
aos_string_t *part_number_marker, int *truncated);
/**
* @brief parse uploads from xml body for list multipart upload
**/
void oss_list_multipart_uploads_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *upload_list);
void oss_list_multipart_uploads_content_parse(aos_pool_t *p, mxml_node_t *xml_node,
oss_list_multipart_upload_content_t *content);
int oss_list_multipart_uploads_parse_from_body(aos_pool_t *p, aos_list_t *bc,
aos_list_t *upload_list, aos_string_t *key_marker,
aos_string_t *upload_id_marker, int *truncated);
/**
* @brief parse lifecycle rules from xml body
**/
void oss_lifecycle_rule_expire_parse(aos_pool_t *p, mxml_node_t *xml_node,
oss_lifecycle_rule_content_t *content);
void oss_lifecycle_rule_content_parse(aos_pool_t *p, mxml_node_t *xml_node,
oss_lifecycle_rule_content_t *content);
void oss_lifecycle_rule_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *lifecycle_rule_list);
int oss_lifecycle_rules_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_list_t *lifecycle_rule_list);
/**
* @brief parse delete objects contents from xml body
**/
void oss_delete_objects_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *object_list);
void oss_object_key_parse(aos_pool_t *p, mxml_node_t * xml_node, oss_object_key_t *content);
int oss_delete_objects_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_list_t *object_list);
/**
* @brief build body for create live channel
**/
char *build_create_live_channel_xml(aos_pool_t *p, oss_live_channel_configuration_t *config);
void build_create_live_channel_body(aos_pool_t *p, oss_live_channel_configuration_t *config, aos_list_t *body);
/**
* @brief parse create live channel contents from xml body
**/
void oss_publish_url_parse(aos_pool_t *p, mxml_node_t *node, oss_live_channel_publish_url_t *content);
void oss_play_url_parse(aos_pool_t *p, mxml_node_t *node, oss_live_channel_play_url_t *content);
void oss_publish_urls_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *publish_xml_list);
void oss_play_urls_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *play_xml_list);
void oss_create_live_channel_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *publish_xml_path,
aos_list_t *publish_url_list, const char *play_xml_path, aos_list_t *play_url_list);
int oss_create_live_channel_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_list_t *publish_url_list,
aos_list_t *play_url_list);
/**
* @brief parse live channel info content from xml body
**/
void oss_live_channel_info_target_content_parse(aos_pool_t *p, mxml_node_t *xml_node, oss_live_channel_target_t *target);
void oss_live_channel_info_content_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
oss_live_channel_configuration_t *info);
int oss_live_channel_info_parse_from_body(aos_pool_t *p, aos_list_t *bc, oss_live_channel_configuration_t *info);
/**
* @brief parse live channel stat content from xml body
**/
void oss_live_channel_stat_video_content_parse(aos_pool_t *p, mxml_node_t *xml_node, oss_video_stat_t *video_stat);
void oss_live_channel_stat_audio_content_parse(aos_pool_t *p, mxml_node_t *xml_node, oss_audio_stat_t *audio_stat);
void oss_live_channel_stat_content_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path, oss_live_channel_stat_t *stat);
int oss_live_channel_stat_parse_from_body(aos_pool_t *p, aos_list_t *bc, oss_live_channel_stat_t *stat);
/**
* @brief parse live channel from xml body for list list channel
**/
void oss_list_live_channel_content_parse(aos_pool_t *p, mxml_node_t *xml_node, oss_live_channel_content_t *content);
void oss_list_live_channel_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *live_channel_list);
int oss_list_live_channel_parse_from_body(aos_pool_t *p, aos_list_t *bc,
aos_list_t *live_channel_list, aos_string_t *next_marker, int *truncated);
/**
* @brief parse live channel history content from xml body
**/
void oss_live_channel_history_content_parse(aos_pool_t *p, mxml_node_t * xml_node, oss_live_record_content_t *content);
void oss_live_channel_history_contents_parse(aos_pool_t *p, mxml_node_t *root, const char *xml_path,
aos_list_t *live_record_list);
int oss_live_channel_history_parse_from_body(aos_pool_t *p, aos_list_t *bc, aos_list_t *live_record_list);
OSS_CPP_END
#endif