1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
|
NAME
Protocol::IRC - IRC protocol handling
DESCRIPTION
This mix-in class provides a base layer of IRC message handling logic.
It allows reading of IRC messages from a string buffer and dispatching
them to handler methods on its instance.
Protocol::IRC::Client provides an extension to this logic that may be
more convenient for IRC client implementations. Much of the code
provided here is still useful in client applications, so the reader
should be familiar with both modules.
MESSAGE HANDLING
Every incoming message causes a sequence of message handling to occur.
First, the message is parsed, and a hash of data about it is created;
this is called the hints hash. The message and this hash are then
passed down a sequence of potential handlers.
Each handler indicates by return value, whether it considers the
message to have been handled. Processing of the message is not
interrupted the first time a handler declares to have handled a
message. Instead, the hints hash is marked to say it has been handled.
Later handlers can still inspect the message or its hints, using this
information to decide if they wish to take further action.
A message with a command of COMMAND will try handlers in following
places:
1. A method called on_message_COMMAND
$irc->on_message_COMMAND( $message, \%hints )
2. A method called on_message
$irc->on_message( 'COMMAND', $message, \%hints )
For server numeric replies, if the numeric reply has a known name, it
will be attempted first at its known name, before falling back to the
numeric if it was not handled. Unrecognised numerics will be attempted
only at their numeric value.
Because of the wide variety of messages in IRC involving various types
of data the message handling specific cases for certain types of
message, including adding extra hints hash items, or invoking extra
message handler stages. These details are noted here.
Many of these messages create new events; called synthesized messages.
These are messages created by the Protocol::IRC object itself, to
better represent some of the details derived from the primary ones from
the server. These events all take lower-case command names, rather than
capitals, and will have a synthesized key in the hints hash, set to a
true value. These are dispatched and handled identically to regular
primary events, detailed above.
If any handler of the synthesized message returns true, then this marks
the primary message handled as well.
If a message is received that has a gating disposition, extra
processing is applied to it before the processing above. The effect on
its gate is given as a string (one of more, done, fail) to handlers in
the following places:
1. A method called on_message_gate_EFFECT_GATE
$irc->on_message_gate_EFFECT_GATE( $message, \%hints )
2. A method called on_message_gate_EFFECT
$irc->on_message_gate_EFFECT( 'GATE', $message, \%hints )
3. A method called on_message_gate
$irc->on_message_gate( 'EFFECT', 'GATE', $message, \%hints )
Message Hints
When messages arrive they are passed to the appropriate message
handling method, which the implementation may define. As well as the
message, a hash of extra information derived from or relating to the
message is also given.
The following keys will be present in any message hint hash:
handled => BOOL
Initially false. Will be set to true the first time a handler returns
a true value.
prefix_nick => STRING
prefix_user => STRING
prefix_host => STRING
Values split from the message prefix; see the Protocol::IRC::Message
prefix_split method.
prefix_name => STRING
Usually the prefix nick, or the hostname in case the nick isn't
defined (usually on server messages).
prefix_is_me => BOOL
True if the nick mentioned in the prefix refers to this connection.
Added to this set, will be all the values returned by the message's
named_args method. Some of these values may cause yet more values to be
generated.
If the message type defines a target_name:
* target_type => STRING
Either channel or user, as returned by classify_name.
* target_is_me => BOOL
True if the target name is a user and refers to this connection.
Any key whose name ends in _nick or _name will have a corresponding key
added with _folded suffixed on its name, containing the value
casefolded using casefold_name. This is for the convenience of string
comparisons, hash keys, etc..
Any of these keys that are not the prefix_name will additionally have a
corresponding key with _is_me replacing the _nick or _name, containing
the boolean result of calling the is_nick_me method on that name. This
makes it simpler to detect commands or results affecting the user the
connection represents.
METHODS
on_read
$irc->on_read( $buffer )
Informs the protocol implementation that more bytes have been read from
the peer. This method will modify the $buffer directly, and remove from
it the prefix of bytes it has consumed. Any bytes remaining should be
stored by the caller for next time.
Any messages found in the buffer will be passed, in sequence, to the
incoming_message method.
incoming_message
$irc->incoming_message( $message )
Invoked by the on_read method for every incoming IRC message. This
method implements the actual dispatch into various handler methods as
described in the "MESSAGE HANDLING" section above.
This method is exposed so that subclasses can override it, primarily to
wrap extra logic before or after the main dispatch (e.g. for logging or
other processing).
send_message
This method takes arguments in three different forms, depending on
their number and type.
If the first argument is a reference then it must contain a
Protocol::IRC::Message instance which will be sent directly:
$irc->send_message( $message )
Otherwise, the first argument must be a plain string that gives the
command name. If the second argument is a hash, it provides named
arguments in a form similar to "new_from_named_args" in
Protocol::IRC::Message, otherwise the remaining arguments must be the
prefix string and other positional arguments, as plain strings:
$irc->send_message( $command, { %args } )
$irc->send_message( $command, $prefix, @args )
Named Argument Mangling
For symmetry with incoming message processing, this method applies some
adjustment of named arguments for convenience of callers.
* Callers may define a named argument of target; it will be renamed
to target_name.
* If a named argument of text is defined and an "encoder" exists, the
argument value will be encoded using this encoder.
send_ctcp
$irc->send_ctcp( $prefix, $target, $verb, $argstr )
Shortcut to sending a CTCP message. Sends a PRIVMSG to the given
target, containing the given verb and argument string.
send_ctcpreply
$irc->send_ctcpreply( $prefix, $target, $verb, $argstr )
Shortcut to sending a CTCP reply. As send_ctcp but using a NOTICE
instead.
ISUPPORT-DRIVEN UTILITIES
The following methods are controlled by the server information given in
the ISUPPORT settings. They use the isupport required method to query
the information required.
casefold_name
$name_folded = $irc->casefold_name( $name )
Returns the $name, folded in case according to the server's CASEMAPPING
ISUPPORT. Such a folded name will compare using eq according to whether
the server would consider it the same name.
Useful for use in hash keys or similar.
cmp_prefix_flags
$cmp = $irc->cmp_prefix_flags( $lhs, $rhs )
Compares two channel occupant prefix flags, and returns a signed
integer to indicate which of them has higher priviledge, according to
the server's ISUPPORT declaration. Suitable for use in a sort()
function or similar.
cmp_prefix_modes
$cmp = $irc->cmp_prefix_modes( $lhs, $rhs )
Similar to cmp_prefix_flags, but compares channel occupant MODE command
flags.
prefix_mode2flag
$flag = $irc->prefix_mode2flag( $mode )
Converts a channel occupant MODE flag (such as o) into a name prefix
flag (such as @).
prefix_flag2mode
$mode = $irc->prefix_flag2mode( $flag )
The inverse of prefix_mode2flag.
classify_name
$classification = $irc->classify_name( $name )
Returns channel if the given name matches the pattern of names allowed
for channels according to the server's CHANTYPES ISUPPORT. Returns user
if not.
is_nick_me
$me = $irc->is_nick_me( $nick )
Returns true if the given nick refers to that in use by the connection.
INTERNAL MESSAGE HANDLING
The following messages are handled internally by Protocol::IRC.
PING
PING messages are automatically replied to with PONG.
NOTICE and PRIVMSG
Because NOTICE and PRIVMSG are so similar, they are handled together by
synthesized events called text, ctcp and ctcpreply. Depending on the
contents of the text, and whether it was supplied in a PRIVMSG or a
NOTICE, one of these three events will be created.
In all cases, the hints hash will contain a is_notice key being true or
false, depending on whether the original messages was a NOTICE or a
PRIVMSG, a target_name key containing the message target name, a
case-folded version of the name in a target_name_folded key, and a
classification of the target type in a target_type key.
For the user target type, it will contain a boolean in target_is_me to
indicate if the target of the message is the user represented by this
connection.
For the channel target type, it will contain a restriction key
containing the channel message restriction, if present.
For normal text messages, it will contain a key text containing the
actual message text.
For either CTCP message type, it will contain keys ctcp_verb and
ctcp_args with the parsed message. The ctcp_verb will contain the first
space-separated token, and ctcp_args will be a string containing the
rest of the line, otherwise unmodified. This type of message is also
subject to a special stage of handler dispatch, involving the CTCP verb
string. For messages with VERB as the verb, the following are tried.
CTCP may stand for either ctcp or ctcpreply.
1. A method called on_message_CTCP_VERB
$irc->on_message_CTCP_VERB( $message, \%hints )
2. A method called on_message_CTCP
$irc->on_message_CTCP( 'VERB', $message, \%hintss )
3. A method called on_message
$irc->on_message( 'CTCP VERB', $message, \%hints )
REQUIRED METHODS
As this class is an abstract base class, a concrete implementation must
provide the following methods to complete it and make it useable.
write
$irc->write( $string )
Requests the byte string to be sent to the peer
encoder
$encoder = $irc->encoder
Optional. If supplied, returns an Encode object used to encode or
decode the bytes appearing in a text field of a message. If set, all
text strings will be returned, and should be given, as Unicode strings.
They will be encoded or decoded using this object.
invoke
$result = $irc->invoke( $name, @args )
Optional. If provided, invokes the message handling routine called
$name with the given arguments. A default implementation is provided
which simply attempts to invoke a method of the given name, or return
false if no method of that name exists.
If an implementation does override this method, care should be taken to
ensure that methods are tested for and invoked if present, in addition
to any other work the method wishes to perform, as this is the basis by
which derived message handling works.
isupport
$value = $irc->isupport( $field )
Should return the value of the given ISUPPORT field.
As well as the all-capitals server-supplied fields, the following
fields may be requested. Their names are all lowercase and contain
underscores, to distinguish them from server-supplied fields.
prefix_modes => STRING
The mode characters from PREFIX (e.g. ohv)
prefix_flags => STRING
The flag characters from PREFIX (e.g. @%+)
prefixflag_re => Regexp
A precompiled regexp that matches any of the prefix flags
prefix_map_m2f => HASH
A map from mode characters to flag characters
prefix_map_f2m => HASH
A map from flag characters to mode characters
chanmodes_list => ARRAY
A 4-element array containing the split portions of CHANMODES;
[ $listmodes, $argmodes, $argsetmodes, $boolmodes ]
channame_re => Regexp
A precompiled regexp that matches any string beginning with a channel
prefix character in CHANTYPES.
nick
$nick = $irc->nick
Should return the current nick in use by the connection.
nick_folded
$nick_folded = $irc->nick_folded
Optional. If supplied, should return the current nick as case-folded by
the casefold_name method. If not provided, this will be performed by
case-folding the result from nick.
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
|