1NAME
2 POE::Component::Server::IRC - A fully event-driven networkable IRC
3 server daemon module.
4
5SYNOPSIS
6 # A fairly simple example:
7 use strict;
8 use warnings;
9 use POE qw(Component::Server::IRC);
10
11 my %config = (
12 servername => 'simple.poco.server.irc',
13 nicklen => 15,
14 network => 'SimpleNET'
15 );
16
17 my $pocosi = POE::Component::Server::IRC->spawn( config => \%config );
18
19 POE::Session->create(
20 package_states => [
21 'main' => [qw(_start _default)],
22 ],
23 heap => { ircd => $pocosi },
24 );
25
26 $poe_kernel->run();
27
28 sub _start {
29 my ($kernel, $heap) = @_[KERNEL, HEAP];
30
31 $heap->{ircd}->yield('register', 'all');
32
33 # Anyone connecting from the loopback gets spoofed hostname
34 $heap->{ircd}->add_auth(
35 mask => '*@localhost',
36 spoof => 'm33p.com',
37 no_tilde => 1,
38 );
39
40 # We have to add an auth as we have specified one above.
41 $heap->{ircd}->add_auth(mask => '*@*');
42
43 # Start a listener on the 'standard' IRC port.
44 $heap->{ircd}->add_listener(port => 6667);
45
46 # Add an operator who can connect from localhost
47 $heap->{ircd}->add_operator(
48 {
49 username => 'moo',
50 password => 'fishdont',
51 }
52 );
53 }
54
55 sub _default {
56 my ($event, $args) = @_[ARG0 .. $#_];
57
58 print "$event: ";
59 for my $arg (@$args) {
60 if (ref($arg) eq 'ARRAY') {
61 print "[", join ( ", ", @$arg ), "] ";
62 }
63 elsif (ref($arg) eq 'HASH') {
64 print "{", join ( ", ", %$arg ), "} ";
65 }
66 else {
67 print "'$arg' ";
68 }
69 }
70
71 print "\n";
72 }
73
74DESCRIPTION
75 POE::Component::Server::IRC is a POE component which implements an IRC
76 server (also referred to as an IRC daemon or IRCd). It should be
77 compliant with the pertient IRC RFCs and is based on reverse engineering
78 Hybrid IRCd behaviour with regards to interactions with IRC clients and
79 other IRC servers.
80
81 Yes, that's right. POE::Component::Server::IRC is capable of linking to
82 foreign IRC networks. It supports the TS5 server to server protocol and
83 has been tested with linking to Hybrid-7 based networks. It should in
84 theory work with any TS5-based IRC network.
85
86 POE::Component::Server::IRC also has a services API, which enables one
87 to extend the IRCd to create IRC Services. This is fully event-driven
88 (of course =]). There is also a Plugin system, similar to that sported
89 by POE::Component::IRC.
90
91 Note: This is a subclass of POE::Component::Server::IRC::Backend. You
92 should read its documentation too.
93
94CONSTRUCTOR
95 "spawn"
96 Returns a new instance of the component. Takes the following parameters:
97
98 * 'config', a hashref of configuration options, see the "configure"
99 method for details.
100
101 Any other parameters will be passed along to
102 POE::Component::Server::IRC::Backend's "create" method.
103
104 If the component is spawned from within another session then that
105 session will automagically be registered with the component to receive
106 events and be sent an "ircd_registered" event.
107
108METHODS
109 Information
110 "server_name"
111 No arguments, returns the name of the ircd.
112
113 "server_version"
114 No arguments, returns the software version of the ircd.
115
116 "server_created"
117 No arguments, returns a string signifying when the ircd was created.
118
119 "server_config"
120 Takes one argument, the server configuration value to query.
121
122 Configuration
123 These methods provide mechanisms for configuring and controlling the
124 IRCd component.
125
126 "configure"
127 Configures your new shiny IRCd.
128
129 Takes a number of parameters:
130
131 * 'servername', a name to bless your shiny new IRCd with, defaults to
132 'poco.server.irc';
133
134 * 'serverdesc', a description for your IRCd, defaults to 'Poco? POCO?
135 POCO!';
136
137 * 'network', the name of the IRC network you will be creating,
138 defaults to 'poconet';
139
140 * 'nicklen', the max length of nicknames to support, defaults to 9.
141 Note: the nicklen must be the same on all servers on your IRC
142 network;
143
144 * 'maxtargets', max number of targets a user can send PRIVMSG/NOTICE's
145 to, defaults to 4;
146
147 * 'maxchannels', max number of channels users may join, defaults to
148 15;
149
150 * 'version', change the server version that is reported;
151
152 * 'admin', an arrayref consisting of the 3 lines that will be returned
153 by ADMIN;
154
155 * 'info', an arrayref consisting of lines to be returned by INFO;
156
157 * 'ophacks', set to true to enable oper hacks. Default is false;
158
159 * 'whoisactually', setting this to a false value means that only opers
160 can see 338. Defaults to true;
161
162 "add_auth"
163 By default the IRCd allows any user to connect to the server without a
164 password. Configuring auths enables you to control who can connect and
165 set passwords required to connect.
166
167 Takes the following parameters:
168
169 * 'mask', a user@host or user@ipaddress mask to match against,
170 mandatory;
171
172 * 'password', if specified, any client matching the mask must provide
173 this to connect;
174
175 * 'spoof', if specified, any client matching the mask will have their
176 hostname changed to this;
177
178 * 'no_tilde', if specified, the '~' prefix is removed from their
179 username;
180
181 Auth masks are processed in order of addition.
182
183 If auth masks have been defined, then a connecting user *must* match one
184 of the masks in order to be authorised to connect. This is a feature >;)
185
186 "del_auth"
187 Takes a single argument, the mask to remove.
188
189 "add_operator"
190 This adds an O line to the IRCd. Takes a number of parameters:
191
192 * 'username', the username of the IRC oper, mandatory;
193
194 * 'password', the password, mandatory;
195
196 * 'ipmask', either a scalar ipmask or an arrayref of Net::Netmask
197 objects;
198
199 A scalar ipmask can contain '*' to match any number of characters or '?'
200 to match one character. If no 'ipmask' is provided, operators are only
201 allowed to OPER from the loopback interface.
202
203 'password' can be either plain-text, "crypt"'d or unix/apache md5. See
204 the "mkpasswd" function in POE::Component::Server::IRC::Common for how
205 to generate passwords.
206
207 "del_operator"
208 Takes a single argument, the username to remove.
209
210 "add_peer"
211 Adds peer servers that we will allow to connect to us and who we will
212 connect to. Takes the following parameters:
213
214 * 'name', the name of the server. This is the IRC name, not hostname,
215 mandatory;
216
217 * 'pass', the password they must supply to us, mandatory;
218
219 * 'rpass', the password we need to supply to them, mandatory;
220
221 * 'type', the type of server, 'c' for a connecting server, 'r' for one
222 that we will connect to;
223
224 * 'raddress', the remote address to connect to, implies 'type' eq 'r';
225
226 * 'rport', the remote port to connect to, default is 6667;
227
228 * 'ipmask', either a scalar ipmask or an arrayref of Net::Netmask
229 objects;
230
231 * 'auto', if set to true value will automatically connect to remote
232 server if type is 'r';
233
234 * 'zip', set to a true value to enable ziplink support. This must be
235 done on both ends of the connection. Requires
236 POE::Filter::Zlib::Stream;
237
238 "del_peer"
239 Takes a single argument, the peer to remove. This does not disconnect
240 the said peer if it is currently connected.
241
242 State queries
243 The following methods allow you to query state information regarding
244 nicknames, channels, and peers.
245
246 "state_nicks"
247 Takes no arguments, returns a list of all nicknames in the state.
248
249 "state_chans"
250 Takes no arguments, returns a list of all channels in the state.
251
252 "state_peers"
253 Takes no arguments, returns a list of all irc servers in the state.
254
255 "state_nick_exists"
256 Takes one argument, a nickname, returns true or false dependent on
257 whether the given nickname exists or not.
258
259 "state_chan_exists"
260 Takes one argument, a channel name, returns true or false dependent on
261 whether the given channel exists or not.
262
263 "state_peer_exists"
264 Takes one argument, a peer server name, returns true or false dependent
265 on whether the given peer exists or not.
266
267 "state_user_full"
268 Takes one argument, a nickname, returns that users full nick!user@host
269 if they exist, undef if they don't.
270
271 "state_user_nick"
272 Takes one argument, a nickname, returns the proper nickname for that
273 user. Returns undef if the nick doesn't exist.
274
275 "state_user_umode"
276 Takes one argument, a nickname, returns that users mode setting.
277
278 "state_user_is_operator"
279 Takes one argument, a nickname, returns true or false dependent on
280 whether the given nickname is an IRC operator or not.
281
282 "state_user_chans"
283 Takes one argument, a nickname, returns a list of channels that that
284 nick is a member of.
285
286 "state_user_server"
287 Takes one argument, a nickname, returns the name of the peer server that
288 that user is connected from.
289
290 "state_chan_list"
291 Takes one argument, a channel name, returns a list of the member nicks
292 on that channel.
293
294 "state_chan_list_prefixed"
295 Takes one argument, a channel name, returns a list of the member nicks
296 on that channel, nicknames will be prefixed with @%+ if they are +o +h
297 or +v, respectively.
298
299 "state_chan_topic"
300 Takes one argument, a channel name, returns undef if no topic is set on
301 that channel, or an arrayref consisting of the topic, who set it and the
302 time they set it.
303
304 "state_chan_mode_set"
305 Takes two arguments, a channel name and a channel mode character.
306 Returns true if that channel mode is set, false otherwise.
307
308 "state_is_chan_member"
309 Takes two arguments, a nick and a channel name. Returns true if that
310 nick is on channel, false otherwise.
311
312 "state_user_chan_mode"
313 Takes two arguments, a nick and a channel name. Returns that nicks
314 status (+ohv or '') on that channel.
315
316 "state_is_chan_op"
317 Takes two arguments, a nick and a channel name. Returns true if that
318 nick is an channel operator, false otherwise.
319
320 "state_is_chan_hop"
321 Takes two arguments, a nick and a channel name. Returns true if that
322 nick is an channel half-operator, false otherwise.
323
324 "state_has_chan_voice"
325 Takes two arguments, a nick and a channel name. Returns true if that
326 nick has channel voice, false otherwise.
327
328 Server actions
329 "daemon_server_kill"
330 Takes two arguments, a nickname and a comment (which is optional);
331 Issues a SERVER KILL of the given nick;
332
333 "daemon_server_mode"
334 First argument is a channel name, remaining arguments are channel modes
335 and their parameters to apply.
336
337 "daemon_server_kick"
338 Takes two arguments that are mandatory and an optional one: channel
339 name, nickname of the user to kick and a pithy comment.
340
341 "daemon_server_remove"
342 Takes two arguments that are mandatory and an optional one: channel
343 name, nickname of the user to remove and a pithy comment.
344
345 "daemon_server_wallops"
346 Takes one argument, the message text to send.
347
348INPUT EVENTS
349 These are POE events that can be sent to the component.
350
351 "add_spoofed_nick"
352 Takes a single argument a hashref which should have the following keys:
353
354 * 'nick', the nickname to add, mandatory;
355
356 * 'user', the ident you want the nick to have, defaults to the same as
357 the nick;
358
359 * 'hostname', the hostname, defaults to the server name;
360
361 * 'umode', specify whether this is to be an IRCop etc, defaults to
362 'i';
363
364 * 'ts', unixtime, default is time(), best not to meddle;
365
366 Note: spoofed nicks are currently only really functional for use as IRC
367 services.
368
369 "del_spoofed_nick"
370 Takes a single mandatory argument, the spoofed nickname to remove.
371 Optionally, you may specify a quit message for the spoofed nick.
372
373 Spoofed nick commands
374 The following input events are for the benefit of spoofed nicks. All
375 require a nickname of a spoofed nick as the first argument.
376
377 "daemon_cmd_join"
378 Takes two arguments, a spoofed nick and a channel name to join.
379
380 "daemon_cmd_part"
381 Takes two arguments, a spoofed nick and a channel name to part from.
382
383 "daemon_cmd_mode"
384 Takes at least three arguments, a spoofed nick, a channel and a channel
385 mode to apply. Additional arguments are parameters for the channel
386 modes.
387
388 "daemon_cmd_kick"
389 Takes at least three arguments, a spoofed nick, a channel name and the
390 nickname of a user to kick from that channel. You may supply a fourth
391 argument which will be the kick comment.
392
393 "daemon_cmd_topic"
394 Takes three arguments, a spoofed nick, a channel name and the topic to
395 set on that channel. If the third argument is an empty string then the
396 channel topic will be unset.
397
398 "daemon_cmd_nick"
399 Takes two arguments, a spoofed nick and a new nickname to change to.
400
401 "daemon_cmd_gline"
402 Takes three arguments, a spoofed nick, a user@host mask to gline and a
403 reason for the gline.
404
405 "daemon_cmd_kline"
406 Takes a number of arguments depending on where the KLINE is to be
407 applied and for how long:
408
409 To set a permanent KLINE:
410
411 $ircd->yield(
412 'daemon_cmd_kline',
413 $spoofed_nick,
414 $nick || $user_host_mask,
415 $reason,
416 );
417
418 To set a temporary 10 minute KLINE:
419
420 $ircd->yield(
421 'daemon_cmd_kline',
422 $spoofed_nick,
423 10,
424 $nick || $user_host_mask,
425 $reason,
426 );
427
428 To set a temporary 10 minute KLINE on all servers:
429
430 $ircd->yield(
431 'daemon_cmd_kline',
432 $spoofed_nick,
433 10,
434 $nick || $user_host_mask,
435 'on',
436 '*',
437 $reason,
438 );
439
440 "daemon_cmd_unkline"
441 Removes a KLINE as indicated by the user@host mask supplied.
442
443 To remove a KLINE:
444
445 $ircd->yield(
446 'daemon_cmd_unkline',
447 $spoofed_nick,
448 $user_host_mask,
449 );
450
451 To remove a KLINE from all servers:
452
453 $ircd->yield(
454 'daemon_cmd_unkline',
455 $spoofed_nick,
456 $user_host_mask,
457 'on',
458 '*',
459 );
460
461 "daemon_cmd_rkline"
462 Used to set a regex based KLINE. The regex given must be based on a
463 user@host mask.
464
465 To set a permanent RKLINE:
466
467 $ircd->yield(
468 'daemon_cmd_rkline',
469 $spoofed_nick,
470 '^.*$@^(yahoo|google|microsoft)\.com$',
471 $reason,
472 );
473
474 To set a temporary 10 minute RKLINE:
475
476 $ircd->yield(
477 'daemon_cmd_rkline',
478 $spoofed_nick,
479 10,
480 '^.*$@^(yahoo|google|microsoft)\.com$',
481 $reason,
482 );
483
484 To set a temporary 10 minute RKLINE on all servers:
485
486 $ircd->yield(
487 'daemon_cmd_kline',
488 $spoofed_nick,
489 10,
490 '^.*$@^(yahoo|google|microsoft)\.com$',
491 'on',
492 '*',
493 $reason,
494 );
495
496 "daemon_cmd_sjoin"
497 Takes two arguments a spoofed nickname and an existing channel name.
498 This command will then manipulate the channel timestamp to clear all
499 modes on that channel, including existing channel operators, reset the
500 channel mode to '+nt', the spoofed nick will then join the channel and
501 gain channel ops.
502
503 "daemon_cmd_privmsg"
504 Takes three arguments, a spoofed nickname, a target (which can be a
505 nickname or a channel name) and whatever text you wish to send.
506
507 "daemon_cmd_notice"
508 Takes three arguments, a spoofed nickname, a target (which can be a
509 nickname or a channel name) and whatever text you wish to send.
510
511 "daemon_cmd_locops"
512 Takes two arguments, a spoofed nickname and the text message to send to
513 local operators.
514
515 "daemon_cmd_wallops"
516 Takes two arguments, a spoofed nickname and the text message to send to
517 all operators.
518
519 "daemon_cmd_operwall"
520 Takes two arguments, a spoofed nickname and the text message to send to
521 all operators.
522
523OUTPUT EVENTS
524 "ircd_daemon_error"
525 Emitted: when we fail to register with a peer;
526 Target: all plugins and registered sessions;
527 Args:
528
529 * "ARG0", the connection id;
530
531 * "ARG1", the server name;
532
533 * "ARG2", the reason;
534
535 "ircd_daemon_server"
536 Emitted: when a server is introduced onto the network;
537 Target: all plugins and registered sessions;
538 Args:
539
540 * "ARG0", the server name;
541
542 * "ARG1", the name of the server that is introducing them;
543
544 * "ARG2", the hop count;
545
546 * "ARG3", the server description;
547
548 "ircd_daemon_squit"
549 Emitted: when a server quits the network;
550 Target: all plugins and registered sessions;
551 Args:
552
553 * "ARG0", the server name;
554
555 "ircd_daemon_nick"
556 Emitted: when a user is introduced onto the network or changes their
557 nickname
558 Target: all plugins and registered sessions;
559 Args (new user):
560
561 * "ARG0", the nickname;
562
563 * "ARG1", the hop count;
564
565 * "ARG2", the time stamp (TS);
566
567 * "ARG3", the user mode;
568
569 * "ARG4", the ident;
570
571 * "ARG5", the hostname;
572
573 * "ARG6", the server name;
574
575 * "ARG7", the real name;
576
577 Args (nick change):
578
579 * "ARG0", the full nick!user@host;
580
581 * "ARG1", the new nickname;
582
583 "ircd_daemon_umode"
584 Emitted: when a user changes their user mode;
585 Target: all plugins and registered sessions;
586 Args:
587
588 * "ARG0", the full nick!user@host;
589
590 * "ARG1", the user mode change;
591
592 "ircd_daemon_quit"
593 Emitted: when a user quits or the server they are on squits;
594 Target: all plugins and registered sessions;
595 Args:
596
597 * "ARG0", the full nick!user@host;
598
599 * "ARG1", the quit message;
600
601 "ircd_daemon_join"
602 Emitted: when a user joins a channel
603 Target: all plugins and registered sessions;
604 Args:
605
606 * "ARG0", the full nick!user@host;
607
608 * "ARG1", the channel name;
609
610 "ircd_daemon_part"
611 Emitted: when a user parts a channel;
612 Target: all plugins and registered sessions;
613 Args:
614
615 * "ARG0", the full nick!user@host;
616
617 * "ARG1", the channel name;
618
619 * "ARG2", the part message;
620
621 "ircd_daemon_kick"
622 Emitted: when a user is kicked from a channel;
623 Target: all plugins and registered sessions;
624 Args:
625
626 * "ARG0", the full nick!user@host of the kicker;
627
628 * "ARG1", the channel name;
629
630 * "ARG2", the nick of the kicked user;
631
632 * "ARG3", the kick message;
633
634 "ircd_daemon_mode"
635 Emitted: when a channel mode is changed;
636 Target: all plugins and registered sessions;
637 Args:
638
639 * "ARG0", the full nick!user@host or server name;
640
641 * "ARG1", the channel name;
642
643 * "ARG2..$#_", the modes and their arguments;
644
645 "ircd_daemon_topic"
646 Emitted: when a channel topic is changed
647 Target: all plugins and registered sessions;
648 Args:
649
650 * "ARG0", the full nick!user@host of the changer;
651
652 * "ARG1", the channel name;
653
654 * "ARG2", the new topic;
655
656 "ircd_daemon_public"
657 Emitted: when a channel message is sent (a spoofed nick must be in the
658 channel)
659 Target: all plugins and registered sessions;
660 Args:
661
662 * "ARG0", the full nick!user@host of the sender;
663
664 * "ARG1", the channel name;
665
666 * "ARG2", the message;
667
668 "ircd_daemon_privmsg"
669 Emitted: when someone sends a private message to a spoofed nick
670 Target: all plugins and registered sessions;
671 Args:
672
673 * "ARG0", the full nick!user@host of the sender;
674
675 * "ARG1", the spoofed nick targeted;
676
677 * "ARG2", the message;
678
679 "ircd_daemon_notice"
680 Emitted: when someone sends a notice to a spoofed nick or channel
681 Target: all plugins and registered sessions;
682 Args:
683
684 * "ARG0", the full nick!user@host of the sender;
685
686 * "ARG1", the spoofed nick targeted or channel spoofed nick is in;
687
688 * "ARG2", the message;
689
690 "ircd_daemon_invite"
691 Emitted: when someone invites a spoofed nick to a channel;
692 Target: all plugins and registered sessions;
693 Args:
694
695 * "ARG0", the full nick!user@host of the inviter;
696
697 * "ARG1", the spoofed nick being invited;
698
699 * "ARG2", the channel being invited to;
700
701 "ircd_daemon_rehash"
702 Emitted: when an oper issues a REHASH command;
703 Target: all plugins and registered sessions;
704 Args:
705
706 * "ARG0", the full nick!user@host of the oper;
707
708 "ircd_daemon_die"
709 Emitted: when an oper issues a DIE command;
710 Target: all plugins and registered sessions;
711 Args:
712
713 * "ARG0", the full nick!user@host of the oper;
714
715 Note: the component will shutdown, this is a feature;
716
717 "ircd_daemon_gline"
718 Emitted: when an oper issues a GLINE command;
719 Target: all plugins and registered sessions;
720 Args:
721
722 * "ARG0", the full nick!user@host;
723
724 * "ARG1", the user mask;
725
726 * "ARG2", the host mask;
727
728 * "ARG3", the reason;
729
730 "ircd_daemon_kline"
731 Emitted: when an oper issues a KLINE command;
732 Target: all plugins and registered sessions;
733 Args:
734
735 * "ARG0", the full nick!user@host;
736
737 * "ARG1", the target for the KLINE;
738
739 * "ARG2", the duration in seconds;
740
741 * "ARG3", the user mask;
742
743 * "ARG4", the host mask;
744
745 * "ARG5", the reason;
746
747 "ircd_daemon_rkline"
748 Emitted: when an oper issues an RKLINE command;
749 Target: all plugins and registered sessions;
750 Args:
751
752 * "ARG0", the full nick!user@host;
753
754 * "ARG1", the target for the RKLINE;
755
756 * "ARG2", the duration in seconds;
757
758 * "ARG3", the user mask;
759
760 * "ARG4", the host mask;
761
762 * "ARG5", the reason;
763
764 "ircd_daemon_unkline"
765 Emitted: when an oper issues an UNKLINE command;
766 Target: all plugins and registered sessions;
767 Args:
768
769 * "ARG0", the full nick!user@host;
770
771 * "ARG1", the target for the UNKLINE;
772
773 * "ARG2", the user mask;
774
775 * "ARG3", the host mask;
776
777 "ircd_daemon_locops"
778 Emitted: when an oper issues a LOCOPS command;
779 Target: all plugins and registered sessions;
780 Args:
781
782 * "ARG0", the full nick!user@host;
783
784 * "ARG1", the locops message;
785
786 "ircd_daemon_operwall"
787 Emitted: when an oper issues a WALLOPS or OPERWALL command;
788 Target: all plugins and registered sessions;
789 Args:
790
791 * "ARG0", the full nick!user@host;
792
793 * "ARG1", the wallops or operwall message;
794
795 "ircd_daemon_wallops"
796 Emitted: when a server issues a WALLOPS;
797 Target: all plugins and registered sessions;
798 Args:
799
800 * "ARG0", the server name;
801
802 * "ARG1", the wallops message;
803
804BUGS
805 A few have turned up in the past and they are sure to again. Please use
806 <http://rt.cpan.org/> to report any. Alternatively, email the current
807 maintainer.
808
809DEVELOPMENT
810 You can find the latest source on github:
811 <http://github.com/bingos/poe-component-server-irc>
812
813 The project's developers usually hang out in the "#poe" IRC channel on
814 irc.perl.org. Do drop us a line.
815
816MAINTAINER
817 Hinrik Örn Sigurðsson <hinrik.sig@gmail.com>
818
819AUTHOR
820 Chris 'BinGOs' Williams
821
822LICENSE
823 Copyright "(c)" Chris Williams
824
825 This module may be used, modified, and distributed under the same terms
826 as Perl itself. Please see the license that came with your Perl
827 distribution for details.
828
829KUDOS
830 Rocco Caputo for creating POE.
831
832 Buu for pestering me when I started to procrastinate =]
833
834SEE ALSO
835 POE <http://poe.perl.org/>
836
837 POE::Component::Server::IRC::Backend
838
839 Net::Netmask
840
841 Hybrid IRCD <http://ircd-hybrid.com/>
842
843 TSOra <http://www.idolnet.org/docs/README.TSora>
844
845 RFC 2810 <http://www.faqs.org/rfcs/rfc2810.html>
846
847 RFC 2811 <http://www.faqs.org/rfcs/rfc2811.html>
848
849 RFC 2812 <http://www.faqs.org/rfcs/rfc2812.html>
850
851 RFC 2813 <http://www.faqs.org/rfcs/rfc2813.html>
852
853