Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nghttp2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
nghttp2
Commits
03b32d92
Commit
03b32d92
authored
Sep 18, 2015
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'LPardue-h2load-http1_a'
parents
1c2fcc2a
604732b6
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
503 additions
and
137 deletions
+503
-137
src/Makefile.am
src/Makefile.am
+2
-1
src/h2load.cc
src/h2load.cc
+139
-49
src/h2load.h
src/h2load.h
+15
-1
src/h2load_http1_session.cc
src/h2load_http1_session.cc
+181
-0
src/h2load_http1_session.h
src/h2load_http1_session.h
+58
-0
src/shrpx-unittest.cc
src/shrpx-unittest.cc
+2
-2
src/shrpx.cc
src/shrpx.cc
+2
-2
src/shrpx_config.cc
src/shrpx_config.cc
+4
-35
src/shrpx_config.h
src/shrpx_config.h
+0
-14
src/shrpx_config_test.cc
src/shrpx_config_test.cc
+0
-28
src/shrpx_config_test.h
src/shrpx_config_test.h
+0
-1
src/util.cc
src/util.cc
+48
-4
src/util.h
src/util.h
+23
-0
src/util_test.cc
src/util_test.cc
+28
-0
src/util_test.h
src/util_test.h
+1
-0
No files found.
src/Makefile.am
View file @
03b32d92
...
...
@@ -86,7 +86,8 @@ h2load_SOURCES = util.cc util.h \
timegm.c timegm.h
\
ssl.cc ssl.h
\
h2load_session.h
\
h2load_http2_session.cc h2load_http2_session.h
h2load_http2_session.cc h2load_http2_session.h
\
h2load_http1_session.cc h2load_http1_session.h
if
HAVE_SPDYLAY
h2load_SOURCES
+=
h2load_spdy_session.cc h2load_spdy_session.h
...
...
src/h2load.cc
View file @
03b32d92
This diff is collapsed.
Click to expand it.
src/h2load.h
View file @
03b32d92
...
...
@@ -62,6 +62,7 @@ struct Worker;
struct
Config
{
std
::
vector
<
std
::
vector
<
nghttp2_nv
>>
nva
;
std
::
vector
<
std
::
vector
<
const
char
*>>
nv
;
std
::
vector
<
std
::
string
>
h1reqs
;
std
::
vector
<
ev_tstamp
>
timings
;
nghttp2
::
Headers
custom_headers
;
std
::
string
scheme
;
...
...
@@ -86,7 +87,13 @@ struct Config {
ssize_t
conn_active_timeout
;
// amount of time to wait after the last request is made on a connection
ssize_t
conn_inactivity_timeout
;
enum
{
PROTO_HTTP2
,
PROTO_SPDY2
,
PROTO_SPDY3
,
PROTO_SPDY3_1
}
no_tls_proto
;
enum
{
PROTO_HTTP2
,
PROTO_SPDY2
,
PROTO_SPDY3
,
PROTO_SPDY3_1
,
PROTO_HTTP1_1
}
no_tls_proto
;
// file descriptor for upload data
int
data_fd
;
uint16_t
port
;
...
...
@@ -94,6 +101,9 @@ struct Config {
bool
verbose
;
bool
timing_script
;
std
::
string
base_uri
;
// list of supported NPN/ALPN protocol strings in the order of
// preference.
std
::
vector
<
std
::
string
>
npn_list
;
Config
();
~
Config
();
...
...
@@ -187,6 +197,7 @@ struct Worker {
size_t
progress_interval
;
uint32_t
id
;
bool
tls_info_report_done
;
bool
app_info_report_done
;
size_t
nconns_made
;
size_t
nclients
;
size_t
rate
;
...
...
@@ -227,6 +238,7 @@ struct Client {
Buffer
<
64
_k
>
wb
;
ev_timer
conn_active_watcher
;
ev_timer
conn_inactivity_watcher
;
std
::
string
selected_proto
;
enum
{
ERR_CONNECT_FAIL
=
-
100
};
...
...
@@ -242,6 +254,7 @@ struct Client {
void
process_abandoned_streams
();
void
report_progress
();
void
report_tls_info
();
void
report_app_info
();
void
terminate_session
();
int
do_read
();
...
...
@@ -263,6 +276,7 @@ struct Client {
void
on_request
(
int32_t
stream_id
);
void
on_header
(
int32_t
stream_id
,
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
);
void
on_status_code
(
int32_t
stream_id
,
uint16_t
status
);
void
on_stream_close
(
int32_t
stream_id
,
bool
success
,
RequestStat
*
req_stat
);
void
record_request_time
(
RequestStat
*
req_stat
);
...
...
src/h2load_http1_session.cc
0 → 100644
View file @
03b32d92
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 British Broadcasting Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "h2load_http1_session.h"
#include <cassert>
#include <cerrno>
#include "h2load.h"
#include "util.h"
#include "template.h"
#include <iostream>
#include <fstream>
#include "http-parser/http_parser.h"
using
namespace
nghttp2
;
namespace
h2load
{
Http1Session
::
Http1Session
(
Client
*
client
)
:
stream_req_counter_
(
1
),
stream_resp_counter_
(
1
),
client_
(
client
),
htp_
(),
complete_
(
false
)
{
http_parser_init
(
&
htp_
,
HTTP_RESPONSE
);
htp_
.
data
=
this
;
}
Http1Session
::~
Http1Session
()
{}
namespace
{
// HTTP response message begin
int
htp_msg_begincb
(
http_parser
*
htp
)
{
return
0
;
}
}
// namespace
namespace
{
// HTTP response status code
int
htp_statuscb
(
http_parser
*
htp
,
const
char
*
at
,
size_t
length
)
{
auto
session
=
static_cast
<
Http1Session
*>
(
htp
->
data
);
auto
client
=
session
->
get_client
();
client
->
on_status_code
(
session
->
stream_resp_counter_
,
htp
->
status_code
);
return
0
;
}
}
// namespace
namespace
{
// HTTP response message complete
int
htp_msg_completecb
(
http_parser
*
htp
)
{
auto
session
=
static_cast
<
Http1Session
*>
(
htp
->
data
);
auto
client
=
session
->
get_client
();
client
->
on_stream_close
(
session
->
stream_resp_counter_
,
true
,
session
->
req_stats_
[
session
->
stream_resp_counter_
]);
session
->
stream_resp_counter_
+=
2
;
return
0
;
}
}
// namespace
namespace
{
int
htp_hdr_keycb
(
http_parser
*
htp
,
const
char
*
data
,
size_t
len
)
{
auto
session
=
static_cast
<
Http1Session
*>
(
htp
->
data
);
auto
client
=
session
->
get_client
();
client
->
worker
->
stats
.
bytes_head
+=
len
;
return
0
;
}
}
// namespace
namespace
{
int
htp_hdr_valcb
(
http_parser
*
htp
,
const
char
*
data
,
size_t
len
)
{
auto
session
=
static_cast
<
Http1Session
*>
(
htp
->
data
);
auto
client
=
session
->
get_client
();
client
->
worker
->
stats
.
bytes_head
+=
len
;
return
0
;
}
}
// namespace
namespace
{
int
htp_body_cb
(
http_parser
*
htp
,
const
char
*
data
,
size_t
len
)
{
auto
session
=
static_cast
<
Http1Session
*>
(
htp
->
data
);
auto
client
=
session
->
get_client
();
client
->
record_ttfb
();
client
->
worker
->
stats
.
bytes_body
+=
len
;
return
0
;
}
}
// namespace
namespace
{
http_parser_settings
htp_hooks
=
{
htp_msg_begincb
,
// http_cb on_message_begin;
nullptr
,
// http_data_cb on_url;
htp_statuscb
,
// http_data_cb on_status;
htp_hdr_keycb
,
// http_data_cb on_header_field;
htp_hdr_valcb
,
// http_data_cb on_header_value;
nullptr
,
// http_cb on_headers_complete;
htp_body_cb
,
// http_data_cb on_body;
htp_msg_completecb
// http_cb on_message_complete;
};
}
// namespace
void
Http1Session
::
on_connect
()
{
client_
->
signal_write
();
}
void
Http1Session
::
submit_request
(
RequestStat
*
req_stat
)
{
auto
config
=
client_
->
worker
->
config
;
auto
req
=
config
->
h1reqs
[
client_
->
reqidx
];
client_
->
reqidx
++
;
if
(
client_
->
reqidx
==
config
->
h1reqs
.
size
())
{
client_
->
reqidx
=
0
;
}
assert
(
req_stat
);
client_
->
record_request_time
(
req_stat
);
client_
->
wb
.
write
(
req
.
c_str
(),
req
.
size
());
client_
->
on_request
(
stream_req_counter_
);
req_stats_
[
stream_req_counter_
]
=
req_stat
;
// increment for next request
stream_req_counter_
+=
2
;
}
int
Http1Session
::
on_read
(
const
uint8_t
*
data
,
size_t
len
)
{
auto
nread
=
http_parser_execute
(
&
htp_
,
&
htp_hooks
,
reinterpret_cast
<
const
char
*>
(
data
),
len
);
if
(
client_
->
worker
->
config
->
verbose
)
{
std
::
cout
.
write
(
reinterpret_cast
<
const
char
*>
(
data
),
nread
);
}
auto
htperr
=
HTTP_PARSER_ERRNO
(
&
htp_
);
if
(
htperr
!=
HPE_OK
)
{
std
::
cerr
<<
"[ERROR] HTTP parse error: "
<<
"("
<<
http_errno_name
(
htperr
)
<<
") "
<<
http_errno_description
(
htperr
)
<<
std
::
endl
;
return
-
1
;
}
return
0
;
}
int
Http1Session
::
on_write
()
{
if
(
complete_
)
{
return
-
1
;
}
return
0
;
}
void
Http1Session
::
terminate
()
{
complete_
=
true
;
}
Client
*
Http1Session
::
get_client
()
{
return
client_
;
}
}
// namespace h2load
src/h2load_http1_session.h
0 → 100644
View file @
03b32d92
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 British Broadcasting Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef H2LOAD_HTTP1_SESSION_H
#define H2LOAD_HTTP1_SESSION_H
#include "h2load_session.h"
#include <nghttp2/nghttp2.h>
namespace
h2load
{
struct
Client
;
class
Http1Session
:
public
Session
{
public:
Http1Session
(
Client
*
client
);
virtual
~
Http1Session
();
virtual
void
on_connect
();
virtual
void
submit_request
(
RequestStat
*
req_stat
);
virtual
int
on_read
(
const
uint8_t
*
data
,
size_t
len
);
virtual
int
on_write
();
virtual
void
terminate
();
Client
*
get_client
();
int32_t
stream_req_counter_
;
int32_t
stream_resp_counter_
;
std
::
unordered_map
<
int32_t
,
RequestStat
*>
req_stats_
;
private:
Client
*
client_
;
http_parser
htp_
;
bool
complete_
;
};
}
// namespace h2load
#endif // H2LOAD_HTTP1_SESSION_H
src/shrpx-unittest.cc
View file @
03b32d92
...
...
@@ -118,8 +118,6 @@ int main(int argc, char *argv[]) {
shrpx
::
test_downstream_assemble_request_cookie
)
||
!
CU_add_test
(
pSuite
,
"downstream_rewrite_location_response_header"
,
shrpx
::
test_downstream_rewrite_location_response_header
)
||
!
CU_add_test
(
pSuite
,
"config_parse_config_str_list"
,
shrpx
::
test_shrpx_config_parse_config_str_list
)
||
!
CU_add_test
(
pSuite
,
"config_parse_header"
,
shrpx
::
test_shrpx_config_parse_header
)
||
!
CU_add_test
(
pSuite
,
"config_parse_log_format"
,
...
...
@@ -169,6 +167,8 @@ int main(int argc, char *argv[]) {
!
CU_add_test
(
pSuite
,
"util_localtime_date"
,
shrpx
::
test_util_localtime_date
)
||
!
CU_add_test
(
pSuite
,
"util_get_uint64"
,
shrpx
::
test_util_get_uint64
)
||
!
CU_add_test
(
pSuite
,
"util_parse_config_str_list"
,
shrpx
::
test_util_parse_config_str_list
)
||
!
CU_add_test
(
pSuite
,
"gzip_inflate"
,
test_nghttp2_gzip_inflate
)
||
!
CU_add_test
(
pSuite
,
"buffer_write"
,
nghttp2
::
test_buffer_write
)
||
!
CU_add_test
(
pSuite
,
"pool_recycle"
,
nghttp2
::
test_pool_recycle
)
||
...
...
src/shrpx.cc
View file @
03b32d92
...
...
@@ -2437,11 +2437,11 @@ int main(int argc, char **argv) {
}
if
(
get_config
()
->
npn_list
.
empty
())
{
mod_config
()
->
npn_list
=
parse_config_str_list
(
DEFAULT_NPN_LIST
);
mod_config
()
->
npn_list
=
util
::
parse_config_str_list
(
DEFAULT_NPN_LIST
);
}
if
(
get_config
()
->
tls_proto_list
.
empty
())
{
mod_config
()
->
tls_proto_list
=
parse_config_str_list
(
DEFAULT_TLS_PROTO_LIST
);
util
::
parse_config_str_list
(
DEFAULT_TLS_PROTO_LIST
);
}
mod_config
()
->
tls_proto_mask
=
...
...
src/shrpx_config.cc
View file @
03b32d92
...
...
@@ -260,37 +260,6 @@ std::string read_passwd_from_file(const char *filename) {
return
line
;
}
std
::
vector
<
Range
<
const
char
*>>
split_config_str_list
(
const
char
*
s
,
char
delim
)
{
size_t
len
=
1
;
auto
last
=
s
+
strlen
(
s
);
for
(
const
char
*
first
=
s
,
*
d
=
nullptr
;
(
d
=
std
::
find
(
first
,
last
,
delim
))
!=
last
;
++
len
,
first
=
d
+
1
)
;
auto
list
=
std
::
vector
<
Range
<
const
char
*>>
(
len
);
len
=
0
;
for
(
auto
first
=
s
;;
++
len
)
{
auto
stop
=
std
::
find
(
first
,
last
,
delim
);
list
[
len
]
=
{
first
,
stop
};
if
(
stop
==
last
)
{
break
;
}
first
=
stop
+
1
;
}
return
list
;
}
std
::
vector
<
std
::
string
>
parse_config_str_list
(
const
char
*
s
,
char
delim
)
{
auto
ranges
=
split_config_str_list
(
s
,
delim
);
auto
res
=
std
::
vector
<
std
::
string
>
();
res
.
reserve
(
ranges
.
size
());
for
(
const
auto
&
range
:
ranges
)
{
res
.
emplace_back
(
range
.
first
,
range
.
second
);
}
return
res
;
}
std
::
pair
<
std
::
string
,
std
::
string
>
parse_header
(
const
char
*
optarg
)
{
// We skip possible ":" at the start of optarg.
...
...
@@ -590,7 +559,7 @@ namespace {
void
parse_mapping
(
const
DownstreamAddr
&
addr
,
const
char
*
src
)
{
// This returns at least 1 element (it could be empty string). We
// will append '/' to all patterns, so it becomes catch-all pattern.
auto
mapping
=
split_config_str_list
(
src
,
':'
);
auto
mapping
=
util
::
split_config_str_list
(
src
,
':'
);
assert
(
!
mapping
.
empty
());
for
(
const
auto
&
raw_pattern
:
mapping
)
{
auto
done
=
false
;
...
...
@@ -1684,11 +1653,11 @@ int parse_config(const char *opt, const char *optarg,
LOG
(
WARN
)
<<
opt
<<
": not implemented yet"
;
return
parse_uint_with_unit
(
&
mod_config
()
->
worker_write_burst
,
opt
,
optarg
);
case
SHRPX_OPTID_NPN_LIST
:
mod_config
()
->
npn_list
=
parse_config_str_list
(
optarg
);
mod_config
()
->
npn_list
=
util
::
parse_config_str_list
(
optarg
);
return
0
;
case
SHRPX_OPTID_TLS_PROTO_LIST
:
mod_config
()
->
tls_proto_list
=
parse_config_str_list
(
optarg
);
mod_config
()
->
tls_proto_list
=
util
::
parse_config_str_list
(
optarg
);
return
0
;
case
SHRPX_OPTID_VERIFY_CLIENT
:
...
...
@@ -1726,7 +1695,7 @@ int parse_config(const char *opt, const char *optarg,
case
SHRPX_OPTID_PADDING
:
return
parse_uint
(
&
mod_config
()
->
padding
,
opt
,
optarg
);
case
SHRPX_OPTID_ALTSVC
:
{
auto
tokens
=
parse_config_str_list
(
optarg
);
auto
tokens
=
util
::
parse_config_str_list
(
optarg
);
if
(
tokens
.
size
()
<
2
)
{
// Requires at least protocol_id and port
...
...
src/shrpx_config.h
View file @
03b32d92
...
...
@@ -433,20 +433,6 @@ int load_config(const char *filename, std::set<std::string> &include_set);
// Read passwd from |filename|
std
::
string
read_passwd_from_file
(
const
char
*
filename
);
template
<
typename
T
>
using
Range
=
std
::
pair
<
T
,
T
>
;
// Parses delimited strings in |s| and returns the array of substring,
// delimited by |delim|. The any white spaces around substring are
// treated as a part of substring.
std
::
vector
<
std
::
string
>
parse_config_str_list
(
const
char
*
s
,
char
delim
=
','
);
// Parses delimited strings in |s| and returns the array of pointers,
// each element points to the beginning and one beyond last of
// substring in |s|. The delimiter is given by |delim|. The any
// white spaces around substring are treated as a part of substring.
std
::
vector
<
Range
<
const
char
*>>
split_config_str_list
(
const
char
*
s
,
char
delim
);
// Parses header field in |optarg|. We expect header field is formed
// like "NAME: VALUE". We require that NAME is non empty string. ":"
// is allowed at the start of the NAME, but NAME == ":" is not
...
...
src/shrpx_config_test.cc
View file @
03b32d92
...
...
@@ -36,34 +36,6 @@
namespace
shrpx
{
void
test_shrpx_config_parse_config_str_list
(
void
)
{
auto
res
=
parse_config_str_list
(
"a"
);
CU_ASSERT
(
1
==
res
.
size
());
CU_ASSERT
(
"a"
==
res
[
0
]);
res
=
parse_config_str_list
(
"a,"
);
CU_ASSERT
(
2
==
res
.
size
());
CU_ASSERT
(
"a"
==
res
[
0
]);
CU_ASSERT
(
""
==
res
[
1
]);
res
=
parse_config_str_list
(
":a::"
,
':'
);
CU_ASSERT
(
4
==
res
.
size
());
CU_ASSERT
(
""
==
res
[
0
]);
CU_ASSERT
(
"a"
==
res
[
1
]);
CU_ASSERT
(
""
==
res
[
2
]);
CU_ASSERT
(
""
==
res
[
3
]);
res
=
parse_config_str_list
(
""
);
CU_ASSERT
(
1
==
res
.
size
());
CU_ASSERT
(
""
==
res
[
0
]);
res
=
parse_config_str_list
(
"alpha,bravo,charlie"
);
CU_ASSERT
(
3
==
res
.
size
());
CU_ASSERT
(
"alpha"
==
res
[
0
]);
CU_ASSERT
(
"bravo"
==
res
[
1
]);
CU_ASSERT
(
"charlie"
==
res
[
2
]);
}
void
test_shrpx_config_parse_header
(
void
)
{
auto
p
=
parse_header
(
"a: b"
);
CU_ASSERT
(
"a"
==
p
.
first
);
...
...
src/shrpx_config_test.h
View file @
03b32d92
...
...
@@ -31,7 +31,6 @@
namespace
shrpx
{
void
test_shrpx_config_parse_config_str_list
(
void
);
void
test_shrpx_config_parse_header
(
void
);
void
test_shrpx_config_parse_log_format
(
void
);
void
test_shrpx_config_read_tls_ticket_key_file
(
void
);
...
...
src/util.cc
View file @
03b32d92
...
...
@@ -770,7 +770,7 @@ bool check_h2_is_selected(const unsigned char *proto, size_t len) {
}
namespace
{
bool
select_
h2
(
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
bool
select_
proto
(
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
const
unsigned
char
*
in
,
unsigned
int
inlen
,
const
char
*
key
,
unsigned
int
keylen
)
{
for
(
auto
p
=
in
,
end
=
in
+
inlen
;
p
+
keylen
<=
end
;
p
+=
*
p
+
1
)
{
...
...
@@ -786,14 +786,25 @@ bool select_h2(const unsigned char **out, unsigned char *outlen,
bool
select_h2
(
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
const
unsigned
char
*
in
,
unsigned
int
inlen
)
{
return
select_
h2
(
out
,
outlen
,
in
,
inlen
,
NGHTTP2_PROTO_ALPN
,
return
select_
proto
(
out
,
outlen
,
in
,
inlen
,
NGHTTP2_PROTO_ALPN
,
str_size
(
NGHTTP2_PROTO_ALPN
))
||
select_
h2
(
out
,
outlen
,
in
,
inlen
,
NGHTTP2_H2_16_ALPN
,
select_
proto
(
out
,
outlen
,
in
,
inlen
,
NGHTTP2_H2_16_ALPN
,
str_size
(
NGHTTP2_H2_16_ALPN
))
||
select_
h2
(
out
,
outlen
,
in
,
inlen
,
NGHTTP2_H2_14_ALPN
,
select_
proto
(
out
,
outlen
,
in
,
inlen
,
NGHTTP2_H2_14_ALPN
,
str_size
(
NGHTTP2_H2_14_ALPN
));
}
bool
select_protocol
(
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
const
unsigned
char
*
in
,
unsigned
int
inlen
,
std
::
vector
<
std
::
string
>
proto_list
)
{
for
(
const
auto
&
proto
:
proto_list
)
{
if
(
select_proto
(
out
,
outlen
,
in
,
inlen
,
proto
.
c_str
(),
static_cast
<
unsigned
int
>
(
proto
.
size
())))
{
return
true
;
}
}
return
false
;
}
std
::
vector
<
unsigned
char
>
get_default_alpn
()
{
auto
res
=
std
::
vector
<
unsigned
char
>
(
str_size
(
NGHTTP2_PROTO_ALPN
)
+
str_size
(
NGHTTP2_H2_16_ALPN
)
+
...
...
@@ -807,6 +818,39 @@ std::vector<unsigned char> get_default_alpn() {
return
res
;
}
std
::
vector
<
Range
<
const
char
*>>
split_config_str_list
(
const
char
*
s
,
char
delim
)
{
size_t
len
=
1
;
auto
last
=
s
+
strlen
(
s
);
for
(
const
char
*
first
=
s
,
*
d
=
nullptr
;
(
d
=
std
::
find
(
first
,
last
,
delim
))
!=
last
;
++
len
,
first
=
d
+
1
)
;
auto
list
=
std
::
vector
<
Range
<
const
char
*>>
(
len
);
len
=
0
;
for
(
auto
first
=
s
;;
++
len
)
{
auto
stop
=
std
::
find
(
first
,
last
,
delim
);
list
[
len
]
=
{
first
,
stop
};
if
(
stop
==
last
)
{
break
;
}
first
=
stop
+
1
;
}
return
list
;
}
std
::
vector
<
std
::
string
>
parse_config_str_list
(
const
char
*
s
,
char
delim
)
{
auto
ranges
=
split_config_str_list
(
s
,
delim
);
auto
res
=
std
::
vector
<
std
::
string
>
();
res
.
reserve
(
ranges
.
size
());
for
(
const
auto
&
range
:
ranges
)
{
res
.
emplace_back
(
range
.
first
,
range
.
second
);
}
return
res
;
}
int
make_socket_closeonexec
(
int
fd
)
{
int
flags
;
int
rv
;
...
...
src/util.h
View file @
03b32d92
...
...
@@ -58,6 +58,9 @@ constexpr const char NGHTTP2_H2_16[] = "h2-16";
constexpr
const
char
NGHTTP2_H2_14_ALPN
[]
=
"\x5h2-14"
;
constexpr
const
char
NGHTTP2_H2_14
[]
=
"h2-14"
;
constexpr
const
char
NGHTTP2_H1_1_ALPN
[]
=
"\x8http/1.1"
;
constexpr
const
char
NGHTTP2_H1_1
[]
=
"http/1.1"
;
namespace
util
{
extern
const
char
DEFAULT_STRIP_CHARSET
[];
...
...
@@ -572,10 +575,30 @@ bool check_h2_is_selected(const unsigned char *alpn, size_t len);
bool
select_h2
(
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
const
unsigned
char
*
in
,
unsigned
int
inlen
);
// Selects protocol ALPN ID if one of identifiers contained in |protolist| is
// present in |in| of length inlen. Returns true if identifier is
// selected.
bool
select_protocol
(
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
const
unsigned
char
*
in
,
unsigned
int
inlen
,
std
::
vector
<
std
::
string
>
proto_list
);
// Returns default ALPN protocol list, which only contains supported
// HTTP/2 protocol identifier.
std
::
vector
<
unsigned
char
>
get_default_alpn
();
template
<
typename
T
>
using
Range
=
std
::
pair
<
T
,
T
>
;
// Parses delimited strings in |s| and returns the array of substring,
// delimited by |delim|. The any white spaces around substring are
// treated as a part of substring.
std
::
vector
<
std
::
string
>
parse_config_str_list
(
const
char
*
s
,
char
delim
=
','
);
// Parses delimited strings in |s| and returns the array of pointers,
// each element points to the beginning and one beyond last of
// substring in |s|. The delimiter is given by |delim|. The any
// white spaces around substring are treated as a part of substring.
std
::
vector
<
Range
<
const
char
*>>
split_config_str_list
(
const
char
*
s
,
char
delim
);
// Returns given time |tp| in Common Log format (e.g.,
// 03/Jul/2014:00:19:38 +0900)
// Expected type of |tp| is std::chrono::timepoint
...
...
src/util_test.cc
View file @
03b32d92
...
...
@@ -412,4 +412,32 @@ void test_util_get_uint64(void) {
}
}
void
test_util_parse_config_str_list
(
void
)
{
auto
res
=
util
::
parse_config_str_list
(
"a"
);
CU_ASSERT
(
1
==
res
.
size
());
CU_ASSERT
(
"a"
==
res
[
0
]);
res
=
util
::
parse_config_str_list
(
"a,"
);
CU_ASSERT
(
2
==
res
.
size
());
CU_ASSERT
(
"a"
==
res
[
0
]);
CU_ASSERT
(
""
==
res
[
1
]);
res
=
util
::
parse_config_str_list
(
":a::"
,
':'
);
CU_ASSERT
(
4
==
res
.
size
());
CU_ASSERT
(
""
==
res
[
0
]);
CU_ASSERT
(
"a"
==
res
[
1
]);
CU_ASSERT
(
""
==
res
[
2
]);
CU_ASSERT
(
""
==
res
[
3
]);
res
=
util
::
parse_config_str_list
(
""
);
CU_ASSERT
(
1
==
res
.
size
());
CU_ASSERT
(
""
==
res
[
0
]);
res
=
util
::
parse_config_str_list
(
"alpha,bravo,charlie"
);
CU_ASSERT
(
3
==
res
.
size
());
CU_ASSERT
(
"alpha"
==
res
[
0
]);
CU_ASSERT
(
"bravo"
==
res
[
1
]);
CU_ASSERT
(
"charlie"
==
res
[
2
]);
}
}
// namespace shrpx
src/util_test.h
View file @
03b32d92
...
...
@@ -56,6 +56,7 @@ void test_util_ends_with(void);
void
test_util_parse_http_date
(
void
);
void
test_util_localtime_date
(
void
);
void
test_util_get_uint64
(
void
);
void
test_util_parse_config_str_list
(
void
);
}
// namespace shrpx
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment