about summary refs log tree commit homepage
path: root/public-inbox-nntpd
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2015-09-18 01:37:53 +0000
committerEric Wong <e@80x24.org>2015-09-18 21:23:53 +0000
commit761736a312a103ba522abac52a604564f9e788ce (patch)
tree283a952c417d4be4573e1e26a9b546e0b1fdadf6 /public-inbox-nntpd
parent62ee3cb36dd08f17e444e96dc80108464ee10cba (diff)
downloadpublic-inbox-761736a312a103ba522abac52a604564f9e788ce.tar.gz
Implementing NEWNEWS, XHDR, XOVER efficiently will require
additional caching on top of msgmap.

This seems to work with lynx and slrnpull, haven't tried clients.

DO NOT run in production, yet, denial-of-service vulnerabilities
await!
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;