From 85c83085eeb14be7e7b9a395fa9408241ecb8244 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 25 Apr 2016 05:12:43 +0000 Subject: split out NNTPD and HTTPD* modules Hopefully this modularizes things a little and allows us to work on a combined super server to save RAM. --- lib/PublicInbox/HTTPD.pm | 46 ++++++++++++++++++++++++++++++++ lib/PublicInbox/HTTPD/Async.pm | 35 +++++++++++++++++++++++++ lib/PublicInbox/NNTPD.pm | 59 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 lib/PublicInbox/HTTPD.pm create mode 100644 lib/PublicInbox/HTTPD/Async.pm create mode 100644 lib/PublicInbox/NNTPD.pm (limited to 'lib') diff --git a/lib/PublicInbox/HTTPD.pm b/lib/PublicInbox/HTTPD.pm new file mode 100644 index 00000000..78efaa50 --- /dev/null +++ b/lib/PublicInbox/HTTPD.pm @@ -0,0 +1,46 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ + +package PublicInbox::HTTPD; +use strict; +use warnings; +use Plack::Util; +require PublicInbox::HTTPD::Async; +require PublicInbox::Daemon; + +sub pi_httpd_async { + my ($io, $cb) = @_; + PublicInbox::HTTPD::Async->new($io, $cb); +} + +sub new { + my ($class, $sock, $app) = @_; + my $n = getsockname($sock) or die "not a socket: $sock $!\n"; + my ($host, $port) = PublicInbox::Daemon::host_with_port($n); + + my %env = ( + SERVER_NAME => $host, + SERVER_PORT => $port, + SCRIPT_NAME => '', + 'psgi.version' => [ 1, 1 ], + 'psgi.errors' => \*STDERR, + 'psgi.url_scheme' => 'http', + 'psgi.nonblocking' => Plack::Util::TRUE, + 'psgi.streaming' => Plack::Util::TRUE, + 'psgi.run_once' => Plack::Util::FALSE, + 'psgi.multithread' => Plack::Util::FALSE, + 'psgi.multiprocess' => Plack::Util::TRUE, + 'psgix.harakiri'=> Plack::Util::FALSE, + 'psgix.input.buffered' => Plack::Util::TRUE, + 'pi-httpd.async' => do { + no warnings 'once'; + *pi_httpd_async + }, + ); + bless { + app => $app, + env => \%env + }, $class; +} + +1; diff --git a/lib/PublicInbox/HTTPD/Async.pm b/lib/PublicInbox/HTTPD/Async.pm new file mode 100644 index 00000000..63985026 --- /dev/null +++ b/lib/PublicInbox/HTTPD/Async.pm @@ -0,0 +1,35 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ +# +# XXX This is a totally unstable API for public-inbox internal use only +# This is exposed via the 'pi-httpd.async' key in the PSGI env hash. +# The name of this key is not even stable! +# Currently is is intended for use with read-only pipes. +package PublicInbox::HTTPD::Async; +use strict; +use warnings; +use base qw(Danga::Socket); +use fields qw(cb); + +sub new { + my ($class, $io, $cb) = @_; + my $self = fields::new($class); + IO::Handle::blocking($io, 0); + $self->SUPER::new($io); + $self->{cb} = $cb; + $self->watch_read(1); + $self; +} + +sub event_read { $_[0]->{cb}->() } +sub event_hup { $_[0]->{cb}->() } +sub event_err { $_[0]->{cb}->() } +sub sysread { shift->{sock}->sysread(@_) } + +sub close { + my $self = shift; + $self->{cb} = undef; + $self->SUPER::close(@_); +} + +1; diff --git a/lib/PublicInbox/NNTPD.pm b/lib/PublicInbox/NNTPD.pm new file mode 100644 index 00000000..85109ea7 --- /dev/null +++ b/lib/PublicInbox/NNTPD.pm @@ -0,0 +1,59 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ + +# represents an NNTPD (currently a singleton), +# see script/public-inbox-nntpd for how it is used +package PublicInbox::NNTPD; +use strict; +use warnings; +require PublicInbox::NewsGroup; +require PublicInbox::Config; + +sub new { + my ($class) = @_; + bless { + groups => {}, + err => \*STDERR, + out => \*STDOUT, + grouplist => [], + }, $class; +} + +sub refresh_groups () { + my ($self) = @_; + my $pi_config = PublicInbox::Config->new; + my $new = {}; + my @list; + foreach my $k (keys %$pi_config) { + $k =~ /\Apublicinbox\.([^\.]+)\.mainrepo\z/ or next; + my $g = $1; + my $git_dir = $pi_config->{$k}; + my $addr = $pi_config->{"publicinbox.$g.address"}; + my $ngname = $pi_config->{"publicinbox.$g.newsgroup"}; + if (defined $ngname) { + next if ($ngname eq ''); # disabled + $g = $ngname; + } + my $ng = PublicInbox::NewsGroup->new($g, $git_dir, $addr); + my $old_ng = $self->{groups}->{$g}; + + # Reuse the old one if possible since it can hold + # references to valid mm and gcf objects + if ($old_ng) { + $old_ng->update($ng); + $ng = $old_ng; + } + + # Only valid if msgmap and search works + if ($ng->usable) { + $new->{$g} = $ng; + push @list, $ng; + } + } + @list = sort { $a->{name} cmp $b->{name} } @list; + $self->{grouplist} = \@list; + # this will destroy old groups that got deleted + %{$self->{groups}} = %$new; +} + +1; -- cgit v1.2.3-24-ge0c7