• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

examples/H23-Apr-2016-149129

lib/POE/Component/Server/H03-May-2022-964317

t/H23-Apr-2016-1,5811,319

ChangesH A D23-Apr-2016605 1813

Changes.oldH A D23-Apr-2016756 3021

LICENSEH A D23-Apr-201617.9 KiB380292

MANIFESTH A D23-Apr-2016501 2827

META.jsonH A D23-Apr-20161.7 KiB6664

META.ymlH A D23-Apr-2016864 3130

Makefile.PLH A D23-Apr-20161.6 KiB6756

READMEH A D23-Apr-201616.1 KiB520363

dist.iniH A D23-Apr-2016385 2016

README

1NAME
2
3    POE::Component::Server::NNTP - A POE component that provides NNTP
4    server functionality.
5
6VERSION
7
8    version 1.06
9
10SYNOPSIS
11
12      use strict;
13      use POE qw(Component::Server::NNTP);
14
15      my %groups;
16
17      while(<DATA>) {
18        chomp;
19        push @{ $groups{'perl.cpan.testers'}->{'<perl.cpan.testers-381062@nntp.perl.org>'} }, $_;
20      }
21
22      my $nntpd = POE::Component::Server::NNTP->spawn(
23                    alias   => 'nntpd',
24                    posting => 0,
25                    port    => 10119,
26      );
27
28      POE::Session->create(
29        package_states => [
30            'main' => [ qw(
31                            _start
32                            nntpd_connection
33                            nntpd_disconnected
34                            nntpd_cmd_post
35                            nntpd_cmd_ihave
36                            nntpd_cmd_slave
37                            nntpd_cmd_newnews
38                            nntpd_cmd_newgroups
39                            nntpd_cmd_list
40                            nntpd_cmd_group
41                            nntpd_cmd_article
42            ) ],
43        ],
44        options => { trace => 0 },
45      );
46
47      $poe_kernel->run();
48      exit 0;
49
50      sub _start {
51        my ($kernel,$heap) = @_[KERNEL,HEAP];
52        $heap->{clients} = { };
53        $kernel->post( 'nntpd', 'register', 'all' );
54        return;
55      }
56
57      sub nntpd_connection {
58        my ($kernel,$heap,$client_id) = @_[KERNEL,HEAP,ARG0];
59        $heap->{clients}->{ $client_id } = { };
60        return;
61      }
62
63      sub nntpd_disconnected {
64        my ($kernel,$heap,$client_id) = @_[KERNEL,HEAP,ARG0];
65        delete $heap->{clients}->{ $client_id };
66        return;
67      }
68
69      sub nntpd_cmd_slave {
70        my ($kernel,$sender,$client_id) = @_[KERNEL,SENDER,ARG0];
71        $kernel->post( $sender, 'send_to_client', $client_id, '202 slave status noted' );
72        return;
73      }
74
75      sub nntpd_cmd_post {
76        my ($kernel,$sender,$client_id) = @_[KERNEL,SENDER,ARG0];
77        $kernel->post( $sender, 'send_to_client', $client_id, '440 posting not allowed' );
78        return;
79      }
80
81      sub nntpd_cmd_ihave {
82        my ($kernel,$sender,$client_id) = @_[KERNEL,SENDER,ARG0];
83        $kernel->post( $sender, 'send_to_client', $client_id, '435 article not wanted' );
84        return;
85      }
86
87      sub nntpd_cmd_newnews {
88        my ($kernel,$sender,$client_id) = @_[KERNEL,SENDER,ARG0];
89        $kernel->post( $sender, 'send_to_client', $client_id, '230 list of new articles follows' );
90        $kernel->post( $sender, 'send_to_client', $client_id, '.' );
91        return;
92      }
93
94      sub nntpd_cmd_newgroups {
95        my ($kernel,$sender,$client_id) = @_[KERNEL,SENDER,ARG0];
96        $kernel->post( $sender, 'send_to_client', $client_id, '231 list of new newsgroups follows' );
97        $kernel->post( $sender, 'send_to_client', $client_id, '.' );
98        return;
99      }
100
101      sub nntpd_cmd_list {
102        my ($kernel,$sender,$client_id) = @_[KERNEL,SENDER,ARG0];
103        $kernel->post( $sender, 'send_to_client', $client_id, '215 list of newsgroups follows' );
104        foreach my $group ( keys %groups ) {
105            my $reply = join ' ', $group, scalar keys %{ $groups{$group} }, 1, 'n';
106            $kernel->post( $sender, 'send_to_client', $client_id, $reply );
107        }
108        $kernel->post( $sender, 'send_to_client', $client_id, '.' );
109        return;
110      }
111
112      sub nntpd_cmd_group {
113        my ($kernel,$sender,$client_id,$group) = @_[KERNEL,SENDER,ARG0,ARG1];
114        unless ( $group or exists $groups{lc $group} ) {
115           $kernel->post( $sender, 'send_to_client', $client_id, '411 no such news group' );
116           return;
117        }
118        $group = lc $group;
119        $kernel->post( $sender, 'send_to_client', $client_id, "211 1 1 1 $group selected" );
120        $_[HEAP]->{clients}->{ $client_id } = { group => $group };
121        return;
122      }
123
124      sub nntpd_cmd_article {
125        my ($kernel,$sender,$client_id,$article) = @_[KERNEL,SENDER,ARG0,ARG1];
126        my $group = 'perl.cpan.testers';
127        if ( !$article and !defined $_[HEAP]->{clients}->{ $client_id}->{group} ) {
128           $kernel->post( $sender, 'send_to_client', $client_id, '412 no newsgroup selected' );
129           return;
130        }
131        $article = 1 unless $article;
132        if ( $article !~ /^<.*>$/ and $article ne '1' ) {
133           $kernel->post( $sender, 'send_to_client', $client_id, '423 no such article number' );
134           return;
135        }
136        if ( $article =~ /^<.*>$/ and !defined $groups{$group}->{$article} ) {
137           $kernel->post( $sender, 'send_to_client', $client_id, '430 no such article found' );
138           return;
139        }
140        foreach my $msg_id ( keys %{ $groups{$group} } ) {
141          $kernel->post( $sender, 'send_to_client', $client_id, "220 1 $msg_id article retrieved - head and body follow" );
142          $kernel->post( $sender, 'send_to_client', $client_id, $_ ) for @{ $groups{$group}->{$msg_id } };
143          $kernel->post( $sender, 'send_to_client', $client_id, '.' );
144        }
145        return;
146      }
147
148      __END__
149      Newsgroups: perl.cpan.testers
150      Path: nntp.perl.org
151      Date: Fri,  1 Dec 2006 09:27:56 +0000
152      Subject: PASS POE-Component-IRC-5.14 cygwin-thread-multi-64int 1.5.21(0.15642)
153      From: chris@bingosnet.co.uk
154      Message-ID: <perl.cpan.testers-381062@nntp.perl.org>
155
156      This distribution has been tested as part of the cpan-testers
157      effort to test as many new uploads to CPAN as possible.  See
158      http://testers.cpan.org/
159
160DESCRIPTION
161
162    POE::Component::Server::NNTP is a POE component that implements an RFC
163    977 http://www.faqs.org/rfcs/rfc977.html NNTP server. It is the
164    companion component to POE::Component::Client::NNTP which implements
165    NNTP client functionality.
166
167    You spawn an NNTP server component, create your POE sessions then
168    register your session to receive events. Whenever clients connect,
169    disconnect or send valid NNTP protocol commands you will receive an
170    event and an unique client ID. You then parse and process the commands
171    given and send back applicable NNTP responses.
172
173    This component doesn't implement the news database and as such is not
174    by itself a complete NNTP daemon implementation.
175
176CONSTRUCTOR
177
178    spawn
179
180      Takes a number of optional arguments:
181
182        'alias', set an alias on the component;
183        'address', bind the component to a particular address, defaults to INADDR_ANY;
184        'port', start the listening server on a different port, defaults to 119;
185        'options', a hashref of POE::Session options;
186        'posting', a true or false value that determines whether the poco
187                   responds with a 200 or 201 to clients;
188        'handle_connects', true or false whether the poco sends 200/201
189                   responses to connecting clients automagically;
190        'extra_cmds', an arrayref of additional NNTP commands that you
191                   wish to implement.
192
193      Returns a POE::Component::Server::NNTP object.
194
195METHODS
196
197    session_id
198
199      Returns the POE::Session ID of the component.
200
201    shutdown
202
203      Terminates the component. Shuts down the listener and disconnects
204      connected clients.
205
206    send_event
207
208      Sends an event through the component's event handling system.
209
210    send_to_client
211
212      Send some output to a connected client. First parameter must be a
213      valid client id. Second parameter is a string of text to send.
214
215INPUT
216
217    These are events that the component will accept:
218
219    register
220
221      Takes N arguments: a list of event names that your session wants to
222      listen for, minus the 'nntpd_' prefix, ( this is similar to
223      POE::Component::IRC ).
224
225      Registering for 'all' will cause it to send all NNTPD-related events
226      to you; this is the easiest way to handle it.
227
228    unregister
229
230      Takes N arguments: a list of event names which you don't want to
231      receive. If you've previously done a 'register' for a particular
232      event which you no longer care about, this event will tell the NNTPD
233      to stop sending them to you. (If you haven't, it just ignores you. No
234      big deal).
235
236    shutdown
237
238      Terminates the component. Shuts down the listener and disconnects
239      connected clients.
240
241    send_event
242
243      Sends an event through the component's event handling system.
244
245    send_to_client
246
247      Send some output to a connected client. First parameter must be a
248      valid client ID. Second parameter is a string of text to send.
249
250OUTPUT
251
252    The component sends the following events to registered sessions:
253
254    nntpd_registered
255
256      This event is sent to a registering session. ARG0 is
257      POE::Component::Server::NNTP object.
258
259    nntpd_listener_failed
260
261      Generated if the component cannot either start a listener or there is
262      a problem accepting client connections. ARG0 contains the name of the
263      operation that failed. ARG1 and ARG2 hold numeric and string values
264      for $!, respectively.
265
266    nntpd_connection
267
268      Generated whenever a client connects to the component. ARG0 is the
269      client ID, ARG1 is the client's IP address, ARG2 is the client's TCP
270      port. ARG3 is our IP address and ARG4 is our socket port.
271
272    nntpd_disconnected
273
274      Generated whenever a client disconnects. ARG0 is the client ID.
275
276    nntpd_cmd_*
277
278      Generated for each NNTP command that a connected client sends to us.
279      ARG0 is the client ID. ARG1 .. ARGn are any parameters that are sent
280      with the command. Check the RFC http://www.faqs.org/rfcs/rfc977.html
281      for details.
282
283    nntpd_posting
284
285      When the component receives a posting from a client, either as the
286      result of a IHAVE or POST command, this event is issued. ARG0 will be
287      the client ID. ARG1 will be either a '335' or '340' indicating what
288      the posting relates to ( either an IHAVE or POST ). ARG2 will be an
289      arrayref containing the raw lines that the client sent us. No
290      additional parsing is undertaken on this data.
291
292PLUGINS
293
294    POE::Component::Server::NNTP utilises POE::Component::Pluggable to
295    enable a POE::Component::IRC type plugin system.
296
297 PLUGIN HANDLER TYPES
298
299    There are two types of handlers that can registered for by plugins,
300    these are
301
302    NNTPD
303
304      These are the 'nntpd_' prefixed events that are generated. In a
305      handler arguments are passed as scalar refs so that you may mangle
306      the values if required.
307
308    NNTPC
309
310      These are generated whenever a response is sent to a client. Again,
311      any arguments passed are scalar refs for manglement. There is really
312      on one type of this handler generated 'NNTPC_response'
313
314 PLUGIN EXIT CODES
315
316    Plugin handlers should return a particular value depending on what
317    action they wish to happen to the event. These values are available as
318    constants which you can use with the following line:
319
320      use POE::Component::Server::NNTP::Constants qw(:ALL);
321
322    The return values have the following significance:
323
324    NNTPD_EAT_NONE
325
326      This means the event will continue to be processed by remaining
327      plugins and finally, sent to interested sessions that registered for
328      it.
329
330    NNTP_EAT_CLIENT
331
332      This means the event will continue to be processed by remaining
333      plugins but it will not be sent to any sessions that registered for
334      it. This means nothing will be sent out on the wire if it was an
335      NNTPC event, beware!
336
337    NNTPD_EAT_PLUGIN
338
339      This means the event will not be processed by remaining plugins, it
340      will go straight to interested sessions.
341
342    NNTPD_EAT_ALL
343
344      This means the event will be completely discarded, no plugin or
345      session will see it. This means nothing will be sent out on the wire
346      if it was an NNTPC event, beware!
347
348 PLUGIN METHODS
349
350    The following methods are available:
351
352    pipeline
353
354      Returns the POE::Component::Pluggable::Pipeline object.
355
356    plugin_add
357
358      Accepts two arguments:
359
360        The alias for the plugin
361        The actual plugin object
362
363      The alias is there for the user to refer to it, as it is possible to
364      have multiple plugins of the same kind active in one
365      POE::Component::Server::NNTP object.
366
367      This method goes through the pipeline's push() method.
368
369       This method will call $plugin->plugin_register( $nntpd )
370
371      Returns the number of plugins now in the pipeline if plugin was
372      initialized, undef if not.
373
374    plugin_del
375
376      Accepts one argument:
377
378        The alias for the plugin or the plugin object itself
379
380      This method goes through the pipeline's remove() method.
381
382      This method will call $plugin->plugin_unregister( $nntpd )
383
384      Returns the plugin object if the plugin was removed, undef if not.
385
386    plugin_get
387
388      Accepts one argument:
389
390        The alias for the plugin
391
392      This method goes through the pipeline's get() method.
393
394      Returns the plugin object if it was found, undef if not.
395
396    plugin_list
397
398      Has no arguments.
399
400      Returns a hashref of plugin objects, keyed on alias, or an empty list
401      if there are no plugins loaded.
402
403    plugin_order
404
405      Has no arguments.
406
407      Returns an arrayref of plugin objects, in the order which they are
408      encountered in the pipeline.
409
410    plugin_register
411
412      Accepts the following arguments:
413
414        The plugin object
415        The type of the hook, NNTPD or NNTPC
416        The event name(s) to watch
417
418      The event names can be as many as possible, or an arrayref. They
419      correspond to the prefixed events and naturally, arbitrary events
420      too.
421
422      You do not need to supply events with the prefix in front of them,
423      just the names.
424
425      It is possible to register for all events by specifying 'all' as an
426      event.
427
428      Returns 1 if everything checked out fine, undef if something's
429      seriously wrong
430
431    plugin_unregister
432
433      Accepts the following arguments:
434
435        The plugin object
436        The type of the hook, NNTPD or NNTPC
437        The event name(s) to unwatch
438
439      The event names can be as many as possible, or an arrayref. They
440      correspond to the prefixed events and naturally, arbitrary events
441      too.
442
443      You do not need to supply events with the prefix in front of them,
444      just the names.
445
446      It is possible to register for all events by specifying 'all' as an
447      event.
448
449      Returns 1 if all the event name(s) was unregistered, undef if some
450      was not found.
451
452 PLUGIN TEMPLATE
453
454    The basic anatomy of a plugin is:
455
456            package Plugin;
457
458            # Import the constants, of course you could provide your own
459            # constants as long as they map correctly.
460            use POE::Component::Server::NNTP::Constants qw( :ALL );
461
462            # Our constructor
463            sub new {
464                    ...
465            }
466
467            # Required entry point for plugins
468            sub plugin_register {
469                    my( $self, $nntpd ) = @_;
470
471                    # Register events we are interested in
472                    $nntpd->plugin_register( $self, 'NNTPD', qw(all) );
473
474                    # Return success
475                    return 1;
476            }
477
478            # Required exit point for pluggable
479            sub plugin_unregister {
480                    my( $self, $nntpd ) = @_;
481
482                    # Pluggable will automatically unregister events for the plugin
483
484                    # Do some cleanup...
485
486                    # Return success
487                    return 1;
488            }
489
490            sub _default {
491                    my( $self, $nntpd, $event ) = splice @_, 0, 3;
492
493                    print "Default called for $event\n";
494
495                    # Return an exit code
496                    return NNTPD_EAT_NONE;
497            }
498
499SEE ALSO
500
501    POE::Component::Client::NNTP
502
503    RFC 977 http://www.faqs.org/rfcs/rfc977.html
504
505    RFC 1036 http://www.faqs.org/rfcs/rfc1036.html
506
507    POE::Component::Pluggable
508
509AUTHOR
510
511    Chris Williams <chris@bingosnet.co.uk>
512
513COPYRIGHT AND LICENSE
514
515    This software is copyright (c) 2016 by Chris Williams.
516
517    This is free software; you can redistribute it and/or modify it under
518    the same terms as the Perl 5 programming language system itself.
519
520