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
78e51494
Commit
78e51494
authored
Jan 01, 2014
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
src: Support ALPN
Requires unreleased OpenSSL >= 1.0.2
parent
f0d73239
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
191 additions
and
45 deletions
+191
-45
src/HttpServer.cc
src/HttpServer.cc
+57
-9
src/HttpServer.h
src/HttpServer.h
+1
-0
src/nghttp.cc
src/nghttp.cc
+51
-12
src/shrpx_client_handler.cc
src/shrpx_client_handler.cc
+28
-17
src/shrpx_http2_session.cc
src/shrpx_http2_session.cc
+21
-6
src/shrpx_ssl.cc
src/shrpx_ssl.cc
+33
-1
No files found.
src/HttpServer.cc
View file @
78e51494
...
...
@@ -196,6 +196,7 @@ Http2Handler::~Http2Handler()
SSL_shutdown
(
ssl_
);
}
if
(
bev_
)
{
bufferevent_disable
(
bev_
,
EV_READ
|
EV_WRITE
);
bufferevent_free
(
bev_
);
}
if
(
ssl_
)
{
...
...
@@ -398,19 +399,30 @@ int Http2Handler::verify_npn_result()
{
const
unsigned
char
*
next_proto
=
nullptr
;
unsigned
int
next_proto_len
;
// Check the negotiated protocol in NPN or ALPN
SSL_get0_next_proto_negotiated
(
ssl_
,
&
next_proto
,
&
next_proto_len
);
if
(
next_proto
)
{
std
::
string
proto
(
next_proto
,
next_proto
+
next_proto_len
);
if
(
sessions_
->
get_config
()
->
verbose
)
{
std
::
cout
<<
"The negotiated next protocol: "
<<
proto
<<
std
::
endl
;
}
if
(
proto
==
NGHTTP2_PROTO_VERSION_ID
)
{
return
0
;
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
if
(
next_proto
)
{
std
::
string
proto
(
next_proto
,
next_proto
+
next_proto_len
);
if
(
sessions_
->
get_config
()
->
verbose
)
{
std
::
cout
<<
"The negotiated protocol: "
<<
proto
<<
std
::
endl
;
}
if
(
proto
==
NGHTTP2_PROTO_VERSION_ID
)
{
return
0
;
}
break
;
}
else
{
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_get0_alpn_selected
(
ssl_
,
&
next_proto
,
&
next_proto_len
);
#else // OPENSSL_VERSION_NUMBER < 0x10002000L
break
;
#endif // OPENSSL_VERSION_NUMBER < 0x10002000L
}
}
std
::
cerr
<<
"The negotiated next protocol is not supported."
std
::
cerr
<<
"Client did not advertise HTTP/2.0 protocol."
<<
" (nghttp2 expects "
<<
NGHTTP2_PROTO_VERSION_ID
<<
")"
<<
std
::
endl
;
return
0
;
return
-
1
;
}
int
Http2Handler
::
sendcb
(
const
uint8_t
*
data
,
size_t
len
)
...
...
@@ -1094,6 +1106,33 @@ int start_listen(event_base *evbase, Sessions *sessions,
}
}
// namespace
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
namespace
{
int
alpn_select_proto_cb
(
SSL
*
ssl
,
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
const
unsigned
char
*
in
,
unsigned
int
inlen
,
void
*
arg
)
{
auto
config
=
reinterpret_cast
<
HttpServer
*>
(
arg
)
->
get_config
();
if
(
config
->
verbose
)
{
std
::
cout
<<
"[ALPN] client offers:"
<<
std
::
endl
;
}
if
(
config
->
verbose
)
{
for
(
unsigned
int
i
=
0
;
i
<
inlen
;
i
+=
in
[
i
]
+
1
)
{
std
::
cout
<<
" * "
;
std
::
cout
.
write
(
reinterpret_cast
<
const
char
*>
(
&
in
[
i
+
1
]),
in
[
i
]);
std
::
cout
<<
std
::
endl
;
}
}
if
(
nghttp2_select_next_protocol
(
const_cast
<
unsigned
char
**>
(
out
),
outlen
,
in
,
inlen
)
<=
0
)
{
return
SSL_TLSEXT_ERR_NOACK
;
}
return
SSL_TLSEXT_ERR_OK
;
}
}
// namespace
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
int
HttpServer
::
run
()
{
SSL_CTX
*
ssl_ctx
=
nullptr
;
...
...
@@ -1138,6 +1177,10 @@ int HttpServer::run()
next_proto
.
second
=
proto_list
[
0
]
+
1
;
SSL_CTX_set_next_protos_advertised_cb
(
ssl_ctx
,
next_proto_cb
,
&
next_proto
);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN selection callback
SSL_CTX_set_alpn_select_cb
(
ssl_ctx
,
alpn_select_proto_cb
,
this
);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
}
auto
evbase
=
event_base_new
();
...
...
@@ -1152,4 +1195,9 @@ int HttpServer::run()
return
0
;
}
const
Config
*
HttpServer
::
get_config
()
const
{
return
config_
;
}
}
// namespace nghttp2
src/HttpServer.h
View file @
78e51494
...
...
@@ -137,6 +137,7 @@ public:
HttpServer
(
const
Config
*
config
);
int
listen
();
int
run
();
const
Config
*
get_config
()
const
;
private:
const
Config
*
config_
;
};
...
...
src/nghttp.cc
View file @
78e51494
...
...
@@ -1223,6 +1223,15 @@ void print_stats(const HttpClient& client)
}
}
// namespace
namespace
{
void
print_protocol_nego_error
()
{
std
::
cerr
<<
"Server did not select HTTP/2.0 protocol."
<<
" (nghttp2 expects "
<<
NGHTTP2_PROTO_VERSION_ID
<<
")"
<<
std
::
endl
;
}
}
// namespace
namespace
{
int
client_select_next_proto_cb
(
SSL
*
ssl
,
unsigned
char
**
out
,
unsigned
char
*
outlen
,
...
...
@@ -1231,8 +1240,7 @@ int client_select_next_proto_cb(SSL* ssl,
{
if
(
config
.
verbose
)
{
print_timer
();
std
::
cout
<<
" NPN select next protocol: the remote server offers:"
<<
std
::
endl
;
std
::
cout
<<
"[NPN] server offers:"
<<
std
::
endl
;
}
for
(
unsigned
int
i
=
0
;
i
<
inlen
;
i
+=
in
[
i
]
+
1
)
{
if
(
config
.
verbose
)
{
...
...
@@ -1242,15 +1250,8 @@ int client_select_next_proto_cb(SSL* ssl,
}
}
if
(
nghttp2_select_next_protocol
(
out
,
outlen
,
in
,
inlen
)
<=
0
)
{
std
::
cerr
<<
"Server did not advertise HTTP/2.0 protocol."
<<
" (nghttp2 expects "
<<
NGHTTP2_PROTO_VERSION_ID
<<
")"
<<
std
::
endl
;
}
else
{
if
(
config
.
verbose
)
{
std
::
cout
<<
" NPN selected the protocol: "
;
std
::
cout
.
write
(
reinterpret_cast
<
const
char
*>
(
*
out
),
(
size_t
)
*
outlen
);
std
::
cout
<<
std
::
endl
;
}
print_protocol_nego_error
();
return
SSL_TLSEXT_ERR_NOACK
;
}
return
SSL_TLSEXT_ERR_OK
;
}
...
...
@@ -1312,7 +1313,37 @@ void eventcb(bufferevent *bev, short events, void *ptr)
if
(
client
->
need_upgrade
())
{
rv
=
client
->
on_upgrade_connect
();
}
else
{
// TODO Check NPN result and fail fast?
// Check NPN or ALPN result
const
unsigned
char
*
next_proto
=
nullptr
;
unsigned
int
next_proto_len
;
SSL_get0_next_proto_negotiated
(
client
->
ssl
,
&
next_proto
,
&
next_proto_len
);
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
if
(
next_proto
)
{
if
(
config
.
verbose
)
{
std
::
cout
<<
"The negotiated protocol: "
;
std
::
cout
.
write
(
reinterpret_cast
<
const
char
*>
(
next_proto
),
next_proto_len
);
std
::
cout
<<
std
::
endl
;
}
if
(
NGHTTP2_PROTO_VERSION_ID_LEN
!=
next_proto_len
||
memcmp
(
NGHTTP2_PROTO_VERSION_ID
,
next_proto
,
NGHTTP2_PROTO_VERSION_ID_LEN
)
!=
0
)
{
next_proto
=
nullptr
;
}
break
;
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_get0_alpn_selected
(
client
->
ssl
,
&
next_proto
,
&
next_proto_len
);
#else // OPENSSL_VERSION_NUMBER < 0x10002000L
break
;
#endif // OPENSSL_VERSION_NUMBER < 0x10002000L
}
if
(
!
next_proto
)
{
print_protocol_nego_error
();
client
->
disconnect
();
return
;
}
rv
=
client
->
on_connect
();
}
if
(
rv
!=
0
)
{
...
...
@@ -1404,6 +1435,14 @@ int communicate(const std::string& scheme, const std::string& host,
}
SSL_CTX_set_next_proto_select_cb
(
ssl_ctx
,
client_select_next_proto_cb
,
nullptr
);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
unsigned
char
proto_list
[
255
];
proto_list
[
0
]
=
NGHTTP2_PROTO_VERSION_ID_LEN
;
memcpy
(
&
proto_list
[
1
],
NGHTTP2_PROTO_VERSION_ID
,
NGHTTP2_PROTO_VERSION_ID_LEN
);
SSL_CTX_set_alpn_protos
(
ssl_ctx
,
proto_list
,
proto_list
[
0
]
+
1
);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
}
{
HttpClient
client
{
callbacks
,
evbase
,
ssl_ctx
};
...
...
src/shrpx_client_handler.cc
View file @
78e51494
...
...
@@ -299,26 +299,37 @@ int ClientHandler::validate_next_proto()
// First set callback for catch all cases
set_bev_cb
(
upstream_readcb
,
upstream_writecb
,
upstream_eventcb
);
SSL_get0_next_proto_negotiated
(
ssl_
,
&
next_proto
,
&
next_proto_len
);
if
(
next_proto
)
{
std
::
string
proto
(
next_proto
,
next_proto
+
next_proto_len
);
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"The negotiated next protocol: "
<<
proto
;
}
if
(
proto
==
NGHTTP2_PROTO_VERSION_ID
)
{
set_bev_cb
(
upstream_http2_connhd_readcb
,
upstream_writecb
,
upstream_eventcb
);
upstream_
=
util
::
make_unique
<
Http2Upstream
>
(
this
);
return
0
;
}
else
{
#ifdef HAVE_SPDYLAY
uint16_t
version
=
spdylay_npn_get_version
(
next_proto
,
next_proto_len
);
if
(
version
)
{
upstream_
=
util
::
make_unique
<
SpdyUpstream
>
(
version
,
this
);
return
0
;
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
if
(
next_proto
)
{
if
(
LOG_ENABLED
(
INFO
))
{
std
::
string
proto
(
next_proto
,
next_proto
+
next_proto_len
);
CLOG
(
INFO
,
this
)
<<
"The negotiated next protocol: "
<<
proto
;
}
if
(
next_proto_len
==
NGHTTP2_PROTO_VERSION_ID_LEN
&&
memcmp
(
NGHTTP2_PROTO_VERSION_ID
,
next_proto
,
NGHTTP2_PROTO_VERSION_ID_LEN
)
==
0
)
{
set_bev_cb
(
upstream_http2_connhd_readcb
,
upstream_writecb
,
upstream_eventcb
);
upstream_
=
util
::
make_unique
<
Http2Upstream
>
(
this
);
return
0
;
}
else
{
#ifdef HAVE_SPDYLAY
uint16_t
version
=
spdylay_npn_get_version
(
next_proto
,
next_proto_len
);
if
(
version
)
{
upstream_
=
util
::
make_unique
<
SpdyUpstream
>
(
version
,
this
);
return
0
;
}
#endif // HAVE_SPDYLAY
}
break
;
}
}
else
{
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_get0_alpn_selected
(
ssl_
,
&
next_proto
,
&
next_proto_len
);
#else // OPENSSL_VERSION_NUMBER < 0x10002000L
break
;
#endif // OPENSSL_VERSION_NUMBER < 0x10002000L
}
if
(
!
next_proto
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"No proto negotiated."
;
}
...
...
src/shrpx_http2_session.cc
View file @
78e51494
...
...
@@ -1120,15 +1120,30 @@ int on_unknown_frame_recv_callback(nghttp2_session *session,
int
Http2Session
::
on_connect
()
{
int
rv
;
const
unsigned
char
*
next_proto
=
nullptr
;
unsigned
int
next_proto_len
;
if
(
ssl_ctx_
)
{
const
unsigned
char
*
next_proto
=
nullptr
;
unsigned
int
next_proto_len
;
SSL_get0_next_proto_negotiated
(
ssl_
,
&
next_proto
,
&
next_proto_len
);
std
::
string
proto
(
next_proto
,
next_proto
+
next_proto_len
);
if
(
LOG_ENABLED
(
INFO
))
{
SSLOG
(
INFO
,
this
)
<<
"Negotiated next protocol: "
<<
proto
;
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
if
(
next_proto
)
{
if
(
LOG_ENABLED
(
INFO
))
{
std
::
string
proto
(
next_proto
,
next_proto
+
next_proto_len
);
SSLOG
(
INFO
,
this
)
<<
"Negotiated next protocol: "
<<
proto
;
}
if
(
next_proto_len
!=
NGHTTP2_PROTO_VERSION_ID_LEN
||
memcmp
(
NGHTTP2_PROTO_VERSION_ID
,
next_proto
,
NGHTTP2_PROTO_VERSION_ID_LEN
)
!=
0
)
{
return
-
1
;
}
break
;
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_get0_alpn_selected
(
ssl_
,
&
next_proto
,
&
next_proto_len
);
#else // OPENSSL_VERSION_NUMBER < 0x10002000L
break
;
#endif // OPENSSL_VERSION_NUMBER < 0x10002000L
}
if
(
proto
!=
NGHTTP2_PROTO_VERSION_ID
)
{
if
(
!
next_proto
)
{
return
-
1
;
}
}
...
...
src/shrpx_ssl.cc
View file @
78e51494
...
...
@@ -132,6 +132,23 @@ int servername_callback(SSL *ssl, int *al, void *arg)
}
}
// namespace
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
namespace
{
int
alpn_select_proto_cb
(
SSL
*
ssl
,
const
unsigned
char
**
out
,
unsigned
char
*
outlen
,
const
unsigned
char
*
in
,
unsigned
int
inlen
,
void
*
arg
)
{
if
(
nghttp2_select_next_protocol
(
const_cast
<
unsigned
char
**>
(
out
),
outlen
,
in
,
inlen
)
==
-
1
)
{
return
SSL_TLSEXT_ERR_NOACK
;
}
return
SSL_TLSEXT_ERR_OK
;
}
}
// namespace
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX
*
create_ssl_context
(
const
char
*
private_key_file
,
const
char
*
cert_file
)
{
...
...
@@ -241,11 +258,16 @@ SSL_CTX* create_ssl_context(const char *private_key_file,
}
SSL_CTX_set_tlsext_servername_callback
(
ssl_ctx
,
servername_callback
);
// NPN advertisement
auto
proto_list_len
=
set_npn_prefs
(
proto_list
,
get_config
()
->
npn_list
,
get_config
()
->
npn_list_len
);
next_proto
.
first
=
proto_list
;
next_proto
.
second
=
proto_list_len
;
SSL_CTX_set_next_protos_advertised_cb
(
ssl_ctx
,
next_proto_cb
,
&
next_proto
);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN selection callback
SSL_CTX_set_alpn_select_cb
(
ssl_ctx
,
alpn_select_proto_cb
,
nullptr
);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return
ssl_ctx
;
}
...
...
@@ -322,8 +344,18 @@ SSL_CTX* create_ssl_client_context()
DIE
();
}
}
// NPN selection callback
SSL_CTX_set_next_proto_select_cb
(
ssl_ctx
,
select_next_proto_cb
,
nullptr
);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN advertisement
auto
proto_list_len
=
set_npn_prefs
(
proto_list
,
get_config
()
->
npn_list
,
get_config
()
->
npn_list_len
);
next_proto
.
first
=
proto_list
;
next_proto
.
second
=
proto_list_len
;
SSL_CTX_set_alpn_protos
(
ssl_ctx
,
proto_list
,
proto_list
[
0
]
+
1
);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return
ssl_ctx
;
}
...
...
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