Skip to content

Commit

Permalink
add data_reader_http
Browse files Browse the repository at this point in the history
  • Loading branch information
xianjimli committed Dec 22, 2023
1 parent 267cb72 commit 901dd67
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 6 deletions.
3 changes: 3 additions & 0 deletions docs/changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# 最新动态

2023/12/22
* 增加data\_reader\_http。

2023/12/21
* 增加控件继承的函数指针查找父集的逻辑(感谢智明提供补丁)

Expand Down
20 changes: 20 additions & 0 deletions src/awtk_global.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
#include "base/vgcanvas_asset_manager.h"
#endif

#ifdef WITH_SOCKET
#include "tkc/socket_helper.h"
#endif/*WITH_SOCKET*/

#ifdef WITH_FSCRIPT_EXT
#ifndef WITH_DATA_READER_WRITER
#define WITH_DATA_READER_WRITER
Expand All @@ -59,6 +63,9 @@
#include "tkc/data_reader_file.h"
#include "tkc/data_reader_mem.h"
#include "base/data_reader_asset.h"
#ifdef WITH_SOCKET
#include "tkc/data_reader_http.h"
#endif/*WITH_SOCKET*/
#endif /*WITH_DATA_READER_WRITER*/

#include "base/widget_animator_manager.h"
Expand Down Expand Up @@ -300,6 +307,12 @@ ret_t tk_pre_init(void) {
data_reader_factory_register(data_reader_factory(), "asset", data_reader_asset_create);
data_reader_factory_register(data_reader_factory(), "mem", data_reader_mem_create);
data_writer_factory_register(data_writer_factory(), "wbuffer", data_writer_wbuffer_create);
#ifdef WITH_SOCKET
data_reader_factory_register(data_reader_factory(), "http", data_reader_http_create);
#ifdef WITH_MBEDTLS
data_reader_factory_register(data_reader_factory(), "https", data_reader_http_create);
#endif/*WITH_MBEDTLS*/
#endif/*WITH_SOCKET*/
#endif /*WITH_DATA_READER_WRITER*/
inited = TRUE;
}
Expand Down Expand Up @@ -327,6 +340,9 @@ ret_t tk_init(wh_t w, wh_t h, app_type_t app_type, const char* app_name, const c
loop = main_loop_init(w, h);
}
return_value_if_fail(loop != NULL, RET_FAIL);
#ifdef WITH_SOCKET
tk_socket_init();
#endif/*WITH_SOCKET*/

return RET_OK;
}
Expand Down Expand Up @@ -416,6 +432,10 @@ ret_t tk_deinit_internal(void) {
#endif
tk_semaphore_destroy(s_clear_cache_semaphore);

#ifdef WITH_SOCKET
tk_socket_deinit();
#endif/*WITH_SOCKET*/

return RET_OK;
}

Expand Down
20 changes: 20 additions & 0 deletions src/streams/inet/iostream_mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,24 @@ tk_iostream_t* tk_iostream_mbedtls_create(mbedtls_conn_t* conn) {

return TK_IOSTREAM(obj);
}

#include "streams/inet/mbedtls_client.h"

tk_iostream_t* tk_iostream_mbedtls_create_client(const char* host, uint16_t port) {
mbedtls_conn_t* conn = NULL;
tk_iostream_t* io = NULL;
char sport[16] = {0};
return_value_if_fail(host != NULL, NULL);

tk_snprintf(sport, sizeof(sport), "%d", (int)port);
conn = mbedtls_conn_client_create(host, sport, NULL, 0);
return_value_if_fail(conn != NULL, NULL);

io = tk_iostream_mbedtls_create(conn);
if (io == NULL) {
mbedtls_conn_destroy(conn);
}

return io;
}
#endif /*WITH_MBEDTLS*/
13 changes: 13 additions & 0 deletions src/streams/inet/iostream_mbedtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ struct _tk_iostream_mbedtls_t {
*/
tk_iostream_t* tk_iostream_mbedtls_create(mbedtls_conn_t* conn);

/**
* @method tk_iostream_mbedtls_create_client
*
* 创建iostream对象。
*
* @param {const char*} host 主机地址。
* @param {uint16_t} port 端口号。
*
* @return {tk_iostream_t*} 返回iostream对象。
*
*/
tk_iostream_t* tk_iostream_mbedtls_create_client(const char* host, uint16_t port);

#define TK_IOSTREAM_MBEDTLS(obj) ((tk_iostream_mbedtls_t*)(obj))

END_C_DECLS
Expand Down
23 changes: 17 additions & 6 deletions src/streams/stream_factory.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
#include "tkc/path.h"
#include "tkc/utils.h"
#include "tkc/serial_helper.h"
#ifdef WITH_SOCKET
#ifdef WITH_SOCKET
#include "streams/inet/iostream_tcp.h"
#include "streams/inet/iostream_udp.h"
#endif/*WITH_SOCKET*/
#endif /*WITH_SOCKET*/
#ifdef WITH_MBEDTLS
#include "streams/inet/iostream_mbedtls.h"
#endif /*WITH_MBEDTLS*/
#include "streams/serial/iostream_serial.h"

#include "streams/stream_factory.h"
Expand All @@ -39,13 +42,21 @@ tk_iostream_t* tk_stream_factory_create_iostream(const char* url) {
return_value_if_fail(aurl != NULL, NULL);

if (tk_str_start_with(url, STR_SCHEMA_TCP)) {
#ifdef WITH_SOCKET
#ifdef WITH_SOCKET
io = tk_iostream_tcp_create_client(aurl->host, aurl->port);
#endif/*WITH_SOCKET*/
#endif /*WITH_SOCKET*/
} else if (tk_str_start_with(url, STR_SCHEMA_UDP)) {
#ifdef WITH_SOCKET
#ifdef WITH_SOCKET
io = tk_iostream_udp_create_client(aurl->host, aurl->port);
#endif/*WITH_SOCKET*/
#endif /*WITH_SOCKET*/
} else if (tk_str_start_with(url, STR_SCHEMA_HTTP)) {
#ifdef WITH_SOCKET
io = tk_iostream_tcp_create_client(aurl->host, aurl->port);
#endif /*WITH_SOCKET*/
} else if (tk_str_start_with(url, STR_SCHEMA_HTTPS)) {
#ifdef WITH_MBEDTLS
io = tk_iostream_mbedtls_create_client(aurl->host, aurl->port);
#endif /*WITH_MBEDTLS*/
} else if (tk_str_eq(aurl->schema, "serial")) {
char filename[MAX_PATH + 1] = {0};

Expand Down
160 changes: 160 additions & 0 deletions src/tkc/data_reader_http.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/**
* File: data_reader.c
* Author: AWTK Develop Team
* Brief: data_reader
*
* Copyright (c) 2019 - 2023 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License http for more details.
*
*/

/**
* History:
* ================================================================
* 2023-12-22 Li XianJing <[email protected]> created
*
*/

#include "tkc/mem.h"
#include "tkc/url.h"
#include "tkc/utils.h"
#include "tkc/buffer.h"
#include "tkc/data_reader_http.h"
#include "streams/stream_factory.h"

typedef struct _data_reader_http_t {
data_reader_t data_reader;

uint64_t size;
uint8_t* data;
} data_reader_http_t;

static const char* url_get_path(const char* url) {
const char* p = NULL;
return_value_if_fail(url != NULL, NULL);

p = strstr(url, "://");
if (p != NULL) {
p += 3;
p = strchr(p, '/');
if (p == NULL) {
p = "/";
}
}

return p;
}

static ret_t data_reader_http_get(data_reader_http_t* http, const char* url) {
char buff[1024];
int32_t nr = 0;
url_t* aurl = NULL;
const char* p = NULL;
tk_iostream_t* io = NULL;
return_value_if_fail(url != NULL && http != NULL, RET_BAD_PARAMS);

aurl = url_create(url);
return_value_if_fail(aurl != NULL, RET_BAD_PARAMS);

io = tk_stream_factory_create_iostream(url);
return_value_if_fail(io != NULL, RET_BAD_PARAMS);

tk_snprintf(buff, sizeof(buff) - 1, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", url_get_path(url),
aurl->host);
nr = tk_iostream_write(io, buff, strlen(buff));
url_destroy(aurl);
goto_error_if_fail(nr > 0);

nr = tk_iostream_read(io, buff, sizeof(buff) - 1);
if (nr > 0) {
buff[nr] = '\0';
p = strstr(buff, "Content-Length:");
goto_error_if_fail(p != NULL);
p += strlen("Content-Length:");
while (*p == ' ') {
p++;
}
http->size = tk_atoi(p);
goto_error_if_fail(http->size > 0);

http->data = TKMEM_ALLOC(http->size + 1);
goto_error_if_fail(http->data != NULL);

p = strstr(buff, "\r\n\r\n");
goto_error_if_fail(p != NULL);

p += 4;
nr = nr - (p - buff);
memcpy(http->data, p, nr);

if (http->size > nr) {
nr = tk_iostream_read_len(io, http->data + nr, http->size - nr, TK_ISTREAM_DEFAULT_TIMEOUT);
goto_error_if_fail(nr > 0);
}

http->data[http->size] = '\0';
}

TK_OBJECT_UNREF(io);

return RET_OK;
error:
TK_OBJECT_UNREF(io);

return RET_FAIL;
}

static int32_t data_reader_http_read(data_reader_t* reader, uint64_t offset, void* data,
uint32_t size) {
data_reader_http_t* http = (data_reader_http_t*)reader;
return_value_if_fail(http != NULL && data != NULL, 0);
return_value_if_fail(offset <= http->size, 0);
size = tk_min(size, http->size - offset);

memcpy(data, http->data + offset, size);

return size;
}

static uint64_t data_reader_http_get_size(data_reader_t* reader) {
data_reader_http_t* http = (data_reader_http_t*)reader;
return_value_if_fail(http != NULL, 0);

return http->size;
}

static ret_t data_reader_http_destroy(data_reader_t* reader) {
data_reader_http_t* http = (data_reader_http_t*)reader;

TKMEM_FREE(http->data);
TKMEM_FREE(http);

return RET_OK;
}

static const data_reader_vtable_t s_data_reader_http_vtable = {
.read = data_reader_http_read,
.get_size = data_reader_http_get_size,
.destroy = data_reader_http_destroy,
};

data_reader_t* data_reader_http_create(const char* url) {
data_reader_http_t* http = NULL;
return_value_if_fail(url != NULL, NULL);
http = TKMEM_ZALLOC(data_reader_http_t);
return_value_if_fail(http != NULL, NULL);

if (data_reader_http_get(http, url) != RET_OK) {
TKMEM_FREE(http->data);
TKMEM_FREE(http);
return NULL;
}

http->data_reader.vt = &s_data_reader_http_vtable;

return (data_reader_t*)http;
}
55 changes: 55 additions & 0 deletions src/tkc/data_reader_http.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* File: data_reader_http.h
* Author: AWTK Develop Team
* Brief: data_reader http
*
* Copyright (c) 2019 - 2023 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License http for more details.
*
*/

/**
* History:
* ================================================================
* 2023-12-22 Li XianJing <[email protected]> created
*
*/

#ifndef TK_DATA_READER_HTTP_H
#define TK_DATA_READER_HTTP_H

#include "tkc/data_reader.h"

BEGIN_C_DECLS

/**
* @class data_reader_http_t
* @parent data_reader_t
* @annotation ["fake"]
* 基于HTTP/HTTPS实现的 data_reader。通过 data_reader_factory 创建 reader 时,URL的格式如下(请用函数data_reader_http_build_url生成):
*
* ```
* http://t.weather.sojson.com/api/weather/city/101030100
* https://restapi.amap.com/v3/weather/weatherInfo?city=110101&key=%3C%E7%94%A8%E6%88%B7key%3E
* ```
*/

/**
* @method data_reader_http_create
* 创建基于文件的data reader。
* > 不要直接调用,而是注册到 data\_reader\_factory后,通过data\_reader\_factory调用。
* @annotation ["constructor"]
*
* @param {const char*} url URL。
*
* @return {data_reader_t*} 返回data reader对象。
*/
data_reader_t* data_reader_http_create(const char* url);

END_C_DECLS

#endif /*TK_DATA_READER_HTTP_H*/
Loading

0 comments on commit 901dd67

Please sign in to comment.