about summary refs log tree commit homepage
path: root/public-inbox-nntpd
diff options
context:
space:
mode:
Diffstat (limited to 'public-inbox-nntpd')
-rw-r--r--public-inbox-nntpd77
1 files changed, 77 insertions, 0 deletions
diff --git a/public-inbox-nntpd b/public-inbox-nntpd
new file mode 100644
index 00000000..7fec840e
--- /dev/null
+++ b/public-inbox-nntpd
@@ -0,0 +1,77 @@
+#!/usr/bin/perl -w
+# Copyright (C) 2015 all contributors <meta@public-inbox.org>
+# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
+use strict;
+use warnings;
+require Danga::Socket;
+use IO::Socket;
+use Socket qw(SO_KEEPALIVE IPPROTO_TCP TCP_NODELAY);
+require PublicInbox::NNTP;
+require PublicInbox::NewsGroup;
+my $nntpd = PublicInbox::NNTPD->new;
+my $refresh = sub { $nntpd->refresh_groups };
+
+my %opts = (
+        LocalAddr => '127.0.0.1:1133',
+        Type => SOCK_STREAM,
+        Proto => 'tcp',
+        Blocking => 0,
+        Reuse => 1,
+        Listen => 1024,
+);
+my $s = IO::Socket::INET->new(%opts) or die "Error creating socket: $@\n";
+$s->sockopt(SO_KEEPALIVE, 1);
+$s->setsockopt(IPPROTO_TCP, TCP_NODELAY, 1);
+
+$SIG{PIPE} = 'IGNORE';
+$SIG{HUP} = $refresh;
+$refresh->();
+
+Danga::Socket->AddOtherFds(fileno($s) => sub {
+        while (my $c = $s->accept) {
+                $c->blocking(0); # no accept4 :<
+                PublicInbox::NNTP->new($c, $nntpd);
+        }
+});
+Danga::Socket->EventLoop();
+
+package PublicInbox::NNTPD;
+use strict;
+use warnings;
+use fields qw(groups err out);
+
+sub new {
+        my ($class) = @_;
+        my $self = fields::new($class);
+        $self->{groups} = {};
+        $self;
+}
+
+sub refresh_groups {
+        my ($self) = @_;
+        require PublicInbox::Config;
+        my $pi_config = PublicInbox::Config->new;
+        my $new = {};
+        foreach my $k (keys %$pi_config) {
+                $k =~ /\Apublicinbox\.([^\.]+)\.mainrepo\z/ or next;
+                my $g = $1;
+                my $git_dir = $pi_config->{$k};
+                my $address = $pi_config->{"publicinbox.$g.address"};
+                my $ng = PublicInbox::NewsGroup->new($g, $git_dir, $address);
+                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 works
+                $new->{$g} = $ng if $ng->mm;
+        }
+        # this will destroy old groups that got deleted
+        %{$self->{groups}} = %$new;
+};
+
+1;