@ -1,5 +1,5 @@
/*
/*
* Copyright ( c ) 2006 - 201 8 , RT - Thread Development Team
* Copyright ( c ) 2006 - 201 9 , RT - Thread Development Team
*
*
* SPDX - License - Identifier : Apache - 2.0
* SPDX - License - Identifier : Apache - 2.0
*
*
@ -14,11 +14,17 @@
* 2018 - 08 - 07 chenyong modify header processing
* 2018 - 08 - 07 chenyong modify header processing
*/
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <string.h>
# include <sys/time.h>
# include < ctyp e.h>
# include <webclient.h>
# include <webclient.h>
# if defined(RT_USING_LIBC) || defined(RT_USING_MINILIBC) || defined(RT_LIBC_USING_TIME)
# include <sys/time.h>
# endif
/* support both enable and disable "SAL_USING_POSIX" */
/* support both enable and disable "SAL_USING_POSIX" */
# if defined(RT_USING_SAL)
# if defined(RT_USING_SAL)
# include <netdb.h>
# include <netdb.h>
@ -43,7 +49,39 @@
extern long int strtol ( const char * nptr , char * * endptr , int base ) ;
extern long int strtol ( const char * nptr , char * * endptr , int base ) ;
static int webclient_send ( struct webclient_session * session , const unsigned char * buffer , size_t len , int flag )
static int webclient_strncasecmp ( const char * a , const char * b , size_t n )
{
uint8_t c1 , c2 ;
if ( n < = 0 )
return 0 ;
do {
c1 = tolower ( * a + + ) ;
c2 = tolower ( * b + + ) ;
} while ( - - n & & c1 & & c1 = = c2 ) ;
return c1 - c2 ;
}
static const char * webclient_strstri ( const char * str , const char * subStr )
{
int len = strlen ( subStr ) ;
if ( len = = 0 )
{
return RT_NULL ;
}
while ( * str )
{
if ( webclient_strncasecmp ( str , subStr , len ) = = 0 )
{
return str ;
}
+ + str ;
}
return RT_NULL ;
}
static int webclient_send ( struct webclient_session * session , const void * buffer , size_t len , int flag )
{
{
# ifdef WEBCLIENT_USING_MBED_TLS
# ifdef WEBCLIENT_USING_MBED_TLS
if ( session - > tls_session )
if ( session - > tls_session )
@ -55,14 +93,14 @@ static int webclient_send(struct webclient_session* session, const unsigned char
return send ( session - > socket , buffer , len , flag ) ;
return send ( session - > socket , buffer , len , flag ) ;
}
}
static int webclient_recv ( struct webclient_session * session , unsigned char * buffer , size_t len , int flag )
static int webclient_recv ( struct webclient_session * session , void * buffer , size_t len , int flag )
{
{
# ifdef WEBCLIENT_USING_MBED_TLS
# ifdef WEBCLIENT_USING_MBED_TLS
if ( session - > tls_session )
if ( session - > tls_session )
{
{
return mbedtls_client_read ( session - > tls_session , buffer , len ) ;
return mbedtls_client_read ( session - > tls_session , buffer , len ) ;
}
}
# endif
# endif
return recv ( session - > socket , buffer , len , flag ) ;
return recv ( session - > socket , buffer , len , flag ) ;
}
}
@ -83,8 +121,8 @@ static int webclient_read_line(struct webclient_session *session, char *buffer,
if ( session - > is_tls & & ( rc = = MBEDTLS_ERR_SSL_WANT_READ | | rc = = MBEDTLS_ERR_SSL_WANT_WRITE ) )
if ( session - > is_tls & & ( rc = = MBEDTLS_ERR_SSL_WANT_READ | | rc = = MBEDTLS_ERR_SSL_WANT_WRITE ) )
{
{
continue ;
continue ;
}
}
# endif
# endif
if ( rc < = 0 )
if ( rc < = 0 )
return rc ;
return rc ;
@ -116,17 +154,23 @@ static int webclient_read_line(struct webclient_session *session, char *buffer,
* @ return 0 on resolve server address OK , others failed
* @ return 0 on resolve server address OK , others failed
*
*
* URL example :
* URL example :
* http : //www.rt-thread.org/
* http : //www.rt-thread.org
* http : //www.rt-thread.org:80
* https : //www.rt-thread.org/
* http : //192.168.1.1:80/index.htm
* http : //192.168.1.1:80/index.htm
* http : //[fe80::1]
* http : //[fe80::1]/
* http : //[fe80::1]/index.html
* http : //[fe80::1]/index.html
* http : //[fe80::1]:80/index.html
* http : //[fe80::1]:80/index.html
*/
*/
static int webclient_resolve_address ( struct webclient_session * session , struct addrinfo * * res ,
static int webclient_resolve_address ( struct webclient_session * session , struct addrinfo * * res ,
const char * url , char * * request )
const char * url , const char * * request )
{
{
int rc = WEBCLIENT_OK ;
int rc = WEBCLIENT_OK ;
char * ptr ;
char * ptr ;
char port_str [ 6 ] = " 80 " ; /* default port of 80(http) */
char port_str [ 6 ] = " 80 " ; /* default port of 80(http) */
const char * port_ptr ;
const char * path_ptr ;
const char * host_addr = 0 ;
const char * host_addr = 0 ;
int url_len , host_addr_len = 0 ;
int url_len , host_addr_len = 0 ;
@ -163,46 +207,40 @@ static int webclient_resolve_address(struct webclient_session *session, struct a
goto __exit ;
goto __exit ;
}
}
host_addr_len = ptr - host_addr ;
host_addr_len = ptr - host_addr ;
}
ptr = rt_strstr ( host_addr + host_addr_len , " / " ) ;
path_ptr = rt_strstr ( host_addr , " / " ) ;
if ( ! ptr )
* request = path_ptr ? path_ptr : " / " ;
{
rc = - WEBCLIENT_ERROR ;
goto __exit ;
}
else if ( ptr ! = ( host_addr + host_addr_len + 1 ) )
{
int port_len = ptr - host_addr - host_addr_len - 2 ;
rt_strncpy ( port_str , host_addr + host_addr_len + 2 , port_len ) ;
/* resolve port */
port_str [ port_len ] = ' \0 ' ;
port_ptr = rt_strstr ( host_addr + host_addr_len , " : " ) ;
}
if ( port_ptr & & path_ptr & & ( port_ptr < path_ptr ) )
{
int port_len = path_ptr - port_ptr - 1 ;
* request = ( char * ) ptr ;
rt_strncpy ( port_str , port_ptr + 1 , port_len ) ;
port_str [ port_len ] = ' \0 ' ;
}
}
else /* ipv4 or domain. */
if ( port_ptr & & ( ! path_ptr ) )
{
{
char * port_ptr ;
strcpy ( port_str , port_ptr + 1 ) ;
}
ptr = rt_strstr ( host_addr , " / " ) ;
/* ipv4 or domain. */
if ( ! ptr )
if ( ! host_addr_len )
{
if ( port_ptr )
{
{
rc = - WEBCLIENT_ERROR ;
host_addr_len = port_ptr - host_addr ;
goto __exit ;
}
}
host_addr_len = ptr - host_addr ;
else if ( path_ptr )
* request = ( char * ) ptr ;
/* resolve port */
port_ptr = rt_strstr ( host_addr , " : " ) ;
if ( port_ptr & & port_ptr < ptr )
{
{
int port_len = ptr - port_ptr - 1 ;
host_addr_len = path_ptr - host_addr ;
}
rt_strncpy ( port_str , port_ptr + 1 , port_len ) ;
else
port_str [ port_len ] = ' \0 ' ;
{
host_addr_len = strlen ( host_addr ) ;
host_addr_len = port_ptr - host_addr ;
}
}
}
}
@ -238,7 +276,7 @@ static int webclient_resolve_address(struct webclient_session *session, struct a
{
{
return - WEBCLIENT_NOMEM ;
return - WEBCLIENT_NOMEM ;
}
}
return rc ;
return rc ;
}
}
# endif
# endif
@ -333,14 +371,11 @@ static int webclient_connect(struct webclient_session *session, const char *URI)
int socket_handle ;
int socket_handle ;
struct timeval timeout ;
struct timeval timeout ;
struct addrinfo * res = RT_NULL ;
struct addrinfo * res = RT_NULL ;
char * req_url ;
const char * req_url ;
RT_ASSERT ( session ) ;
RT_ASSERT ( session ) ;
RT_ASSERT ( URI ) ;
RT_ASSERT ( URI ) ;
/* initialize the socket of session */
session - > socket = - 1 ;
timeout . tv_sec = WEBCLIENT_DEFAULT_TIMEO ;
timeout . tv_sec = WEBCLIENT_DEFAULT_TIMEO ;
timeout . tv_usec = 0 ;
timeout . tv_usec = 0 ;
@ -353,7 +388,7 @@ static int webclient_connect(struct webclient_session *session, const char *URI)
{
{
LOG_E ( " connect failed, https client open URI(%s) failed! " , URI ) ;
LOG_E ( " connect failed, https client open URI(%s) failed! " , URI ) ;
return - WEBCLIENT_ERROR ;
return - WEBCLIENT_ERROR ;
}
}
session - > is_tls = RT_TRUE ;
session - > is_tls = RT_TRUE ;
# else
# else
LOG_E ( " not support https connect, please enable webclient https configure! " ) ;
LOG_E ( " not support https connect, please enable webclient https configure! " ) ;
@ -527,7 +562,7 @@ const char *webclient_header_fields_get(struct webclient_session *session, const
resp_buf = session - > header - > buffer ;
resp_buf = session - > header - > buffer ;
while ( resp_buf_len < session - > header - > length )
while ( resp_buf_len < session - > header - > length )
{
{
if ( rt_strstr ( resp_buf , fields ) )
if ( webclient_strstri ( resp_buf , fields ) = = resp_buf )
{
{
char * mime_ptr = RT_NULL ;
char * mime_ptr = RT_NULL ;
@ -652,7 +687,7 @@ static int webclient_send_header(struct webclient_session *session, int method)
}
}
/* header data end */
/* header data end */
rt_snprintf ( session - > header - > buffer + session - > header - > length , session - > header - > size , " \r \n " ) ;
rt_snprintf ( session - > header - > buffer + session - > header - > length , session - > header - > size - session - > header - > length , " \r \n " ) ;
session - > header - > length + = 2 ;
session - > header - > length + = 2 ;
/* check header size */
/* check header size */
@ -671,6 +706,27 @@ static int webclient_send_header(struct webclient_session *session, int method)
}
}
}
}
/* get and echo request header data */
{
char * header_str , * header_ptr ;
int header_line_len ;
LOG_D ( " request header: " ) ;
for ( header_str = session - > header - > buffer ; ( header_ptr = rt_strstr ( header_str , " \r \n " ) ) ! = RT_NULL ; )
{
header_line_len = header_ptr - header_str ;
if ( header_line_len > 0 )
{
LOG_D ( " %.*s " , header_line_len , header_str ) ;
}
header_str = header_ptr + rt_strlen ( " \r \n " ) ;
}
# ifdef WEBCLIENT_DEBUG
LOG_RAW ( " \n " ) ;
# endif
}
__exit :
__exit :
return rc ;
return rc ;
}
}
@ -697,6 +753,7 @@ int webclient_handle_response(struct webclient_session *session)
rt_memset ( session - > header - > buffer , 0x00 , session - > header - > size ) ;
rt_memset ( session - > header - > buffer , 0x00 , session - > header - > size ) ;
session - > header - > length = 0 ;
session - > header - > length = 0 ;
LOG_D ( " response header: " ) ;
/* We now need to read the header information */
/* We now need to read the header information */
while ( 1 )
while ( 1 )
{
{
@ -719,6 +776,9 @@ int webclient_handle_response(struct webclient_session *session)
/* set terminal charater */
/* set terminal charater */
mime_buffer [ rc - 1 ] = ' \0 ' ;
mime_buffer [ rc - 1 ] = ' \0 ' ;
/* echo response header data */
LOG_D ( " %s " , mime_buffer ) ;
session - > header - > length + = rc ;
session - > header - > length + = rc ;
if ( session - > header - > length > = session - > header - > size )
if ( session - > header - > length > = session - > header - > size )
@ -803,6 +863,8 @@ struct webclient_session *webclient_session_create(size_t header_sz)
return RT_NULL ;
return RT_NULL ;
}
}
/* initialize the socket of session */
session - > socket = - 1 ;
session - > content_length = - 1 ;
session - > content_length = - 1 ;
session - > header = ( struct webclient_header * ) web_calloc ( 1 , sizeof ( struct webclient_header ) ) ;
session - > header = ( struct webclient_header * ) web_calloc ( 1 , sizeof ( struct webclient_header ) ) ;
@ -815,7 +877,7 @@ struct webclient_session *webclient_session_create(size_t header_sz)
}
}
session - > header - > size = header_sz ;
session - > header - > size = header_sz ;
session - > header - > buffer = ( char * ) web_ malloc( header_sz ) ;
session - > header - > buffer = ( char * ) web_ calloc( 1 , header_sz ) ;
if ( session - > header - > buffer = = RT_NULL )
if ( session - > header - > buffer = = RT_NULL )
{
{
LOG_E ( " webclient create failed, no memory for session header buffer! " ) ;
LOG_E ( " webclient create failed, no memory for session header buffer! " ) ;
@ -828,6 +890,8 @@ struct webclient_session *webclient_session_create(size_t header_sz)
return session ;
return session ;
}
}
static int webclient_clean ( struct webclient_session * session ) ;
/**
/**
* send GET request to http server and get response header .
* send GET request to http server and get response header .
*
*
@ -864,6 +928,9 @@ int webclient_get(struct webclient_session *session, const char *URI)
/* handle the response header of webclient server */
/* handle the response header of webclient server */
resp_status = webclient_handle_response ( session ) ;
resp_status = webclient_handle_response ( session ) ;
LOG_D ( " get position handle response(%d). " , resp_status ) ;
if ( resp_status > 0 )
if ( resp_status > 0 )
{
{
const char * location = webclient_header_fields_get ( session , " Location " ) ;
const char * location = webclient_header_fields_get ( session , " Location " ) ;
@ -879,26 +946,17 @@ int webclient_get(struct webclient_session *session, const char *URI)
return - WEBCLIENT_NOMEM ;
return - WEBCLIENT_NOMEM ;
}
}
/* close old client session */
/* clean webclient session */
webclient_close ( session ) ;
webclient_clean ( session ) ;
/* clean webclient session header */
/* create new client session by location url */
session - > header - > length = 0 ;
session = webclient_session_create ( WEBCLIENT_HEADER_BUFSZ ) ;
rt_memset ( session - > header - > buffer , 0 , session - > header - > size ) ;
if ( session = = RT_NULL )
{
return - WEBCLIENT_NOMEM ;
}
rc = webclient_get ( session , new_url ) ;
rc = webclient_get ( session , new_url ) ;
web_free ( new_url ) ;
web_free ( new_url ) ;
return rc ;
return rc ;
}
}
else if ( resp_status ! = 200 )
{
LOG_E ( " get failed, handle response(%d) error! " , resp_status ) ;
return resp_status ;
}
}
}
return resp_status ;
return resp_status ;
@ -943,6 +1001,9 @@ int webclient_get_position(struct webclient_session *session, const char *URI, i
/* handle the response header of webclient server */
/* handle the response header of webclient server */
resp_status = webclient_handle_response ( session ) ;
resp_status = webclient_handle_response ( session ) ;
LOG_D ( " get position handle response(%d). " , resp_status ) ;
if ( resp_status > 0 )
if ( resp_status > 0 )
{
{
const char * location = webclient_header_fields_get ( session , " Location " ) ;
const char * location = webclient_header_fields_get ( session , " Location " ) ;
@ -958,26 +1019,17 @@ int webclient_get_position(struct webclient_session *session, const char *URI, i
return - WEBCLIENT_NOMEM ;
return - WEBCLIENT_NOMEM ;
}
}
/* close old client session */
/* clean webclient session */
webclient_close ( session ) ;
webclient_clean ( session ) ;
/* clean webclient session header */
/* create new client session by location url */
session - > header - > length = 0 ;
session = webclient_session_create ( WEBCLIENT_HEADER_BUFSZ ) ;
rt_memset ( session - > header - > buffer , 0 , session - > header - > size ) ;
if ( session = = RT_NULL )
{
return - WEBCLIENT_NOMEM ;
}
rc = webclient_get ( session , new_url ) ;
rc = webclient_get_position ( session , new_url , position ) ;
web_free ( new_url ) ;
web_free ( new_url ) ;
return rc ;
return rc ;
}
}
else if ( resp_status ! = 206 )
{
LOG_E ( " get failed, handle response(%d) error! " , resp_status ) ;
return resp_status ;
}
}
}
return resp_status ;
return resp_status ;
@ -989,15 +1041,16 @@ int webclient_get_position(struct webclient_session *session, const char *URI, i
* @ param session webclient session
* @ param session webclient session
* @ param URI input server URI address
* @ param URI input server URI address
* @ param header POST request header , can ' t be empty
* @ param header POST request header , can ' t be empty
* @ param post_data data sen t to the server
* @ param post_data data sen d to the server
* = NULL : just connect server and send header
* = NULL : just connect server and send header
* ! = NULL : send header and body data , resolve response data
* ! = NULL : send header and body data , resolve response data
* @ param data_len the length of send data
*
*
* @ return < 0 : send POST request failed
* @ return < 0 : send POST request failed
* = 0 : send POST header success
* = 0 : send POST header success
* > 0 : response http status code
* > 0 : response http status code
*/
*/
int webclient_post ( struct webclient_session * session , const char * URI , const char * post_data )
int webclient_post ( struct webclient_session * session , const char * URI , const void * post_data , size_t data_len )
{
{
int rc = WEBCLIENT_OK ;
int rc = WEBCLIENT_OK ;
int resp_status = 0 ;
int resp_status = 0 ;
@ -1005,6 +1058,12 @@ int webclient_post(struct webclient_session *session, const char *URI, const cha
RT_ASSERT ( session ) ;
RT_ASSERT ( session ) ;
RT_ASSERT ( URI ) ;
RT_ASSERT ( URI ) ;
if ( ( post_data ! = RT_NULL ) & & ( data_len = = 0 ) )
{
LOG_E ( " input post data length failed " ) ;
return - WEBCLIENT_ERROR ;
}
rc = webclient_connect ( session , URI ) ;
rc = webclient_connect ( session , URI ) ;
if ( rc ! = WEBCLIENT_OK )
if ( rc ! = WEBCLIENT_OK )
{
{
@ -1019,17 +1078,13 @@ int webclient_post(struct webclient_session *session, const char *URI, const cha
return rc ;
return rc ;
}
}
if ( post_data )
if ( post_data & & ( data_len > 0 ) )
{
{
webclient_write ( session , ( unsigned char * ) post_data , rt_strlen ( post_data ) ) ;
webclient_write ( session , post_data , data_len ) ;
/* resolve response data, get http status code */
/* resolve response data, get http status code */
resp_status = webclient_handle_response ( session ) ;
resp_status = webclient_handle_response ( session ) ;
if ( resp_status ! = 200 )
LOG_D ( " post handle response(%d). " , resp_status ) ;
{
LOG_E ( " post failed, handle response(%d) error. " , resp_status ) ;
return resp_status ;
}
}
}
return resp_status ;
return resp_status ;
@ -1070,6 +1125,7 @@ static int webclient_next_chunk(struct webclient_session *session)
RT_ASSERT ( session ) ;
RT_ASSERT ( session ) ;
rt_memset ( line , 0x00 , sizeof ( line ) ) ;
length = webclient_read_line ( session , line , sizeof ( line ) ) ;
length = webclient_read_line ( session , line , sizeof ( line ) ) ;
if ( length > 0 )
if ( length > 0 )
{
{
@ -1100,6 +1156,7 @@ static int webclient_next_chunk(struct webclient_session *session)
/* end of chunks */
/* end of chunks */
closesocket ( session - > socket ) ;
closesocket ( session - > socket ) ;
session - > socket = - 1 ;
session - > socket = - 1 ;
session - > chunk_sz = - 1 ;
}
}
return session - > chunk_sz ;
return session - > chunk_sz ;
@ -1116,7 +1173,7 @@ static int webclient_next_chunk(struct webclient_session *session)
* = 0 : http server disconnect
* = 0 : http server disconnect
* > 0 : successfully read data length
* > 0 : successfully read data length
*/
*/
int webclient_read ( struct webclient_session * session , unsigned char * buffer , size_t length )
int webclient_read ( struct webclient_session * session , void * buffer , size_t length )
{
{
int bytes_read = 0 ;
int bytes_read = 0 ;
int total_read = 0 ;
int total_read = 0 ;
@ -1124,6 +1181,12 @@ int webclient_read(struct webclient_session *session, unsigned char *buffer, siz
RT_ASSERT ( session ) ;
RT_ASSERT ( session ) ;
/* get next chunk size is zero, client is already closed, return zero */
if ( session - > chunk_sz < 0 )
{
return 0 ;
}
if ( session - > socket < 0 )
if ( session - > socket < 0 )
{
{
return - WEBCLIENT_DISCONNECT ;
return - WEBCLIENT_DISCONNECT ;
@ -1187,18 +1250,18 @@ int webclient_read(struct webclient_session *session, unsigned char *buffer, siz
left = length ;
left = length ;
do
do
{
{
bytes_read = webclient_recv ( session , buffer + total_read , left , 0 ) ;
bytes_read = webclient_recv ( session , ( void * ) ( ( char * ) buffer + total_read ) , left , 0 ) ;
if ( bytes_read < = 0 )
if ( bytes_read < = 0 )
{
{
# if defined(WEBCLIENT_USING_SAL_TLS) || defined(WEBCLIENT_USING_MBED_TLS)
# if defined(WEBCLIENT_USING_SAL_TLS) || defined(WEBCLIENT_USING_MBED_TLS)
if ( session - > is_tls & &
if ( session - > is_tls & &
( bytes_read = = MBEDTLS_ERR_SSL_WANT_READ | | bytes_read = = MBEDTLS_ERR_SSL_WANT_WRITE ) )
( bytes_read = = MBEDTLS_ERR_SSL_WANT_READ | | bytes_read = = MBEDTLS_ERR_SSL_WANT_WRITE ) )
{
{
continue ;
continue ;
}
}
# endif
# endif
LOG_ E ( " receive data error(%d). " , bytes_read ) ;
LOG_ D ( " receive data error(%d). " , bytes_read ) ;
if ( total_read )
if ( total_read )
{
{
@ -1245,7 +1308,7 @@ int webclient_read(struct webclient_session *session, unsigned char *buffer, siz
* = 0 : http server disconnect
* = 0 : http server disconnect
* > 0 : successfully write data length
* > 0 : successfully write data length
*/
*/
int webclient_write ( struct webclient_session * session , const unsigned char * buffer , size_t length )
int webclient_write ( struct webclient_session * session , const void * buffer , size_t length )
{
{
int bytes_write = 0 ;
int bytes_write = 0 ;
int total_write = 0 ;
int total_write = 0 ;
@ -1266,11 +1329,11 @@ int webclient_write(struct webclient_session *session, const unsigned char *buff
/* send all of data on the buffer. */
/* send all of data on the buffer. */
do
do
{
{
bytes_write = webclient_send ( session , buffer + total_write , left , 0 ) ;
bytes_write = webclient_send ( session , ( void * ) ( ( char * ) buffer + total_write ) , left , 0 ) ;
if ( bytes_write < = 0 )
if ( bytes_write < = 0 )
{
{
# if defined(WEBCLIENT_USING_SAL_TLS) || defined(WEBCLIENT_USING_MBED_TLS)
# if defined(WEBCLIENT_USING_SAL_TLS) || defined(WEBCLIENT_USING_MBED_TLS)
if ( session - > is_tls & &
if ( session - > is_tls & &
( bytes_write = = MBEDTLS_ERR_SSL_WANT_READ | | bytes_write = = MBEDTLS_ERR_SSL_WANT_WRITE ) )
( bytes_write = = MBEDTLS_ERR_SSL_WANT_READ | | bytes_write = = MBEDTLS_ERR_SSL_WANT_WRITE ) )
{
{
continue ;
continue ;
@ -1308,17 +1371,9 @@ int webclient_write(struct webclient_session *session, const unsigned char *buff
return total_write ;
return total_write ;
}
}
/**
/* close session socket, free host and request url */
* close a webclient client session .
static int webclient_clean ( struct webclient_session * session )
*
* @ param session http client session
*
* @ return 0 : close success
*/
int webclient_close ( struct webclient_session * session )
{
{
RT_ASSERT ( session ) ;
# ifdef WEBCLIENT_USING_MBED_TLS
# ifdef WEBCLIENT_USING_MBED_TLS
if ( session - > tls_session )
if ( session - > tls_session )
{
{
@ -1328,7 +1383,7 @@ int webclient_close(struct webclient_session *session)
{
{
if ( session - > socket > = 0 )
if ( session - > socket > = 0 )
{
{
closesocket ( session - > socket ) ;
closesocket ( session - > socket ) ;
session - > socket = - 1 ;
session - > socket = - 1 ;
}
}
}
}
@ -1343,13 +1398,33 @@ int webclient_close(struct webclient_session *session)
if ( session - > host )
if ( session - > host )
{
{
web_free ( session - > host ) ;
web_free ( session - > host ) ;
session - > host = RT_NULL ;
}
}
if ( session - > req_url )
if ( session - > req_url )
{
{
web_free ( session - > req_url ) ;
web_free ( session - > req_url ) ;
session - > req_url = RT_NULL ;
}
}
session - > content_length = - 1 ;
return 0 ;
}
/**
* close a webclient client session .
*
* @ param session http client session
*
* @ return 0 : close success
*/
int webclient_close ( struct webclient_session * session )
{
RT_ASSERT ( session ) ;
webclient_clean ( session ) ;
if ( session - > header & & session - > header - > buffer )
if ( session - > header & & session - > header - > buffer )
{
{
web_free ( session - > header - > buffer ) ;
web_free ( session - > header - > buffer ) ;
@ -1374,10 +1449,11 @@ int webclient_close(struct webclient_session *session)
*
*
* @ param session wenclient session
* @ param session wenclient session
* @ param response response buffer address
* @ param response response buffer address
* @ param resp_len response buffer length
*
*
* @ return response data size
* @ return response data size
*/
*/
int webclient_response ( struct webclient_session * session , unsigned char * * response )
int webclient_response ( struct webclient_session * session , void * * response , size_t * resp_len )
{
{
unsigned char * buf_ptr ;
unsigned char * buf_ptr ;
unsigned char * response_buf = 0 ;
unsigned char * response_buf = 0 ;
@ -1423,8 +1499,8 @@ int webclient_response(struct webclient_session *session, unsigned char **respon
int result_sz ;
int result_sz ;
result_sz = session - > content_length ;
result_sz = session - > content_length ;
response_buf = web_ malloc( result_sz + 1 ) ;
response_buf = web_ calloc( 1 , result_sz + 1 ) ;
if ( ! response_buf )
if ( response_buf = = RT_NULL )
{
{
return - WEBCLIENT_NOMEM ;
return - WEBCLIENT_NOMEM ;
}
}
@ -1449,13 +1525,67 @@ int webclient_response(struct webclient_session *session, unsigned char **respon
if ( response_buf )
if ( response_buf )
{
{
* response = response_buf ;
* response = ( void * ) response_buf ;
* ( response_buf + total_read ) = ' \0 ' ;
* ( response_buf + total_read ) = ' \0 ' ;
* resp_len = total_read ;
}
}
return total_read ;
return total_read ;
}
}
/**
* add request ( GET / POST ) header data .
*
* @ param request_header add request buffer address
* @ param fmt fields format
*
* @ return < = 0 : add header failed
* > 0 : add header data size
*/
int webclient_request_header_add ( char * * request_header , const char * fmt , . . . )
{
rt_int32_t length , header_length ;
char * header ;
va_list args ;
RT_ASSERT ( request_header ) ;
if ( * request_header = = RT_NULL )
{
header = rt_calloc ( 1 , WEBCLIENT_HEADER_BUFSZ ) ;
if ( header = = RT_NULL )
{
LOG_E ( " No memory for webclient request header add. " ) ;
return RT_NULL ;
}
* request_header = header ;
}
else
{
header = * request_header ;
}
va_start ( args , fmt ) ;
header_length = rt_strlen ( header ) ;
length = rt_vsnprintf ( header + header_length , WEBCLIENT_HEADER_BUFSZ - header_length , fmt , args ) ;
if ( length < 0 )
{
LOG_E ( " add request header data failed, return length(%d) error. " , length ) ;
return - WEBCLIENT_ERROR ;
}
va_end ( args ) ;
/* check header size */
if ( rt_strlen ( header ) > = WEBCLIENT_HEADER_BUFSZ )
{
LOG_E ( " not enough request header data size(%d)! " , WEBCLIENT_HEADER_BUFSZ ) ;
return - WEBCLIENT_ERROR ;
}
return length ;
}
/**
/**
* send request ( GET / POST ) to server and get response data .
* send request ( GET / POST ) to server and get response data .
*
*
@ -1466,16 +1596,18 @@ int webclient_response(struct webclient_session *session, unsigned char **respon
* @ param post_data data sent to the server
* @ param post_data data sent to the server
* = NULL : it is GET request
* = NULL : it is GET request
* ! = NULL : it is POST request
* ! = NULL : it is POST request
* @ param data_len send data length
* @ param response response buffer address
* @ param response response buffer address
* @ param resp_len response buffer length
*
*
* @ return < 0 : request failed
* @ return < 0 : request failed
* > = 0 : response buffer size
* > = 0 : response buffer size
*/
*/
int webclient_request ( const char * URI , const char * header , const char * post_data , unsigned char * * response )
int webclient_request ( const char * URI , const char * header , const void * post_data , size_t data_len , void * * response , size_t * resp_len )
{
{
struct webclient_session * session ;
struct webclient_session * session = RT_NULL ;
int rc = WEBCLIENT_OK ;
int rc = WEBCLIENT_OK ;
int totle_length ;
int totle_length = 0 ;
RT_ASSERT ( URI ) ;
RT_ASSERT ( URI ) ;
@ -1485,8 +1617,22 @@ int webclient_request(const char *URI, const char *header, const char *post_data
return - WEBCLIENT_ERROR ;
return - WEBCLIENT_ERROR ;
}
}
if ( ( post_data ! = RT_NULL ) & & ( data_len = = 0 ) )
{
LOG_E ( " input post data length failed " ) ;
return - WEBCLIENT_ERROR ;
}
if ( ( response ! = RT_NULL & & resp_len = = RT_NULL ) | |
( response = = RT_NULL & & resp_len ! = RT_NULL ) )
{
LOG_E ( " input response data or length failed " ) ;
return - WEBCLIENT_ERROR ;
}
if ( post_data = = RT_NULL )
if ( post_data = = RT_NULL )
{
{
/* send get request */
session = webclient_session_create ( WEBCLIENT_HEADER_BUFSZ ) ;
session = webclient_session_create ( WEBCLIENT_HEADER_BUFSZ ) ;
if ( session = = RT_NULL )
if ( session = = RT_NULL )
{
{
@ -1496,7 +1642,15 @@ int webclient_request(const char *URI, const char *header, const char *post_data
if ( header ! = RT_NULL )
if ( header ! = RT_NULL )
{
{
rt_strncpy ( session - > header - > buffer , header , rt_strlen ( header ) ) ;
char * header_str , * header_ptr ;
int header_line_length ;
for ( header_str = ( char * ) header ; ( header_ptr = rt_strstr ( header_str , " \r \n " ) ) ! = RT_NULL ; )
{
header_line_length = header_ptr + rt_strlen ( " \r \n " ) - header_str ;
webclient_header_fields_add ( session , " %.*s " , header_line_length , header_str ) ;
header_str + = header_line_length ;
}
}
}
if ( webclient_get ( session , URI ) ! = 200 )
if ( webclient_get ( session , URI ) ! = 200 )
@ -1505,7 +1659,7 @@ int webclient_request(const char *URI, const char *header, const char *post_data
goto __exit ;
goto __exit ;
}
}
totle_length = webclient_response ( session , response );
totle_length = webclient_response ( session , response , resp_len );
if ( totle_length < = 0 )
if ( totle_length < = 0 )
{
{
rc = - WEBCLIENT_ERROR ;
rc = - WEBCLIENT_ERROR ;
@ -1514,6 +1668,7 @@ int webclient_request(const char *URI, const char *header, const char *post_data
}
}
else
else
{
{
/* send post request */
session = webclient_session_create ( WEBCLIENT_HEADER_BUFSZ ) ;
session = webclient_session_create ( WEBCLIENT_HEADER_BUFSZ ) ;
if ( session = = RT_NULL )
if ( session = = RT_NULL )
{
{
@ -1523,22 +1678,34 @@ int webclient_request(const char *URI, const char *header, const char *post_data
if ( header ! = RT_NULL )
if ( header ! = RT_NULL )
{
{
rt_strncpy ( session - > header - > buffer , header , rt_strlen ( header ) ) ;
char * header_str , * header_ptr ;
int header_line_length ;
for ( header_str = ( char * ) header ; ( header_ptr = rt_strstr ( header_str , " \r \n " ) ) ! = RT_NULL ; )
{
header_line_length = header_ptr + rt_strlen ( " \r \n " ) - header_str ;
webclient_header_fields_add ( session , " %.*s " , header_line_length , header_str ) ;
header_str + = header_line_length ;
}
}
}
else
if ( rt_strstr ( session - > header - > buffer , " Content-Length " ) = = RT_NULL )
{
{
/* build header for upload */
webclient_header_fields_add ( session , " Content-Length: %d \r \n " , rt_strlen ( post_data ) ) ;
webclient_header_fields_add ( session , " Content-Length: %d \r \n " , rt_strlen ( post_data ) ) ;
}
if ( rt_strstr ( session - > header - > buffer , " Content-Type " ) = = RT_NULL )
{
webclient_header_fields_add ( session , " Content-Type: application/octet-stream \r \n " ) ;
webclient_header_fields_add ( session , " Content-Type: application/octet-stream \r \n " ) ;
}
}
if ( webclient_post ( session , URI , post_data ) ! = 200 )
if ( webclient_post ( session , URI , post_data , data_len ) ! = 200 )
{
{
rc = - WEBCLIENT_ERROR ;
rc = - WEBCLIENT_ERROR ;
goto __exit ;
goto __exit ;
}
}
totle_length = webclient_response ( session , response );
totle_length = webclient_response ( session , response , resp_len );
if ( totle_length < = 0 )
if ( totle_length < = 0 )
{
{
rc = - WEBCLIENT_ERROR ;
rc = - WEBCLIENT_ERROR ;
@ -1546,11 +1713,6 @@ int webclient_request(const char *URI, const char *header, const char *post_data
}
}
}
}
if ( header ! = RT_NULL )
{
rt_strncpy ( session - > header - > buffer , header , rt_strlen ( header ) ) ;
}
__exit :
__exit :
if ( session )
if ( session )
{
{