http: pass timeout using extended config
App can now pass http connection timeout using extended configuration, ext cfg type TRANSPORT_ENDPT_EXT_CFG_HTTP, value (in seconds) set in ext cfg member opaque. It is optional, default value is 60 seconds. Type: improvement Change-Id: Ibeff4bbd3153421be350ff564ec3c8e52e5b9639 Signed-off-by: Matus Fabian <matfabia@cisco.com>
This commit is contained in:

committed by
Florin Coras

parent
dced40dcac
commit
841672258a
@ -32,7 +32,7 @@ func init() {
|
||||
HttpInvalidContentLengthTest, HttpInvalidTargetSyntaxTest, HttpStaticPathTraversalTest, HttpUriDecodeTest,
|
||||
HttpHeadersTest, HttpStaticFileHandlerTest, HttpStaticFileHandlerDefaultMaxAgeTest, HttpClientTest, HttpClientErrRespTest, HttpClientPostFormTest,
|
||||
HttpClientPostFileTest, HttpClientPostFilePtrTest, AuthorityFormTargetTest, HttpRequestLineTest,
|
||||
HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest)
|
||||
HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest, HttpConnTimeoutTest)
|
||||
RegisterNoTopoSoloTests(HttpStaticPromTest, HttpGetTpsTest, HttpGetTpsInterruptModeTest, PromConcurrentConnectionsTest,
|
||||
PromMemLeakTest, HttpClientPostMemLeakTest, HttpInvalidClientRequestMemLeakTest, HttpPostTpsTest, HttpPostTpsInterruptModeTest,
|
||||
PromConsecutiveConnectionsTest)
|
||||
@ -804,10 +804,10 @@ func HttpCliBadRequestTest(s *NoTopoSuite) {
|
||||
func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) {
|
||||
vpp := s.GetContainerByName("vpp").VppInstance
|
||||
serverAddress := s.VppAddr()
|
||||
s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
|
||||
s.Log(vpp.Vppctl("http static server uri tls://" + serverAddress + "/80 url-handlers debug"))
|
||||
|
||||
client := NewHttpClient(defaultHttpTimeout)
|
||||
req, err := http.NewRequest("GET", "http://"+serverAddress+":80/version.json", nil)
|
||||
req, err := http.NewRequest("GET", "https://"+serverAddress+":80/version.json", nil)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
resp, err := client.Do(req)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
@ -1205,3 +1205,33 @@ func HeaderServerTest(s *NoTopoSuite) {
|
||||
s.AssertHttpHeaderWithValue(resp, "Server", "http_cli_server")
|
||||
s.AssertHttpHeaderWithValue(resp, "Content-Type", "text/html")
|
||||
}
|
||||
|
||||
func HttpConnTimeoutTest(s *NoTopoSuite) {
|
||||
vpp := s.GetContainerByName("vpp").VppInstance
|
||||
serverAddress := s.VppAddr()
|
||||
s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug keepalive-timeout 2"))
|
||||
|
||||
req := "GET /version.json HTTP/1.1\r\nHost:" + serverAddress + ":80\r\nUser-Agent:test\r\n\r\n"
|
||||
conn, err := net.DialTimeout("tcp", serverAddress+":80", time.Second*30)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
defer conn.Close()
|
||||
err = conn.SetDeadline(time.Now().Add(time.Second * 30))
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
_, err = conn.Write([]byte(req))
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
reply := make([]byte, 1024)
|
||||
_, err = conn.Read(reply)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
s.AssertContains(string(reply), "HTTP/1.1 200 OK")
|
||||
s.Log(vpp.Vppctl("show session verbose 2"))
|
||||
|
||||
s.Log("waiting for close on the server side")
|
||||
time.Sleep(time.Second * 5)
|
||||
s.Log(vpp.Vppctl("show session verbose 2"))
|
||||
|
||||
_, err = conn.Write([]byte(req))
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
reply = make([]byte, 1024)
|
||||
_, err = conn.Read(reply)
|
||||
s.AssertMatchError(err, io.EOF, "connection not closed by server")
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hst
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -90,6 +91,7 @@ func NewHttpClient(timeout time.Duration) *http.Client {
|
||||
transport := http.DefaultTransport
|
||||
transport.(*http.Transport).Proxy = nil
|
||||
transport.(*http.Transport).DisableKeepAlives = true
|
||||
transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: timeout,
|
||||
|
@ -380,6 +380,7 @@ hcc_connect ()
|
||||
hcc_main_t *hcm = &hcc_main;
|
||||
hcc_worker_t *wrk;
|
||||
hcc_session_t *hs;
|
||||
transport_endpt_ext_cfg_t *ext_cfg;
|
||||
|
||||
vec_validate (a, 0);
|
||||
clib_memset (a, 0, sizeof (a[0]));
|
||||
@ -387,6 +388,11 @@ hcc_connect ()
|
||||
clib_memcpy (&a->sep_ext, &hcm->connect_sep, sizeof (hcm->connect_sep));
|
||||
a->app_index = hcm->app_index;
|
||||
|
||||
/* set http (response) timeout to 10 seconds */
|
||||
ext_cfg = session_endpoint_add_ext_cfg (
|
||||
&a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_HTTP, sizeof (ext_cfg->opaque));
|
||||
ext_cfg->opaque = 10;
|
||||
|
||||
/* allocate http session on main thread */
|
||||
wrk = hcc_worker_get (0);
|
||||
hs = hcc_session_alloc (wrk);
|
||||
|
@ -158,6 +158,7 @@ http_ho_conn_alloc (void)
|
||||
hc->h_hc_index = hc - hm->ho_conn_pool;
|
||||
hc->h_pa_session_handle = SESSION_INVALID_HANDLE;
|
||||
hc->h_tc_session_handle = SESSION_INVALID_HANDLE;
|
||||
hc->timeout = HTTP_CONN_TIMEOUT;
|
||||
return hc->h_hc_index;
|
||||
}
|
||||
|
||||
@ -169,6 +170,7 @@ http_listener_alloc (void)
|
||||
|
||||
pool_get_zero (hm->listener_pool, lhc);
|
||||
lhc->c_c_index = lhc - hm->listener_pool;
|
||||
lhc->timeout = HTTP_CONN_TIMEOUT;
|
||||
return lhc->c_c_index;
|
||||
}
|
||||
|
||||
@ -1821,6 +1823,7 @@ http_transport_connect (transport_endpoint_cfg_t *tep)
|
||||
int error;
|
||||
u32 hc_index;
|
||||
session_t *ho;
|
||||
transport_endpt_ext_cfg_t *ext_cfg;
|
||||
app_worker_t *app_wrk = app_worker_get (sep->app_wrk_index);
|
||||
|
||||
clib_memset (cargs, 0, sizeof (*cargs));
|
||||
@ -1837,6 +1840,13 @@ http_transport_connect (transport_endpoint_cfg_t *tep)
|
||||
hc->state = HTTP_CONN_STATE_CONNECTING;
|
||||
cargs->api_context = hc_index;
|
||||
|
||||
ext_cfg = session_endpoint_get_ext_cfg (sep, TRANSPORT_ENDPT_EXT_CFG_HTTP);
|
||||
if (ext_cfg)
|
||||
{
|
||||
HTTP_DBG (1, "app set timeout %u", ext_cfg->opaque);
|
||||
hc->timeout = ext_cfg->opaque;
|
||||
}
|
||||
|
||||
hc->is_server = 0;
|
||||
|
||||
if (vec_len (app->name))
|
||||
@ -1894,7 +1904,10 @@ http_start_listen (u32 app_listener_index, transport_endpoint_cfg_t *tep)
|
||||
|
||||
ext_cfg = session_endpoint_get_ext_cfg (sep, TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
|
||||
if (ext_cfg)
|
||||
tp = TRANSPORT_PROTO_TLS;
|
||||
{
|
||||
HTTP_DBG (1, "app set tls");
|
||||
tp = TRANSPORT_PROTO_TLS;
|
||||
}
|
||||
args->sep_ext.transport_proto = tp;
|
||||
|
||||
if (vnet_listen (args))
|
||||
@ -1903,6 +1916,13 @@ http_start_listen (u32 app_listener_index, transport_endpoint_cfg_t *tep)
|
||||
lhc_index = http_listener_alloc ();
|
||||
lhc = http_listener_get (lhc_index);
|
||||
|
||||
ext_cfg = session_endpoint_get_ext_cfg (sep, TRANSPORT_ENDPT_EXT_CFG_HTTP);
|
||||
if (ext_cfg)
|
||||
{
|
||||
HTTP_DBG (1, "app set timeout %u", ext_cfg->opaque);
|
||||
lhc->timeout = ext_cfg->opaque;
|
||||
}
|
||||
|
||||
/* Grab transport connection listener and link to http listener */
|
||||
lhc->h_tc_session_handle = args->handle;
|
||||
al = app_listener_get_w_handle (lhc->h_tc_session_handle);
|
||||
|
@ -388,6 +388,7 @@ typedef struct http_tc_
|
||||
|
||||
http_conn_state_t state;
|
||||
u32 timer_handle;
|
||||
u32 timeout;
|
||||
u8 pending_timer;
|
||||
u8 *app_name;
|
||||
u8 *host;
|
||||
|
@ -43,15 +43,13 @@ http_conn_timer_start (http_conn_t *hc)
|
||||
{
|
||||
http_tw_ctx_t *twc = &http_tw_ctx;
|
||||
u32 hs_handle;
|
||||
u64 timeout;
|
||||
|
||||
ASSERT (hc->timer_handle == HTTP_TIMER_HANDLE_INVALID);
|
||||
timeout = HTTP_CONN_TIMEOUT;
|
||||
hs_handle = hc->c_thread_index << 24 | hc->c_c_index;
|
||||
|
||||
clib_spinlock_lock (&twc->tw_lock);
|
||||
hc->timer_handle =
|
||||
tw_timer_start_2t_1w_2048sl (&twc->tw, hs_handle, 0, timeout);
|
||||
tw_timer_start_2t_1w_2048sl (&twc->tw, hs_handle, 0, hc->timeout);
|
||||
clib_spinlock_unlock (&twc->tw_lock);
|
||||
}
|
||||
|
||||
@ -74,19 +72,16 @@ static inline void
|
||||
http_conn_timer_update (http_conn_t *hc)
|
||||
{
|
||||
http_tw_ctx_t *twc = &http_tw_ctx;
|
||||
u64 timeout;
|
||||
u32 hs_handle;
|
||||
|
||||
timeout = HTTP_CONN_TIMEOUT;
|
||||
|
||||
clib_spinlock_lock (&twc->tw_lock);
|
||||
if (hc->timer_handle != HTTP_TIMER_HANDLE_INVALID)
|
||||
tw_timer_update_2t_1w_2048sl (&twc->tw, hc->timer_handle, timeout);
|
||||
tw_timer_update_2t_1w_2048sl (&twc->tw, hc->timer_handle, hc->timeout);
|
||||
else
|
||||
{
|
||||
hs_handle = hc->c_thread_index << 24 | hc->c_c_index;
|
||||
hc->timer_handle =
|
||||
tw_timer_start_2t_1w_2048sl (&twc->tw, hs_handle, 0, timeout);
|
||||
tw_timer_start_2t_1w_2048sl (&twc->tw, hs_handle, 0, hc->timeout);
|
||||
}
|
||||
clib_spinlock_unlock (&twc->tw_lock);
|
||||
}
|
||||
|
@ -162,6 +162,8 @@ typedef struct
|
||||
u32 max_age;
|
||||
/** Formatted max_age: "max-age=xyz" */
|
||||
u8 *max_age_formatted;
|
||||
/** Timeout during which client connection will stay open */
|
||||
u32 keepalive_timeout;
|
||||
|
||||
/** hash table of file extensions to mime types string indices */
|
||||
uword *mime_type_indices_by_file_extensions;
|
||||
|
@ -804,6 +804,7 @@ hss_listen (void)
|
||||
vnet_listen_args_t _a, *a = &_a;
|
||||
char *uri = "tcp://0.0.0.0/80";
|
||||
u8 need_crypto;
|
||||
transport_endpt_ext_cfg_t *ext_cfg;
|
||||
int rv;
|
||||
|
||||
clib_memset (a, 0, sizeof (*a));
|
||||
@ -820,9 +821,13 @@ hss_listen (void)
|
||||
sep.transport_proto = TRANSPORT_PROTO_HTTP;
|
||||
clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
|
||||
|
||||
ext_cfg = session_endpoint_add_ext_cfg (
|
||||
&a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_HTTP, sizeof (ext_cfg->opaque));
|
||||
ext_cfg->opaque = hsm->keepalive_timeout;
|
||||
|
||||
if (need_crypto)
|
||||
{
|
||||
transport_endpt_ext_cfg_t *ext_cfg = session_endpoint_add_ext_cfg (
|
||||
ext_cfg = session_endpoint_add_ext_cfg (
|
||||
&a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_CRYPTO,
|
||||
sizeof (transport_endpt_crypto_cfg_t));
|
||||
ext_cfg->crypto.ckpair_index = hsm->ckpair_index;
|
||||
@ -898,6 +903,7 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||
hsm->fifo_size = 0;
|
||||
hsm->cache_size = 10 << 20;
|
||||
hsm->max_age = HSS_DEFAULT_MAX_AGE;
|
||||
hsm->keepalive_timeout = 60;
|
||||
|
||||
/* Get a line of input. */
|
||||
if (!unformat_user (input, unformat_line_input, line_input))
|
||||
@ -922,6 +928,9 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||
;
|
||||
else if (unformat (line_input, "debug %d", &hsm->debug_level))
|
||||
;
|
||||
else if (unformat (line_input, "keepalive-timeout %d",
|
||||
&hsm->keepalive_timeout))
|
||||
;
|
||||
else if (unformat (line_input, "debug"))
|
||||
hsm->debug_level = 1;
|
||||
else if (unformat (line_input, "ptr-thresh %U", unformat_memory_size,
|
||||
@ -985,14 +994,16 @@ done:
|
||||
* http static server www-root /tmp/www uri tcp://0.0.0.0/80 cache-size 2m
|
||||
* @cliend
|
||||
* @cliexcmd{http static server www-root <path> [prealloc-fios <nn>]
|
||||
* [private-segment-size <nnMG>] [fifo-size <nbytes>] [uri <uri>]}
|
||||
* [private-segment-size <nnMG>] [fifo-size <nbytes>] [uri <uri>]
|
||||
* [keepalive-timeout <nn>]}
|
||||
?*/
|
||||
VLIB_CLI_COMMAND (hss_create_command, static) = {
|
||||
.path = "http static server",
|
||||
.short_help =
|
||||
"http static server www-root <path> [prealloc-fifos <nn>]\n"
|
||||
"[private-segment-size <nnMG>] [fifo-size <nbytes>] [max-age <nseconds>]\n"
|
||||
"[uri <uri>] [ptr-thresh <nn>] [url-handlers] [debug [nn]]\n",
|
||||
"[uri <uri>] [ptr-thresh <nn>] [url-handlers] [debug [nn]]\n"
|
||||
"[keepalive-timeout <nn>]\n",
|
||||
.function = hss_create_command_fn,
|
||||
};
|
||||
|
||||
|
@ -2389,6 +2389,50 @@ session_test_sdl (vlib_main_t *vm, unformat_input_t *input)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
session_test_ext_cfg (vlib_main_t *vm, unformat_input_t *input)
|
||||
{
|
||||
session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
|
||||
transport_endpt_ext_cfg_t *ext_cfg;
|
||||
|
||||
ext_cfg = session_endpoint_add_ext_cfg (&sep, TRANSPORT_ENDPT_EXT_CFG_HTTP,
|
||||
sizeof (ext_cfg->opaque));
|
||||
ext_cfg->opaque = 60;
|
||||
|
||||
ext_cfg =
|
||||
session_endpoint_add_ext_cfg (&sep, TRANSPORT_ENDPT_EXT_CFG_CRYPTO,
|
||||
sizeof (transport_endpt_crypto_cfg_t));
|
||||
ext_cfg->crypto.ckpair_index = 1;
|
||||
|
||||
ext_cfg = session_endpoint_add_ext_cfg (&sep, TRANSPORT_ENDPT_EXT_CFG_NONE,
|
||||
sizeof (ext_cfg->opaque));
|
||||
ext_cfg->opaque = 345;
|
||||
|
||||
ext_cfg = session_endpoint_get_ext_cfg (&sep, TRANSPORT_ENDPT_EXT_CFG_HTTP);
|
||||
SESSION_TEST ((ext_cfg != 0),
|
||||
"TRANSPORT_ENDPT_EXT_CFG_HTTP should be present");
|
||||
SESSION_TEST ((ext_cfg->opaque == 60),
|
||||
"TRANSPORT_ENDPT_EXT_CFG_HTTP opaque value should be 60: %u",
|
||||
ext_cfg->opaque);
|
||||
ext_cfg =
|
||||
session_endpoint_get_ext_cfg (&sep, TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
|
||||
SESSION_TEST ((ext_cfg != 0),
|
||||
"TRANSPORT_ENDPT_EXT_CFG_CRYPTO should be present");
|
||||
SESSION_TEST (
|
||||
(ext_cfg->crypto.ckpair_index == 1),
|
||||
"TRANSPORT_ENDPT_EXT_CFG_HTTP ckpair_index value should be 1: %u",
|
||||
ext_cfg->crypto.ckpair_index);
|
||||
ext_cfg = session_endpoint_get_ext_cfg (&sep, TRANSPORT_ENDPT_EXT_CFG_NONE);
|
||||
SESSION_TEST ((ext_cfg != 0),
|
||||
"TRANSPORT_ENDPT_EXT_CFG_NONE should be present");
|
||||
SESSION_TEST ((ext_cfg->opaque == 345),
|
||||
"TRANSPORT_ENDPT_EXT_CFG_HTTP opaque value should be 345: %u",
|
||||
ext_cfg->opaque);
|
||||
session_endpoint_free_ext_cfgs (&sep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
session_test (vlib_main_t * vm,
|
||||
unformat_input_t * input, vlib_cli_command_t * cmd_arg)
|
||||
@ -2419,6 +2463,8 @@ session_test (vlib_main_t * vm,
|
||||
res = session_test_enable_disable (vm, input);
|
||||
else if (unformat (input, "sdl"))
|
||||
res = session_test_sdl (vm, input);
|
||||
else if (unformat (input, "ext-cfg"))
|
||||
res = session_test_ext_cfg (vm, input);
|
||||
else if (unformat (input, "all"))
|
||||
{
|
||||
if ((res = session_test_basic (vm, input)))
|
||||
@ -2439,6 +2485,8 @@ session_test (vlib_main_t * vm,
|
||||
goto done;
|
||||
if ((res = session_test_sdl (vm, input)))
|
||||
goto done;
|
||||
if ((res = session_test_ext_cfg (vm, input)))
|
||||
goto done;
|
||||
if ((res = session_test_enable_disable (vm, input)))
|
||||
goto done;
|
||||
}
|
||||
|
@ -953,9 +953,7 @@ session_endpoint_get_ext_cfg (session_endpoint_cfg_t *sep_ext,
|
||||
{
|
||||
if (ext_cfg->type == type)
|
||||
return ext_cfg;
|
||||
ext_cfg =
|
||||
(transport_endpt_ext_cfg_t *) (sep_ext->ext_cfgs.data + ext_cfg->len +
|
||||
TRANSPORT_ENDPT_EXT_CFG_HEADER_SIZE);
|
||||
ext_cfg = (transport_endpt_ext_cfg_t *) (ext_cfg->data + ext_cfg->len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -284,6 +284,7 @@ typedef enum transport_endpt_ext_cfg_type_
|
||||
{
|
||||
TRANSPORT_ENDPT_EXT_CFG_NONE,
|
||||
TRANSPORT_ENDPT_EXT_CFG_CRYPTO,
|
||||
TRANSPORT_ENDPT_EXT_CFG_HTTP,
|
||||
} transport_endpt_ext_cfg_type_t;
|
||||
|
||||
typedef struct transport_endpt_crypto_cfg_
|
||||
|
Reference in New Issue
Block a user