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
01739295
Commit
01739295
authored
Jan 08, 2015
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nghttpx: Rename ListenHandler as ConnectionHandler
parent
f5707577
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
72 additions
and
66 deletions
+72
-66
src/Makefile.am
src/Makefile.am
+1
-1
src/shrpx.cc
src/shrpx.cc
+30
-30
src/shrpx_accept_handler.cc
src/shrpx_accept_handler.cc
+3
-2
src/shrpx_accept_handler.h
src/shrpx_accept_handler.h
+3
-3
src/shrpx_connection_handler.cc
src/shrpx_connection_handler.cc
+28
-24
src/shrpx_connection_handler.h
src/shrpx_connection_handler.h
+7
-6
No files found.
src/Makefile.am
View file @
01739295
...
...
@@ -101,7 +101,7 @@ NGHTTPX_SRCS = \
shrpx_config.cc shrpx_config.h
\
shrpx_error.h
\
shrpx_accept_handler.cc shrpx_accept_handler.h
\
shrpx_
listen_handler.cc shrpx_liste
n_handler.h
\
shrpx_
connection_handler.cc shrpx_connectio
n_handler.h
\
shrpx_client_handler.cc shrpx_client_handler.h
\
shrpx_upstream.h
\
shrpx_http2_upstream.cc shrpx_http2_upstream.h
\
...
...
src/shrpx.cc
View file @
01739295
...
...
@@ -54,7 +54,7 @@
#include <nghttp2/nghttp2.h>
#include "shrpx_config.h"
#include "shrpx_
liste
n_handler.h"
#include "shrpx_
connectio
n_handler.h"
#include "shrpx_ssl.h"
#include "shrpx_worker_config.h"
#include "shrpx_worker.h"
...
...
@@ -139,7 +139,7 @@ int resolve_hostname(sockaddr_union *addr, size_t *addrlen,
}
// namespace
namespace
{
std
::
unique_ptr
<
AcceptHandler
>
create_acceptor
(
Liste
nHandler
*
handler
,
std
::
unique_ptr
<
AcceptHandler
>
create_acceptor
(
Connectio
nHandler
*
handler
,
int
family
)
{
{
auto
envfd
=
...
...
@@ -294,7 +294,7 @@ void save_pid() {
namespace
{
void
reopen_log_signal_cb
(
struct
ev_loop
*
loop
,
ev_signal
*
w
,
int
revents
)
{
auto
listener_handler
=
static_cast
<
Liste
nHandler
*>
(
w
->
data
);
auto
conn_handler
=
static_cast
<
Connectio
nHandler
*>
(
w
->
data
);
if
(
LOG_ENABLED
(
INFO
))
{
LOG
(
INFO
)
<<
"Reopening log files: worker_info("
<<
worker_config
<<
")"
;
...
...
@@ -303,14 +303,14 @@ void reopen_log_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
(
void
)
reopen_log_files
();
if
(
get_config
()
->
num_worker
>
1
)
{
listener
_handler
->
worker_reopen_log_files
();
conn
_handler
->
worker_reopen_log_files
();
}
}
}
// namespace
namespace
{
void
exec_binary_signal_cb
(
struct
ev_loop
*
loop
,
ev_signal
*
w
,
int
revents
)
{
auto
listener_handler
=
static_cast
<
Liste
nHandler
*>
(
w
->
data
);
auto
conn_handler
=
static_cast
<
Connectio
nHandler
*>
(
w
->
data
);
LOG
(
NOTICE
)
<<
"Executing new binary"
;
...
...
@@ -349,14 +349,14 @@ void exec_binary_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
auto
envp
=
util
::
make_unique
<
char
*
[]
>
(
envlen
+
3
+
1
);
size_t
envidx
=
0
;
auto
acceptor4
=
listener
_handler
->
get_acceptor4
();
auto
acceptor4
=
conn
_handler
->
get_acceptor4
();
if
(
acceptor4
)
{
std
::
string
fd4
=
ENV_LISTENER4_FD
"="
;
fd4
+=
util
::
utos
(
acceptor4
->
get_fd
());
envp
[
envidx
++
]
=
strdup
(
fd4
.
c_str
());
}
auto
acceptor6
=
listener
_handler
->
get_acceptor6
();
auto
acceptor6
=
conn
_handler
->
get_acceptor6
();
if
(
acceptor6
)
{
std
::
string
fd6
=
ENV_LISTENER6_FD
"="
;
fd6
+=
util
::
utos
(
acceptor6
->
get_fd
());
...
...
@@ -401,20 +401,20 @@ void exec_binary_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
namespace
{
void
graceful_shutdown_signal_cb
(
struct
ev_loop
*
loop
,
ev_signal
*
w
,
int
revents
)
{
auto
listener_handler
=
static_cast
<
Liste
nHandler
*>
(
w
->
data
);
auto
conn_handler
=
static_cast
<
Connectio
nHandler
*>
(
w
->
data
);
LOG
(
NOTICE
)
<<
"Graceful shutdown signal received"
;
worker_config
->
graceful_shutdown
=
true
;
listener
_handler
->
disable_acceptor
();
conn
_handler
->
disable_acceptor
();
// After disabling accepting new connection, disptach incoming
// connection in backlog.
listener
_handler
->
accept_pending_connection
();
conn
_handler
->
accept_pending_connection
();
listener
_handler
->
graceful_shutdown_worker
();
conn
_handler
->
graceful_shutdown_worker
();
// We have accepted all pending connections. Shutdown main event
// loop.
...
...
@@ -424,8 +424,8 @@ void graceful_shutdown_signal_cb(struct ev_loop *loop, ev_signal *w,
namespace
{
void
refresh_cb
(
struct
ev_loop
*
loop
,
ev_timer
*
w
,
int
revents
)
{
auto
listener_handler
=
static_cast
<
Liste
nHandler
*>
(
w
->
data
);
auto
worker_stat
=
listener
_handler
->
get_worker_stat
();
auto
conn_handler
=
static_cast
<
Connectio
nHandler
*>
(
w
->
data
);
auto
worker_stat
=
conn
_handler
->
get_worker_stat
();
// In multi threaded mode (get_config()->num_worker > 1), we have to
// wait for event notification to workers to finish.
...
...
@@ -438,7 +438,7 @@ void refresh_cb(struct ev_loop *loop, ev_timer *w, int revents) {
namespace
{
void
renew_ticket_key_cb
(
struct
ev_loop
*
loop
,
ev_timer
*
w
,
int
revents
)
{
auto
listener_handler
=
static_cast
<
Liste
nHandler
*>
(
w
->
data
);
auto
conn_handler
=
static_cast
<
Connectio
nHandler
*>
(
w
->
data
);
const
auto
&
old_ticket_keys
=
worker_config
->
ticket_keys
;
auto
ticket_keys
=
std
::
make_shared
<
TicketKeys
>
();
...
...
@@ -475,7 +475,7 @@ void renew_ticket_key_cb(struct ev_loop *loop, ev_timer *w, int revents) {
worker_config
->
ticket_keys
=
ticket_keys
;
listener
_handler
->
worker_renew_ticket_keys
(
ticket_keys
);
conn
_handler
->
worker_renew_ticket_keys
(
ticket_keys
);
}
}
// namespace
...
...
@@ -497,8 +497,8 @@ int event_loop() {
:
nullptr
;
}
auto
listener
_handler
=
util
::
make_unique
<
Liste
nHandler
>
(
loop
,
sv_ssl_ctx
,
cl_ssl_ctx
);
auto
conn
_handler
=
util
::
make_unique
<
Connectio
nHandler
>
(
loop
,
sv_ssl_ctx
,
cl_ssl_ctx
);
if
(
get_config
()
->
daemon
)
{
if
(
daemon
(
0
,
0
)
==
-
1
)
{
auto
error
=
errno
;
...
...
@@ -514,16 +514,16 @@ int event_loop() {
save_pid
();
}
auto
acceptor6
=
create_acceptor
(
listener
_handler
.
get
(),
AF_INET6
);
auto
acceptor4
=
create_acceptor
(
listener
_handler
.
get
(),
AF_INET
);
auto
acceptor6
=
create_acceptor
(
conn
_handler
.
get
(),
AF_INET6
);
auto
acceptor4
=
create_acceptor
(
conn
_handler
.
get
(),
AF_INET
);
if
(
!
acceptor6
&&
!
acceptor4
)
{
LOG
(
FATAL
)
<<
"Failed to listen on address "
<<
get_config
()
->
host
.
get
()
<<
", port "
<<
get_config
()
->
port
;
exit
(
EXIT_FAILURE
);
}
listener
_handler
->
set_acceptor4
(
std
::
move
(
acceptor4
));
listener
_handler
->
set_acceptor6
(
std
::
move
(
acceptor6
));
conn
_handler
->
set_acceptor4
(
std
::
move
(
acceptor4
));
conn
_handler
->
set_acceptor6
(
std
::
move
(
acceptor6
));
// ListenHandler loads private key, and we listen on a priveleged port.
// After that, we drop the root privileges if needed.
...
...
@@ -533,7 +533,7 @@ int event_loop() {
if
(
sv_ssl_ctx
&&
get_config
()
->
auto_tls_ticket_key
)
{
// Renew ticket key every 12hrs
ev_timer_init
(
&
renew_ticket_key_timer
,
renew_ticket_key_cb
,
0.
,
12
*
3600.
);
renew_ticket_key_timer
.
data
=
listener
_handler
.
get
();
renew_ticket_key_timer
.
data
=
conn
_handler
.
get
();
ev_timer_again
(
loop
,
&
renew_ticket_key_timer
);
// Generate first session ticket key before running workers.
...
...
@@ -554,11 +554,11 @@ int event_loop() {
#endif // !NOTHREADS
if
(
get_config
()
->
num_worker
>
1
)
{
listener
_handler
->
create_worker_thread
(
get_config
()
->
num_worker
);
conn
_handler
->
create_worker_thread
(
get_config
()
->
num_worker
);
}
else
if
(
get_config
()
->
downstream_proto
==
PROTO_HTTP2
)
{
listener
_handler
->
create_http2_session
();
conn
_handler
->
create_http2_session
();
}
else
{
listener
_handler
->
create_http1_connect_blocker
();
conn
_handler
->
create_http1_connect_blocker
();
}
#ifndef NOTHREADS
...
...
@@ -570,23 +570,23 @@ int event_loop() {
ev_signal
reopen_log_sig
;
ev_signal_init
(
&
reopen_log_sig
,
reopen_log_signal_cb
,
REOPEN_LOG_SIGNAL
);
reopen_log_sig
.
data
=
listener
_handler
.
get
();
reopen_log_sig
.
data
=
conn
_handler
.
get
();
ev_signal_start
(
loop
,
&
reopen_log_sig
);
ev_signal
exec_bin_sig
;
ev_signal_init
(
&
exec_bin_sig
,
exec_binary_signal_cb
,
EXEC_BINARY_SIGNAL
);
exec_bin_sig
.
data
=
listener
_handler
.
get
();
exec_bin_sig
.
data
=
conn
_handler
.
get
();
ev_signal_start
(
loop
,
&
exec_bin_sig
);
ev_signal
graceful_shutdown_sig
;
ev_signal_init
(
&
graceful_shutdown_sig
,
graceful_shutdown_signal_cb
,
GRACEFUL_SHUTDOWN_SIGNAL
);
graceful_shutdown_sig
.
data
=
listener
_handler
.
get
();
graceful_shutdown_sig
.
data
=
conn
_handler
.
get
();
ev_signal_start
(
loop
,
&
graceful_shutdown_sig
);
ev_timer
refresh_timer
;
ev_timer_init
(
&
refresh_timer
,
refresh_cb
,
0.
,
1.
);
refresh_timer
.
data
=
listener
_handler
.
get
();
refresh_timer
.
data
=
conn
_handler
.
get
();
ev_timer_again
(
loop
,
&
refresh_timer
);
if
(
LOG_ENABLED
(
INFO
))
{
...
...
@@ -595,7 +595,7 @@ int event_loop() {
ev_run
(
loop
,
0
);
listener
_handler
->
join_worker
();
conn
_handler
->
join_worker
();
return
0
;
}
...
...
src/shrpx_accept_handler.cc
View file @
01739295
...
...
@@ -26,7 +26,7 @@
#include <unistd.h>
#include "shrpx_
liste
n_handler.h"
#include "shrpx_
connectio
n_handler.h"
#include "shrpx_config.h"
#include "util.h"
...
...
@@ -41,7 +41,8 @@ void acceptcb(struct ev_loop *loop, ev_io *w, int revent) {
}
}
// namespace
AcceptHandler
::
AcceptHandler
(
int
fd
,
ListenHandler
*
h
)
:
conn_hnr_
(
h
),
fd_
(
fd
)
{
AcceptHandler
::
AcceptHandler
(
int
fd
,
ConnectionHandler
*
h
)
:
conn_hnr_
(
h
),
fd_
(
fd
)
{
ev_io_init
(
&
wev_
,
acceptcb
,
fd_
,
EV_READ
);
wev_
.
data
=
this
;
ev_io_start
(
conn_hnr_
->
get_loop
(),
&
wev_
);
...
...
src/shrpx_accept_handler.h
View file @
01739295
...
...
@@ -31,11 +31,11 @@
namespace
shrpx
{
class
Liste
nHandler
;
class
Connectio
nHandler
;
class
AcceptHandler
{
public:
AcceptHandler
(
int
fd
,
Liste
nHandler
*
h
);
AcceptHandler
(
int
fd
,
Connectio
nHandler
*
h
);
~
AcceptHandler
();
void
accept_connection
();
void
enable
();
...
...
@@ -44,7 +44,7 @@ public:
private:
ev_io
wev_
;
Liste
nHandler
*
conn_hnr_
;
Connectio
nHandler
*
conn_hnr_
;
int
fd_
;
};
...
...
src/shrpx_
liste
n_handler.cc
→
src/shrpx_
connectio
n_handler.cc
View file @
01739295
...
...
@@ -22,7 +22,7 @@
* 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 "shrpx_
liste
n_handler.h"
#include "shrpx_
connectio
n_handler.h"
#include <unistd.h>
...
...
@@ -46,10 +46,10 @@ namespace shrpx {
namespace
{
void
acceptor_disable_cb
(
struct
ev_loop
*
loop
,
ev_timer
*
w
,
int
revent
)
{
auto
h
=
static_cast
<
Liste
nHandler
*>
(
w
->
data
);
auto
h
=
static_cast
<
Connectio
nHandler
*>
(
w
->
data
);
// If we are in graceful shutdown period, we must not enable
//
evlistene
rs again.
//
accepto
rs again.
if
(
worker_config
->
graceful_shutdown
)
{
return
;
}
...
...
@@ -58,8 +58,8 @@ void acceptor_disable_cb(struct ev_loop *loop, ev_timer *w, int revent) {
}
}
// namespace
ListenHandler
::
Liste
nHandler
(
struct
ev_loop
*
loop
,
SSL_CTX
*
sv_ssl_ctx
,
SSL_CTX
*
cl_ssl_ctx
)
ConnectionHandler
::
Connectio
nHandler
(
struct
ev_loop
*
loop
,
SSL_CTX
*
sv_ssl_ctx
,
SSL_CTX
*
cl_ssl_ctx
)
:
loop_
(
loop
),
sv_ssl_ctx_
(
sv_ssl_ctx
),
cl_ssl_ctx_
(
cl_ssl_ctx
),
// rate_limit_group_(bufferevent_rate_limit_group_new(
// evbase, get_config()->worker_rate_limit_cfg)),
...
...
@@ -69,12 +69,12 @@ ListenHandler::ListenHandler(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx,
disable_acceptor_timer_
.
data
=
this
;
}
ListenHandler
::~
Liste
nHandler
()
{
ConnectionHandler
::~
Connectio
nHandler
()
{
// bufferevent_rate_limit_group_free(rate_limit_group_);
ev_timer_stop
(
loop_
,
&
disable_acceptor_timer_
);
}
void
Liste
nHandler
::
worker_reopen_log_files
()
{
void
Connectio
nHandler
::
worker_reopen_log_files
()
{
WorkerEvent
wev
;
memset
(
&
wev
,
0
,
sizeof
(
wev
));
...
...
@@ -85,7 +85,7 @@ void ListenHandler::worker_reopen_log_files() {
}
}
void
Liste
nHandler
::
worker_renew_ticket_keys
(
void
Connectio
nHandler
::
worker_renew_ticket_keys
(
const
std
::
shared_ptr
<
TicketKeys
>
&
ticket_keys
)
{
WorkerEvent
wev
;
...
...
@@ -98,7 +98,7 @@ void ListenHandler::worker_renew_ticket_keys(
}
}
void
Liste
nHandler
::
create_worker_thread
(
size_t
num
)
{
void
Connectio
nHandler
::
create_worker_thread
(
size_t
num
)
{
#ifndef NOTHREADS
assert
(
workers_
.
size
()
==
0
);
...
...
@@ -113,7 +113,7 @@ void ListenHandler::create_worker_thread(size_t num) {
#endif // NOTHREADS
}
void
Liste
nHandler
::
join_worker
()
{
void
Connectio
nHandler
::
join_worker
()
{
#ifndef NOTHREADS
int
n
=
0
;
...
...
@@ -132,7 +132,7 @@ void ListenHandler::join_worker() {
#endif // NOTHREADS
}
void
Liste
nHandler
::
graceful_shutdown_worker
()
{
void
Connectio
nHandler
::
graceful_shutdown_worker
()
{
if
(
get_config
()
->
num_worker
==
1
)
{
return
;
}
...
...
@@ -150,7 +150,7 @@ void ListenHandler::graceful_shutdown_worker() {
}
}
int
Liste
nHandler
::
handle_connection
(
int
fd
,
sockaddr
*
addr
,
int
addrlen
)
{
int
Connectio
nHandler
::
handle_connection
(
int
fd
,
sockaddr
*
addr
,
int
addrlen
)
{
if
(
LOG_ENABLED
(
INFO
))
{
LLOG
(
INFO
,
this
)
<<
"Accepted connection. fd="
<<
fd
;
}
...
...
@@ -198,35 +198,39 @@ int ListenHandler::handle_connection(int fd, sockaddr *addr, int addrlen) {
return
0
;
}
struct
ev_loop
*
Liste
nHandler
::
get_loop
()
const
{
struct
ev_loop
*
Connectio
nHandler
::
get_loop
()
const
{
return
loop_
;
}
void
Liste
nHandler
::
create_http2_session
()
{
void
Connectio
nHandler
::
create_http2_session
()
{
http2session_
=
util
::
make_unique
<
Http2Session
>
(
loop_
,
cl_ssl_ctx_
);
}
void
Liste
nHandler
::
create_http1_connect_blocker
()
{
void
Connectio
nHandler
::
create_http1_connect_blocker
()
{
http1_connect_blocker_
=
util
::
make_unique
<
ConnectBlocker
>
(
loop_
);
}
const
WorkerStat
*
Liste
nHandler
::
get_worker_stat
()
const
{
const
WorkerStat
*
Connectio
nHandler
::
get_worker_stat
()
const
{
return
worker_stat_
.
get
();
}
void
Liste
nHandler
::
set_acceptor4
(
std
::
unique_ptr
<
AcceptHandler
>
h
)
{
void
Connectio
nHandler
::
set_acceptor4
(
std
::
unique_ptr
<
AcceptHandler
>
h
)
{
acceptor4_
=
std
::
move
(
h
);
}
AcceptHandler
*
ListenHandler
::
get_acceptor4
()
const
{
return
acceptor4_
.
get
();
}
AcceptHandler
*
ConnectionHandler
::
get_acceptor4
()
const
{
return
acceptor4_
.
get
();
}
void
Liste
nHandler
::
set_acceptor6
(
std
::
unique_ptr
<
AcceptHandler
>
h
)
{
void
Connectio
nHandler
::
set_acceptor6
(
std
::
unique_ptr
<
AcceptHandler
>
h
)
{
acceptor6_
=
std
::
move
(
h
);
}
AcceptHandler
*
ListenHandler
::
get_acceptor6
()
const
{
return
acceptor6_
.
get
();
}
AcceptHandler
*
ConnectionHandler
::
get_acceptor6
()
const
{
return
acceptor6_
.
get
();
}
void
Liste
nHandler
::
enable_acceptor
()
{
void
Connectio
nHandler
::
enable_acceptor
()
{
if
(
acceptor4_
)
{
acceptor4_
->
enable
();
}
...
...
@@ -236,7 +240,7 @@ void ListenHandler::enable_acceptor() {
}
}
void
Liste
nHandler
::
disable_acceptor
()
{
void
Connectio
nHandler
::
disable_acceptor
()
{
if
(
acceptor4_
)
{
acceptor4_
->
disable
();
}
...
...
@@ -246,7 +250,7 @@ void ListenHandler::disable_acceptor() {
}
}
void
Liste
nHandler
::
disable_acceptor_temporary
(
ev_tstamp
t
)
{
void
Connectio
nHandler
::
disable_acceptor_temporary
(
ev_tstamp
t
)
{
if
(
t
==
0.
||
ev_is_active
(
&
disable_acceptor_timer_
))
{
return
;
}
...
...
@@ -257,7 +261,7 @@ void ListenHandler::disable_acceptor_temporary(ev_tstamp t) {
ev_timer_start
(
loop_
,
&
disable_acceptor_timer_
);
}
void
Liste
nHandler
::
accept_pending_connection
()
{
void
Connectio
nHandler
::
accept_pending_connection
()
{
if
(
acceptor4_
)
{
acceptor4_
->
accept_connection
();
}
...
...
src/shrpx_
liste
n_handler.h
→
src/shrpx_
connectio
n_handler.h
View file @
01739295
...
...
@@ -22,8 +22,8 @@
* 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 SHRPX_
LISTE
N_HANDLER_H
#define SHRPX_
LISTE
N_HANDLER_H
#ifndef SHRPX_
CONNECTIO
N_HANDLER_H
#define SHRPX_
CONNECTIO
N_HANDLER_H
#include "shrpx.h"
...
...
@@ -49,10 +49,11 @@ struct WorkerStat;
struct
TicketKeys
;
// TODO should be renamed as ConnectionHandler
class
Liste
nHandler
{
class
Connectio
nHandler
{
public:
ListenHandler
(
struct
ev_loop
*
loop
,
SSL_CTX
*
sv_ssl_ctx
,
SSL_CTX
*
cl_ssl_ctx
);
~
ListenHandler
();
ConnectionHandler
(
struct
ev_loop
*
loop
,
SSL_CTX
*
sv_ssl_ctx
,
SSL_CTX
*
cl_ssl_ctx
);
~
ConnectionHandler
();
int
handle_connection
(
int
fd
,
sockaddr
*
addr
,
int
addrlen
);
void
create_worker_thread
(
size_t
num
);
void
worker_reopen_log_files
();
...
...
@@ -94,4 +95,4 @@ private:
}
// namespace shrpx
#endif // SHRPX_
LISTE
N_HANDLER_H
#endif // SHRPX_
CONNECTIO
N_HANDLER_H
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