2018-09-06 10:12:08 +08:00
# include <stdlib.h>
# include <http_common.h>
# include <assert.h>
# include <string.h>
# include <math.h>
# include <sys/param.h>
# include <event2/buffer.h>
2018-09-17 15:44:44 +08:00
# include <tfe_http.h>
# include <tfe_utils.h>
# include <http_half.h>
2018-09-27 15:12:18 +08:00
# include <http_convert.h>
2018-10-11 10:41:27 +08:00
# include <event.h>
2018-09-17 15:44:44 +08:00
2018-09-06 10:12:08 +08:00
# define __PARSER_TO_HF_PRIVATE(_parser) ((struct http_half_private *)(_parser->data))
static enum tfe_http_std_field __str_header_field_to_std_field_id ( const char * str_field , size_t len )
{
/* TODO: store the header text in hash table or rbtree, or use AC multistring search algo. */
2019-09-16 11:37:18 +08:00
for ( unsigned int i = 0 ; i < __str_std_header_field_map_size ; i + + )
2018-09-06 10:12:08 +08:00
{
2019-09-23 19:07:32 +08:00
const char * std_header_field_iter = __str_std_header_field_map [ i ] ;
if ( std_header_field_iter = = NULL )
2018-09-06 10:12:08 +08:00
continue ;
2019-09-23 19:07:32 +08:00
/* std_header_field_iter must contains '\0' */
size_t std_field_length = strlen ( std_header_field_iter ) ;
/* but the str_field may don't contains '\0', so must use strnlen */
size_t field_length = strnlen ( str_field , len ) ;
if ( std_field_length ! = field_length )
continue ;
if ( strncasecmp ( std_header_field_iter , str_field , std_field_length ) ! = 0 )
2018-09-06 10:12:08 +08:00
continue ;
return ( enum tfe_http_std_field ) i ;
}
return TFE_HTTP_UNKNOWN_FIELD ;
}
2018-09-26 21:31:17 +08:00
uint16_t __hf_content_encoding_parse ( const char * str_content_encoding )
{
if ( strcasestr ( str_content_encoding , " gzip " ) ! = NULL )
{
return HTTP_ACCEPT_ENCODING_GZIP ;
}
if ( strcasestr ( str_content_encoding , " x-gzip " ) ! = NULL )
{
return HTTP_ACCEPT_ENCODING_X_GZIP ;
}
if ( strcasestr ( str_content_encoding , " deflate " ) ! = NULL )
{
return HTTP_ACCEPT_ENCODING_DEFLATE ;
}
if ( strcasestr ( str_content_encoding , " bzip2 " ) ! = NULL )
{
return HTTP_ACCEPT_ENCODING_BZIP2 ;
}
if ( strcasestr ( str_content_encoding , " x-bzip2 " ) ! = NULL )
{
return HTTP_ACCEPT_ENCODING_X_BZIP2 ;
}
2018-12-09 18:02:43 +06:00
if ( strcasestr ( str_content_encoding , " br " ) ! = NULL )
{
return HTTP_ACCEPT_ENCODING_BR ;
}
2018-09-27 15:12:18 +08:00
return HTTP_ACCEPT_ENCODING_NONE ;
2018-09-26 21:31:17 +08:00
}
2018-09-28 16:43:24 +08:00
const char * __hf_content_encoding_to_str ( unsigned int encode )
{
switch ( encode )
{
case HTTP_ACCEPT_ENCODING_GZIP : return " gzip " ;
case HTTP_ACCEPT_ENCODING_X_GZIP : return " x-gzip " ;
case HTTP_ACCEPT_ENCODING_DEFLATE : return " deflate " ;
case HTTP_ACCEPT_ENCODING_BZIP2 : return " bzip2 " ;
case HTTP_ACCEPT_ENCODING_X_BZIP2 : return " x-bzip2 " ;
2018-12-09 18:02:43 +06:00
case HTTP_ACCEPT_ENCODING_BR : return " br " ;
2018-09-28 16:43:24 +08:00
default : return " " ;
}
}
2018-09-06 10:12:08 +08:00
/* To flush header field and value which stash in evbuffer */
static void __http_half_header_kv_complete ( struct http_half_private * hf_private )
{
size_t sz_evbuf_field = evbuffer_get_length ( hf_private - > evbuf_header_field ) ;
size_t sz_evbuf_value = evbuffer_get_length ( hf_private - > evbuf_header_value ) ;
enum tfe_http_std_field std_field_id ;
struct http_field_name compact_field ;
static const char __zero = 0 ;
const char * str_field ;
const char * str_value ;
/* No header field or length of header field is zero, ignore this field-value pair. */
if ( evbuffer_get_length ( hf_private - > evbuf_header_field ) = = 0 )
{
goto __clear_buffer ;
}
/* Write a '\0' for evbuffers */
evbuffer_add ( hf_private - > evbuf_header_field , & __zero , sizeof ( __zero ) ) ;
evbuffer_add ( hf_private - > evbuf_header_value , & __zero , sizeof ( __zero ) ) ;
2018-09-18 18:50:25 +08:00
sz_evbuf_field = evbuffer_get_length ( hf_private - > evbuf_header_field ) ;
sz_evbuf_value = evbuffer_get_length ( hf_private - > evbuf_header_value ) ;
2018-09-06 10:12:08 +08:00
/* Convert evbuffer to const char * pair */
str_field = ( const char * ) evbuffer_pullup ( hf_private - > evbuf_header_field , sz_evbuf_field ) ;
str_value = ( const char * ) evbuffer_pullup ( hf_private - > evbuf_header_value , sz_evbuf_value ) ;
std_field_id = __str_header_field_to_std_field_id ( str_field , sz_evbuf_field ) ;
if ( std_field_id ! = TFE_HTTP_UNKNOWN_FIELD )
{
compact_field . field_id = std_field_id ;
compact_field . field_name = NULL ;
}
else
{
compact_field . field_id = TFE_HTTP_UNKNOWN_FIELD ;
compact_field . field_name = ( char * ) str_field ;
}
tfe_http_field_write ( & hf_private - > hf_public , & compact_field , str_value ) ;
goto __clear_buffer ;
__clear_buffer :
evbuffer_drain ( hf_private - > evbuf_header_field , sz_evbuf_field ) ;
evbuffer_drain ( hf_private - > evbuf_header_value , sz_evbuf_value ) ;
2018-09-18 18:50:25 +08:00
hf_private - > is_evbuf_header_value_set = false ;
hf_private - > is_evbuf_header_field_set = false ;
2018-09-06 10:12:08 +08:00
}
void __hf_public_req_fill_from_private ( struct http_half_private * hf_private , struct http_parser * parser )
{
struct tfe_http_half * hf_public = & hf_private - > hf_public ;
struct tfe_http_req_spec * hf_req_spec = & hf_public - > req_spec ;
/* accept-encoding, host is located in header's K-V structure */
2018-09-12 15:29:35 +08:00
hf_req_spec - > method = ( enum tfe_http_std_method ) parser - > method ;
2018-11-04 18:30:33 +08:00
hf_private - > method_or_status = ( enum tfe_http_std_method ) parser - > method ;
2018-10-25 16:47:19 +08:00
2018-09-26 21:31:17 +08:00
const static struct http_field_name __host_field_name = { TFE_HTTP_HOST , NULL } ;
2018-09-12 15:29:35 +08:00
hf_req_spec - > host = ( char * ) tfe_http_field_read ( hf_public , & __host_field_name ) ;
2018-09-06 10:12:08 +08:00
/* uri is stored in underlay evbuffer, we need to append a terminal zero */
static const char __zero = 0 ;
evbuffer_add ( hf_private - > evbuf_uri , & __zero , sizeof ( __zero ) ) ;
2018-09-12 15:29:35 +08:00
hf_req_spec - > uri = ( char * ) evbuffer_pullup ( hf_private - > evbuf_uri , evbuffer_get_length ( hf_private - > evbuf_uri ) ) ;
2018-09-06 10:12:08 +08:00
2018-09-23 20:01:11 +08:00
/* TODO: url is more complex. need to review RFC */
if ( hf_req_spec - > uri [ 0 ] ! = ' \0 ' & & hf_req_spec - > uri [ 0 ] ! = ' / ' )
{
asprintf ( & hf_private - > url_storage , " %s/%s " , hf_req_spec - > host , hf_req_spec - > uri ) ;
}
else
{
asprintf ( & hf_private - > url_storage , " %s%s " , hf_req_spec - > host , hf_req_spec - > uri ) ;
}
hf_req_spec - > url = hf_private - > url_storage ;
assert ( hf_req_spec - > url ! = NULL ) ;
2018-09-28 15:43:02 +08:00
/* Accept-Encoding */
const static struct http_field_name __accept_encoding_name = { TFE_HTTP_ACCEPT_ENCODING , NULL } ;
2018-09-28 19:52:01 +08:00
const char * __str_accept_encoding = tfe_http_field_read ( hf_public , & __accept_encoding_name ) ;
2018-09-28 15:43:02 +08:00
if ( __str_accept_encoding ! = NULL )
{
hf_private - > accept_content_encoding = __hf_content_encoding_parse ( __str_accept_encoding ) ;
}
else
{
hf_private - > accept_content_encoding = HTTP_ACCEPT_ENCODING_NONE ;
}
2018-09-06 10:12:08 +08:00
}
void __hf_public_resp_fill_from_private ( struct http_half_private * hf_private , struct http_parser * parser )
{
struct tfe_http_half * hf_public = & hf_private - > hf_public ;
struct tfe_http_resp_spec * hf_resp_spec = & hf_public - > resp_spec ;
/* Status Code */
hf_resp_spec - > resp_code = parser - > status_code ;
2018-09-23 17:33:05 +08:00
/* Content Type */
2018-09-26 21:31:17 +08:00
const static struct http_field_name __cont_encoding_type_name = { TFE_HTTP_CONT_TYPE , NULL } ;
2018-09-23 17:33:05 +08:00
hf_resp_spec - > content_type = ( char * ) tfe_http_field_read ( hf_public , & __cont_encoding_type_name ) ;
/* Content Length */
2018-09-26 21:31:17 +08:00
const static struct http_field_name __cont_encoding_length_name = { TFE_HTTP_CONT_LENGTH , NULL } ;
2018-09-23 17:33:05 +08:00
hf_resp_spec - > content_length = ( char * ) tfe_http_field_read ( hf_public , & __cont_encoding_length_name ) ;
/* Content Encoding */
2018-09-26 21:31:17 +08:00
const static struct http_field_name __cont_encoding_field_name = { TFE_HTTP_CONT_ENCODING , NULL } ;
2018-09-12 15:29:35 +08:00
hf_resp_spec - > content_encoding = ( char * ) tfe_http_field_read ( hf_public , & __cont_encoding_field_name ) ;
2018-09-26 21:31:17 +08:00
if ( hf_resp_spec - > content_encoding ! = NULL )
{
hf_private - > content_encoding = __hf_content_encoding_parse ( hf_resp_spec - > content_encoding ) ;
}
else
{
2018-09-27 16:27:32 +08:00
hf_private - > content_encoding = HTTP_ACCEPT_ENCODING_NONE ;
2018-09-26 21:31:17 +08:00
}
2018-09-06 10:12:08 +08:00
}
/* ==================================================================================================================
* REQUEST PARSER CALLBACKS
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2018-09-12 15:29:35 +08:00
# define __HF_PRIVATE_CHANGE_STATUS(_status, _now, _to) \
2018-09-07 17:27:23 +08:00
do { assert ( _status = = _now ) ; _status = _to ; } while ( 0 )
2018-09-06 10:12:08 +08:00
static int __parser_callback_on_message_begin ( struct http_parser * parser )
{
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE ( parser ) ;
assert ( hf_private - > evbuf_uri = = NULL & & hf_private - > evbuf_body = = NULL ) ;
assert ( hf_private - > evbuf_header_field = = NULL & & hf_private - > evbuf_header_value = = NULL ) ;
hf_private - > evbuf_header_field = evbuffer_new ( ) ;
hf_private - > evbuf_header_value = evbuffer_new ( ) ;
2018-09-18 18:50:25 +08:00
hf_private - > is_evbuf_header_field_set = false ;
hf_private - > is_evbuf_header_value_set = false ;
2018-09-07 17:27:23 +08:00
2018-09-18 18:50:25 +08:00
hf_private - > evbuf_uri = evbuffer_new ( ) ;
hf_private - > evbuf_body = evbuffer_new ( ) ;
2018-09-17 15:44:44 +08:00
hf_private - > body_status = STATUS_INIT ;
hf_private - > message_status = STATUS_READING ;
2018-09-12 15:29:35 +08:00
2018-09-17 15:44:44 +08:00
/* Never call user's callback, need to defer data */
hf_private - > stream_action = ACTION_DEFER_DATA ;
2018-09-06 10:12:08 +08:00
return 0 ;
}
static int __parser_callback_on_uri_field ( struct http_parser * parser , const char * at , size_t length )
{
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE ( parser ) ;
return evbuffer_add ( hf_private - > evbuf_uri , at , length ) ;
}
static int __parser_callback_on_header_field ( struct http_parser * parser , const char * at , size_t length )
{
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE ( parser ) ;
2018-09-18 18:50:25 +08:00
if ( hf_private - > is_evbuf_header_field_set & & hf_private - > is_evbuf_header_value_set )
2018-09-06 10:12:08 +08:00
{
__http_half_header_kv_complete ( hf_private ) ;
}
2018-09-18 18:50:25 +08:00
hf_private - > is_evbuf_header_field_set = true ;
2018-09-06 10:12:08 +08:00
return evbuffer_add ( hf_private - > evbuf_header_field , at , length ) ;
}
static int __parser_callback_on_header_value ( struct http_parser * parser , const char * at , size_t length )
{
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE ( parser ) ;
2018-09-18 18:50:25 +08:00
hf_private - > is_evbuf_header_value_set = true ;
2018-09-06 10:12:08 +08:00
return evbuffer_add ( hf_private - > evbuf_header_value , at , length ) ;
}
static int __parser_callback_on_headers_complete ( http_parser * parser )
{
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE ( parser ) ;
enum tfe_http_direction hf_direction = hf_private - > hf_public . direction ;
2018-10-11 10:41:27 +08:00
struct http_session_private * hs_private = hf_private - > session ;
2018-09-06 10:12:08 +08:00
if ( evbuffer_get_length ( hf_private - > evbuf_header_field ) ! = 0 )
{
__http_half_header_kv_complete ( hf_private ) ;
}
struct tfe_http_half * hf_public = & hf_private - > hf_public ;
hf_public - > major_version = parser - > http_major ;
hf_public - > minor_version = parser - > http_minor ;
2018-09-25 10:17:50 +08:00
/* Copy version to session */
2018-10-11 10:41:27 +08:00
if ( hs_private ! = NULL )
2018-09-25 10:17:50 +08:00
{
2018-10-11 10:41:27 +08:00
to_hs_public ( hs_private ) - > major_version = hf_public - > major_version ;
to_hs_public ( hs_private ) - > minor_version = hf_public - > minor_version ;
2018-09-25 10:17:50 +08:00
}
2018-09-06 10:12:08 +08:00
if ( hf_direction = = TFE_HTTP_REQUEST )
{
__hf_public_req_fill_from_private ( hf_private , parser ) ;
}
else
{
__hf_public_resp_fill_from_private ( hf_private , parser ) ;
}
2018-10-25 16:47:19 +08:00
/* for POST, must contains 'content-length' */
if ( hf_direction = = TFE_HTTP_REQUEST & & hf_private - > method_or_status = = TFE_HTTP_METHOD_POST )
{
const static struct http_field_name __cont_encoding_field_name = { TFE_HTTP_CONT_LENGTH , NULL } ;
char * __str_content_length = ( char * ) tfe_http_field_read ( hf_public , & __cont_encoding_field_name ) ;
/* Does not contain a content-length, passthrough the whole TCP connection */
2018-11-04 18:30:33 +08:00
if ( unlikely ( __str_content_length = = NULL ) )
{
2022-11-03 16:31:02 +08:00
const struct http_field_name __transfer_encoding_field_name = { TFE_HTTP_TRANSFER_ENCODING , NULL } ;
char * __str_transfer_encoding = ( char * ) tfe_http_field_read ( hf_public , & __transfer_encoding_field_name ) ;
if ( ! ( __str_transfer_encoding & & strncasecmp ( __str_transfer_encoding , " chunked " , strlen ( " chunked " ) ) = = 0 ) )
{
const char * __str_stream = hf_private - > session - > hc_private - > stream - > str_stream_info ;
TFE_LOG_ERROR ( g_http_plugin - > logger , " the content-length and transfer-encoding field not set, passthrough the whole tcp connection: %s. " , __str_stream ) ;
hf_private - > is_passthrough = true ;
return - 1 ;
}
2018-11-04 18:30:33 +08:00
}
2018-10-25 16:47:19 +08:00
}
2018-10-11 10:41:27 +08:00
tfe_http_event event = ( hf_direction = = TFE_HTTP_REQUEST ) ? EV_HTTP_REQ_HDR : EV_HTTP_RESP_HDR ;
if ( hf_private - > event_cb )
2018-09-17 15:44:44 +08:00
{
2018-10-14 18:45:02 +08:00
hf_private - > event_cb ( hf_private , event , NULL , 0 , hf_private - > event_cb_user ) ;
2018-09-17 15:44:44 +08:00
}
2018-10-11 10:41:27 +08:00
/* The setup of user stream option indicates that the way to handle the request/response has
* been decided , we should conform the resolution */
if ( hf_private - > is_user_stream_action_set )
2018-09-17 15:44:44 +08:00
{
2018-10-11 10:41:27 +08:00
assert ( hf_private - > stream_action = = ACTION_DEFER_DATA ) ;
hf_private - > stream_action = hf_private - > user_stream_action ;
2018-09-17 15:44:44 +08:00
}
2018-09-12 15:29:35 +08:00
2019-09-04 17:19:56 +08:00
/* user's suspend tag is set, which indicate that the way to handle request/response
* cannot be determinate at now , need to defer */
2018-10-28 20:13:17 +08:00
else if ( hs_private & & hs_private - > suspend_tag_signal )
2018-09-25 20:32:24 +08:00
{
2018-10-11 10:41:27 +08:00
/* Pause parser, prevent to parse request/response body,
* The body should be parsed after resume ( ) */
http_parser_pause ( parser , 1 ) ;
/* Record the event, this event will be trigger again at resume() */
hs_private - > suspend_event = event ;
/* Suspend must be setup at DEFER status.
* The request / response cannot be suspend once any bytes has been forwarded to upstream */
assert ( hf_private - > stream_action = = ACTION_DEFER_DATA ) ;
2018-09-25 20:32:24 +08:00
}
2019-09-04 17:19:56 +08:00
/* Otherwise, forward the request/response */
2018-09-25 20:32:24 +08:00
else
{
hf_private - > stream_action = ACTION_FORWARD_DATA ;
}
2018-09-06 10:12:08 +08:00
return 0 ;
}
2018-09-07 17:27:23 +08:00
static int __parser_callback_on_body ( struct http_parser * parser , const char * at , size_t length )
{
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE ( parser ) ;
2018-09-17 15:44:44 +08:00
enum tfe_http_direction hf_direction = hf_private - > hf_public . direction ;
enum tfe_http_event ev_body_begin ;
enum tfe_http_event ev_body_cont ;
if ( hf_direction = = TFE_HTTP_REQUEST )
{
ev_body_begin = EV_HTTP_REQ_BODY_BEGIN ;
ev_body_cont = EV_HTTP_REQ_BODY_CONT ;
}
else
{
ev_body_begin = EV_HTTP_RESP_BODY_BEGIN ;
ev_body_cont = EV_HTTP_RESP_BODY_CONT ;
}
if ( hf_private - > body_status = = STATUS_INIT & & hf_private - > event_cb )
{
2018-09-27 15:12:18 +08:00
/* Create ungzip context */
if ( hf_private - > content_encoding ! = HTTP_ACCEPT_ENCODING_NONE )
{
2018-09-28 15:05:54 +08:00
hf_private - > cv_uncompress_object = hf_content_uncompress_create (
2018-09-27 15:12:18 +08:00
hf_private - > content_encoding , hf_private - > event_cb , hf_private - > event_cb_user ) ;
2018-09-28 15:05:54 +08:00
if ( unlikely ( hf_private - > cv_uncompress_object = = NULL ) ) assert ( 0 ) ;
2018-09-27 15:12:18 +08:00
}
2018-09-17 15:44:44 +08:00
hf_private - > event_cb ( hf_private , ev_body_begin , NULL , parser - > content_length , hf_private - > event_cb_user ) ;
2018-09-27 15:12:18 +08:00
hf_private - > body_status = STATUS_READING ;
2018-09-17 15:44:44 +08:00
}
2018-09-27 15:12:18 +08:00
int ret = 0 ;
2018-09-20 11:37:12 +08:00
if ( hf_private - > event_cb & & length ! = 0 )
2018-09-17 15:44:44 +08:00
{
2018-09-28 15:05:54 +08:00
if ( hf_private - > cv_uncompress_object ! = NULL )
2018-09-27 15:12:18 +08:00
{
2018-09-28 15:05:54 +08:00
ret = hf_content_uncompress_write ( hf_private - > cv_uncompress_object , hf_private , ev_body_cont ,
( const unsigned char * ) at , length ) ;
2018-09-27 15:12:18 +08:00
}
else
{
ret = hf_private - > event_cb ( hf_private , ev_body_cont , ( const unsigned char * ) at ,
length , hf_private - > event_cb_user ) ;
}
2018-11-25 15:23:44 +08:00
if ( unlikely ( ret < 0 ) )
2018-09-27 15:12:18 +08:00
{
2018-11-25 15:23:44 +08:00
static const char * __str_error_uncompress = " Failed at uncompress HTTP body " ;
static const char * __str_error_event = " Failed at calling user's callback for HTTP body " ;
const char * __what = hf_private - > cv_uncompress_object ! = NULL ? __str_error_uncompress : __str_error_event ;
const char * __str_stream = hf_private - > session - > hc_private - > stream - > str_stream_info ;
const char * __str_url = hf_private - > session - > hs_public . req - > req_spec . url ;
2018-12-09 18:02:43 +06:00
TFE_LOG_ERROR ( g_http_plugin - > logger , " %s %s %s, ret = %d. " , __str_stream , __str_url , __what , ret ) ;
2018-11-25 15:23:44 +08:00
hf_private - > is_passthrough = true ; return - 1 ;
2018-09-27 15:12:18 +08:00
}
2018-09-17 15:44:44 +08:00
}
return 0 ;
2018-09-07 17:27:23 +08:00
}
2018-09-06 10:12:08 +08:00
static int __parser_callback_on_message_complete ( http_parser * parser )
{
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE ( parser ) ;
2018-09-17 15:44:44 +08:00
enum tfe_http_direction hf_direction = hf_private - > hf_public . direction ;
2018-09-20 11:37:12 +08:00
enum tfe_http_event ev_message_end ;
2018-09-17 15:44:44 +08:00
enum tfe_http_event ev_body_end ;
if ( hf_direction = = TFE_HTTP_REQUEST )
{
2018-09-20 11:37:12 +08:00
ev_message_end = EV_HTTP_REQ_END ;
2018-09-17 15:44:44 +08:00
ev_body_end = EV_HTTP_REQ_BODY_END ;
}
else
{
2018-09-20 11:37:12 +08:00
ev_message_end = EV_HTTP_RESP_END ;
2018-09-17 15:44:44 +08:00
ev_body_end = EV_HTTP_RESP_BODY_END ;
}
2018-09-20 11:37:12 +08:00
if ( hf_private - > event_cb & & hf_private - > body_status = = STATUS_READING )
2018-09-17 15:44:44 +08:00
{
hf_private - > event_cb ( hf_private , ev_body_end , NULL , 0 , hf_private - > event_cb_user ) ;
}
2018-09-07 17:27:23 +08:00
2018-09-20 11:37:12 +08:00
if ( hf_private - > event_cb )
{
hf_private - > event_cb ( hf_private , ev_message_end , NULL , 0 , hf_private - > event_cb_user ) ;
}
2018-09-17 15:44:44 +08:00
hf_private - > body_status = STATUS_COMPLETE ;
hf_private - > message_status = STATUS_COMPLETE ;
http_parser_pause ( parser , 1 ) ;
2018-09-06 10:12:08 +08:00
return 0 ;
}
static http_parser_settings __http_half_parse_setting =
2018-09-17 15:44:44 +08:00
{
. on_message_begin = __parser_callback_on_message_begin ,
. on_url = __parser_callback_on_uri_field ,
. on_status = NULL ,
. on_header_field = __parser_callback_on_header_field ,
. on_header_value = __parser_callback_on_header_value ,
. on_headers_complete = __parser_callback_on_headers_complete ,
. on_body = __parser_callback_on_body ,
. on_message_complete = __parser_callback_on_message_complete ,
. on_chunk_header = NULL ,
. on_chunk_complete = NULL
} ;
2018-09-06 10:12:08 +08:00
2018-09-12 15:29:35 +08:00
const char * hf_ops_field_read ( const struct tfe_http_half * half , const struct http_field_name * field )
{
const struct http_half_private * hf_private = to_hf_private ( half ) ;
assert ( hf_private - > major = = 0 | | hf_private - > major = = 1 ) ;
struct http_header_private * __header_iter = NULL ;
struct http_header_private * __header_found = NULL ;
TAILQ_FOREACH ( __header_iter , & hf_private - > header_list , next )
{
if ( http_field_name_compare ( __header_iter - > field , field ) ! = 0 ) continue ;
__header_found = __header_iter ;
break ;
}
return __header_found ! = NULL ? __header_iter - > value : NULL ;
}
2018-09-28 16:43:24 +08:00
int hf_ops_field_write ( struct tfe_http_half * half , const struct http_field_name * field , const char * value )
2018-09-12 15:29:35 +08:00
{
struct http_half_private * hf_private = to_hf_private ( half ) ;
assert ( hf_private - > major = = 0 | | hf_private - > major = = 1 ) ;
2019-08-22 11:17:27 +08:00
/* Add a k-v in the tail of the header list */
if ( value ! = NULL )
2018-09-28 16:43:24 +08:00
{
2019-08-22 11:17:27 +08:00
struct http_header_private * new_header = ALLOC ( struct http_header_private , 1 ) ;
new_header - > field = http_field_name_duplicate ( field ) ;
new_header - > value = tfe_strdup ( value ) ;
TAILQ_INSERT_TAIL ( & hf_private - > header_list , new_header , next ) ;
2018-09-28 16:43:24 +08:00
}
2019-08-22 11:17:27 +08:00
/* Delete a value */
2018-09-28 19:52:01 +08:00
else
{
2019-08-22 11:17:27 +08:00
struct http_header_private * header_iter = NULL ;
struct http_header_private * header_titer = NULL ;
bool delete_success = false ;
TAILQ_FOREACH_SAFE ( header_iter , & hf_private - > header_list , next , header_titer )
{
if ( http_field_name_compare ( header_iter - > field , field ) ! = 0 )
continue ;
TAILQ_REMOVE ( & hf_private - > header_list , header_iter , next ) ;
http_field_name_destory ( header_iter - > field ) ;
free ( header_iter - > value ) ;
free ( header_iter ) ;
delete_success = true ;
}
return delete_success ? 0 : - ENOENT ;
2018-09-28 19:52:01 +08:00
}
2018-09-12 15:29:35 +08:00
return 0 ;
}
struct tfe_http_half * hf_ops_allow_write ( const struct tfe_http_half * half )
{
return ( struct tfe_http_half * ) half ;
}
const char * hf_ops_field_iterate ( const struct tfe_http_half * half , void * * iter , struct http_field_name * field )
{
struct http_header_private * * __header_iter = ( struct http_header_private * * ) iter ;
const struct http_half_private * hf_private = to_hf_private ( half ) ;
if ( * __header_iter = = NULL )
{
* __header_iter = TAILQ_FIRST ( & hf_private - > header_list ) ;
}
else
{
* __header_iter = TAILQ_NEXT ( * __header_iter , next ) ;
}
if ( * __header_iter = = NULL ) return NULL ;
/* Reference of inner data, user should copy it */
field - > field_id = ( * __header_iter ) - > field - > field_id ;
field - > field_name = ( * __header_iter ) - > field - > field_name ;
return ( * __header_iter ) - > value ;
}
int hf_ops_append_body ( struct tfe_http_half * half , char * buff , size_t size , int flag )
{
2018-09-25 11:15:00 +08:00
struct http_half_private * hf_private = to_hf_private ( half ) ;
2018-09-25 20:32:24 +08:00
/* Indicate the body is finished */
if ( buff = = NULL & & size = = 0 )
{
hf_private - > message_status = STATUS_COMPLETE ;
return 0 ;
}
if ( hf_private - > evbuf_body = = NULL )
{
hf_private - > evbuf_body = evbuffer_new ( ) ;
}
2018-09-28 15:43:02 +08:00
int ret = 0 ;
if ( hf_private - > cv_compress_object )
{
ret = hf_content_compress_write ( hf_private - > cv_compress_object ,
2018-09-28 19:52:01 +08:00
( const unsigned char * ) buff , size , hf_private - > evbuf_body , 0 ) ;
2018-09-28 15:43:02 +08:00
}
else
{
ret = evbuffer_add ( hf_private - > evbuf_body , buff , size ) ;
}
return ret ;
2018-09-12 15:29:35 +08:00
}
2018-10-16 10:45:18 +08:00
int hf_ops_body_begin ( struct tfe_http_half * half , int by_stream )
{
struct http_half_private * hf_private = to_hf_private ( half ) ;
2018-10-22 21:22:59 +08:00
struct http_session_private * hs_private = hf_private - > session ;
2018-10-16 10:45:18 +08:00
assert ( hf_private - > evbuf_body = = NULL ) ;
if ( by_stream )
{
2018-10-16 16:37:27 +08:00
/* By stream, we do not support content-encoding for now,
* send body directly without compression */
2018-11-04 18:30:33 +08:00
if ( hf_private - > cv_compress_object ! = NULL )
2018-10-16 16:37:27 +08:00
{
hf_content_compress_destroy ( hf_private - > cv_compress_object ) ;
hf_private - > cv_compress_object = NULL ;
}
hf_private - > content_encoding = HTTP_ACCEPT_ENCODING_NONE ;
2018-10-26 20:30:06 +08:00
hf_private - > message_status = STATUS_READING ;
2018-10-16 10:45:18 +08:00
hf_private - > is_setup_by_stream = true ;
2018-10-22 21:22:59 +08:00
hs_private - > release_lock + + ;
2018-10-16 10:45:18 +08:00
}
hf_private - > evbuf_body = evbuffer_new ( ) ;
return 0 ;
}
int hf_ops_body_data ( struct tfe_http_half * half , const unsigned char * data , size_t sz_data )
{
struct http_half_private * hf_private = to_hf_private ( half ) ;
struct evbuffer * __tmp_output_buffer = evbuffer_new ( ) ;
int ret = 0 ;
/* Need to compress output */
if ( hf_private - > cv_compress_object )
{
ret = hf_content_compress_write ( hf_private - > cv_compress_object , data , sz_data , __tmp_output_buffer , 0 ) ;
}
else
{
ret = evbuffer_add ( __tmp_output_buffer , data , sz_data ) ;
}
if ( ret < 0 ) goto __out ;
ret = evbuffer_add_buffer ( hf_private - > evbuf_body , __tmp_output_buffer ) ;
/* Have write ctx, should write the body to TCP stream immediately but not to store in evbuf_body */
if ( hf_private - > write_ctx )
{
/* Perpare to write data, TODO: write to TCP stream by transfer evbuffer */
const unsigned char * ptr_write_data = evbuffer_pullup ( hf_private - > evbuf_body , - 1 ) ;
size_t sz_write_data = evbuffer_get_length ( hf_private - > evbuf_body ) ;
assert ( ptr_write_data ! = NULL & & sz_write_data > = 0 ) ;
tfe_stream_write_frag ( hf_private - > write_ctx , ptr_write_data , sz_write_data ) ;
/* Need to drain all data */
evbuffer_drain ( hf_private - > evbuf_body , sz_write_data ) ;
}
__out :
evbuffer_free ( __tmp_output_buffer ) ;
return ret ;
}
int hf_ops_body_end ( struct tfe_http_half * half )
{
struct http_half_private * hf_private = to_hf_private ( half ) ;
2018-10-22 21:22:59 +08:00
struct http_session_private * hs_private = hf_private - > session ;
2018-10-16 10:45:18 +08:00
if ( hf_private - > write_ctx )
{
tfe_stream_write_frag_end ( hf_private - > write_ctx ) ;
hf_private - > write_ctx = NULL ;
}
hf_private - > body_status = STATUS_COMPLETE ;
hf_private - > message_status = STATUS_COMPLETE ;
2018-10-16 20:01:25 +08:00
2018-11-04 18:30:33 +08:00
if ( hf_private - > is_setup_by_stream )
2018-10-22 21:22:59 +08:00
{
2018-10-26 20:30:06 +08:00
hs_private - > release_lock - - ;
2018-10-22 21:22:59 +08:00
}
2018-10-16 10:45:18 +08:00
return 0 ;
}
2018-09-12 15:29:35 +08:00
void hf_private_destory ( struct http_half_private * hf_private )
{
2018-09-17 15:44:44 +08:00
if ( hf_private - > parse_object ! = NULL )
{
free ( hf_private - > parse_object ) ;
2018-11-14 15:55:51 +08:00
hf_private - > parse_object = NULL ;
}
struct http_header_private * header_iter = NULL ;
struct http_header_private * header_titer = NULL ;
TAILQ_FOREACH_SAFE ( header_iter , & hf_private - > header_list , next , header_titer )
{
TAILQ_REMOVE ( & hf_private - > header_list , header_iter , next ) ;
2018-11-29 16:24:45 +08:00
http_field_name_destory ( header_iter - > field ) ;
2018-11-14 15:55:51 +08:00
free ( header_iter - > value ) ;
free ( header_iter ) ;
2018-09-17 15:44:44 +08:00
}
if ( hf_private - > event_cb_user_deleter ! = NULL )
{
hf_private - > event_cb_user_deleter ( hf_private - > event_cb_user ) ;
}
2018-11-14 15:55:51 +08:00
if ( hf_private - > evbuf_uri ! = NULL )
{
evbuffer_free ( hf_private - > evbuf_uri ) ;
hf_private - > evbuf_uri = NULL ;
}
if ( hf_private - > url_storage )
{
free ( hf_private - > url_storage ) ;
hf_private - > url_storage = NULL ;
}
if ( hf_private - > cv_uncompress_object )
{
hf_content_uncompress_destroy ( hf_private - > cv_uncompress_object ) ;
hf_private - > cv_uncompress_object = NULL ;
}
if ( hf_private - > cv_compress_object )
{
hf_content_compress_destroy ( hf_private - > cv_compress_object ) ;
hf_private - > cv_compress_object = NULL ;
}
if ( hf_private - > evbuf_header_field )
{
evbuffer_free ( hf_private - > evbuf_header_field ) ;
hf_private - > evbuf_header_field = NULL ;
}
if ( hf_private - > evbuf_header_value )
{
evbuffer_free ( hf_private - > evbuf_header_value ) ;
hf_private - > evbuf_header_value = NULL ;
}
if ( hf_private - > evbuf_body )
{
evbuffer_free ( hf_private - > evbuf_body ) ;
hf_private - > evbuf_body = NULL ;
}
if ( hf_private - > evbuf_raw )
{
evbuffer_free ( hf_private - > evbuf_raw ) ;
hf_private - > evbuf_raw = NULL ;
}
2018-09-12 15:29:35 +08:00
free ( hf_private ) ;
}
void hf_ops_free ( struct tfe_http_half * half )
{
return hf_private_destory ( to_hf_private ( half ) ) ;
}
struct tfe_http_half_ops __http_half_ops =
2018-09-25 10:17:50 +08:00
{
. ops_http_field_read = hf_ops_field_read ,
. ops_http_field_write = hf_ops_field_write ,
. ops_http_allow_write = hf_ops_allow_write ,
. ops_http_field_iterate = hf_ops_field_iterate ,
. ops_append_body = hf_ops_append_body ,
2018-10-16 16:37:27 +08:00
. ops_body_begin = hf_ops_body_begin ,
. ops_body_data = hf_ops_body_data ,
. ops_body_end = hf_ops_body_end ,
2018-09-25 10:17:50 +08:00
. ops_free = hf_ops_free
} ;
2018-09-12 15:29:35 +08:00
2018-09-06 10:12:08 +08:00
struct http_half_private * hf_private_create ( tfe_http_direction ht_dir , short major , short minor )
{
struct http_half_private * hf_private = ALLOC ( struct http_half_private , 1 ) ;
assert ( hf_private ! = NULL & & ( major = = 0 | | major = = 1 ) & & ( minor = = 0 | | minor = = 1 ) ) ;
assert ( ht_dir = = TFE_HTTP_REQUEST | | ht_dir = = TFE_HTTP_RESPONSE ) ;
/* PUBLIC */
2018-09-26 16:00:28 +08:00
hf_private - > hf_public . major_version = major ;
hf_private - > hf_public . minor_version = minor ;
2018-09-06 10:12:08 +08:00
hf_private - > hf_public . direction = ht_dir ;
2018-09-12 15:29:35 +08:00
hf_private - > hf_public . ops = & __http_half_ops ;
2018-09-06 10:12:08 +08:00
/* PRIVATE */
2018-11-29 19:02:07 +08:00
hf_private - > parse_object = ALLOC ( struct http_parser , 1 ) ;
2018-09-06 10:12:08 +08:00
assert ( hf_private - > parse_object ! = NULL ) ;
if ( ht_dir = = TFE_HTTP_REQUEST )
{
http_parser_init ( hf_private - > parse_object , HTTP_REQUEST ) ;
}
else
{
http_parser_init ( hf_private - > parse_object , HTTP_RESPONSE ) ;
}
hf_private - > parse_settings = & __http_half_parse_setting ;
hf_private - > parse_object - > data = hf_private ;
2018-09-26 16:00:28 +08:00
hf_private - > major = major ;
hf_private - > minor = minor ;
2018-09-18 18:50:25 +08:00
TAILQ_INIT ( & hf_private - > header_list ) ;
2018-09-06 10:12:08 +08:00
return hf_private ;
}
2018-09-17 15:44:44 +08:00
void hf_private_set_callback ( struct http_half_private * hf_private , hf_private_cb * cb ,
void * user , void ( * user_deleter ) ( void * ) )
{
hf_private - > event_cb = cb ;
hf_private - > event_cb_user = user ;
hf_private - > event_cb_user_deleter = user_deleter ;
}
2018-09-18 18:50:25 +08:00
void hf_private_set_session ( struct http_half_private * hf_private , struct http_session_private * hs_private )
{
hf_private - > session = hs_private ;
}
2018-09-06 10:12:08 +08:00
int hf_private_parse ( struct http_half_private * hf_private , const unsigned char * data , size_t len )
{
assert ( hf_private - > parse_cursor < = len ) ;
/* Caculate the memory zones to scan. The zone from data to data + cursor has been scaned
* at last construct procedure , so we don ' t need to scan again . */
const char * __data_with_offset = ( const char * ) TFE_PTR_ADD ( data , hf_private - > parse_cursor ) ;
size_t __len_with_offset = len - hf_private - > parse_cursor ;
/* Scan the memory zone */
size_t sz_parsed = http_parser_execute ( hf_private - > parse_object ,
& __http_half_parse_setting , __data_with_offset , __len_with_offset ) ;
2018-10-11 10:41:27 +08:00
bool __is_paused = false ;
if ( HTTP_PARSER_ERRNO ( hf_private - > parse_object ) = = HPE_PAUSED )
{
http_parser_pause ( hf_private - > parse_object , 0 ) ;
__is_paused = true ;
}
2018-10-24 15:40:26 +08:00
if ( hf_private - > parse_object - > upgrade )
{
hf_private - > is_upgrade = true ;
}
2018-09-27 15:12:18 +08:00
if ( sz_parsed = = __len_with_offset )
2018-09-06 10:12:08 +08:00
{
2018-09-12 15:29:35 +08:00
hf_private - > parse_cursor + = sz_parsed ;
2018-10-11 10:41:27 +08:00
return __is_paused ? 1 : 0 ;
2018-09-07 17:27:23 +08:00
}
2018-09-17 15:44:44 +08:00
/* The paused parsar indicate the message boundary has been touched, we should return.
* resume it to normal status */
2018-10-11 10:41:27 +08:00
if ( __is_paused )
2018-09-06 10:12:08 +08:00
{
2018-10-26 20:30:06 +08:00
hf_private - > parse_cursor + = sz_parsed ;
2018-09-17 15:44:44 +08:00
return 1 ;
2018-09-06 10:12:08 +08:00
}
2018-09-17 15:44:44 +08:00
hf_private - > parse_errno = HTTP_PARSER_ERRNO ( hf_private - > parse_object ) ;
2018-09-27 15:12:18 +08:00
assert ( hf_private - > parse_errno ! = HPE_OK ) ;
2018-09-17 15:44:44 +08:00
return - 1 ;
}
static struct tfe_http_session * hs_ops_allow_write ( const struct tfe_http_session * session )
{
2018-09-25 10:17:50 +08:00
struct http_session_private * hs_private = to_hs_private ( ( struct tfe_http_session * ) session ) ;
return http_frame_currect_plugin_preempt ( hs_private - > ht_frame ) = = 0 ? ( struct tfe_http_session * ) session : NULL ;
2018-09-17 15:44:44 +08:00
}
void hs_ops_detach ( const struct tfe_http_session * session )
{
2018-09-25 10:17:50 +08:00
struct http_session_private * hs_private = to_hs_private ( ( struct tfe_http_session * ) session ) ;
2018-09-17 15:44:44 +08:00
return http_frame_currect_plugin_detach ( hs_private - > ht_frame ) ;
}
void hs_ops_drop ( struct tfe_http_session * session )
2018-10-11 10:41:27 +08:00
{ }
2018-12-09 21:20:24 +06:00
void hs_ops_kill ( struct tfe_http_session * session )
{
struct http_session_private * hs_private = to_hs_private ( ( struct tfe_http_session * ) session ) ;
hs_private - > kill_signal = true ;
}
2018-10-11 10:41:27 +08:00
void hs_ops_suspend ( struct tfe_http_session * session )
2018-09-17 15:44:44 +08:00
{
2018-10-11 10:41:27 +08:00
struct http_session_private * hs_private = to_hs_private ( session ) ;
2018-10-28 20:13:17 +08:00
hs_private - > suspend_tag_signal = true ;
2018-10-11 10:41:27 +08:00
}
void hs_ops_resume ( struct tfe_http_session * session )
{
struct http_session_private * hs_private = to_hs_private ( session ) ;
2018-10-14 20:29:52 +08:00
struct http_connection_private * hc_private = hs_private - > hc_private ;
2018-10-26 20:30:06 +08:00
if ( hs_private - > suspend_tag_effective )
{
tfe_stream_resume ( hc_private - > stream ) ;
2018-10-28 20:13:17 +08:00
hs_private - > resume_tag_singal = true ;
2018-10-26 20:30:06 +08:00
}
2018-09-17 15:44:44 +08:00
}
2018-09-25 20:32:24 +08:00
// TODO: change the return type to int, there is something happend where -1 returned.
void hs_ops_request_set ( struct tfe_http_session * session , struct tfe_http_half * req_user )
2018-09-17 15:44:44 +08:00
{
2018-09-25 10:17:50 +08:00
struct http_session_private * hs_private = to_hs_private ( session ) ;
2018-09-25 20:32:24 +08:00
struct http_half_private * hf_in_private = to_hf_request_private ( hs_private ) ;
struct http_half_private * hf_user_private = to_hf_private ( req_user ) ;
2018-09-25 10:17:50 +08:00
2018-09-25 20:32:24 +08:00
if ( hf_in_private ! = NULL )
{
if ( hf_in_private - > stream_action = = ACTION_DEFER_DATA )
{
hf_in_private - > user_stream_action = ACTION_DROP_DATA ;
hf_in_private - > is_user_stream_action_set = true ;
}
else
{
assert ( 0 ) ;
}
}
assert ( hs_private - > hf_private_req_user = = NULL ) ;
hs_private - > hf_private_req_user = hf_user_private ;
2018-10-26 20:30:06 +08:00
hs_private - > hf_private_req_user - > session = hs_private ;
2018-09-17 15:44:44 +08:00
}
void hs_ops_response_set ( struct tfe_http_session * session , struct tfe_http_half * resp )
{
2018-09-25 10:17:50 +08:00
struct http_half_private * hf_private = to_hf_private ( resp ) ;
struct http_session_private * hs_private = to_hs_private ( session ) ;
2018-10-18 16:20:22 +08:00
struct http_half_private * hf_in_req_private = to_hf_request_private ( hs_private ) ;
struct http_half_private * hf_in_resp_private = to_hf_response_private ( hs_private ) ;
2018-09-25 20:32:24 +08:00
2018-10-18 16:20:22 +08:00
/* Call at request's callback, early response */
2018-11-04 18:30:33 +08:00
if ( hf_in_req_private ! = NULL & & hf_in_resp_private = = NULL )
2018-09-25 20:32:24 +08:00
{
2018-10-18 16:20:22 +08:00
/* Drop the incoming request */
if ( hf_in_req_private - > stream_action = = ACTION_DEFER_DATA )
2018-09-25 20:32:24 +08:00
{
2018-10-18 16:20:22 +08:00
hf_in_req_private - > user_stream_action = ACTION_DROP_DATA ;
hf_in_req_private - > is_user_stream_action_set = true ;
2018-09-25 20:32:24 +08:00
}
2018-10-18 16:20:22 +08:00
}
/* Call at response's callback, replace incoming response */
if ( hf_in_req_private ! = NULL & & hf_in_resp_private ! = NULL )
{
if ( hf_in_resp_private - > stream_action = = ACTION_DEFER_DATA )
2018-09-25 20:32:24 +08:00
{
2018-10-18 16:20:22 +08:00
hf_in_resp_private - > user_stream_action = ACTION_DROP_DATA ;
hf_in_resp_private - > is_user_stream_action_set = true ;
2018-09-25 20:32:24 +08:00
}
}
2018-09-25 10:17:50 +08:00
assert ( hs_private - > hf_private_resp_user = = NULL ) ;
hs_private - > hf_private_resp_user = hf_private ;
2018-10-26 20:30:06 +08:00
hs_private - > hf_private_resp_user - > session = hs_private ;
2018-09-17 15:44:44 +08:00
}
struct tfe_http_half * hs_ops_request_create ( struct tfe_http_session * session ,
enum tfe_http_std_method method , const char * uri )
{
2018-09-25 10:17:50 +08:00
struct http_half_private * hf_req_private = hf_private_create ( TFE_HTTP_REQUEST ,
session - > major_version , session - > minor_version ) ;
hf_req_private - > method_or_status = method ;
hf_req_private - > url_storage = tfe_strdup ( uri ) ;
hf_req_private - > is_setup_by_user = true ;
return to_hf_public ( hf_req_private ) ;
2018-09-17 15:44:44 +08:00
}
struct tfe_http_half * hs_ops_response_create ( struct tfe_http_session * session , int resp_code )
{
2018-09-25 10:17:50 +08:00
struct http_half_private * hf_resp_private = hf_private_create ( TFE_HTTP_RESPONSE ,
session - > major_version , session - > minor_version ) ;
hf_resp_private - > method_or_status = resp_code ;
hf_resp_private - > is_setup_by_user = true ;
2018-09-28 15:43:02 +08:00
/* Inherit from request in currect session */
struct http_session_private * ss_private = to_hs_private ( session ) ;
struct http_half_private * hf_req_private = to_hf_request_private ( ss_private ) ;
/* we must send content in encode that client asked,
* but dont need to be accordance with upstream server ' s response */
unsigned int content_encoding = HTTP_ACCEPT_ENCODING_NONE ;
if ( hf_req_private ! = NULL )
{
hf_resp_private - > content_encoding = hf_req_private - > accept_content_encoding ;
content_encoding = hf_resp_private - > content_encoding ;
}
/* Create content compress content */
if ( content_encoding ! = HTTP_ACCEPT_ENCODING_NONE )
{
hf_resp_private - > cv_compress_object = hf_content_compress_create ( content_encoding ) ;
assert ( hf_resp_private - > cv_compress_object ! = NULL ) ;
}
2018-09-25 10:17:50 +08:00
return to_hf_public ( hf_resp_private ) ;
2018-09-17 15:44:44 +08:00
}
struct tfe_http_session_ops __http_session_ops =
2018-09-25 10:17:50 +08:00
{
. ops_allow_write = hs_ops_allow_write ,
. ops_detach = hs_ops_detach ,
. ops_drop = hs_ops_drop ,
2018-10-11 10:41:27 +08:00
. ops_suspend = hs_ops_suspend ,
. ops_resume = hs_ops_resume ,
2018-12-09 21:20:24 +06:00
. ops_kill = hs_ops_kill ,
2018-09-25 10:17:50 +08:00
. ops_request_set = hs_ops_request_set ,
. ops_response_set = hs_ops_response_set ,
. ops_request_create = hs_ops_request_create ,
. ops_response_create = hs_ops_response_create
} ;
void __construct_request_line ( struct http_half_private * hf_private )
2018-09-17 15:44:44 +08:00
{
2018-09-26 21:31:17 +08:00
enum tfe_http_std_method __std_method = ( enum tfe_http_std_method ) hf_private - > method_or_status ;
2018-09-25 20:32:24 +08:00
const char * __str_method = http_std_method_to_string ( __std_method ) ;
if ( __str_method = = NULL )
{
__str_method = " " ;
}
evbuffer_add_printf ( hf_private - > evbuf_raw , " %s %s HTTP/%d.%d \r \n " ,
__str_method , hf_private - > url_storage , hf_private - > major , hf_private - > minor ) ;
2018-09-25 10:17:50 +08:00
}
void __construct_response_line ( struct http_half_private * hf_private )
{
enum tfe_http_std_status __resp_code = ( enum tfe_http_std_status ) hf_private - > method_or_status ;
const char * __str_resp_code = http_std_status_to_string ( __resp_code ) ;
if ( __str_resp_code = = NULL )
{
__str_resp_code = " " ;
}
evbuffer_add_printf ( hf_private - > evbuf_raw , " HTTP/%d.%d %d %s \r \n " ,
hf_private - > major , hf_private - > minor , __resp_code , __str_resp_code ) ;
}
void hf_private_construct ( struct http_half_private * hf_private )
{
assert ( hf_private - > is_setup_by_user ) ;
struct tfe_http_half * hf_public = to_hf_public ( hf_private ) ;
/* Clear the output buffer */
if ( hf_private - > evbuf_raw = = NULL )
{
hf_private - > evbuf_raw = evbuffer_new ( ) ;
assert ( hf_private - > evbuf_raw ! = NULL ) ;
}
else
{
size_t __buf_length = evbuffer_get_length ( hf_private - > evbuf_raw ) ;
evbuffer_drain ( hf_private - > evbuf_raw , __buf_length ) ;
}
2018-09-28 16:43:24 +08:00
/* Terminal the end of gzip stream */
if ( hf_private - > evbuf_body & & hf_private - > cv_compress_object )
{
hf_content_compress_write ( hf_private - > cv_compress_object , NULL , 0 , hf_private - > evbuf_body , 1 ) ;
}
2019-01-10 15:48:22 +06:00
if ( hf_private - > evbuf_body & & hf_private - > content_encoding ! = HTTP_ACCEPT_ENCODING_NONE )
2018-09-28 16:43:24 +08:00
{
const char * __str_content_encoding = __hf_content_encoding_to_str ( hf_private - > content_encoding ) ;
const static struct http_field_name __cont_encoding_type_name = { TFE_HTTP_CONT_ENCODING , NULL } ;
2019-08-22 11:51:09 +08:00
/* Delete the origin encoding type, and add a new one */
tfe_http_field_write ( hf_public , & __cont_encoding_type_name , NULL ) ;
2018-09-28 16:43:24 +08:00
tfe_http_field_write ( hf_public , & __cont_encoding_type_name , __str_content_encoding ) ;
}
/* have body, write content-length and content-type */
2018-10-18 13:42:43 +08:00
if ( hf_private - > evbuf_body & & ! hf_private - > is_setup_by_stream )
2018-09-28 16:43:24 +08:00
{
/* To string */
char str_sz_evbuf_body [ TFE_STRING_MAX ] ;
snprintf ( str_sz_evbuf_body , sizeof ( str_sz_evbuf_body ) - 1 , " %lu " , evbuffer_get_length ( hf_private - > evbuf_body ) ) ;
const static struct http_field_name __cont_encoding_length_name = { TFE_HTTP_CONT_LENGTH , NULL } ;
2019-08-22 11:51:09 +08:00
tfe_http_field_write ( hf_public , & __cont_encoding_length_name , NULL ) ;
2018-09-28 16:43:24 +08:00
tfe_http_field_write ( hf_public , & __cont_encoding_length_name , str_sz_evbuf_body ) ;
2018-09-28 19:52:01 +08:00
/* If origin is chunked, now delete chunked tag */
const static struct http_field_name __cont_transfer_encoding_name = { TFE_HTTP_TRANSFER_ENCODING , NULL } ;
tfe_http_field_write ( hf_public , & __cont_transfer_encoding_name , NULL ) ;
2018-09-28 16:43:24 +08:00
}
2018-09-25 10:17:50 +08:00
/* HTTP Request/Response first line */
if ( hf_public - > direction = = TFE_HTTP_REQUEST ) __construct_request_line ( hf_private ) ;
else __construct_response_line ( hf_private ) ;
/* Headers */
void * iterator = NULL ;
struct http_field_name field_name { } ;
for ( const char * str_value = tfe_http_field_iterate ( hf_public , & iterator , & field_name ) ;
str_value ! = NULL ; str_value = tfe_http_field_iterate ( hf_public , & iterator , & field_name ) )
{
2018-11-29 16:24:45 +08:00
const char * str_field = http_field_name_to_string ( & field_name ) ;
2018-09-25 10:17:50 +08:00
evbuffer_add_printf ( hf_private - > evbuf_raw , " %s: %s \r \n " , str_field , str_value ) ;
}
2018-10-26 20:30:06 +08:00
/* Trace Tags */
evbuffer_add_printf ( hf_private - > evbuf_raw , " %s: tfe/%s \r \n " , " X-TG-Construct-By " , tfe_version ( ) ) ;
2018-09-25 10:17:50 +08:00
/* delimitor between header and body */
evbuffer_add_printf ( hf_private - > evbuf_raw , " \r \n " ) ;
2018-09-28 15:43:02 +08:00
2018-09-25 11:15:00 +08:00
/* add body */
if ( hf_private - > evbuf_body )
{
evbuffer_add_buffer ( hf_private - > evbuf_raw , hf_private - > evbuf_body ) ;
}
return ;
2018-09-25 10:17:50 +08:00
}
2018-09-17 15:44:44 +08:00
2018-10-22 21:22:59 +08:00
struct http_session_private * hs_private_create ( struct http_connection_private * hc_private , unsigned int thread_id ,
2018-11-04 18:30:33 +08:00
struct http_half_private * hf_private_req , struct http_half_private * hf_private_resp )
2018-09-17 15:44:44 +08:00
{
struct http_session_private * __hs_private = ALLOC ( struct http_session_private , 1 ) ;
2018-10-22 21:22:59 +08:00
__hs_private - > thread_id = thread_id ;
2018-09-17 15:44:44 +08:00
/* HS-PUBLIC */
__hs_private - > hs_public . ops = & __http_session_ops ;
__hs_private - > hs_public . req = hf_private_req ! = NULL ? to_hf_public ( hf_private_req ) : NULL ;
__hs_private - > hs_public . resp = hf_private_req ! = NULL ? to_hf_public ( hf_private_resp ) : NULL ;
__hs_private - > hs_public . session_id = hc_private - > session_id_counter + + ;
2022-09-09 10:44:11 +08:00
__hs_private - > hs_public . start_time = time ( NULL ) ;
2018-09-17 15:44:44 +08:00
/* HS-PRIVATE*/
__hs_private - > hc_private = hc_private ;
2018-11-04 18:30:33 +08:00
__hs_private - > str_stream_info = tfe_strdup ( hc_private - > stream - > str_stream_info ) ;
2018-09-17 15:44:44 +08:00
return __hs_private ;
}
2018-09-21 15:03:33 +08:00
void __write_access_log ( struct http_session_private * hs_private )
{
/* Prepare to write session access log */
/* Request */
struct http_half_private * request = to_hf_request_private ( hs_private ) ;
/* Response */
2018-09-23 17:33:05 +08:00
struct http_half_private * response = to_hf_response_private ( hs_private ) ;
2018-09-21 15:03:33 +08:00
/* Req-Public */
struct tfe_http_req_spec * req_spec = request ? & to_hf_public ( request ) - > req_spec : NULL ;
/* Resp-Public */
struct tfe_http_resp_spec * resp_spec = response ? & to_hf_public ( response ) - > resp_spec : NULL ;
/* Method */
const char * __str_method = req_spec ? http_std_method_to_string ( req_spec - > method ) : " - " ;
/* URL */
const char * __str_url = req_spec ? req_spec - > url : " - " ;
2018-09-23 17:33:05 +08:00
/* Resp code */
char __str_resp_code [ TFE_STRING_MAX ] ;
if ( resp_spec )
{
2018-09-25 10:17:50 +08:00
snprintf ( __str_resp_code , sizeof ( __str_resp_code ) - 1 , " %d " , resp_spec - > resp_code ) ;
2018-09-23 17:33:05 +08:00
}
else
{
2018-09-25 10:17:50 +08:00
snprintf ( __str_resp_code , sizeof ( __str_resp_code ) - 1 , " %s " , " - " ) ;
2018-09-23 17:33:05 +08:00
}
/* Content Type */
2018-10-24 20:53:29 +08:00
const char * __str_cont_type = resp_spec ? resp_spec - > content_type ! = NULL ? resp_spec - > content_type : " - " : " - " ;
2018-09-23 17:33:05 +08:00
/* Content Encoding */
2018-11-04 18:30:33 +08:00
const char * __str_cont_encoding =
resp_spec ? resp_spec - > content_encoding ! = NULL ? resp_spec - > content_encoding : " - " : " - " ;
2018-10-24 15:40:26 +08:00
/* Upgrade Tag */
2018-10-24 20:53:29 +08:00
const char * __str_upgrade = response ? response - > is_upgrade ? " UPGRADE " : " - " : " - " ;
2018-09-23 17:33:05 +08:00
2018-10-25 16:47:19 +08:00
/* PASSTHROUGH */
const char * __str_req_passthrough = request ? request - > is_passthrough ? " PASS-THROUGH/REQ " : " - " : " - " ;
const char * __str_resp_passthrough = response ? response - > is_passthrough ? " PASS-THROUGH/REP " : " - " : " - " ;
2018-10-28 20:13:17 +08:00
/* USER SETUP REQUEST/RESPONSE */
const char * __str_user_req = hs_private - > hf_private_req_user ? " USER/REQ " : " - " ;
const char * __str_user_resp = hs_private - > hf_private_resp_user ? " USER/RESP " : " - " ;
/* SUSPEND */
const char * __str_suspend = hs_private - > suspend_counter > 0 ? " SUSPEND " : " - " ;
2018-09-23 17:33:05 +08:00
char * __access_log ;
2018-11-04 18:30:33 +08:00
asprintf ( & __access_log , " %s %d %s %s HTTP/%d.%d %s %s %s %s %s %s %s %s %s " , hs_private - > str_stream_info ,
hs_private - > hs_public . session_id , __str_method , __str_url ,
request - > major , request - > minor , __str_resp_code , __str_cont_type , __str_cont_encoding ,
2018-10-28 20:13:17 +08:00
__str_upgrade , __str_req_passthrough , __str_resp_passthrough , __str_user_req , __str_user_resp , __str_suspend ) ;
2018-09-21 15:03:33 +08:00
2018-12-09 18:02:43 +06:00
TFE_LOG_INFO ( g_http_plugin - > logger , " %s " , __access_log ) ;
2018-09-23 17:33:05 +08:00
free ( __access_log ) ;
2018-09-21 15:03:33 +08:00
}
2018-10-22 21:22:59 +08:00
void hs_private_destroy ( struct http_session_private * hs_private )
2018-09-17 15:44:44 +08:00
{
2018-10-22 21:22:59 +08:00
struct http_half_private * hf_req = to_hf_request_private ( hs_private ) ;
struct http_half_private * hf_resp = to_hf_response_private ( hs_private ) ;
2018-09-21 15:03:33 +08:00
__write_access_log ( hs_private ) ;
2018-10-22 21:22:59 +08:00
if ( hf_req ! = NULL )
{
hf_private_destory ( hf_req ) ;
}
if ( hf_resp ! = NULL )
{
hf_private_destory ( hf_resp ) ;
}
2018-11-04 18:30:33 +08:00
if ( hs_private - > str_stream_info )
{
free ( hs_private - > str_stream_info ) ;
}
2018-10-22 21:22:59 +08:00
if ( hs_private - > hf_private_req_user )
{
2018-10-28 20:13:17 +08:00
assert ( hs_private - > hf_private_req_user - > message_status = = STATUS_COMPLETE ) ;
2018-10-22 21:22:59 +08:00
hf_private_destory ( hs_private - > hf_private_req_user ) ;
}
if ( hs_private - > hf_private_resp_user )
{
2018-10-28 20:13:17 +08:00
assert ( hs_private - > hf_private_resp_user - > message_status = = STATUS_COMPLETE ) ;
2018-10-22 21:22:59 +08:00
hf_private_destory ( hs_private - > hf_private_resp_user ) ;
}
assert ( hs_private - > ht_frame = = NULL ) ;
2018-09-17 15:44:44 +08:00
free ( hs_private ) ;
2018-09-06 10:12:08 +08:00
}
2018-09-23 17:33:05 +08:00
2018-10-22 21:22:59 +08:00
void hs_private_gc_destroy ( struct http_session_private * hs_private , struct hs_private_list * gc_list )
{
2018-10-26 20:30:06 +08:00
if ( hs_private - > release_lock > 0 )
{
TAILQ_INSERT_TAIL ( gc_list , hs_private , next ) ;
2018-11-04 18:30:33 +08:00
hs_private - > hc_private = NULL ;
2018-10-26 20:30:06 +08:00
hs_private - > in_gc_queue = true ;
}
else
{
return hs_private_destroy ( hs_private ) ;
}
}
bool hs_private_can_destroy ( struct http_session_private * hs_private )
{
return hs_private - > release_lock < = 0 ;
2018-10-22 21:22:59 +08:00
}
2018-09-25 10:17:50 +08:00
void hs_private_hf_private_set ( struct http_session_private * hs_private ,
struct http_half_private * hf , enum tfe_http_direction direction )
2018-09-23 17:33:05 +08:00
{
struct tfe_http_half * * ref_old_half_public ;
struct http_half_private * old_half_private ;
if ( direction = = TFE_HTTP_REQUEST )
{
ref_old_half_public = & hs_private - > hs_public . req ;
old_half_private = to_hf_private ( * ref_old_half_public ) ;
}
else
{
ref_old_half_public = & hs_private - > hs_public . resp ;
old_half_private = to_hf_private ( * ref_old_half_public ) ;
}
if ( old_half_private ! = NULL )
{
hf_private_destory ( old_half_private ) ;
* ref_old_half_public = to_hf_public ( hf ) ;
}
else
{
* ref_old_half_public = to_hf_public ( hf ) ;
}
return ;
}
struct http_half_private * hs_private_hf_private_release ( struct http_session_private * hs_private ,
enum tfe_http_direction )
{
return nullptr ;
}