mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-29 17:22:56 +08:00
add requests module, add rtt adapter
This commit is contained in:
parent
353fc0bce6
commit
39c44e20a8
1873
package/requests/webclient.c
Normal file
1873
package/requests/webclient.c
Normal file
File diff suppressed because it is too large
Load Diff
207
package/requests/webclient.h
Normal file
207
package/requests/webclient.h
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-05-05 Bernard the first version
|
||||
* 2013-06-10 Bernard fix the slow speed issue when download file.
|
||||
* 2015-11-14 aozima add content_length_remainder.
|
||||
* 2017-12-23 aozima update gethostbyname to getaddrinfo.
|
||||
* 2018-01-04 aozima add ipv6 address support.
|
||||
* 2018-07-26 chenyong modify log information
|
||||
* 2018-08-07 chenyong modify header processing
|
||||
*/
|
||||
|
||||
#ifndef __WEBCLIENT_H__
|
||||
#define __WEBCLIENT_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "pika_adapter_rtt.h"
|
||||
/* depend on the socket module */
|
||||
#include "../socket/platform_socket.h"
|
||||
|
||||
#define RT_USING_SAL 1
|
||||
|
||||
#if defined(WEBCLIENT_USING_MBED_TLS) || defined(WEBCLIENT_USING_SAL_TLS)
|
||||
#include <tls_client.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef web_malloc
|
||||
#define web_malloc rt_malloc
|
||||
#endif
|
||||
|
||||
#ifndef web_calloc
|
||||
#define web_calloc rt_calloc
|
||||
#endif
|
||||
|
||||
#ifndef web_realloc
|
||||
#define web_realloc rt_realloc
|
||||
#endif
|
||||
|
||||
#ifndef web_free
|
||||
#define web_free rt_free
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The gcc libc api is not threadsafe,
|
||||
* especially the float type operation.
|
||||
* So, use rt_xxx whose RT-Thread threadsafe api to instead of strandard libc
|
||||
* api.
|
||||
*/
|
||||
#ifndef web_memset
|
||||
#define web_memset rt_memset
|
||||
#endif
|
||||
|
||||
#ifndef web_memcpy
|
||||
#define web_memcpy rt_memcpy
|
||||
#endif
|
||||
|
||||
#ifndef web_memcmp
|
||||
#define web_memcmp rt_memcmp
|
||||
#endif
|
||||
|
||||
#ifndef web_snprintf
|
||||
#define web_snprintf rt_snprintf
|
||||
#endif
|
||||
|
||||
#ifndef web_vsnprintf
|
||||
#define web_vsnprintf rt_vsnprintf
|
||||
#endif
|
||||
|
||||
#ifndef web_strdup
|
||||
#define web_strdup rt_strdup
|
||||
#endif
|
||||
|
||||
#define WEBCLIENT_SW_VERSION "2.3.0"
|
||||
#define WEBCLIENT_SW_VERSION_NUM 0x20300
|
||||
|
||||
#define WEBCLIENT_HEADER_BUFSZ 4096
|
||||
#define WEBCLIENT_RESPONSE_BUFSZ 4096
|
||||
|
||||
enum WEBCLIENT_STATUS {
|
||||
WEBCLIENT_OK,
|
||||
WEBCLIENT_ERROR,
|
||||
WEBCLIENT_TIMEOUT,
|
||||
WEBCLIENT_NOMEM,
|
||||
WEBCLIENT_NOSOCKET,
|
||||
WEBCLIENT_NOBUFFER,
|
||||
WEBCLIENT_CONNECT_FAILED,
|
||||
WEBCLIENT_DISCONNECT,
|
||||
WEBCLIENT_FILE_ERROR,
|
||||
};
|
||||
|
||||
enum WEBCLIENT_METHOD {
|
||||
WEBCLIENT_USER_METHOD,
|
||||
WEBCLIENT_GET,
|
||||
WEBCLIENT_POST,
|
||||
WEBCLIENT_HEAD
|
||||
};
|
||||
|
||||
struct webclient_header {
|
||||
char* buffer;
|
||||
size_t length; /* content header buffer size */
|
||||
|
||||
size_t size; /* maximum support header size */
|
||||
};
|
||||
|
||||
struct webclient_session {
|
||||
struct webclient_header* header; /* webclient response header information */
|
||||
int socket;
|
||||
int resp_status;
|
||||
|
||||
char* host; /* server host */
|
||||
char* req_url; /* HTTP request address*/
|
||||
|
||||
int chunk_sz;
|
||||
int chunk_offset;
|
||||
|
||||
int content_length;
|
||||
size_t content_remainder; /* remainder of content length */
|
||||
int (*handle_function)(char* buffer, int size); /* handle function */
|
||||
|
||||
rt_bool_t is_tls; /* HTTPS connect */
|
||||
#ifdef WEBCLIENT_USING_MBED_TLS
|
||||
MbedTLSSession* tls_session; /* mbedtls connect session */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* create webclient session and set header response size */
|
||||
struct webclient_session* webclient_session_create(size_t header_sz);
|
||||
|
||||
/* send HTTP GET request */
|
||||
int webclient_get(struct webclient_session* session, const char* URI);
|
||||
|
||||
/* send HTTP HEAD request */
|
||||
int webclient_shard_head_function(struct webclient_session* session,
|
||||
const char* URI,
|
||||
int* length);
|
||||
|
||||
/* send HTTP Range parameter, shard download */
|
||||
int webclient_shard_position_function(struct webclient_session* session,
|
||||
const char* URI,
|
||||
int start,
|
||||
int length,
|
||||
int mem_size);
|
||||
int* webclient_register_shard_position_function(
|
||||
struct webclient_session* session,
|
||||
int (*handle_function)(char* buffer, int size));
|
||||
|
||||
/* send HTTP POST request */
|
||||
int webclient_post(struct webclient_session* session,
|
||||
const char* URI,
|
||||
const void* post_data,
|
||||
size_t data_len);
|
||||
|
||||
/* close and release wenclient session */
|
||||
int webclient_close(struct webclient_session* session);
|
||||
|
||||
int webclient_set_timeout(struct webclient_session* session, int millisecond);
|
||||
|
||||
/* send or receive data from server */
|
||||
int webclient_read(struct webclient_session* session,
|
||||
void* buffer,
|
||||
size_t size);
|
||||
int webclient_write(struct webclient_session* session,
|
||||
const void* buffer,
|
||||
size_t size);
|
||||
|
||||
/* webclient GET/POST header buffer operate by the header fields */
|
||||
int webclient_header_fields_add(struct webclient_session* session,
|
||||
const char* fmt,
|
||||
...);
|
||||
const char* webclient_header_fields_get(struct webclient_session* session,
|
||||
const char* fields);
|
||||
|
||||
/* send HTTP POST/GET request, and get response data */
|
||||
int webclient_response(struct webclient_session* session,
|
||||
void** response,
|
||||
size_t* resp_len);
|
||||
int webclient_request(const char* URI,
|
||||
const char* header,
|
||||
const void* post_data,
|
||||
size_t data_len,
|
||||
void** response,
|
||||
size_t* resp_len);
|
||||
int webclient_request_header_add(char** request_header, const char* fmt, ...);
|
||||
int webclient_resp_status_get(struct webclient_session* session);
|
||||
int webclient_content_length_get(struct webclient_session* session);
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
/* file related operations */
|
||||
int webclient_get_file(const char* URI, const char* filename);
|
||||
int webclient_post_file(const char* URI,
|
||||
const char* filename,
|
||||
const char* form_data);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
322
package/requests/webclient_file.c
Normal file
322
package/requests/webclient_file.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-07-26 chenyong modify log information
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pika_adapter_rtt.h"
|
||||
#include "webclient.h"
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define DBG_ENABLE
|
||||
#define DBG_SECTION_NAME "web.file"
|
||||
#ifdef WEBCLIENT_DEBUG
|
||||
#define DBG_LEVEL DBG_LOG
|
||||
#else
|
||||
#define DBG_LEVEL DBG_INFO
|
||||
#endif /* WEBCLIENT_DEBUG */
|
||||
#define DBG_COLOR
|
||||
#include <rtdbg.h>
|
||||
|
||||
/**
|
||||
* send GET request and store response data into the file.
|
||||
*
|
||||
* @param URI input server address
|
||||
* @param filename store response date to filename
|
||||
*
|
||||
* @return <0: GET request failed
|
||||
* =0: success
|
||||
*/
|
||||
int webclient_get_file(const char* URI, const char* filename)
|
||||
{
|
||||
int fd = -1, rc = WEBCLIENT_OK;
|
||||
size_t offset;
|
||||
int length, total_length = 0;
|
||||
unsigned char *ptr = RT_NULL;
|
||||
struct webclient_session* session = RT_NULL;
|
||||
int resp_status = 0;
|
||||
|
||||
session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
|
||||
if(session == RT_NULL)
|
||||
{
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if ((resp_status = webclient_get(session, URI)) != 200)
|
||||
{
|
||||
LOG_E("get file failed, wrong response: %d (-0x%X).", resp_status, resp_status);
|
||||
rc = -WEBCLIENT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG_E("get file failed, open file(%s) error.", filename);
|
||||
rc = -WEBCLIENT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
ptr = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (ptr == RT_NULL)
|
||||
{
|
||||
LOG_E("get file failed, no memory for response buffer.");
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (session->content_length < 0)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
length = webclient_read(session, ptr, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (length > 0)
|
||||
{
|
||||
write(fd, ptr, length);
|
||||
total_length += length;
|
||||
LOG_RAW(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (offset = 0; offset < (size_t) session->content_length;)
|
||||
{
|
||||
length = webclient_read(session, ptr,
|
||||
session->content_length - offset > WEBCLIENT_RESPONSE_BUFSZ ?
|
||||
WEBCLIENT_RESPONSE_BUFSZ : session->content_length - offset);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
write(fd, ptr, length);
|
||||
total_length += length;
|
||||
LOG_RAW(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
if (total_length)
|
||||
{
|
||||
LOG_D("save %d bytes.", total_length);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (session != RT_NULL)
|
||||
{
|
||||
webclient_close(session);
|
||||
}
|
||||
|
||||
if (ptr != RT_NULL)
|
||||
{
|
||||
web_free(ptr);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* post file to http server.
|
||||
*
|
||||
* @param URI input server address
|
||||
* @param filename post data filename
|
||||
* @param form_data form data
|
||||
*
|
||||
* @return <0: POST request failed
|
||||
* =0: success
|
||||
*/
|
||||
int webclient_post_file(const char* URI, const char* filename,
|
||||
const char* form_data)
|
||||
{
|
||||
size_t length;
|
||||
char boundary[60];
|
||||
int fd = -1, rc = WEBCLIENT_OK;
|
||||
char *header = RT_NULL, *header_ptr;
|
||||
unsigned char *buffer = RT_NULL, *buffer_ptr;
|
||||
struct webclient_session* session = RT_NULL;
|
||||
int resp_data_len = 0;
|
||||
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG_D("post file failed, open file(%s) error.", filename);
|
||||
rc = -WEBCLIENT_FILE_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/* get the size of file */
|
||||
length = lseek(fd, 0, SEEK_END);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
buffer = (unsigned char *) web_calloc(1, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (buffer == RT_NULL)
|
||||
{
|
||||
LOG_D("post file failed, no memory for response buffer.");
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
header = (char *) web_calloc(1, WEBCLIENT_HEADER_BUFSZ);
|
||||
if (header == RT_NULL)
|
||||
{
|
||||
LOG_D("post file failed, no memory for header buffer.");
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
header_ptr = header;
|
||||
|
||||
/* build boundary */
|
||||
web_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get());
|
||||
|
||||
/* build encapsulated mime_multipart information*/
|
||||
buffer_ptr = buffer;
|
||||
/* first boundary */
|
||||
buffer_ptr += web_snprintf((char*) buffer_ptr,
|
||||
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s\r\n", boundary);
|
||||
buffer_ptr += web_snprintf((char*) buffer_ptr,
|
||||
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
|
||||
"Content-Disposition: form-data; %s\r\n", form_data);
|
||||
buffer_ptr += web_snprintf((char*) buffer_ptr,
|
||||
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
|
||||
"Content-Type: application/octet-stream\r\n\r\n");
|
||||
/* calculate content-length */
|
||||
length += buffer_ptr - buffer;
|
||||
length += strlen(boundary) + 8; /* add the last boundary */
|
||||
|
||||
/* build header for upload */
|
||||
header_ptr += web_snprintf(header_ptr,
|
||||
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
|
||||
"Content-Length: %d\r\n", length);
|
||||
header_ptr += web_snprintf(header_ptr,
|
||||
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
|
||||
"Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
|
||||
|
||||
session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
|
||||
if(session == RT_NULL)
|
||||
{
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
strncpy(session->header->buffer, header, strlen(header));
|
||||
session->header->length = strlen(session->header->buffer);
|
||||
|
||||
rc = webclient_post(session, URI, NULL, 0);
|
||||
if(rc < 0)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/* send mime_multipart */
|
||||
webclient_write(session, buffer, buffer_ptr - buffer);
|
||||
|
||||
/* send file data */
|
||||
while (1)
|
||||
{
|
||||
length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (length <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
webclient_write(session, buffer, length);
|
||||
}
|
||||
|
||||
/* send last boundary */
|
||||
web_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, "\r\n--%s--\r\n", boundary);
|
||||
webclient_write(session, buffer, strlen(boundary) + 8);
|
||||
|
||||
extern int webclient_handle_response(struct webclient_session *session);
|
||||
if( webclient_handle_response(session) != 200)
|
||||
{
|
||||
rc = -WEBCLIENT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
resp_data_len = webclient_content_length_get(session);
|
||||
if (resp_data_len > 0)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
|
||||
web_memset(buffer, 0x00, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
do
|
||||
{
|
||||
bytes_read = webclient_read(session, buffer,
|
||||
resp_data_len < WEBCLIENT_RESPONSE_BUFSZ ? resp_data_len : WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (bytes_read <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
resp_data_len -= bytes_read;
|
||||
} while(resp_data_len > 0);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (session != RT_NULL)
|
||||
{
|
||||
webclient_close(session);
|
||||
}
|
||||
|
||||
if (buffer != RT_NULL)
|
||||
{
|
||||
web_free(buffer);
|
||||
}
|
||||
|
||||
if (header != RT_NULL)
|
||||
{
|
||||
web_free(header);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wget(int argc, char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
rt_kprintf("Please using: wget <URI> <filename>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
webclient_get_file(argv[1], argv[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
#include <finsh.h>
|
||||
MSH_CMD_EXPORT(wget, Get file by URI: wget <URI> <filename>.);
|
||||
#endif /* FINSH_USING_MSH */
|
||||
|
||||
#endif /* RT_USING_DFS */
|
3
port/linux/.vscode/settings.json
vendored
3
port/linux/.vscode/settings.json
vendored
@ -70,7 +70,8 @@
|
||||
"datastack.h": "c",
|
||||
"syscall.h": "c",
|
||||
"fcntl.h": "c",
|
||||
"pikastddata_bytearray.h": "c"
|
||||
"pikastddata_bytearray.h": "c",
|
||||
"webclient.h": "c"
|
||||
},
|
||||
"python.formatting.provider": "autopep8",
|
||||
"C_Cpp.errorSquiggles": "Disabled"
|
||||
|
1873
port/linux/package/pikascript/pikascript-lib/requests/webclient.c
Normal file
1873
port/linux/package/pikascript/pikascript-lib/requests/webclient.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-05-05 Bernard the first version
|
||||
* 2013-06-10 Bernard fix the slow speed issue when download file.
|
||||
* 2015-11-14 aozima add content_length_remainder.
|
||||
* 2017-12-23 aozima update gethostbyname to getaddrinfo.
|
||||
* 2018-01-04 aozima add ipv6 address support.
|
||||
* 2018-07-26 chenyong modify log information
|
||||
* 2018-08-07 chenyong modify header processing
|
||||
*/
|
||||
|
||||
#ifndef __WEBCLIENT_H__
|
||||
#define __WEBCLIENT_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "pika_adapter_rtt.h"
|
||||
/* depend on the socket module */
|
||||
#include "../socket/platform_socket.h"
|
||||
|
||||
#define RT_USING_SAL 1
|
||||
|
||||
#if defined(WEBCLIENT_USING_MBED_TLS) || defined(WEBCLIENT_USING_SAL_TLS)
|
||||
#include <tls_client.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef web_malloc
|
||||
#define web_malloc rt_malloc
|
||||
#endif
|
||||
|
||||
#ifndef web_calloc
|
||||
#define web_calloc rt_calloc
|
||||
#endif
|
||||
|
||||
#ifndef web_realloc
|
||||
#define web_realloc rt_realloc
|
||||
#endif
|
||||
|
||||
#ifndef web_free
|
||||
#define web_free rt_free
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The gcc libc api is not threadsafe,
|
||||
* especially the float type operation.
|
||||
* So, use rt_xxx whose RT-Thread threadsafe api to instead of strandard libc
|
||||
* api.
|
||||
*/
|
||||
#ifndef web_memset
|
||||
#define web_memset rt_memset
|
||||
#endif
|
||||
|
||||
#ifndef web_memcpy
|
||||
#define web_memcpy rt_memcpy
|
||||
#endif
|
||||
|
||||
#ifndef web_memcmp
|
||||
#define web_memcmp rt_memcmp
|
||||
#endif
|
||||
|
||||
#ifndef web_snprintf
|
||||
#define web_snprintf rt_snprintf
|
||||
#endif
|
||||
|
||||
#ifndef web_vsnprintf
|
||||
#define web_vsnprintf rt_vsnprintf
|
||||
#endif
|
||||
|
||||
#ifndef web_strdup
|
||||
#define web_strdup rt_strdup
|
||||
#endif
|
||||
|
||||
#define WEBCLIENT_SW_VERSION "2.3.0"
|
||||
#define WEBCLIENT_SW_VERSION_NUM 0x20300
|
||||
|
||||
#define WEBCLIENT_HEADER_BUFSZ 4096
|
||||
#define WEBCLIENT_RESPONSE_BUFSZ 4096
|
||||
|
||||
enum WEBCLIENT_STATUS {
|
||||
WEBCLIENT_OK,
|
||||
WEBCLIENT_ERROR,
|
||||
WEBCLIENT_TIMEOUT,
|
||||
WEBCLIENT_NOMEM,
|
||||
WEBCLIENT_NOSOCKET,
|
||||
WEBCLIENT_NOBUFFER,
|
||||
WEBCLIENT_CONNECT_FAILED,
|
||||
WEBCLIENT_DISCONNECT,
|
||||
WEBCLIENT_FILE_ERROR,
|
||||
};
|
||||
|
||||
enum WEBCLIENT_METHOD {
|
||||
WEBCLIENT_USER_METHOD,
|
||||
WEBCLIENT_GET,
|
||||
WEBCLIENT_POST,
|
||||
WEBCLIENT_HEAD
|
||||
};
|
||||
|
||||
struct webclient_header {
|
||||
char* buffer;
|
||||
size_t length; /* content header buffer size */
|
||||
|
||||
size_t size; /* maximum support header size */
|
||||
};
|
||||
|
||||
struct webclient_session {
|
||||
struct webclient_header* header; /* webclient response header information */
|
||||
int socket;
|
||||
int resp_status;
|
||||
|
||||
char* host; /* server host */
|
||||
char* req_url; /* HTTP request address*/
|
||||
|
||||
int chunk_sz;
|
||||
int chunk_offset;
|
||||
|
||||
int content_length;
|
||||
size_t content_remainder; /* remainder of content length */
|
||||
int (*handle_function)(char* buffer, int size); /* handle function */
|
||||
|
||||
rt_bool_t is_tls; /* HTTPS connect */
|
||||
#ifdef WEBCLIENT_USING_MBED_TLS
|
||||
MbedTLSSession* tls_session; /* mbedtls connect session */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* create webclient session and set header response size */
|
||||
struct webclient_session* webclient_session_create(size_t header_sz);
|
||||
|
||||
/* send HTTP GET request */
|
||||
int webclient_get(struct webclient_session* session, const char* URI);
|
||||
|
||||
/* send HTTP HEAD request */
|
||||
int webclient_shard_head_function(struct webclient_session* session,
|
||||
const char* URI,
|
||||
int* length);
|
||||
|
||||
/* send HTTP Range parameter, shard download */
|
||||
int webclient_shard_position_function(struct webclient_session* session,
|
||||
const char* URI,
|
||||
int start,
|
||||
int length,
|
||||
int mem_size);
|
||||
int* webclient_register_shard_position_function(
|
||||
struct webclient_session* session,
|
||||
int (*handle_function)(char* buffer, int size));
|
||||
|
||||
/* send HTTP POST request */
|
||||
int webclient_post(struct webclient_session* session,
|
||||
const char* URI,
|
||||
const void* post_data,
|
||||
size_t data_len);
|
||||
|
||||
/* close and release wenclient session */
|
||||
int webclient_close(struct webclient_session* session);
|
||||
|
||||
int webclient_set_timeout(struct webclient_session* session, int millisecond);
|
||||
|
||||
/* send or receive data from server */
|
||||
int webclient_read(struct webclient_session* session,
|
||||
void* buffer,
|
||||
size_t size);
|
||||
int webclient_write(struct webclient_session* session,
|
||||
const void* buffer,
|
||||
size_t size);
|
||||
|
||||
/* webclient GET/POST header buffer operate by the header fields */
|
||||
int webclient_header_fields_add(struct webclient_session* session,
|
||||
const char* fmt,
|
||||
...);
|
||||
const char* webclient_header_fields_get(struct webclient_session* session,
|
||||
const char* fields);
|
||||
|
||||
/* send HTTP POST/GET request, and get response data */
|
||||
int webclient_response(struct webclient_session* session,
|
||||
void** response,
|
||||
size_t* resp_len);
|
||||
int webclient_request(const char* URI,
|
||||
const char* header,
|
||||
const void* post_data,
|
||||
size_t data_len,
|
||||
void** response,
|
||||
size_t* resp_len);
|
||||
int webclient_request_header_add(char** request_header, const char* fmt, ...);
|
||||
int webclient_resp_status_get(struct webclient_session* session);
|
||||
int webclient_content_length_get(struct webclient_session* session);
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
/* file related operations */
|
||||
int webclient_get_file(const char* URI, const char* filename);
|
||||
int webclient_post_file(const char* URI,
|
||||
const char* filename,
|
||||
const char* form_data);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-07-26 chenyong modify log information
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pika_adapter_rtt.h"
|
||||
#include "webclient.h"
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define DBG_ENABLE
|
||||
#define DBG_SECTION_NAME "web.file"
|
||||
#ifdef WEBCLIENT_DEBUG
|
||||
#define DBG_LEVEL DBG_LOG
|
||||
#else
|
||||
#define DBG_LEVEL DBG_INFO
|
||||
#endif /* WEBCLIENT_DEBUG */
|
||||
#define DBG_COLOR
|
||||
#include <rtdbg.h>
|
||||
|
||||
/**
|
||||
* send GET request and store response data into the file.
|
||||
*
|
||||
* @param URI input server address
|
||||
* @param filename store response date to filename
|
||||
*
|
||||
* @return <0: GET request failed
|
||||
* =0: success
|
||||
*/
|
||||
int webclient_get_file(const char* URI, const char* filename)
|
||||
{
|
||||
int fd = -1, rc = WEBCLIENT_OK;
|
||||
size_t offset;
|
||||
int length, total_length = 0;
|
||||
unsigned char *ptr = RT_NULL;
|
||||
struct webclient_session* session = RT_NULL;
|
||||
int resp_status = 0;
|
||||
|
||||
session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
|
||||
if(session == RT_NULL)
|
||||
{
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if ((resp_status = webclient_get(session, URI)) != 200)
|
||||
{
|
||||
LOG_E("get file failed, wrong response: %d (-0x%X).", resp_status, resp_status);
|
||||
rc = -WEBCLIENT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG_E("get file failed, open file(%s) error.", filename);
|
||||
rc = -WEBCLIENT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
ptr = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (ptr == RT_NULL)
|
||||
{
|
||||
LOG_E("get file failed, no memory for response buffer.");
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (session->content_length < 0)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
length = webclient_read(session, ptr, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (length > 0)
|
||||
{
|
||||
write(fd, ptr, length);
|
||||
total_length += length;
|
||||
LOG_RAW(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (offset = 0; offset < (size_t) session->content_length;)
|
||||
{
|
||||
length = webclient_read(session, ptr,
|
||||
session->content_length - offset > WEBCLIENT_RESPONSE_BUFSZ ?
|
||||
WEBCLIENT_RESPONSE_BUFSZ : session->content_length - offset);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
write(fd, ptr, length);
|
||||
total_length += length;
|
||||
LOG_RAW(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
if (total_length)
|
||||
{
|
||||
LOG_D("save %d bytes.", total_length);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (session != RT_NULL)
|
||||
{
|
||||
webclient_close(session);
|
||||
}
|
||||
|
||||
if (ptr != RT_NULL)
|
||||
{
|
||||
web_free(ptr);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* post file to http server.
|
||||
*
|
||||
* @param URI input server address
|
||||
* @param filename post data filename
|
||||
* @param form_data form data
|
||||
*
|
||||
* @return <0: POST request failed
|
||||
* =0: success
|
||||
*/
|
||||
int webclient_post_file(const char* URI, const char* filename,
|
||||
const char* form_data)
|
||||
{
|
||||
size_t length;
|
||||
char boundary[60];
|
||||
int fd = -1, rc = WEBCLIENT_OK;
|
||||
char *header = RT_NULL, *header_ptr;
|
||||
unsigned char *buffer = RT_NULL, *buffer_ptr;
|
||||
struct webclient_session* session = RT_NULL;
|
||||
int resp_data_len = 0;
|
||||
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG_D("post file failed, open file(%s) error.", filename);
|
||||
rc = -WEBCLIENT_FILE_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/* get the size of file */
|
||||
length = lseek(fd, 0, SEEK_END);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
buffer = (unsigned char *) web_calloc(1, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (buffer == RT_NULL)
|
||||
{
|
||||
LOG_D("post file failed, no memory for response buffer.");
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
header = (char *) web_calloc(1, WEBCLIENT_HEADER_BUFSZ);
|
||||
if (header == RT_NULL)
|
||||
{
|
||||
LOG_D("post file failed, no memory for header buffer.");
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
header_ptr = header;
|
||||
|
||||
/* build boundary */
|
||||
web_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get());
|
||||
|
||||
/* build encapsulated mime_multipart information*/
|
||||
buffer_ptr = buffer;
|
||||
/* first boundary */
|
||||
buffer_ptr += web_snprintf((char*) buffer_ptr,
|
||||
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s\r\n", boundary);
|
||||
buffer_ptr += web_snprintf((char*) buffer_ptr,
|
||||
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
|
||||
"Content-Disposition: form-data; %s\r\n", form_data);
|
||||
buffer_ptr += web_snprintf((char*) buffer_ptr,
|
||||
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
|
||||
"Content-Type: application/octet-stream\r\n\r\n");
|
||||
/* calculate content-length */
|
||||
length += buffer_ptr - buffer;
|
||||
length += strlen(boundary) + 8; /* add the last boundary */
|
||||
|
||||
/* build header for upload */
|
||||
header_ptr += web_snprintf(header_ptr,
|
||||
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
|
||||
"Content-Length: %d\r\n", length);
|
||||
header_ptr += web_snprintf(header_ptr,
|
||||
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
|
||||
"Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
|
||||
|
||||
session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
|
||||
if(session == RT_NULL)
|
||||
{
|
||||
rc = -WEBCLIENT_NOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
strncpy(session->header->buffer, header, strlen(header));
|
||||
session->header->length = strlen(session->header->buffer);
|
||||
|
||||
rc = webclient_post(session, URI, NULL, 0);
|
||||
if(rc < 0)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/* send mime_multipart */
|
||||
webclient_write(session, buffer, buffer_ptr - buffer);
|
||||
|
||||
/* send file data */
|
||||
while (1)
|
||||
{
|
||||
length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (length <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
webclient_write(session, buffer, length);
|
||||
}
|
||||
|
||||
/* send last boundary */
|
||||
web_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, "\r\n--%s--\r\n", boundary);
|
||||
webclient_write(session, buffer, strlen(boundary) + 8);
|
||||
|
||||
extern int webclient_handle_response(struct webclient_session *session);
|
||||
if( webclient_handle_response(session) != 200)
|
||||
{
|
||||
rc = -WEBCLIENT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
resp_data_len = webclient_content_length_get(session);
|
||||
if (resp_data_len > 0)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
|
||||
web_memset(buffer, 0x00, WEBCLIENT_RESPONSE_BUFSZ);
|
||||
do
|
||||
{
|
||||
bytes_read = webclient_read(session, buffer,
|
||||
resp_data_len < WEBCLIENT_RESPONSE_BUFSZ ? resp_data_len : WEBCLIENT_RESPONSE_BUFSZ);
|
||||
if (bytes_read <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
resp_data_len -= bytes_read;
|
||||
} while(resp_data_len > 0);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (session != RT_NULL)
|
||||
{
|
||||
webclient_close(session);
|
||||
}
|
||||
|
||||
if (buffer != RT_NULL)
|
||||
{
|
||||
web_free(buffer);
|
||||
}
|
||||
|
||||
if (header != RT_NULL)
|
||||
{
|
||||
web_free(header);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wget(int argc, char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
rt_kprintf("Please using: wget <URI> <filename>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
webclient_get_file(argv[1], argv[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
#include <finsh.h>
|
||||
MSH_CMD_EXPORT(wget, Get file by URI: wget <URI> <filename>.);
|
||||
#endif /* FINSH_USING_MSH */
|
||||
|
||||
#endif /* RT_USING_DFS */
|
@ -1,16 +1,5 @@
|
||||
#include "_socket.h"
|
||||
#include "_socket_socket.h"
|
||||
#ifdef __linux__
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
/*
|
||||
You need to create the __platform_socket.h for your platform.
|
||||
For example:
|
||||
You can #include "lwip/socket.h" in the __platform_socket.h
|
||||
*/
|
||||
#include "__platform_socket.h"
|
||||
#endif
|
||||
#include "platform_socket.h"
|
||||
|
||||
#if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 10, 4)
|
||||
#error "This library requires PikaScript version 1.10.4 or higher"
|
||||
|
@ -41,6 +41,14 @@ PIKA_WEAK void* __platform_malloc(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
PIKA_WEAK void* __platform_realloc(void* ptr, size_t size) {
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
PIKA_WEAK void* __platform_calloc(size_t num, size_t size) {
|
||||
return calloc(num, size);
|
||||
}
|
||||
|
||||
PIKA_WEAK void __platform_free(void* ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
@ -78,6 +86,25 @@ PIKA_WEAK int __platform_vsprintf(char* buff, char* fmt, va_list args) {
|
||||
return vsprintf(buff, fmt, args);
|
||||
}
|
||||
|
||||
PIKA_WEAK int __platform_snprintf(char* buff,
|
||||
size_t size,
|
||||
const char* fmt,
|
||||
...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int ret = __platform_vsnprintf(buff, size, fmt, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PIKA_WEAK char* __platform_strdup(const char* src){
|
||||
return strdup(src);
|
||||
}
|
||||
|
||||
PIKA_WEAK size_t __platform_tick_from_millisecond(size_t ms) {
|
||||
return ms;
|
||||
}
|
||||
|
||||
PIKA_WEAK int __platform_vsnprintf(char* buff,
|
||||
size_t size,
|
||||
const char* fmt,
|
||||
|
@ -133,9 +133,14 @@ int __platform_vsnprintf(char* buff,
|
||||
size_t size,
|
||||
const char* fmt,
|
||||
va_list args);
|
||||
int __platform_snprintf(char* buff, size_t size, const char* fmt, ...);
|
||||
char* __platform_strdup(const char* src);
|
||||
size_t __platform_tick_from_millisecond(size_t ms);
|
||||
|
||||
/* libc config */
|
||||
void* __platform_malloc(size_t size);
|
||||
void* __platform_realloc(void* ptr, size_t size);
|
||||
void* __platform_calloc(size_t num, size_t size);
|
||||
void __platform_free(void* ptr);
|
||||
void* __platform_memset(void* mem, int ch, size_t size);
|
||||
void* __platform_memcpy(void* dir, const void* src, size_t size);
|
||||
|
Loading…
x
Reference in New Issue
Block a user