Advertisement
Guest User

Untitled

a guest
May 29th, 2013
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.18 KB | None | 0 0
  1. package Mojo::IOLoop::Server;
  2. use Mojo::Base 'Mojo::EventEmitter';
  3.  
  4. use Carp 'croak';
  5. use File::Basename 'dirname';
  6. use File::Spec::Functions 'catfile';
  7. use IO::Socket::INET;
  8. use Scalar::Util 'weaken';
  9. use Socket qw(IPPROTO_TCP TCP_NODELAY);
  10. use Config;
  11.  
  12. # IPv6 support requires IO::Socket::IP
  13. use constant IPV6 => $ENV{MOJO_NO_IPV6}
  14. ? 0
  15. : eval 'use IO::Socket::IP 0.16 (); 1';
  16.  
  17. # TLS support requires IO::Socket::SSL
  18. use constant TLS => $ENV{MOJO_NO_TLS} ? 0
  19. : eval(IPV6 ? 'use IO::Socket::SSL 1.75 (); 1'
  20. : 'use IO::Socket::SSL 1.75 "inet4"; 1');
  21. use constant TLS_READ => TLS ? IO::Socket::SSL::SSL_WANT_READ() : 0;
  22. use constant TLS_WRITE => TLS ? IO::Socket::SSL::SSL_WANT_WRITE() : 0;
  23.  
  24. # To regenerate the certificate run this command (18.04.2012)
  25. # openssl req -new -x509 -keyout server.key -out server.crt -nodes -days 7300
  26. my $CERT = catfile dirname(__FILE__), 'server.crt';
  27. my $KEY = catfile dirname(__FILE__), 'server.key';
  28.  
  29. has multi_accept => 50;
  30. has reactor => sub {
  31. require Mojo::IOLoop;
  32. Mojo::IOLoop->singleton->reactor;
  33. };
  34.  
  35. sub DESTROY {
  36. my $self = shift;
  37. if (my $port = $self->{port}) { $ENV{MOJO_REUSE} =~ s/(?:^|\,)${port}:\d+// }
  38. return unless my $reactor = $self->{reactor};
  39. $self->stop if $self->{handle};
  40. $reactor->remove($_) for values %{$self->{handles}};
  41. }
  42.  
  43. sub listen {
  44. my $self = shift;
  45. my $args = ref $_[0] ? $_[0] : {@_};
  46.  
  47. # Look for reusable file descriptor
  48. my $reuse = my $port = $self->{port} = $args->{port} || 3000;
  49. $ENV{MOJO_REUSE} ||= '';
  50. my $fd;
  51. if ($ENV{MOJO_REUSE} =~ /(?:^|\,)${reuse}:(\d+)/) { $fd = $1 }
  52.  
  53. # Allow file descriptor inheritance
  54. local $^F = 1000;
  55.  
  56. # Reuse file descriptor
  57. my $handle;
  58. my $class = IPV6 ? 'IO::Socket::IP' : 'IO::Socket::INET';
  59. if (defined $fd) {
  60. $handle = $class->new;
  61. $handle->fdopen($fd, 'r') or croak "Can't open file descriptor $fd: $!";
  62. }
  63.  
  64. # New socket
  65. else {
  66. my %options = (
  67. Listen => $args->{backlog} // SOMAXCONN,
  68. LocalAddr => $args->{address} || '0.0.0.0',
  69. LocalPort => $port,
  70. Proto => 'tcp',
  71. ReuseAddr => 1,
  72. Type => SOCK_STREAM
  73. );
  74. $options{LocalAddr} =~ s/[\[\]]//g;
  75. $handle = $class->new(%options) or croak "Can't create listen socket: $!";
  76. $fd = fileno $handle;
  77. $ENV{MOJO_REUSE} .= length $ENV{MOJO_REUSE} ? ",$reuse:$fd" : "$reuse:$fd";
  78. }
  79. $handle->blocking(0);
  80. $self->{handle} = $handle;
  81.  
  82. return unless $args->{tls};
  83. croak "IO::Socket::SSL 1.75 required for TLS support" unless TLS;
  84.  
  85. # Options (Prioritize RC4 to mitigate BEAST attack)
  86. my $options = $self->{tls} = {
  87. SSL_cert_file => $args->{tls_cert} || $CERT,
  88. SSL_cipher_list =>
  89. '!aNULL:!eNULL:!EXPORT:!DSS:!DES:!SSLv2:!LOW:RC4-SHA:RC4-MD5:ALL',
  90. SSL_honor_cipher_order => 1,
  91. SSL_key_file => $args->{tls_key} || $KEY,
  92. SSL_startHandshake => 0,
  93. SSL_verify_mode => 0x00
  94. };
  95. return unless $args->{tls_ca};
  96. $options->{SSL_ca_file} = -T $args->{tls_ca} ? $args->{tls_ca} : undef;
  97. $options->{SSL_verify_mode}
  98. = defined $args->{tls_verify} ? $args->{tls_verify} : 0x03;
  99. }
  100.  
  101. sub generate_port {
  102. my $socket = IO::Socket::INET->new(Listen => 5, LocalAddr => '127.0.0.1', Proto => 'tcp');
  103. my $port = $socket->sockport;
  104. if ($Config{osname} eq 'cygwin') {
  105. sleep(1);
  106. }
  107. return $port;
  108. }
  109.  
  110. sub start {
  111. my $self = shift;
  112. weaken $self;
  113. $self->reactor->io(
  114. $self->{handle} => sub { $self->_accept for 1 .. $self->multi_accept });
  115. }
  116.  
  117. sub stop { $_[0]->reactor->remove($_[0]{handle}) }
  118.  
  119. sub _accept {
  120. my $self = shift;
  121.  
  122. return unless my $handle = $self->{handle}->accept;
  123. $handle->blocking(0);
  124.  
  125. # Disable Nagle's algorithm
  126. setsockopt $handle, IPPROTO_TCP, TCP_NODELAY, 1;
  127.  
  128. # Start TLS handshake
  129. return $self->emit_safe(accept => $handle) unless my $tls = $self->{tls};
  130. weaken $self;
  131. $tls->{SSL_error_trap} = sub {
  132. return unless my $handle = delete $self->{handles}{shift()};
  133. $self->reactor->remove($handle);
  134. close $handle;
  135. };
  136. return unless $handle = IO::Socket::SSL->start_SSL($handle, %$tls);
  137. $self->reactor->io($handle => sub { $self->_tls($handle) });
  138. $self->{handles}{$handle} = $handle;
  139. }
  140.  
  141. sub _tls {
  142. my ($self, $handle) = @_;
  143.  
  144. # Accepted
  145. if ($handle->accept_SSL) {
  146. $self->reactor->remove($handle);
  147. delete $self->{handles}{$handle};
  148. return $self->emit_safe(accept => $handle);
  149. }
  150.  
  151. # Switch between reading and writing
  152. my $err = $IO::Socket::SSL::SSL_ERROR;
  153. if ($err == TLS_READ) { $self->reactor->watch($handle, 1, 0) }
  154. elsif ($err == TLS_WRITE) { $self->reactor->watch($handle, 1, 1) }
  155. }
  156.  
  157. 1;
  158.  
  159. =head1 NAME
  160.  
  161. Mojo::IOLoop::Server - Non-blocking TCP server
  162.  
  163. =head1 SYNOPSIS
  164.  
  165. use Mojo::IOLoop::Server;
  166.  
  167. # Create listen socket
  168. my $server = Mojo::IOLoop::Server->new;
  169. $server->on(accept => sub {
  170. my ($server, $handle) = @_;
  171. ...
  172. });
  173. $server->listen(port => 3000);
  174.  
  175. # Start and stop accepting connections
  176. $server->start;
  177. $server->stop;
  178.  
  179. # Start reactor if necessary
  180. $server->reactor->start unless $server->reactor->is_running;
  181.  
  182. =head1 DESCRIPTION
  183.  
  184. L<Mojo::IOLoop::Server> accepts TCP connections for L<Mojo::IOLoop>.
  185.  
  186. =head1 EVENTS
  187.  
  188. L<Mojo::IOLoop::Server> inherits all events from L<Mojo::EventEmitter> and can
  189. emit the following new ones.
  190.  
  191. =head2 accept
  192.  
  193. $server->on(accept => sub {
  194. my ($server, $handle) = @_;
  195. ...
  196. });
  197.  
  198. Emitted safely for each accepted connection.
  199.  
  200. =head1 ATTRIBUTES
  201.  
  202. L<Mojo::IOLoop::Server> implements the following attributes.
  203.  
  204. =head2 multi_accept
  205.  
  206. my $multi = $server->multi_accept;
  207. $server = $server->multi_accept(100);
  208.  
  209. Number of connections to accept at once, defaults to C<50>.
  210.  
  211. =head2 reactor
  212.  
  213. my $reactor = $server->reactor;
  214. $server = $server->reactor(Mojo::Reactor::Poll->new);
  215.  
  216. Low level event reactor, defaults to the C<reactor> attribute value of the
  217. global L<Mojo::IOLoop> singleton.
  218.  
  219. =head1 METHODS
  220.  
  221. L<Mojo::IOLoop::Server> inherits all methods from L<Mojo::EventEmitter> and
  222. implements the following new ones.
  223.  
  224. =head2 listen
  225.  
  226. $server->listen(port => 3000);
  227.  
  228. Create a new listen socket. Note that TLS support depends on
  229. L<IO::Socket::SSL> (1.75+) and IPv6 support on L<IO::Socket::IP> (0.16+).
  230.  
  231. These options are currently available:
  232.  
  233. =over 2
  234.  
  235. =item address
  236.  
  237. Local address to listen on, defaults to all.
  238.  
  239. =item backlog
  240.  
  241. Maximum backlog size, defaults to C<SOMAXCONN>.
  242.  
  243. =item port
  244.  
  245. Port to listen on.
  246.  
  247. =item tls
  248.  
  249. Enable TLS.
  250.  
  251. =item tls_ca
  252.  
  253. Path to TLS certificate authority file.
  254.  
  255. =item tls_cert
  256.  
  257. Path to the TLS cert file, defaults to a built-in test certificate.
  258.  
  259. =item tls_key
  260.  
  261. Path to the TLS key file, defaults to a built-in test key.
  262.  
  263. =item tls_verify
  264.  
  265. TLS verification mode, defaults to C<0x03>.
  266.  
  267. =back
  268.  
  269. =head2 generate_port
  270.  
  271. my $port = $server->generate_port;
  272.  
  273. Find a free TCP port, this is a utility function primarily used for tests.
  274.  
  275. =head2 start
  276.  
  277. $server->start;
  278.  
  279. Start accepting connections.
  280.  
  281. =head2 stop
  282.  
  283. $server->stop;
  284.  
  285. Stop accepting connections.
  286.  
  287. =head1 SEE ALSO
  288.  
  289. L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
  290.  
  291. =cut
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement