| 1 |
<?xml version="1.0" encoding="ISO-8859-1"?> |
| 2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11-strict.dtd"> |
| 3 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> |
| 4 |
<head> |
| 5 |
<meta http-equiv="Content-Style-Type" content="text/css"/> |
| 6 |
<style type="text/css">@import "style.css";</style> |
| 7 |
<title>IRC Services Technical Reference Manual - 5. IRC server interface</title> |
| 8 |
</head> |
| 9 |
|
| 10 |
<body> |
| 11 |
<h1 class="title" id="top">IRC Services Technical Reference Manual</h1> |
| 12 |
|
| 13 |
<h2 class="section-title">5. IRC server interface</h2> |
| 14 |
|
| 15 |
<p class="section-toc"> |
| 16 |
5-1. <a href="#s1">Protocol modules: the IRC protocol bridge</a> |
| 17 |
<br/>5-2. <a href="#s2">Specifying protocol features</a> |
| 18 |
<br/>5-3. <a href="#s3">Sending messages to the network</a> |
| 19 |
<br/> 5-3-1. <a href="#s3-1">Required functionality</a> |
| 20 |
<br/> 5-3-2. <a href="#s3-2">Optional functionality</a> |
| 21 |
<br/>5-4. <a href="#s4">Receiving messages from the network</a> |
| 22 |
<br/> 5-4-1. <a href="#s4-1">Required functionality</a> |
| 23 |
<br/> 5-4-2. <a href="#s4-2">Optional functionality</a> |
| 24 |
<br/>5-5. <a href="#s5">Other functions of protocol modules</a> |
| 25 |
<br/>5-6. <a href="#s6">Specific protocol module details</a> |
| 26 |
<br/> 5-6-1. <a href="#s6-1"><tt>protocol/rfc1459</tt></a> |
| 27 |
<br/> 5-6-2. <a href="#s6-2"><tt>protocol/ts8</tt></a> |
| 28 |
<br/> 5-6-3. <a href="#s6-3"><tt>protocol/dalnet</tt></a> |
| 29 |
<br/> 5-6-4. <a href="#s6-4"><tt>protocol/dreamforge</tt></a> |
| 30 |
<br/> 5-6-5. <a href="#s6-5"><tt>protocol/bahamut</tt></a> |
| 31 |
<br/> 5-6-6. <a href="#s6-6"><tt>protocol/hybrid</tt></a> |
| 32 |
<br/> 5-6-7. <a href="#s6-7"><tt>protocol/inspircd</tt></a> |
| 33 |
<br/> 5-6-8. <a href="#s6-8"><tt>protocol/monkey</tt></a> |
| 34 |
<br/> 5-6-9. <a href="#s6-9"><tt>protocol/ptlink</tt></a> |
| 35 |
<br/> 5-6-10. <a href="#s6-10"><tt>protocol/ratbox</tt></a> |
| 36 |
<br/> 5-6-11. <a href="#s6-11"><tt>protocol/solidircd</tt></a> |
| 37 |
<br/> 5-6-12. <a href="#s6-12"><tt>protocol/trircd</tt></a> |
| 38 |
<br/> 5-6-13. <a href="#s6-13"><tt>protocol/undernet-p9</tt></a> |
| 39 |
<br/> 5-6-14. <a href="#s6-14"><tt>protocol/unreal</tt></a> |
| 40 |
<br/> 5-6-14-1. <a href="#s6-14-1">Module prologue</a> |
| 41 |
<br/> 5-6-14-2. <a href="#s6-14-2">Message receiving</a> |
| 42 |
<br/> 5-6-14-3. <a href="#s6-14-3">Message sending</a> |
| 43 |
<br/> 5-6-14-4. <a href="#s6-14-4">Module initialization and cleanup</a> |
| 44 |
<br/>5-7. <a href="#s7">Auxiliary source file details</a> |
| 45 |
<br/> 5-7-1. <a href="#s7-1"><tt>banexcept.c</tt>, <tt>banexcept.h</tt></a> |
| 46 |
<br/> 5-7-2. <a href="#s7-2"><tt>chanprot.c</tt>, <tt>chanprot.h</tt></a> |
| 47 |
<br/> 5-7-3. <a href="#s7-3"><tt>halfop.c</tt>, <tt>halfop.h</tt></a> |
| 48 |
<br/> 5-7-4. <a href="#s7-4"><tt>invitemask.c</tt>, <tt>invitemask.h</tt></a> |
| 49 |
<br/> 5-7-5. <a href="#s7-5"><tt>sjoin.c</tt>, <tt>sjoin.h</tt></a> |
| 50 |
<br/> 5-7-6. <a href="#s7-6"><tt>svsnick.c</tt>, <tt>svsnick.h</tt></a> |
| 51 |
<br/> 5-7-7. <a href="#s7-7"><tt>token.c</tt>, <tt>token.h</tt></a> |
| 52 |
</p> |
| 53 |
|
| 54 |
<p class="backlink"><a href="4.html">Previous section: The module system</a> | |
| 55 |
<a href="index.html">Table of Contents</a> | |
| 56 |
<a href="6.html">Next section: Database handling</a></p> |
| 57 |
|
| 58 |
<!------------------------------------------------------------------------> |
| 59 |
<hr/> |
| 60 |
|
| 61 |
<h3 class="subsection-title" id="s1">5-1. Protocol modules: the IRC protocol bridge</h3> |
| 62 |
|
| 63 |
<p>While the "official" IRC protocol is defined in the document |
| 64 |
<a href="http://www.ietf.org/rfc/rfc1459.txt">RFC 1459</a> |
| 65 |
<span class="remotehost">[www.ietf.org]</span>, modern IRC servers have |
| 66 |
added many extensions to this base protocol over the years, and the current |
| 67 |
state of IRC software is such that it is rare to find an IRC server |
| 68 |
implementation that can communicate with a different implementation. This |
| 69 |
makes the job of Services considerably more difficult, as it must |
| 70 |
communicate with servers in order to perform its job, and there is no |
| 71 |
telling what implementation a particular network administrator will choose.</p> |
| 72 |
|
| 73 |
<p>In order to overcome these differences in protocol, Services makes use |
| 74 |
of <i>protocol modules</i>, a class of modules which interface between the |
| 75 |
generic IRC server implemented by the Services core and the specific |
| 76 |
protocols used by different IRC server implementations. While there are |
| 77 |
some basic assumptions made by the core code about the protocol—for |
| 78 |
example, that the protocol uses lines of text terminated by a CR/LF |
| 79 |
pair—most differences seen in current IRC servers can be handled by |
| 80 |
protocol modules.</p> |
| 81 |
|
| 82 |
<p>The standard protocol modules distributed in Services are located in the |
| 83 |
<tt>modules/protocol</tt> directory, along with auxiliary source and header |
| 84 |
files that implement functionality common to multiple protocols. This |
| 85 |
location is not a requirement, however; third-party modules can be located |
| 86 |
in different directories, provided that they implement the required |
| 87 |
functionality described in this section.</p> |
| 88 |
|
| 89 |
<p>Note that, in order to simplify the module initialization process, |
| 90 |
Services requires that a protocol module be loaded before any other |
| 91 |
modules; this requirement is enforced by the <tt>load_module()</tt> |
| 92 |
routine, as discussed in <a href="4.html#s3-1">section 4-3-1</a>. A number |
| 93 |
of pseudoclient modules alter their behavior depending on features of the |
| 94 |
IRC protocol in use, such as maximum nickname length or support of certain |
| 95 |
nonstandard IRC messages, and this requirement allows such modules to |
| 96 |
simply check the protocol information without having to ensure that a |
| 97 |
protocol module has been loaded (and subsequently watch for protocol module |
| 98 |
loads and unloads). <i>Implementation note: Although <tt>load_module()</tt> |
| 99 |
ensures that a protocol module is loaded first, <tt>unload_module()</tt> |
| 100 |
does <b>not</b> prevent protocol modules from being unloaded! Protocol |
| 101 |
modules should therefore use an <tt>exit_module()</tt> routine that returns |
| 102 |
zero on any unload attempt, except during shutdown. The modules included |
| 103 |
with Services all exhibit this behavior.</i></p> |
| 104 |
|
| 105 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 106 |
|
| 107 |
<!------------------------------------------------------------------------> |
| 108 |
<hr/> |
| 109 |
|
| 110 |
<h3 class="subsection-title" id="s2">5-2. Specifying protocol features</h3> |
| 111 |
|
| 112 |
<p>In addition to providing the functionality listed in subsequent |
| 113 |
sections, protocol modules must inform Services of certain information |
| 114 |
about the protocol in use. This is done by setting the following global |
| 115 |
variables (defined in <tt>send.c</tt>) in the module's <tt>module_init()</tt> |
| 116 |
routine:</p> |
| 117 |
|
| 118 |
<dl> |
| 119 |
<dt><tt>const char *protocol_name</tt></dt> |
| 120 |
<dd>Specifies the name of the protocol supported by the module. This |
| 121 |
variable is provided for informational purposes only. (The current |
| 122 |
core code does not make any use of the variable.)</dd> |
| 123 |
|
| 124 |
<dt><tt>const char *protocol_version</tt></dt> |
| 125 |
<dd>Specifies the version(s) of the protocol supported by the module, |
| 126 |
if applicable (the variable may be left unset if there is only one |
| 127 |
version of the protocol). This variable is provided for |
| 128 |
informational purposes only.</dd> |
| 129 |
|
| 130 |
<dt><tt>int32 protocol_features</tt></dt> |
| 131 |
<dd>Specifies particular features supported by the protocol. The value |
| 132 |
should be a combination (bitwise OR) of zero or more of the |
| 133 |
following flags: |
| 134 |
<ul> |
| 135 |
<li><b><tt>PF_HALFOP</tt>:</b> Supports a "half-op" channel |
| 136 |
user mode (such as <tt>+h</tt> as used with the Unreal |
| 137 |
protocol).</li> |
| 138 |
<li><b><tt>PF_CHANPROT</tt>:</b> Supports a "protected" channel |
| 139 |
user mode (such as <tt>+a</tt> as used with the Unreal |
| 140 |
protocol).</li> |
| 141 |
<li><b><tt>PF_BANEXCEPT</tt>:</b> Supports channel ban |
| 142 |
exceptions.</li> |
| 143 |
<li><b><tt>PF_SZLINE</tt>:</b> Supports an <tt>SZLINE</tt> or |
| 144 |
similar server-to-server command to ban an IP address from |
| 145 |
connecting to any server on the network.</li> |
| 146 |
<li><b><tt>PF_NOQUIT</tt>:</b> Uses "NOQUIT" mode, in which |
| 147 |
servers do not send <tt>QUIT</tt> messages for affected |
| 148 |
clients when a netsplit occurs (see, for example, |
| 149 |
<a href="#s6-5">section 5-6-5</a>).</li> |
| 150 |
<li><b><tt>PF_SVSJOIN</tt>:</b> Supports an <tt>SVSJOIN</tt> or |
| 151 |
similar server-to-server command to force a client to join a |
| 152 |
channel.</li> |
| 153 |
<li><b><tt>PF_CHANGENICK</tt>:</b> Supports a method through |
| 154 |
which a server can forcibly change a client's nickname.</li> |
| 155 |
<li><b><tt>PF_AKILL_EXCL</tt>:</b> Supports autokill exclusions |
| 156 |
(exceptions to network-wide bans as set by the OperServ |
| 157 |
<tt>AKILL</tt> command).</li> |
| 158 |
<li><b><tt>PF_MODETS_FIRST</tt>:</b> Sends the timestamp in a |
| 159 |
channel <tt>MODE</tt> message immediately after the channel |
| 160 |
name, rather than at the end of the message.</li> |
| 161 |
<li><b><tt>PF_INVITEMASK</tt>:</b> Supports channel invite |
| 162 |
masks (masks allowing users who match to join an |
| 163 |
invite-only channel without being invited, such as the |
| 164 |
<tt>+i</tt> channel mode as used with the Unreal |
| 165 |
protocol).</li> |
| 166 |
</ul> |
| 167 |
Note that <tt>protocol_features</tt> is initialized to a value of |
| 168 |
<tt>PF_UNSET</tt> to detect whether its value has been changed, so |
| 169 |
the protocol module should use a direct assignment (rather than an |
| 170 |
OR-assignment) to set the value.</dd> |
| 171 |
|
| 172 |
<dt><tt>int protocol_nickmax</tt></dt> |
| 173 |
<dd>Specifies the maximum number of characters (bytes) allowed in a |
| 174 |
nickname.</dd> |
| 175 |
</dl> |
| 176 |
|
| 177 |
<p><tt>send.c</tt> hooks into the "<tt>load module</tt>" callback to check |
| 178 |
that these variables, as well as the functions listed in |
| 179 |
<a href="#s3-1">section 5-3-1</a>, are appropriately set when a protocol |
| 180 |
module is loaded, generating a fatal error if not. <i>Implementation note: |
| 181 |
As mentioned in <a href="2.html#s5-1">section 2-5-1</a>, there is nothing |
| 182 |
to mark a protocol module as being such, so the callback function simply |
| 183 |
assumes that the first module loaded is a protocol module.</i></p> |
| 184 |
|
| 185 |
<p>There are also three variables which can be optionally set as needed:</p> |
| 186 |
|
| 187 |
<dl> |
| 188 |
<dt><tt>const char *pseudoclient_modes</tt></dt> |
| 189 |
<dd>Specifies the user modes, if any, that should be set on any newly |
| 190 |
introduced pseudoclient; a leading "<tt>+</tt>" should <i>not</i> |
| 191 |
be added. For example, if a protocol includes a user mode |
| 192 |
specifically for pseudoclients, that mode should be set here. |
| 193 |
Defaults to the empty string (no modes). Note that mode |
| 194 |
<tt>o</tt> (operator privilege) should <i>not</i> be specified even |
| 195 |
if some pseudoclients need operator privileges to perform their |
| 196 |
functions; use <tt>pseudoclient_oper</tt> for that instead (see |
| 197 |
below).</dd> |
| 198 |
|
| 199 |
<dt><tt>const char *enforcer_modes</tt></dt> |
| 200 |
<dd>Specifies the user modes, if any, that should be set on |
| 201 |
pseudoclients used as nickname enforcers. Defaults to the empty |
| 202 |
string (no modes).</dd> |
| 203 |
|
| 204 |
<dt><tt>int pseudoclient_oper</tt></dt> |
| 205 |
<dd>Indicates whether pseudoclients which perform actions restricted to |
| 206 |
IRC operators need the IRC operator user mode (<tt>+o</tt>) set. |
| 207 |
Defaults to 1, causing this mode to be set (0 disables |
| 208 |
<tt>+o</tt>).</dd> |
| 209 |
</dl> |
| 210 |
|
| 211 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 212 |
|
| 213 |
<!------------------------------------------------------------------------> |
| 214 |
<hr/> |
| 215 |
|
| 216 |
<h3 class="subsection-title" id="s3">5-3. Sending messages to the network</h3> |
| 217 |
|
| 218 |
<p>The bulk of a protocol module consists of routines to send messages to |
| 219 |
and process messages from the network, handling any peculiarites of the |
| 220 |
particular protocol in use.</p> |
| 221 |
|
| 222 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 223 |
|
| 224 |
|
| 225 |
<h4 class="subsubsection-title" id="s3-1">5-3-1. Required functionality</h4> |
| 226 |
|
| 227 |
<p>A number of the common message sending operations defined in |
| 228 |
<tt>send.c</tt> are defined as function pointers, which the protocol |
| 229 |
module must set to point to appropriate functions (by default, they point |
| 230 |
to a placeholder function which generates a fatal error). These function |
| 231 |
pointers (see <a href="2.html#s5-1">section 2-5-1</a> for descriptions of |
| 232 |
the functions) are:</p> |
| 233 |
|
| 234 |
<ul> |
| 235 |
<li><tt>void (*<b>send_nick</b>)(const char *<i>nick</i>, |
| 236 |
const char *<i>user</i>, const char *<i>host</i>, |
| 237 |
const char *<i>server</i>, const cahr *<i>name</i>, |
| 238 |
const char *<i>modes</i>)</tt></li> |
| 239 |
<li><tt>void (*<b>send_nickchange</b>)(const char *<i>nick</i>, const char *<i>newnick</i>)</tt></li> |
| 240 |
<li><tt>void (*<b>send_namechange</b>)(const char *<i>name</i>, const char *<i>newname</i>)</tt></li> |
| 241 |
<li><tt>void (*<b>send_server</b>)()</tt></li> |
| 242 |
<li><tt>void (*<b>send_server_remote</b>)(const char *<i>server</i>, const char *<i>desc</i>)</tt></li> |
| 243 |
<li><tt>void (*<b>wallops</b>)(const char *<i>source</i>, const char *<i>fmt</i>, ...)</tt></li> |
| 244 |
<li><tt>void (*<b>notice_all</b>)(const char *<i>source</i>, const char *<i>fmt</i>, ...)</tt></li> |
| 245 |
<li><tt>void (*<b>send_channel_cmd</b>)(const char *<i>source</i>, const char *<i>fmt</i>, ...)</tt></li> |
| 246 |
</ul> |
| 247 |
|
| 248 |
<p>Protocol modules must also provide a handler for the "<tt>set |
| 249 |
topic</tt>" callback. The callback function should have the following |
| 250 |
signature:</p> |
| 251 |
|
| 252 |
<div class="code">int set_topic_handler(const char *<i>source</i>, |
| 253 |
Channel *<i>c</i>, |
| 254 |
const char *<i>topic</i>, |
| 255 |
const char *<i>setter</i>, |
| 256 |
time_t <i>t</i>)</div> |
| 257 |
|
| 258 |
<p>This callback is called twice for each time the topic is set. The first |
| 259 |
call is made before the <tt>Channel</tt> structure is changed, and |
| 260 |
<tt><i>topic</i></tt>, <tt><i>setter</i></tt>, and <tt><i>t</i></tt> are |
| 261 |
filled in with the new topic text, the nickname to be used as the topic |
| 262 |
setter, and the timestamp for the topic. The second call is made after |
| 263 |
the <tt>topic</tt> and <tt>topic_setter</tt> fields of the <tt>Channel</tt> |
| 264 |
structure have been set to the new values, and the corresponding parameters |
| 265 |
to the callback (<tt><i>topic</i></tt> and <tt><i>setter</i></tt>) are |
| 266 |
<tt>NULL</tt> for this call. Note that the <tt>topic_time</tt> field is |
| 267 |
<i>not</i> set by the core, and must be set appropriately by the callback |
| 268 |
function; this is because some protocols require that the timestamp of a |
| 269 |
channel topic must be newer or older than the current topic's timestamp for |
| 270 |
the new topic to be accepted.</p> |
| 271 |
|
| 272 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 273 |
|
| 274 |
|
| 275 |
<h4 class="subsubsection-title" id="s3-2">5-3-2. Optional functionality</h4> |
| 276 |
|
| 277 |
<p>In addition to the functions listed above, the OperServ modules |
| 278 |
implementing the autokill and S-line functionality (see sections |
| 279 |
<a href="7.html#s2-2-2">7-2-2-2</a> and <a href="7.html#s2-2-3">7-2-2-3</a>) |
| 280 |
register message-sending callbacks which they expect the protocol module to |
| 281 |
hook into if it supports the relevant messages. These callbacks (see |
| 282 |
<a href="c.html#s3">Appendix C</a> for details) are:</p> |
| 283 |
|
| 284 |
<ul> |
| 285 |
<li><tt><b>send_akill</b></tt>: Sends an autokill to the network.</li> |
| 286 |
<li><tt><b>cancel_akill</b></tt>: Clears an autokill from the network.</li> |
| 287 |
<li><tt><b>send_exclude</b></tt>: Sends an autokill exclusion to the network.</li> |
| 288 |
<li><tt><b>cancel_exclude</b></tt>: Clears an autokill exclusion from the network.</li> |
| 289 |
<li><tt><b>send_sgline</b></tt>: Sends an SGline to the network.</li> |
| 290 |
<li><tt><b>cancel_sgline</b></tt>: Clears an SGline from the network.</li> |
| 291 |
<li><tt><b>send_sqline</b></tt>: Sends an SQline to the network.</li> |
| 292 |
<li><tt><b>cancel_sqline</b></tt>: Clears an SQline from the network.</li> |
| 293 |
<li><tt><b>send_szline</b></tt>: Sends an SZline to the network.</li> |
| 294 |
<li><tt><b>cancel_szline</b></tt>: Clears an SZline from the network.</li> |
| 295 |
</ul> |
| 296 |
|
| 297 |
<p>If any of the callbacks are left unsupported, Services will simply send |
| 298 |
a <tt>KILL</tt> or other appropriate message each time the autokill or |
| 299 |
S-line is triggered. (However, hooking into a "send" callback but not the |
| 300 |
corresponding "cancel" callback can have undesirable consequences!)</p> |
| 301 |
|
| 302 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 303 |
|
| 304 |
<!------------------------------------------------------------------------> |
| 305 |
<hr/> |
| 306 |
|
| 307 |
<h3 class="subsection-title" id="s4">5-4. Receiving messages from the network</h3> |
| 308 |
|
| 309 |
<p>While basic message parsing and processing is handled by the Services |
| 310 |
core, it is up to protocol modules to handle details of the particular |
| 311 |
protocol as well as additional messages used by the protocol.</p> |
| 312 |
|
| 313 |
<p>In Services, processing of received messages is handled using tables of |
| 314 |
message names and corresponding processing routines, as described in |
| 315 |
<a href="2.html#s5-3">section 2-5-3</a>. Protocol modules will typically |
| 316 |
define a message table for messages handled by the module, and call |
| 317 |
<tt>register_messages()</tt> to register the message table during module |
| 318 |
initialization.</p> |
| 319 |
|
| 320 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 321 |
|
| 322 |
|
| 323 |
<h4 class="subsubsection-title" id="s4-1">5-4-1. Required functionality</h4> |
| 324 |
|
| 325 |
<p>The only functionality required in protocol modules is the ability to |
| 326 |
recognize new clients connecting to the network and clients changing |
| 327 |
nicknames. As described in <a href="2.html#s5-3">section 2-5-3</a>, the |
| 328 |
<tt>NICK</tt> and <tt>USER</tt> messages are not supported by the Services |
| 329 |
core because of the differences between protocols in handling them; thus, |
| 330 |
the protocol module must supply its own handler routines for these |
| 331 |
messages, or whatever other messages may be used in their place.</p> |
| 332 |
|
| 333 |
<p>However, in many protocols there are other messages which must be |
| 334 |
handled properly to maintain the network state. These, of course, must be |
| 335 |
processed accordingly as well.</p> |
| 336 |
|
| 337 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 338 |
|
| 339 |
|
| 340 |
<h4 class="subsubsection-title" id="s4-2">5-4-2. Optional functionality</h4> |
| 341 |
|
| 342 |
<p>As described above, modules can add support for additional messages |
| 343 |
through a message table; the default processing for core-handled messages |
| 344 |
can be changed the same way, if (for example) a message takes a different |
| 345 |
set of parameters than the "standard" server assumed by the core code.</p> |
| 346 |
|
| 347 |
<p>There are some types of functionality shared among several servers, such |
| 348 |
as the <tt>SJOIN</tt> message used in protocols such as Bahamut and Unreal |
| 349 |
to update a channel's state with one message, or the "token" systems used |
| 350 |
by some protocols to reduce the bandwidth and processing required for |
| 351 |
inter-server messages. These are implemented by separate source files, |
| 352 |
which can be included in the module's source to implement the particular |
| 353 |
functionality. These are described in <a href="#s7">section 5-7</a>.</p> |
| 354 |
|
| 355 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 356 |
|
| 357 |
<!------------------------------------------------------------------------> |
| 358 |
<hr/> |
| 359 |
|
| 360 |
<h3 class="subsection-title" id="s5">5-5. Other functions of protocol modules</h3> |
| 361 |
|
| 362 |
<p>Aside from handling the sending and receiving of messages particular to |
| 363 |
the protocol, protocol modules must handle any other aspect of |
| 364 |
server-to-server communication that is not done in the core. Chief among |
| 365 |
these is the handling of protocol-specific modes.</p> |
| 366 |
|
| 367 |
<p>Many IRC server implementations add new modes to the basic set; the |
| 368 |
module must be able to recognize and process these modes appropriately. |
| 369 |
This can be done using the core mode-handling facility (see |
| 370 |
<a href="2.html#s6-4">section 2-6-4</a>), or by hooking into the |
| 371 |
<tt>MODE</tt> message callbacks "<tt>user MODE</tt>" and |
| 372 |
"<tt>channel MODE</tt>" (in the case of modes that take parameters, it is |
| 373 |
usually necessary to use the latter method in order to store the parameter |
| 374 |
values in the channel structure). The module may also need to hook into |
| 375 |
various pseudoclient callbacks; see the relevant parts of |
| 376 |
<a href="7.html">section 7</a>, or see the description of the Unreal |
| 377 |
protocol module, which uses most of these callbacks, in |
| 378 |
<a href="#s6-14">section 5-6-14</a> below.</p> |
| 379 |
|
| 380 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 381 |
|
| 382 |
<!------------------------------------------------------------------------> |
| 383 |
<hr/> |
| 384 |
|
| 385 |
<h3 class="subsection-title" id="s6">5-6. Specific protocol module details</h3> |
| 386 |
<p>This section describes each of the protocol modules supplied with |
| 387 |
Services. In addition to the source file for the module itself, some |
| 388 |
protocol modules make use of auxiliary source files in the same directory; |
| 389 |
these files are described in detail in <a href="#s7">section 5-7</a>. For |
| 390 |
the most part, each subsection only covers details unique to that |
| 391 |
particular module, but the <tt>protocol/unreal</tt> module |
| 392 |
(<a href="#s6-14">section 5-6-14</a>), which makes use of almost all |
| 393 |
protocol-related functionality, is discussed in more detail.</p> |
| 394 |
|
| 395 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 396 |
|
| 397 |
|
| 398 |
<h4 class="subsubsection-title" id="s6-1">5-6-1. <tt>protocol/rfc1459</tt></h4> |
| 399 |
|
| 400 |
<p>The <tt>protocol/rfc1459</tt> module provides an interface for servers |
| 401 |
which strictly follow the standard IRC protocol, as defined in RFC 1459. |
| 402 |
While few if any such servers still remain in operation, this module serves |
| 403 |
as a reference implementation for Services.</p> |
| 404 |
|
| 405 |
<p>Since the generic IRC server implemented by Services is very similar to |
| 406 |
the RFC 1459 standard, this module is rather straightforward. In a format |
| 407 |
shared by the other standard protocol modules as well, the module is |
| 408 |
divided into four major parts: routines to process received IRC messages, |
| 409 |
routines to send IRC messages, callback functions, and module-related |
| 410 |
functions and variables.</p> |
| 411 |
|
| 412 |
<p>The only received messages which need special processing are the |
| 413 |
<tt>NICK</tt> and <tt>USER</tt> messages used for introducing clients. |
| 414 |
The module ignores the <tt>NICK</tt> message, assuming that the remote |
| 415 |
server will take care of checking for collisions with the nicknames of any |
| 416 |
pseudoclients introduced by Services, and uses the parameters to the |
| 417 |
<tt>USER</tt> message to initialize the client's data record. Before |
| 418 |
calling <tt>do_nick()</tt> to perform this action, the handler for the |
| 419 |
<tt>USER</tt> message, <tt>m_user()</tt>, sets up a new parameter list |
| 420 |
with the parameters in the order <tt>do_nick()</tt> expects them, filling |
| 421 |
in default values for parameters unavailable in the RFC 1459 protocol. |
| 422 |
(Technically, the hop count parameter is available from the <tt>NICK</tt> |
| 423 |
message, but since it would take considerable extra effort to save this |
| 424 |
value until the <tt>USER</tt> message arrived, and since the hop count is |
| 425 |
not used by Services anyway, this field is simply discarded and a default |
| 426 |
value of 0 used.)</p> |
| 427 |
|
| 428 |
<p>The message-sending routines are likewise simple, for the most part. |
| 429 |
The only routine that deserves special mention is the |
| 430 |
<tt>do_notice_all()</tt> routine, which implements the <tt>notice_all()</tt> |
| 431 |
function of <tt>send.c</tt>. Since the RFC 1459 protocol does not permit a |
| 432 |
wildcard target of a <tt>NOTICE</tt> (or <tt>PRIVMSG</tt>) to be a simple |
| 433 |
"<tt>*</tt>", which would target all clients on the network, the module |
| 434 |
uses the <tt>NetworkDomain</tt> configuration setting, if available, to |
| 435 |
create a more-specific server wildcard mask which will still target all |
| 436 |
clients on the network. If this setting is not available, the routine |
| 437 |
iterates through some common top-level domains (<tt>.com</tt>, |
| 438 |
<tt>.net</tt>, <tt>.org</tt>, and <tt>.edu</tt>) in an attempt to reach as |
| 439 |
many clients as possible.</p> |
| 440 |
|
| 441 |
<p>There is only one callback function defined by the module; it hooks into |
| 442 |
the "<tt>set topic</tt>" callback, used for setting channel topics |
| 443 |
(see <a href="2.html#s6-5">section 2-6-5</a>). Since RFC 1459 places no |
| 444 |
restrictions on topic-changing messages from servers, the callback simply |
| 445 |
sends out a <tt>TOPIC</tt> message on the first call, ignoring the second.</p> |
| 446 |
|
| 447 |
<p>The module initialization routine sets the protocol-specific variables |
| 448 |
(<tt>protocol_name</tt>, <tt>protocol_version</tt>, and so on—since |
| 449 |
there are no "versions" associated with RFC 1459, the version string is |
| 450 |
left empty), installs the handlers for the <tt>NICK</tt> and <tt>USER</tt> |
| 451 |
messages, adds the topic-setting routine to the "<tt>set topic</tt>" |
| 452 |
callback, and installs the function pointers for the various message |
| 453 |
sending operations. Of these, the module cleanup routine removes the |
| 454 |
callback function and message handlers, but it leaves the protocol |
| 455 |
variables and message sending function pointers alone; this is a shortcut |
| 456 |
based on the assumption that the module will never be unloaded at runtime |
| 457 |
(this assumption is enforced by returning zero to refuse unloading if the |
| 458 |
<tt><i>shutdown</i></tt> parameter to the cleanup function is false).</p> |
| 459 |
|
| 460 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 461 |
|
| 462 |
|
| 463 |
<h4 class="subsubsection-title" id="s6-2">5-6-2. <tt>protocol/ts8</tt></h4> |
| 464 |
|
| 465 |
<p>TS8 was one of the earliest additions made to the IRC protocol, and |
| 466 |
includes timestamp (often called TS) values with many messages to indicate |
| 467 |
the time at which certain actions took place. The addition of timestamps |
| 468 |
allowed, among other things, less disruption of the network during |
| 469 |
netjoins; in the case of a nickname collision, for example, timestamps made |
| 470 |
it possible to determine which user was the first claimant on a nickname |
| 471 |
and kill only the second user, rather than killing both of them as the |
| 472 |
original protocol called for.</p> |
| 473 |
|
| 474 |
<p>Other than the addition of timestamps into some IRC messages, the |
| 475 |
<tt>protocol/ts8</tt> module, which supports TS8 as used in the |
| 476 |
<tt>ircd-2.8</tt> series of IRC servers (specifically tested with |
| 477 |
<tt>ircd-2.8.21+TS8</tt>), is very similar to the <tt>protocol/rfc1459</tt> |
| 478 |
module. The one difference worth noting is in the operation of the |
| 479 |
"<tt>set topic</tt>" callback. Under TS8, a server receiving a |
| 480 |
<tt>TOPIC</tt> message from another server will give preference to the |
| 481 |
topic with the older timestamp, ignoring the <tt>TOPIC</tt> message if it |
| 482 |
specifies a timestamp newer than that of the topic currently set on the |
| 483 |
channel; thus, in order to ensure that the topic gets set correctly, the |
| 484 |
callback function modifies the caller's topic timestamp to be one second |
| 485 |
earlier than the timestamp of the channel's current topic if a topic is |
| 486 |
set. This same approach is used in other protocol modules as well to |
| 487 |
ensure that changes made by Services are given priority over the current |
| 488 |
network state regardless of timestamps.</p> |
| 489 |
|
| 490 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 491 |
|
| 492 |
|
| 493 |
<h4 class="subsubsection-title" id="s6-3">5-6-3. <tt>protocol/dalnet</tt></h4> |
| 494 |
|
| 495 |
<p>The <tt>protocol/dalnet</tt> module supports the IRC server released by |
| 496 |
(and used on) the DALnet IRC network, <tt>ircd.dal</tt>, through version |
| 497 |
4.4.13. This server is, incidentally, the server for which Services was |
| 498 |
originally designed, and as such, the module is nearly as concise as those |
| 499 |
for the simpler RFC 1459 and TS8 protocols.</p> |
| 500 |
|
| 501 |
<p>The DALnet IRC server introduced several additions to the standard IRC |
| 502 |
protocol. Most notable, from the point of view of the protocol module, is |
| 503 |
the addition of the <tt>AKILL</tt> and <tt>RAKILL</tt> messages for adding |
| 504 |
and removing network-wide client bans, and the OperServ <tt>AKILL</tt> |
| 505 |
command derives its name from these messages. The module includes callback |
| 506 |
functions for OperServ's "<tt>send_akill</tt>" and "<tt>cancel_akill</tt>" |
| 507 |
callbacks; it also includes entries in the message table for these |
| 508 |
messages, but since there is no need to process <tt>AKILL</tt> messages |
| 509 |
from the network, the handlers for these are <tt>NULL</tt>, along with |
| 510 |
several other messages not recognized by the core message processing code. |
| 511 |
(These messages are included simply to avoid warnings in the log file when |
| 512 |
such messages are received.)</p> |
| 513 |
|
| 514 |
<p>Other changes made to the server-to-server protocol in the DALnet server |
| 515 |
are the unification of the <tt>NICK</tt> and <tt>USER</tt> messages into a |
| 516 |
single <tt>NICK</tt> message, and the addition of the <tt>GLOBOPS</tt> |
| 517 |
message, a <tt>WALLOPS</tt>-like message that cannot be seen by |
| 518 |
non-operators (and which is used for the implementation of the |
| 519 |
<tt>wallops()</tt> routine in preference to <tt>WALLOPS</tt>).</p> |
| 520 |
|
| 521 |
<p>In order to ensure that the <tt>AKILL</tt>-related callbacks mentioned |
| 522 |
above are added when the appropriate OperServ module |
| 523 |
(<tt>operserv/akill</tt>) is loaded, this module also hooks into the |
| 524 |
<tt>"load module"</tt> callback. An "<tt>unload module</tt>" |
| 525 |
callback is also included for completeness, though it does nothing in this |
| 526 |
module.</p> |
| 527 |
|
| 528 |
<p>A close look at the module initialization routine, |
| 529 |
<tt>module_init()</tt>, will show another difference in the DALnet |
| 530 |
protocol. The RFC 1459 standard specifies that the three characters |
| 531 |
<tt>[ \ ]</tt> are to be interepreted as equivalent to |
| 532 |
<tt>{ | }</tt> in nicknames and channel names; this is a holdover |
| 533 |
from the Scandinavian character set which was used by the creators of the |
| 534 |
IRC protocol. DALnet does away with this holdover, and treats |
| 535 |
<tt>[ \ ]</tt> as distinct from <tt>{ | }</tt> when |
| 536 |
doing such string comparisons. By default, however, Services uses the RFC |
| 537 |
1459 rules for comparing nicknames and channel names, so in order to change |
| 538 |
this behavior, the <tt>module_init()</tt> routine modifies the global |
| 539 |
<tt>irc_lowertable[]</tt> array. There are also two changes made to the |
| 540 |
<tt>valid_chan_table[]</tt> array, to accommodate the fact that the DALnet |
| 541 |
protocol allows channel names to begin with "<tt>+</tt>" and does not allow |
| 542 |
colons in channel names.</p> |
| 543 |
|
| 544 |
<p>There is also a <tt>mapstring()</tt> call in the initialization routine |
| 545 |
to change the <tt>OPER_BOUNCY_MODES</tt> message to |
| 546 |
<tt>OPER_BOUNCY_MODES_U_LINE</tt>; this latter message includes a specific |
| 547 |
reference to "U: lines", a type of entry in the DALnet server configuration |
| 548 |
file that indicates servers (like Services) that are allowed to change |
| 549 |
channel modes arbitrarily. Failure to set this correctly on all servers |
| 550 |
can result in the "bouncy modes" phenomenon, where a server reverses mode |
| 551 |
changes made by Services, causing Services to resubmit those changes in an |
| 552 |
infinite loop (see <a href="2.html#s6-3">section 2-6-3</a> for details).</p> |
| 553 |
|
| 554 |
<p>One other piece of code not present in the <tt>rfc1459</tt> or |
| 555 |
<tt>ts8</tt> modules is the mode initialization code. The DALnet protocol |
| 556 |
adds two user modes to the standard mode set: <tt>+g</tt>, indicating |
| 557 |
whether the client wants to receive <tt>GLOBOPS</tt> messages, and |
| 558 |
<tt>+h</tt>, indicating whether the user is identified as a "help-op". |
| 559 |
Neither of these have any effect on the operation of Services, but for |
| 560 |
completeness, they are added to the global mode tables as described in |
| 561 |
<a href="2.html#s6-4">section 2-6-4</a>. The method used for adding the |
| 562 |
modes (the three arrays <tt>new_usermodes[]</tt>, <tt>new_chanmodes[]</tt>, |
| 563 |
and <tt>new_chanusermodes[]</tt>, and the local initialization function |
| 564 |
<tt>init_modes()</tt>, called from <tt>init_module()</tt>) is shared by |
| 565 |
other protocol modules are well.</p> |
| 566 |
|
| 567 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 568 |
|
| 569 |
|
| 570 |
<h4 class="subsubsection-title" id="s6-4">5-6-4. <tt>protocol/dreamforge</tt></h4> |
| 571 |
|
| 572 |
<p>The <tt>protocol/dreamforge</tt> module supports the Dreamforge server |
| 573 |
protocol. Dreamforge is the name given to versions 4.4.15 and later of the |
| 574 |
DALnet IRC server, and as such, this protocol is a direct successor to the |
| 575 |
<tt>dalnet</tt> protocol.</p> |
| 576 |
|
| 577 |
<p>The major difference between the classic DALnet protocol and the |
| 578 |
Dreamforge protocol is the addition of features designed to improve the |
| 579 |
integration of Services-like programs with the network. Chief among these |
| 580 |
is the "Services timestamp" or "servicestamp", a timestamp-like value |
| 581 |
associated with each client which is set by Services and retained by all |
| 582 |
servers as long as the client is connected. This value, or 0 if it has not |
| 583 |
been set, is sent as part of the <tt>NICK</tt> message when announcing a |
| 584 |
new client to the network. Services can set the servicestamp to a unique |
| 585 |
value, and use that value to distinguish clients with certainty, avoiding |
| 586 |
problems arising from servers with out-of-sync clocks or clients that |
| 587 |
connect to the network at the same time. There are also new user and |
| 588 |
channel modes added to identify registered nicknames and channels, and to |
| 589 |
prevent clients with unregistered nicknames from joining a channel.</p> |
| 590 |
|
| 591 |
<p>Most of these changes are handled in the <tt>NICK</tt> message handler, |
| 592 |
<tt>m_nick()</tt>, and the callback functions |
| 593 |
<tt>do_user_servicestamp_change()</tt>, <tt>do_user_mode()</tt>, and |
| 594 |
<tt>do_nick_identified()</tt>. The <tt>do_user_mode()</tt> callback |
| 595 |
function ensures that no other server on the network attempts to change a |
| 596 |
user's servicestamp (note that this can cause mode floods if two copies of |
| 597 |
Services are run on the same network!) or registered-nickname status. The |
| 598 |
function also sets the "Services administrator" (<tt>+a</tt>) user mode if |
| 599 |
the user is known to be a Services administrator, and clears the mode |
| 600 |
otherwise.</p> |
| 601 |
|
| 602 |
<p>In order to check whether a user is a Services administrator, the module |
| 603 |
has to call the <tt>is_services_admin()</tt> function in the |
| 604 |
<tt>operserv/main</tt> module; however, this module may not be loaded. To |
| 605 |
avoid having to check for the module and symbol at every location in the |
| 606 |
code where the function is called, a local helper function, |
| 607 |
<tt>local_is_services_admin()</tt>, is defined at the top of the source |
| 608 |
file, and <tt>is_services_admin()</tt> is redefined (via <tt>#define</tt>) |
| 609 |
to point to this local function. The function itself only checks a cache |
| 610 |
variable to determine whether <tt>is_services_admin()</tt> is available; |
| 611 |
this cache variable is set by the "<tt>load module</tt>" callback |
| 612 |
function when the <tt>operserv/main</tt> module is loaded (and cleared |
| 613 |
again by the "<tt>unload module</tt>" if <tt>operserv/main</tt> is |
| 614 |
unloaded).</p> |
| 615 |
|
| 616 |
<p>The final new aspect to this module's source code is the use of the |
| 617 |
<tt>svsnick.c</tt> auxiliary source file (see <a href="#s7-6">section |
| 618 |
5-7-6</a> for details on this particular file), to support the |
| 619 |
<tt>SVSNICK</tt> message used to forcibly change a client's nickname. In |
| 620 |
order to avoid complexities resulting from compiling the source file |
| 621 |
separately and linking it into the module (in particular, identifier |
| 622 |
collisions during static linking), the <tt>svsnick.c</tt> source file is |
| 623 |
included directly into the module's main source file, <tt>dreamforge.c</tt>. |
| 624 |
<tt>svsnick.c</tt> includes its own initialization and cleanup routines, |
| 625 |
<tt>init_svsnick()</tt> and <tt>exit_svsnick()</tt>, which are called by |
| 626 |
<tt>init_module()</tt> and <tt>exit_module()</tt> respectively.</p> |
| 627 |
|
| 628 |
<p>With respect to server registration, Dreamforge includes a new |
| 629 |
<tt>PROTOCTL</tt> message type, used to inform the remote server about the |
| 630 |
sending server's capabilities; this allows changes and additions to be made |
| 631 |
to the protocol that can be enabled or disabled depending on whether the |
| 632 |
remote server supports them. Services does not make use of any such |
| 633 |
optional features in Dreamforge, however, so the <tt>PROTOCOL</tt> message |
| 634 |
is given a <tt>NULL</tt> handler.</p> |
| 635 |
|
| 636 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 637 |
|
| 638 |
|
| 639 |
<h4 class="subsubsection-title" id="s6-5">5-6-5. <tt>protocol/bahamut</tt></h4> |
| 640 |
|
| 641 |
<p>Bahamut is the successor to the Dreamforge IRC server, and is the server |
| 642 |
currently (2006/8) used on the DALnet IRC network. The |
| 643 |
<tt>protocol/bahamut</tt> module handles versions of Bahamut from 1.8.0 |
| 644 |
onward.</p> |
| 645 |
|
| 646 |
<p>In addition to the <tt>SVSNICK</tt> feature introduced in Dreamforge, |
| 647 |
Bahamut includes <i>ban exceptions</i> for channels (clients matching a ban |
| 648 |
exception mask can join the channel even if they also match a ban mask), |
| 649 |
supported by the auxiliary source file <tt>banexcept.c</tt>; <i>invite |
| 650 |
masks</i> for channels (clients matching an invite mask can join an |
| 651 |
invite-only channel without having to be explicitly invited), supported by |
| 652 |
<tt>invitemask.c</tt>; and a channel-join message for server-to-server |
| 653 |
communications, <tt>SJOIN</tt> (which reduces bandwidth use by allowing |
| 654 |
multiple users and channel modes to be sent in a single message), supported |
| 655 |
by <tt>sjoin.c</tt>. With respect to the latter file, <tt>bahamut.c</tt> |
| 656 |
defines the <tt>BAHAMUT_HACK</tt> symbol before including the file; this is |
| 657 |
to select the Bahamut mode of operation for <tt>SJOIN</tt>, as described in |
| 658 |
<a href="#s7-5">section 5-7-5</a>.</p> |
| 659 |
|
| 660 |
<p>Bahamut includes a <tt>CAPAB</tt> message that functions like |
| 661 |
Dreamforge's <tt>PROTOCTL</tt> to inform the remote server about supported |
| 662 |
protocol features. Services checks for one token in the <tt>CAPAB</tt> |
| 663 |
message: "<tt>NOQUIT</tt>", an extension suppressing (on server-to-server |
| 664 |
links) the client <tt>QUIT</tt> messages generated when a netsplit occurs. |
| 665 |
Services always advertises the <tt>NOQUIT</tt> capability, and sets the |
| 666 |
<tt>PF_NOQUIT</tt> protocol flag if the remote server also supports |
| 667 |
<tt>NOQUIT</tt>.</p> |
| 668 |
|
| 669 |
<p>One difficulty that can arise when using the Bahamut server is that the |
| 670 |
server to which Services connects is configured as a "Services hub" (the |
| 671 |
configuration option "<tt>servtype serviceshub</tt>"). While this |
| 672 |
seems logical from the name, this option is intended only for the custom |
| 673 |
Services program that DALnet uses, and is not compatible with this program, |
| 674 |
Services for IRC Networks. The DALnet Services program is customized to |
| 675 |
work specifically with the Bahamut server and the DALnet network, and as |
| 676 |
such takes certain shortcuts; the "Services hub" option causes the Bahamut |
| 677 |
server to take advantage of these shortcuts, reducing network bandwidth. |
| 678 |
In particular, activating this option causes messages to pseudoclients such |
| 679 |
as NickServ to be sent in an abbreviated form (the <tt>NS</tt>, <tt>CS</tt> |
| 680 |
and similar commands defined under the dummy |
| 681 |
<tt>#ifdef ALLOW_BAHAMUT_SERVICESHUB</tt>, referring to a macro not |
| 682 |
defined anywhere). As Services for IRC Networks cannot assume that these |
| 683 |
clients have particular nicknames, or even that they exist, the |
| 684 |
<tt>protocol/bahamut</tt> module reports an error and aborts the program if |
| 685 |
any of these abbreviated messages are seen. <i>Implementation note: It |
| 686 |
might be feasible to support these if the module exported a |
| 687 |
<tt>register_pseudoclient()</tt> routine, which took a constant indicating |
| 688 |
the pseudoclient, like <tt>BAHAMUT_NS</tt>, and the pseudoclient's nickname |
| 689 |
and stored the nickname locally for processing the given message.</i> The |
| 690 |
"Services hub" option also prevents channel topics and client <tt>AWAY</tt> |
| 691 |
messages from reaching Services, causing channel topic retention and |
| 692 |
MemoServ unaway checking to break.</p> |
| 693 |
|
| 694 |
<p>The Bahamut-specific channel mode <tt>+j</tt> is used to limit the rate |
| 695 |
at which clients can join a channel. It takes the form |
| 696 |
<tt>+j <i>num1</i>:<i>num2</i></tt>, where <tt><i>num1</i></tt> and |
| 697 |
<tt><i>num2</i></tt> are positive integers that set the exact limits on |
| 698 |
joining. Internally, these are stored in the <tt><i>joinrate1</i></tt> and |
| 699 |
<tt><i>joinrate2</i></tt> fields of the <tt>Channel</tt> structure as well |
| 700 |
as the locked-mode set of a registered channel (see |
| 701 |
<a href="7.html#s4-1-1">section 7-4-1-1</a>), and values of 0 in these |
| 702 |
fields indicate that the mode is not set; values of -1 in the locked-mode |
| 703 |
structure indicate that the mode is locked off.</p> |
| 704 |
|
| 705 |
<p>Unlike RFC 1459, Bahamut does not allow control characters in a channel |
| 706 |
name. It also does not allow ASCII 160 (0xA0), presumably because this |
| 707 |
corresponds to an "unbreakable space" in the ISO 8859-1 character set and |
| 708 |
could be confused with an ordinary space by users. The initialization |
| 709 |
routine adjusts the <tt>valid_chan_table[]</tt> array to account for this.</p> |
| 710 |
|
| 711 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 712 |
|
| 713 |
|
| 714 |
<h4 class="subsubsection-title" id="s6-6">5-6-6. <tt>protocol/hybrid</tt></h4> |
| 715 |
|
| 716 |
<p>The <tt>protocol/hybrid</tt> module supports versions 7.0 and later of |
| 717 |
the ircd-hybrid IRC server. Hybrid has a fairly simple design compared to |
| 718 |
other servers, and only supports a few features above the standard set.</p> |
| 719 |
|
| 720 |
<p>The Hybrid server does not ordinarily send channel topics during the |
| 721 |
initial net burst when a server connects, and only allows the channel topic |
| 722 |
to be set by a <tt>TOPIC</tt> message from a client currently in the |
| 723 |
channel. This prevents the ChanServ topic-related functions from working, |
| 724 |
since ChanServ does not join the channel when setting a topic. There is, |
| 725 |
however, a module available for Hybrid which restores the synchronization |
| 726 |
of channel topics on a server link as well as the ability of a server to |
| 727 |
set topics arbitrarily: the "topic burst" module, <tt>m_tburst.so</tt>. To |
| 728 |
simplify processing, the <tt>protocol/hybrid</tt> module requires that its |
| 729 |
uplink server support this topic bursting, and will abort the program if |
| 730 |
that support is missing (as determined by the <tt>CAPAB</tt> message |
| 731 |
received on connection).</p> |
| 732 |
|
| 733 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 734 |
|
| 735 |
|
| 736 |
<h4 class="subsubsection-title" id="s6-7">5-6-7. <tt>protocol/inspircd</tt></h4> |
| 737 |
|
| 738 |
<p>The <tt>protocol/inspircd</tt> supports the InspIRCd IRC server. This |
| 739 |
server shares a number of features with the Unreal server (see |
| 740 |
<a href="#s6-14">section 5-6-14</a>, but was created from scratch, rather |
| 741 |
than by modifying the source code of an existing IRC server as in the case |
| 742 |
of most other servers.</p> |
| 743 |
|
| 744 |
<p>The <tt>inspircd</tt> module uses the <tt>banexcept.c</tt>, |
| 745 |
<tt>invitemask.c</tt>, and <tt>svsnick.c</tt> auxiliary source files |
| 746 |
mentioned above, as well as the <tt>chanprot.c</tt> and <tt>halfop.c</tt> |
| 747 |
files, which are used to implement two additional channel user modes |
| 748 |
supported by InspIRCd: <tt>+a</tt> (protection) and <tt>+h</tt> (half-op). |
| 749 |
A user with <tt>+a</tt> set cannot be kicked by a channel operator unless |
| 750 |
that operator also has <tt>+a</tt> set. Half-op privilege is an extra |
| 751 |
privilege level between <tt>+v</tt> (voiced) and <tt>+o</tt> (channel |
| 752 |
operator); half-ops can set the channel topic and give <tt>+v</tt> to other |
| 753 |
users, but cannot change channel modes or perform other actions that |
| 754 |
ordinary channel operators can do. InspIRCd also has a condensed channel |
| 755 |
join message (<tt>FJOIN</tt>) similar to Bahamut's <tt>SJOIN</tt>, but its |
| 756 |
syntax is different enough that a message handler is included in the module |
| 757 |
itself rather than using the handler in <tt>sjoin.c</tt>.</p> |
| 758 |
|
| 759 |
<p>In addition to autokills and S-lines, InspIRCd supports autokill |
| 760 |
exclusions, similar to channels' ban exceptions but applying to |
| 761 |
network-wide autokill masks. As described in detail in |
| 762 |
<a href="7.html#s2-2-2">section 7-2-2-2</a>, the <tt>operserv/akill</tt> |
| 763 |
module can take advantage of this to implement autokill exclusions without |
| 764 |
having to send <tt>KILL</tt> messages for all autokilled users manually.</p> |
| 765 |
|
| 766 |
<p>Another feature of the InspIRCd protocol is the removal of the |
| 767 |
restriction on sending network-wide messages; as such, the |
| 768 |
<tt>protocol/inspircd</tt> module does not require a <tt>NetworkDomain</tt> |
| 769 |
configuration setting for global messages to be correctly sent.</p> |
| 770 |
|
| 771 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 772 |
|
| 773 |
|
| 774 |
<h4 class="subsubsection-title" id="s6-8">5-6-8. <tt>protocol/monkey</tt></h4> |
| 775 |
|
| 776 |
<p>The <tt>protocol/monkey</tt> module supports the Chunky Monkey IRCD |
| 777 |
server. This server is based on an earlier version of Bahamut; the primary |
| 778 |
Services-visible change is the addition of the half-op (<tt>+h</tt>) |
| 779 |
channel user mode. Features like ban exceptions and invite masks, added to |
| 780 |
Bahamut in later versions, are not present. Other than these differences, |
| 781 |
this module is essentially the same as the <tt>bahamut</tt> module.</p> |
| 782 |
|
| 783 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 784 |
|
| 785 |
|
| 786 |
<h4 class="subsubsection-title" id="s6-9">5-6-9. <tt>protocol/ptlink</tt></h4> |
| 787 |
|
| 788 |
<p>The <tt>protocol/ptlink</tt> module supports the PTlink IRCd server, |
| 789 |
version 6.10.0 and later. This server is based on ircd-hybrid-6, and was |
| 790 |
originally developed for the PTlink IRC network, from which it takes its |
| 791 |
name.</p> |
| 792 |
|
| 793 |
<p>In PTlink, autokills are set and removed using the <tt>GLINE</tt> |
| 794 |
message. Since this can also be used by IRC operators to set and remove |
| 795 |
autokills, Services uses a constant string (defined as <tt>GLINE_WHO</tt> |
| 796 |
at the top of the source file) as the "nickname" associated with the entry. |
| 797 |
Services can then check this value when receiving a <tt>GLINE</tt> message |
| 798 |
from the network, in order to avoid removing entries set by IRC operators. |
| 799 |
(However, nicknames are not stored with <tt>SGLINE</tt> and <tt>SQLINE</tt> |
| 800 |
entries, so operator-set entries will be deleted if they do not match a |
| 801 |
record in Services' databases.) See under the <tt>TKL</tt> message |
| 802 |
handler in <a href="#s6-14">section 5-6-14</a>, which discusses the Unreal |
| 803 |
server, for an explanation of why these entries need to be cleared when |
| 804 |
received from the network.</p> |
| 805 |
|
| 806 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 807 |
|
| 808 |
|
| 809 |
<h4 class="subsubsection-title" id="s6-10">5-6-10. <tt>protocol/ratbox</tt></h4> |
| 810 |
|
| 811 |
<p>The <tt>protocol/ratbox</tt> module supports the ircd-ratbox server. |
| 812 |
This server is derived from ircd-hybrid, and the <tt>ratbox</tt> module is |
| 813 |
likewise very similar to the <tt>hybrid</tt> module.</p> |
| 814 |
|
| 815 |
<p>Like Hybrid, ircd-ratbox does not normally allow servers like Services |
| 816 |
to arbitrarily change channel topics, but this behavior can be changed with |
| 817 |
a similar "topic burst" function. In the case of ircd-ratbox, this |
| 818 |
functionality is built into the server (rather than being a separate |
| 819 |
module), and need only be enabled through the appropriate flag |
| 820 |
("<tt>topicburst</tt>" in the connect block for Services). If this flag is |
| 821 |
not enabled, Services will abort at connection time, as for Hybrid.</p> |
| 822 |
|
| 823 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 824 |
|
| 825 |
|
| 826 |
<h4 class="subsubsection-title" id="s6-11">5-6-11. <tt>protocol/solidircd</tt></h4> |
| 827 |
|
| 828 |
<p>The <tt>protocol/solidircd</tt> module supports the solid-ircd server. |
| 829 |
This server is based on an earlier version of the Bahamut server, with |
| 830 |
several additions and changes.</p> |
| 831 |
|
| 832 |
<p>One new feature supported by solid-ircd is encrypted connections. If a |
| 833 |
client connects to the server via SSL, the client is given user mode |
| 834 |
<tt>+z</tt>; a new channel mode, <tt>+S</tt>, is also available to prevent |
| 835 |
clients without <tt>+z</tt> from entering the channel. This presents a |
| 836 |
problem when <tt>+S</tt> is mode-locked on: since the channel does not |
| 837 |
exist when it is empty, the IRC server will not know to stop a <tt>-z</tt> |
| 838 |
user from entering the channel, and even if Services then sets <tt>+S</tt> |
| 839 |
on the channel, the non-secure user will already be in the channel. In |
| 840 |
order to work around this, Services hooks into the ChanServ |
| 841 |
"<tt>check_kick</tt>" callback, and if a non-secure user tries to join an |
| 842 |
empty channel that is registered and mode-locked <tt>+S</tt>, the user is |
| 843 |
kicked out just as if on the autokick list.</p> |
| 844 |
|
| 845 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 846 |
|
| 847 |
|
| 848 |
<h4 class="subsubsection-title" id="s6-12">5-6-12. <tt>protocol/trircd</tt></h4> |
| 849 |
|
| 850 |
<p>The <tt>protocol/trircd</tt> module supports the tr-ircd server, |
| 851 |
version 5.5 and later. tr-ircd was originally based on the Bahamut server, |
| 852 |
but has been rewritten from scratch since version 5.0.</p> |
| 853 |
|
| 854 |
<p>One feature unique to tr-ircd is the availability of a user mode |
| 855 |
(<tt>+L</tt>)bindicating the language in which the client desires to |
| 856 |
receive server messages. For users with registered nicknames, Services |
| 857 |
sets this to the language selected by the user for their nickname (if |
| 858 |
that language is also supported by tr-ircd) when the user identifies. |
| 859 |
<i>Implementation node: It would also be theoretically possible to use the |
| 860 |
mode's value as a default for sending messages unregistered nicknames, as |
| 861 |
well as the initial language setting of a newly-registered nickname, but |
| 862 |
this is difficult to accomplish without adding the concept of a language |
| 863 |
mode for clients to the Services core.</i> The list of languages supported |
| 864 |
by tr-ircd, taken from the tr-ircd source code, can be found at the top of |
| 865 |
the <tt>trircd.c</tt> module source file (<tt>langhash_init[]</tt>); the |
| 866 |
actual values used in the user mode are hashes created from the language |
| 867 |
name strings, and these hashes are computed and stored in the |
| 868 |
<tt>langhash[]</tt> array by the <tt>init_langhash()</tt> function, called |
| 869 |
at module initialization time.</p> |
| 870 |
|
| 871 |
<p>tr-ircd also supports "channel linking"; this is the ability to make one |
| 872 |
channel into an "alias" for another. When this mode (coincidentally also |
| 873 |
<tt>+L</tt>) is set for a channel <tt>#A</tt> with a parameter of |
| 874 |
<tt>#B</tt>, for example, a user who attempts to join channel <tt>#A</tt> |
| 875 |
will be sent to channel <tt>#B</tt> instead. As a side effect of this, the |
| 876 |
IRC server keeps track of channels which have <tt>+L</tt> set, and does not |
| 877 |
delete them even after the last client leaves. Since Services treats a |
| 878 |
channel with no users as nonexistent, the <tt>trircd</tt> module must hook |
| 879 |
into the low-level "<tt>receive message</tt>" callback to watch for |
| 880 |
<tt>+L</tt> or <tt>-L</tt> messages for empty channels and process them |
| 881 |
accordingly.</p> |
| 882 |
|
| 883 |
<p>At the server-to-server communication level, tr-ircd has the ability to |
| 884 |
send message names as one- or two-character tokens rather than the full |
| 885 |
message names; for example, "<tt>PRIVMSG</tt>" becomes simply "<tt>P</tt>", |
| 886 |
both reducing bandwidth (albeit minimally) and enabling faster lookup of |
| 887 |
commands. These tokens are defined in the <tt>trircd_tokens[]</tt> array, |
| 888 |
and processing is handled by the <tt>token.c</tt> auxiliary source file, |
| 889 |
discussed in <a href="#s7-7">section 5-7-7</a>.</p> |
| 890 |
|
| 891 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 892 |
|
| 893 |
|
| 894 |
<h4 class="subsubsection-title" id="s6-13">5-6-13. <tt>protocol/undernet-p9</tt></h4> |
| 895 |
|
| 896 |
<p>The <tt>protocol/undernet-p9</tt> supports version 2.9 of the Undernet |
| 897 |
IRC server (ircu). This is a fairly old server, derived from the original |
| 898 |
ircd-2.8 server with TS8 additions; the only additional features it |
| 899 |
includes are autokills (set using the <tt>GLINE</tt> message, and not |
| 900 |
propogated in the connection burst) and the merging of the <tt>USER</tt> |
| 901 |
and <tt>NICK</tt> messages into a single <tt>NICK</tt> message.</p> |
| 902 |
|
| 903 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 904 |
|
| 905 |
|
| 906 |
<h4 class="subsubsection-title" id="s6-14">5-6-14. <tt>protocol/unreal</tt></h4> |
| 907 |
|
| 908 |
<p>The <tt>protocol/unreal</tt> module supports version 3.1.1 and later of |
| 909 |
the UnrealIRCd server. Unreal is originally derived from Dreamforge, |
| 910 |
but has made numerous additions, and is one of the most feature-rich IRC |
| 911 |
servers currently in use. This of course means that the protocol module |
| 912 |
is similarly complex; Unreal makes use of nearly all protocol-related |
| 913 |
routines, as well as all seven auxiliary source files. For this reason, the |
| 914 |
<tt>unreal</tt> module's source code is the most heavily commented of the |
| 915 |
protocol modules, and can be seen as a model for how the various parts of |
| 916 |
protocol modules work.</p> |
| 917 |
|
| 918 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 919 |
|
| 920 |
|
| 921 |
<h5 class="subsubsubsection-title" id="s6-14-1">5-6-14-1. Module prologue</h5> |
| 922 |
|
| 923 |
<p>After including appropriate header files and the auxiliary source files |
| 924 |
that implement certain protocol-related functions, the module defines a |
| 925 |
number of local variables:</p> |
| 926 |
<ul> |
| 927 |
<li class="spaced"><tt>module_chanserv</tt>, <tt>module_operserv</tt>: |
| 928 |
Module handles used for accessing external symbols (see below).</li> |
| 929 |
<li class="spaced"><tt>ServerNumeric</tt>, <tt>SetServerTimes</tt>, |
| 930 |
<tt>SVSTIMEFrequency</tt>: Variables to hold values set in the |
| 931 |
configuration file.</li> |
| 932 |
<li class="spaced"><tt>to_svstime</tt>: The timeout (see |
| 933 |
<a href="2.html#s7">section 2-7</a>) used to send <tt>SVSTIME</tt> |
| 934 |
messages at periodic intervals.</li> |
| 935 |
<li class="spaced"><tt>usermode_admin</tt>, <tt>usermode_secure</tt>, |
| 936 |
<tt>usermode_hiding</tt>, <tt>chanmode_admins_only</tt>, |
| 937 |
<tt>chanmode_secure_only</tt>, <tt>chanmode_no_hiding</tt>: |
| 938 |
Bitmasks corresponding to certain sets of modes, used to determine |
| 939 |
whether a client is allowed to enter a particular empty |
| 940 |
channel.</li> |
| 941 |
<li class="spaced"><tt>unreal_version</tt>: Set to the protocol version |
| 942 |
number sent by the remote server at connection registration time, |
| 943 |
and used to determine whether certain protocol features are |
| 944 |
available.</li> |
| 945 |
<li class="spaced"><tt>has_nickip</tt>: Set to nonzero if the remote server |
| 946 |
supports the <tt>NICKIP</tt> feature, used to implement |
| 947 |
SZlines.</li> |
| 948 |
</ul> |
| 949 |
|
| 950 |
<p>These are followed by <tt>#define</tt>s and local variables used to |
| 951 |
access the <tt>s_ChanServ</tt> variable in the ChanServ module, containing |
| 952 |
the nickname of the ChanServ pseudoclient, and the |
| 953 |
<tt>is_services_admin()</tt> function in the OperServ module, returning |
| 954 |
whether the given user is a Services administrator. As described in the |
| 955 |
comments, <tt>#define</tt> macros are used to substitute an access to the |
| 956 |
symbol pointer every time the symbol is used, in order to simplify the |
| 957 |
code.</p> |
| 958 |
|
| 959 |
<p>The next section of the file contains a list of user, channel, and |
| 960 |
channel user modes supported by the Unreal server. In order to register |
| 961 |
these with the core mode processing facility (see |
| 962 |
<a href="2.html#s6-4">section 2-6-4</a>), <tt>unreal.c</tt> defines three |
| 963 |
arrays, one for each mode type, containing the mode characters to be added |
| 964 |
and the corresponding <tt>ModeInfo</tt> structure for each mode. The |
| 965 |
module also defines six local mode flags, corresponding to the mode bitmask |
| 966 |
variables listed above; these flags are ignored by the mode processing |
| 967 |
facility, but the mode setup code uses them to set the bitmask |
| 968 |
variables.</p> |
| 969 |
|
| 970 |
<p>The setup code itself is located in the <tt>init_modes()</tt> routine, |
| 971 |
called during module initialization. This routine iterates through each of |
| 972 |
the arrays, storing the mode data in the arrays exported by the mode |
| 973 |
processing facility. For the user and channel modes, it also checks for |
| 974 |
the locally-defined <tt>ModeInfo</tt> flags, and if a given mode has a flag |
| 975 |
set, the mode's bitmask is added to the appropriate bitmask variable.</p> |
| 976 |
|
| 977 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 978 |
|
| 979 |
|
| 980 |
<h5 class="subsubsubsection-title" id="s6-14-2">5-6-14-2. Message receiving</h5> |
| 981 |
|
| 982 |
<p>After this comes the first major portion of the actual processing code, |
| 983 |
the message handlers. Aside from the mandatory client registration |
| 984 |
handler (the <tt>NICK</tt> message in Unreal), Unreal includes several |
| 985 |
additional messages not supported by the core processing code. The |
| 986 |
messages handled are as follows (each message is handled by a routine |
| 987 |
named <tt>m_<i>message-name</i></tt>, for example the <tt>NICK</tt> |
| 988 |
message is handled by <tt>m_nick()</tt>):</p> |
| 989 |
|
| 990 |
<dl> |
| 991 |
<dt><b><tt>NICK</tt></b></dt> |
| 992 |
<dd>This is the standard client registration message (Unreal merges |
| 993 |
the dual <tt>NICK</tt> and <tt>USER</tt> of RFC 1459 into a single |
| 994 |
<tt>NICK</tt> message at the server level, as most other server |
| 995 |
protocols do). The message is also used for existing clients |
| 996 |
changing nicknames; in that case (where the message has a prefix |
| 997 |
indicating that it came from an existing client), control is |
| 998 |
simply handed off to the <tt>do_nick()</tt> routine from the |
| 999 |
core's client handling code. In the case of a new client, |
| 1000 |
however, <tt>do_nick()</tt> expects the parameters in a slightly |
| 1001 |
different order than Unreal sends them in, so this rearrangement is |
| 1002 |
performed before calling <tt>do_nick()</tt>. Additionally, on |
| 1003 |
servers supporting <tt>NICKIP</tt> (the sending of IP addresses in |
| 1004 |
the <tt>NICK</tt> message), the message will include an extra |
| 1005 |
parameter containing the binary representation of the client's IP |
| 1006 |
address, encoded using base64 encoding; this is decoded, checked |
| 1007 |
for consistency, and passed to <tt>do_nick()</tt> as well. (If |
| 1008 |
<tt>NICKIP</tt> is not supported, a <tt>NULL</tt> parameter is |
| 1009 |
passed, indicating that the IP address is not available.)</dd> |
| 1010 |
|
| 1011 |
<dt><b><tt>PROTOCTL</tt></b></dt> |
| 1012 |
<dd>Unreal uses this message to send information about features |
| 1013 |
supported by the server. Services checks the list of parameters |
| 1014 |
for recognized keywords, and sets appropriate variables to reflect |
| 1015 |
their presence or absence. The recognized feature tokens are: |
| 1016 |
<ul> |
| 1017 |
<li><b><tt>NICKv2</tt>:</b> A new format for the <tt>NICK</tt> |
| 1018 |
message, compared to earlier versions of Unreal. The local |
| 1019 |
variable <tt>got_nickv2</tt> is set when this token is |
| 1020 |
found; if the variable is not set at the end of the |
| 1021 |
function, a fatal error is generated. <i>Implementation |
| 1022 |
note: The variable is declared <tt>static</tt> because |
| 1023 |
Unreal can send more than one <tt>PROTOCTL</tt> message |
| 1024 |
when registering (such as when the parameter list is too |
| 1025 |
long). It would be more robust to use a file-global |
| 1026 |
variable that is checked at the first <tt>NICK</tt> |
| 1027 |
message, but current versions of Unreal always send |
| 1028 |
<tt>NICKv2</tt> in the first message, so this is not |
| 1029 |
currently a problem.</i></li> |
| 1030 |
<li><b><tt>NOQUIT</tt>:</b> The <tt>NOQUIT</tt> feature found in |
| 1031 |
other servers such as Bahamut, in which servers generate |
| 1032 |
client <tt>QUIT</tt> messages for netsplits on their own |
| 1033 |
rather than relaying them through the network.</li> |
| 1034 |
<li><b><tt>NICKIP</tt>:</b> Indicates that IP addresses are sent |
| 1035 |
with client registration messages.</li> |
| 1036 |
<li><b><tt>NICKCHARS</tt>:</b> Specifies additional characters |
| 1037 |
allowed to be used in nicknames. The specification is |
| 1038 |
done by language code; the current version of the module |
| 1039 |
uses the language codes and character sets defined in |
| 1040 |
Unreal 3.2.3.</li> |
| 1041 |
</ul></dd> |
| 1042 |
|
| 1043 |
<dt><b><tt>UMODE2</tt></b></dt> |
| 1044 |
<dd>This is equivalent to the <tt>MODE</tt> message for clients, but |
| 1045 |
omits the nickname parameter (so, for example, "<tt>:<i>nickname</i> |
| 1046 |
MODE <i>nickname</i> -o</tt>" becomes "<tt>:<i>nickname</i> UMODE2 |
| 1047 |
-o</tt>").</dd> |
| 1048 |
|
| 1049 |
<dt><b><tt>SETHOST</tt>, <tt>CHGHOST</tt></b></dt> |
| 1050 |
<dd>These allow setting changing the "fake hostname", the hostname |
| 1051 |
seen in a <tt>WHO</tt> or <tt>WHOIS</tt> reply by non-operators, |
| 1052 |
for a client. <tt>SETHOST</tt> is used by a client to change its |
| 1053 |
own hostname, while <tt>CHGHOST</tt> is used by operators (or |
| 1054 |
servers, such as Services, though Services does not use this at |
| 1055 |
present) to change another client's hostname.</dd> |
| 1056 |
|
| 1057 |
<dt><b><tt>SETIDENT</tt>, <tt>CHGIDENT</tt></b></dt> |
| 1058 |
<dd>These are like <tt>SETHOST</tt> and <tt>CHGHOST</tt> above, but |
| 1059 |
change the client's username (the part of the |
| 1060 |
<tt><i>user</i>@<i>host</i></tt> mask before the <tt>@</tt>).</dd> |
| 1061 |
|
| 1062 |
<dt><b><tt>SETNAME</tt>, <tt>CHGNAME</tt></b></dt> |
| 1063 |
<dd>These are like <tt>SETHOST</tt> and <tt>CHGHOST</tt> above, but |
| 1064 |
change the client's "real name" (also called "gecos").</dd> |
| 1065 |
|
| 1066 |
<dt><b><tt>SJOIN</tt></b></dt> |
| 1067 |
<dd>This is a server-to-server message used both to add a user to a |
| 1068 |
channel and to send a channel's state to the network. The message |
| 1069 |
takes a channel name, timestamp, mode string, optional mode |
| 1070 |
parameters, and a space-separated list of nicknames of clients |
| 1071 |
joining the channel. Nicknames in the nickname list are prefixed |
| 1072 |
with the prefix character(s) for the channel user mode of the |
| 1073 |
client, if any (for example, a channel operator would be listed |
| 1074 |
as <tt>@<i>nickname</i></tt>. Recent versions of Unreal also add |
| 1075 |
channel bans and ban exceptions to the nickname list as well, with |
| 1076 |
prefix characters of <tt>&</tt> and <tt>"</tt> respectively.</dd> |
| 1077 |
|
| 1078 |
<dt><b><tt>SVSMODE</tt>, <tt>SVS2MODE</tt></b></dt> |
| 1079 |
<dd>These messages are used to remotely change a client's modes or |
| 1080 |
to remove all bans on a channel which match a client. In the |
| 1081 |
former case, the messages operate identically to the <tt>MODE</tt> |
| 1082 |
message, except that the source and target client may be different. |
| 1083 |
In the latter case, each server checks the channel's ban list and |
| 1084 |
removes all bans corresponding to that user; Services does this by |
| 1085 |
calling <tt>clear_channel()</tt>, which sends out explicit |
| 1086 |
<tt>MODE</tt> messages to remove the bans, but this is mostly |
| 1087 |
harmless (other than taking up a small amount of bandwidth). The |
| 1088 |
only difference between SVSMODE and SVS2MODE is that, when used to |
| 1089 |
set client modes, the latter sends a <tt>MODE</tt> message to the |
| 1090 |
target client, while the former does not.</dd> |
| 1091 |
|
| 1092 |
<dt><b><tt>SVSNLINE</tt></b></dt> |
| 1093 |
<dd>This message is used for managing what Services refers to as the |
| 1094 |
SGline list, and takes one of two formats: |
| 1095 |
<ul> |
| 1096 |
<li><tt>SVSNLINE + <i>reason</i> :<i>mask</i></tt></li> |
| 1097 |
<li><tt>SVSNLINE - :<i>mask</i></tt></li> |
| 1098 |
</ul> |
| 1099 |
Unlike other access control lists, which are handled by the |
| 1100 |
<tt>TKL</tt> message (discussed below), masks for <tt>SVSNLINE</tt> |
| 1101 |
messages may contain spaces, and thus must be the last parameter of |
| 1102 |
the message. As a corollary, the <tt><i>reason</i></tt> parameter |
| 1103 |
cannot contain spaces. In Services, any spaces in the reason are |
| 1104 |
converted to underscores when an <tt>SVSNLINE +</tt> message is |
| 1105 |
sent.</dd> |
| 1106 |
|
| 1107 |
<dt><b><tt>TKL</tt></b></dt> |
| 1108 |
<dd>This message is used for managing network-wide global connection |
| 1109 |
control lists (autokills and S-lines). The message takes as |
| 1110 |
parameters: |
| 1111 |
<ul> |
| 1112 |
<li>A <tt>+</tt> or <tt>-</tt> indicating whether the mask is being |
| 1113 |
added or removed.</li> |
| 1114 |
<li>The type of the mask (a single character, such as <tt>Z</tt> |
| 1115 |
for SZlines).</li> |
| 1116 |
<li>The username part of the mask.</li> |
| 1117 |
<li>The hostname part of the mask.</li> |
| 1118 |
<li>The entity (client or server) responsible for the action.</li> |
| 1119 |
<li><i>(add only)</i> Timestamp (in Unix <tt>time()</tt> style) |
| 1120 |
for when the mask expires, or 0 if it should not expire.</li> |
| 1121 |
<li><i>(add only)</i> Timestamp at which the mask was added.</li> |
| 1122 |
<li><i>(add only)</i> Reason string associated with the mask.</li> |
| 1123 |
</ul> |
| 1124 |
When a new server connects to the network, all active <tt>TKL</tt> |
| 1125 |
masks are forwarded to the server. This can cause problems if a |
| 1126 |
mask is removed while a server is split from the network; when the |
| 1127 |
split server reconnects, it will send the mask back to the network, |
| 1128 |
causing it to reappear. While there is nothing that Services can |
| 1129 |
do about this in the general case, it does watch for new masks |
| 1130 |
added that give Services itself as the adder (Services uses its own |
| 1131 |
server name as the entity adding the mask, and this is preserved |
| 1132 |
when other servers forward the mask). When it sees such a mask |
| 1133 |
sent from the network, it checks whether that mask actually exists |
| 1134 |
in the current databases, and if not, it sends a <tt>TKL -</tt> |
| 1135 |
message to remove the mask, assuming that a split server has |
| 1136 |
rejoined the network and reintroduced an old mask.</dd> |
| 1137 |
</dl> |
| 1138 |
|
| 1139 |
<p>The extra messages in Unreal along with their handlers are listed in the |
| 1140 |
<tt>unreal_messages[]</tt> table, which is registered at initialization |
| 1141 |
time using <tt>register_messages()</tt> (see <a href="2.html#s5-3">section |
| 1142 |
2-5-3</a>). Some additional messages are also listed with <tt>NULL</tt> |
| 1143 |
handlers in order to prevent warning messages from being written to the log |
| 1144 |
when those messages are received.</p> |
| 1145 |
|
| 1146 |
<p>Unreal also supports the concept of <i>tokens</i>, short names for |
| 1147 |
messages used in server-to-server communication. These slightly reduce the |
| 1148 |
bandwidth needed for messages, but more importantly speed up message |
| 1149 |
lookups, since only one or two characters need to be checked rather than a |
| 1150 |
longer text string. The list of tokens used by Unreal is in the |
| 1151 |
<tt>tokens[]</tt> array; this array is passed to <tt>init_tokens()</tt>, |
| 1152 |
the initialization routine defined in the <tt>tokens.c</tt> auxiliary |
| 1153 |
source file (see <a href="#s7-7">section 5-7-7</a>).</p> |
| 1154 |
|
| 1155 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1156 |
|
| 1157 |
|
| 1158 |
<h5 class="subsubsubsection-title" id="s6-14-3">5-6-14-3. Message sending</h5> |
| 1159 |
|
| 1160 |
<p>Most of the remainder of the source file consists of various routines |
| 1161 |
which send messages to the network. These include the required |
| 1162 |
functionality listed in <a href="#s3-1">section 5-3-1</a>, as well as a |
| 1163 |
number of callback functions which send messages to the network in response |
| 1164 |
to certain events. The routines are as follows:</p> |
| 1165 |
|
| 1166 |
<dl> |
| 1167 |
<dt><tt><b>do_send_svstime()</b></tt></dt> |
| 1168 |
<dd>Sends a <tt>TSCTL SVSTIME</tt> message to the network to |
| 1169 |
synchronize servers' clocks. Used for periodic time |
| 1170 |
synchronization when requested via the <tt>SetServerTimes</tt> |
| 1171 |
configuration directive.</dd> |
| 1172 |
|
| 1173 |
<dt><tt><b>do_send_nick()</b></tt> |
| 1174 |
<br/><tt><b>do_send_nickchange()</b></tt> |
| 1175 |
<br/><tt><b>do_send_namechange()</b></tt> |
| 1176 |
<br/><tt><b>do_send_server()</b></tt> |
| 1177 |
<br/><tt><b>do_send_server_remote()</b></tt> |
| 1178 |
<br/><tt><b>do_wallops()</b></tt> |
| 1179 |
<br/><tt><b>do_notice_all()</b></tt> |
| 1180 |
<br/><tt><b>do_send_channel_cmd()</b></tt></dt> |
| 1181 |
<dd>Implement the corresponding required message routines.</dd> |
| 1182 |
|
| 1183 |
<dt><tt><b>do_receive_message()</b></tt></dt> |
| 1184 |
<dd>Performs special actions on received messages. This callback |
| 1185 |
function has two purposes; one is to watch for and reverse |
| 1186 |
improper servicestamp changes, and the other is to parse the |
| 1187 |
protocol version embedded in the remote server's <tt>SERVER</tt> |
| 1188 |
message at connection registration time. In both of these |
| 1189 |
cases, we do not want to override the standard behavior for the |
| 1190 |
messages, but the current message framework does not allow for |
| 1191 |
this, so we watch for the messages at this lowest level and |
| 1192 |
perform the necessary processing there. With respect to the |
| 1193 |
former case specifically, it would in theory be possible to |
| 1194 |
handle servicestamp changes in <tt>do_user_mode()</tt>, |
| 1195 |
described below, but poor design in Unreal resulted in Services |
| 1196 |
stamps sharing a mode letter (<tt>+d</tt>) with "deaf" mode, so |
| 1197 |
"+d <i>stamp</i>" needs to be treated separately from other |
| 1198 |
mode changes.</dd> |
| 1199 |
|
| 1200 |
<dt><tt><b>do_user_create()</b></tt></dt> |
| 1201 |
<dd>Called when a new <tt>User</tt> structure is created in response |
| 1202 |
to a <tt>NICK</tt> message, this routine stores the "fake hostname" |
| 1203 |
parameter (not handled by <tt>do_nick()</tt>) in the corresponding |
| 1204 |
field in the <tt>User</tt> structure.</dd> |
| 1205 |
|
| 1206 |
<dt><tt><b>do_user_servicestamp_change()</b></tt></dt> |
| 1207 |
<dd>Called when a client is assigned a servicestamp to send the new |
| 1208 |
stamp out to the network.</dd> |
| 1209 |
|
| 1210 |
<dt><tt><b>do_user_mode()</b></tt></dt> |
| 1211 |
<dd>Called when a client's user modes are being changed. Services |
| 1212 |
handles two user modes exclusively: <tt>+r</tt>, indicating that |
| 1213 |
the client's nickname is registered (and the client is in fact the |
| 1214 |
owner of the nickname), and <tt>+a</tt>, indicating that the client |
| 1215 |
is a Services administrator. If another server tries to change |
| 1216 |
either of these modes, Services reverses the change. This routine |
| 1217 |
also watches for users with Services administrator privilege who |
| 1218 |
newly gain IRC operator status, and sets <tt>+a</tt> on them.</dd> |
| 1219 |
|
| 1220 |
<dt><tt><b>do_channel_mode()</b></tt></dt> |
| 1221 |
<dd>Called when a channel's modes are being changed. This routine |
| 1222 |
takes care of storing the <tt>+L</tt> (channel link), <tt>+f</tt> |
| 1223 |
(flood protection), and <tt>+j</tt> (join rate limiting) parameters |
| 1224 |
in the <tt>Channel</tt> structure.</dd> |
| 1225 |
|
| 1226 |
<dt><tt><b>do_clear_channel()</b></tt></dt> |
| 1227 |
<dd>Handles requests to clear bans and exceptions from a channel. |
| 1228 |
Ordinarily, <tt>clear_channel()</tt> will handle bans itself and |
| 1229 |
ban exceptions are handled by the <tt>banexcept.c</tt> auxiliary |
| 1230 |
source file, but Unreal has a feature called "extended ban types", |
| 1231 |
in which a prefix like <tt>~r:</tt> changes the meaning of the ban |
| 1232 |
or exception mask. In order to process these bans correctly, |
| 1233 |
the <tt>protocol/unreal</tt> module has to intervene via the |
| 1234 |
"<tt>clear_channel</tt>" callback and process ban and exception |
| 1235 |
clear requests itself. The actual work is done by |
| 1236 |
<tt>unreal_clear_bans_excepts()</tt>, which calls |
| 1237 |
<tt>unreal_match_ban()</tt> to determine whether a particular mask |
| 1238 |
matches a given client.</dd> |
| 1239 |
|
| 1240 |
<dt><tt><b>do_nick_identified()</b></tt></dt> |
| 1241 |
<dd>Called when a client identifies for its nickname, and sets the |
| 1242 |
<tt>+a</tt> user mode on the client if it has Services |
| 1243 |
administrator (and IRC operator) privileges.</dd> |
| 1244 |
|
| 1245 |
<dt><tt><b>do_set_topic()</b></tt></dt> |
| 1246 |
<dd>Called when setting a topic on a channel (see |
| 1247 |
<a href="#s3-1">section 5-3-1</a>). Unreal ignores topic changes |
| 1248 |
if the topic timestamp is earlier than that of the channel's |
| 1249 |
current topic, so if necessary, the supplied timestamp is advanced |
| 1250 |
to force the topic to be changed.</dd> |
| 1251 |
|
| 1252 |
<dt><tt><b>do_check_modes()</b></tt></dt> |
| 1253 |
<dd>Called when checking the validity of a mode change on a registered |
| 1254 |
channel; ensures that the <tt>+L</tt>, <tt>+f</tt>, and <tt>+j</tt> |
| 1255 |
modes are set properly according to the mode lock data. (The "off" |
| 1256 |
versions, <tt>-L</tt> and so on, do not require parameters and thus |
| 1257 |
can be handled by the standard ChanServ code.)</dd> |
| 1258 |
|
| 1259 |
<dt><tt><b>do_check_chan_user_modes()</b></tt></dt> |
| 1260 |
<dd>Called when checking whether to modify a client's channel user |
| 1261 |
modes. This routine watches for and excludes from the check two |
| 1262 |
classes of clients: other service-type pseudoclients (with user |
| 1263 |
mode <tt>+S</tt> set), since they generally should not be subject |
| 1264 |
to the same restrictions as ordinary clients, and "hiding" users |
| 1265 |
(<tt>+I</tt>), whose presence would be revealed by a mode change.</dd> |
| 1266 |
|
| 1267 |
<dt><tt><b>do_check_kick()</b></tt></dt> |
| 1268 |
<dd>Called when checking whether to allow a user to join a channel. |
| 1269 |
This routine watches for users entering administrator-only, |
| 1270 |
secure-only, or no-hiding channels, and kicks them out if their |
| 1271 |
user modes are incompatible with the channel. (Normally the IRC |
| 1272 |
server will take care of this and Services will never see the join |
| 1273 |
attempt, but when joining a registered channel which is empty, the |
| 1274 |
server will not know anything about the channel's locked modes, so |
| 1275 |
Services must perform the check.)</dd> |
| 1276 |
|
| 1277 |
<dt><tt><b>do_set_mlock()</b></tt></dt> |
| 1278 |
<dd>Called when setting a new mode lock on a registered channel. |
| 1279 |
This routine takes care of setting the aforementioned <tt>+L</tt>, |
| 1280 |
<tt>+f</tt>, and <tt>+j</tt> mode parameters in the mode lock |
| 1281 |
structure, and also ensures that the new mode lock is consistent |
| 1282 |
(<tt>+K</tt> requires <tt>+i</tt> to be set, and <tt>+L</tt> |
| 1283 |
requires <tt>+l</tt>).</dd> |
| 1284 |
|
| 1285 |
<dt><tt><b>do_send_svsjoin()</b></tt></dt> |
| 1286 |
<dd>Called to send a message which forces a user to join a channel. |
| 1287 |
In Unreal, the message is called <tt>SVSJOIN</tt>.</dd> |
| 1288 |
|
| 1289 |
<dt><tt><b>do_send_akill()</b></tt> |
| 1290 |
<br/><tt><b>do_cancel_akill()</b></tt> |
| 1291 |
<br/><tt><b>do_send_exclude()</b></tt> |
| 1292 |
<br/><tt><b>do_cancel_exclude()</b></tt> |
| 1293 |
<br/><tt><b>do_send_sgline()</b></tt> |
| 1294 |
<br/><tt><b>do_send_sqline()</b></tt> |
| 1295 |
<br/><tt><b>do_send_szline()</b></tt> |
| 1296 |
<br/><tt><b>do_cancel_sgline()</b></tt> |
| 1297 |
<br/><tt><b>do_cancel_sqline()</b></tt> |
| 1298 |
<br/><tt><b>do_cancel_szline()</b></tt> |
| 1299 |
</dt> |
| 1300 |
<dd>Called to add or remove autokill, autokill exclusion, or S-line |
| 1301 |
masks.</dd> |
| 1302 |
</dl> |
| 1303 |
|
| 1304 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1305 |
|
| 1306 |
|
| 1307 |
<h5 class="subsubsubsection-title" id="s6-14-4">5-6-14-4. Module initialization and cleanup</h5> |
| 1308 |
|
| 1309 |
<p>The final part of the module source file is the module framework, used |
| 1310 |
by the core module subsystem when loading and unloading the module, along |
| 1311 |
with callback functions to monitor loading and unloading of relevant |
| 1312 |
modules and set appropriate callbacks and local variables.</p> |
| 1313 |
|
| 1314 |
<p>The module's configuration data is stored in the exported array |
| 1315 |
<tt>module_config[]</tt>. The <tt>protocol/unreal</tt> module includes two |
| 1316 |
Unreal-specific configuration options: <tt>ServerNumeric</tt>, to assign |
| 1317 |
Services a "numeric" value to be used with Unreal servers, and |
| 1318 |
<tt>SetServerTimes</tt>, which sets whether and how often Services should |
| 1319 |
synchronize other servers' clocks. The array also includes configuration |
| 1320 |
data from the <tt>SJOIN</tt> handler (defined in <tt>sjoin.h</tt>).</p> |
| 1321 |
|
| 1322 |
<p>The <tt>do_load_module()</tt> and <tt>do_unload_module()</tt> routines |
| 1323 |
watch for various pseudoclient-related modules to be loaded or unloaded. |
| 1324 |
For modules that provide callbacks which the <tt>protocol/unreal</tt> |
| 1325 |
module hooks into, the appropriate callback functions are added here. |
| 1326 |
Additionally, the handles for the <tt>operserv/main</tt> and |
| 1327 |
<tt>chanserv/main</tt> modules, as well as the values (addresses) of the |
| 1328 |
symbols <tt>is_services_admin</tt> and <tt>s_ChanServ</tt>, are saved when |
| 1329 |
the relevant module is loaded and cleared when it is unloaded (see |
| 1330 |
<a href="#s6-14-1">section 5-6-14-1</a>).</p> |
| 1331 |
|
| 1332 |
<p>Finally, the initialization and cleanup functions call the appropriate |
| 1333 |
subroutines in a fairly arbitrary order (except that cleanup is performed |
| 1334 |
in the opposite order of initialization). The initialization and cleanup |
| 1335 |
for the auxiliary source files is also handled here.</p> |
| 1336 |
|
| 1337 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1338 |
|
| 1339 |
<!------------------------------------------------------------------------> |
| 1340 |
<hr/> |
| 1341 |
|
| 1342 |
<h3 class="subsection-title" id="s7">5-7. Auxiliary source file details</h3> |
| 1343 |
|
| 1344 |
<p>In addition to the main protocol files described in |
| 1345 |
<a href="#s6">section 5-6</a>, there are several auxiliary source files |
| 1346 |
which implement functions common to two or more protocols. These are |
| 1347 |
listed below. The source files are all designed to be included directly |
| 1348 |
into the modules which use them; this is to avoid symbol clashes caused by |
| 1349 |
linking the same object file into two or more modules when compiling |
| 1350 |
modules statically. (Each source file also has a corresponding header |
| 1351 |
file, but as this is included by the source file, modules do not need to |
| 1352 |
include the header files separately.)</p> |
| 1353 |
|
| 1354 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1355 |
|
| 1356 |
|
| 1357 |
<h4 class="subsubsection-title" id="s7-1">5-7-1. <tt>banexcept.c</tt>, <tt>banexcept.h</tt></h4> |
| 1358 |
|
| 1359 |
<p>The <tt>banexcept.c</tt> source file implements support for <i>ban |
| 1360 |
exceptions</i>, masks specifying clients which are not subject to channel |
| 1361 |
bans. The channel mode for exceptions is assumed to be <tt>+e</tt>.</p> |
| 1362 |
|
| 1363 |
<p>In addition to handling the actual setting and clearing of ban |
| 1364 |
exceptions (adding or removing masks on the channel's ban exception array), |
| 1365 |
the file also implements a handler for clearing ban exceptions using the |
| 1366 |
<tt>CLEAR_EXCEPTS</tt> flag to <tt>clear_channel()</tt>, as well as a |
| 1367 |
callback function for the ChanServ <tt>CLEAR</tt> command allowing |
| 1368 |
<tt>CLEAR EXCEPTIONS</tt> to be used. Since the latter function is part |
| 1369 |
of the <tt>chanserv/main</tt> module rather than the core, this |
| 1370 |
necessitates the use of "<tt>load module</tt>" and |
| 1371 |
"<tt>unload module</tt>" callbacks to watch for that module being |
| 1372 |
loaded and unloaded.</p> |
| 1373 |
|
| 1374 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1375 |
|
| 1376 |
|
| 1377 |
<h4 class="subsubsection-title" id="s7-2">5-7-2. <tt>chanprot.c</tt>, <tt>chanprot.h</tt></h4> |
| 1378 |
|
| 1379 |
<p>The <tt>chanprot.c</tt> source file implements support for a "protected" |
| 1380 |
channel user mode, preventing ordinary channel operators from kicking a |
| 1381 |
user with that mode. However, the only "support" required is the |
| 1382 |
modification of one language string, which is modified by the |
| 1383 |
initialization routine and restored to its original value by the cleanup |
| 1384 |
routine.</p> |
| 1385 |
|
| 1386 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1387 |
|
| 1388 |
|
| 1389 |
<h4 class="subsubsection-title" id="s7-3">5-7-3. <tt>halfop.c</tt>, <tt>halfop.h</tt></h4> |
| 1390 |
|
| 1391 |
<p>The <tt>halfop.c</tt> source file implements support for a "half-op" |
| 1392 |
channel user mode, assumed to be <tt>+h</tt>. Half-ops occupy a privilege |
| 1393 |
level between voiced users (<tt>+v</tt>) and channel operators |
| 1394 |
(<tt>+o</tt>); typically, they can set <tt>+v</tt> on users and change the |
| 1395 |
channel topic, but cannot change channel modes or kick channel operators. |
| 1396 |
In addition to updating several language strings, the source file adds a |
| 1397 |
callback function for the ChanServ <tt>CLEAR</tt> command allowing |
| 1398 |
<tt>CLEAR HALFOPS</tt> to be used. As with <tt>banexcept.c</tt>, this |
| 1399 |
necessitates the use of load/unload-module callback functions to watch for |
| 1400 |
the ChanServ module being loaded or unloaded.</p> |
| 1401 |
|
| 1402 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1403 |
|
| 1404 |
|
| 1405 |
<h4 class="subsubsection-title" id="s7-4">5-7-4. <tt>invitemask.c</tt>, <tt>invitemask.h</tt></h4> |
| 1406 |
|
| 1407 |
<p>The <tt>invitemask.c</tt> source file implements support for <i>invite |
| 1408 |
masks</i>, masks specifying clients which are allowed to join a <tt>+i</tt> |
| 1409 |
channel without being explicitly invited into the channel. The channel |
| 1410 |
mode for exceptions is assumed to be <tt>+I</tt>. Except for the actual |
| 1411 |
mode character used and structure fields modified, this source file is |
| 1412 |
identical to <tt>banexcept.c</tt>.</p> |
| 1413 |
|
| 1414 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1415 |
|
| 1416 |
|
| 1417 |
<h4 class="subsubsection-title" id="s7-5">5-7-5. <tt>sjoin.c</tt>, <tt>sjoin.h</tt></h4> |
| 1418 |
|
| 1419 |
<p>The <tt>sjoin.c</tt> source file implements support for the |
| 1420 |
<tt>SJOIN</tt> message used in IRC servers such as Bahamut and Unreal. |
| 1421 |
This is easily the most complex of the auxiliary source files.</p> |
| 1422 |
|
| 1423 |
<p>The basic idea of the <tt>SJOIN</tt> message is to condense several |
| 1424 |
types of channel information—channel creation time, channel modes, |
| 1425 |
and users on the channel—into a single message, reducing the |
| 1426 |
bandwidth required to send channel state across the network and reducing |
| 1427 |
the potential for race conditions. There are a few slightly different |
| 1428 |
message formats used, as noted in the source code comments, but in general |
| 1429 |
the message takes the channel name, channel creation time, mode string, |
| 1430 |
(optional) mode parameters, and finally (in a colon-prefixed parameter) the |
| 1431 |
list of clients (nicknames) on the channel. In this last parameter, each |
| 1432 |
client's nickname is prefixed with characters indicating the client's |
| 1433 |
channel user modes; for example, if <tt><i>Nickname</i></tt> is a channel |
| 1434 |
operator on the channel, the client will be listed as |
| 1435 |
<tt>@<i>NickName</i></tt> in the message.</p> |
| 1436 |
|
| 1437 |
<p>Processing of the <tt>SJOIN</tt> message is handled by the |
| 1438 |
<tt>do_sjoin()</tt> routine; the module should call this routine when in |
| 1439 |
receives an <tt>SJOIN</tt> message. <tt>do_sjoin()</tt> looks at the |
| 1440 |
parameters to determine the message's format, then walks through the list |
| 1441 |
of nicknames (and possibly bans and exceptions), adding each one to the |
| 1442 |
channel. If any users actually joined the channel, then the channel modes |
| 1443 |
and timestamp are set afterwards.</p> |
| 1444 |
|
| 1445 |
<p>The <tt>SJOIN</tt> message can also be used as a shortcut to remove all |
| 1446 |
users from a channel with one command. By sending an <tt>SJOIN</tt> with |
| 1447 |
a channel timestamp older than the channel's current timestamp, the remote |
| 1448 |
server will treat Services' <tt>SJOIN</tt> as authoritative. If that |
| 1449 |
message indicates that no users are in the channel (an empty last |
| 1450 |
parameter), then the IRC server will automatically kick all the users |
| 1451 |
currently on the channel, saving Services the trouble of having to send |
| 1452 |
<tt>KICK</tt> messages for all users.</p> |
| 1453 |
|
| 1454 |
<p>Additionally, since <tt>SJOIN</tt> includes the channel's creation time |
| 1455 |
as a parameter, it is possible to use a dummy <tt>SJOIN</tt> message to |
| 1456 |
deliberately set the creation timestamp of a registered channel to the time |
| 1457 |
the channel was registered, ensuring that the channel will always be |
| 1458 |
considered the "canonical" one even if the same channel is created on a |
| 1459 |
split server.. The configuration option <tt>CSSetChannelTime</tt> |
| 1460 |
activates this behavior. (This configuration option is defined in a macro, |
| 1461 |
<tt>SJOIN_CONFIG</tt>, in <tt>sjoin.h</tt>; the module should include this |
| 1462 |
macro as part of its <tt>module_config[]</tt> array.) The actual setting |
| 1463 |
of the channel creation time is done using the "<tt>channel create</tt>" |
| 1464 |
callback; when a user first enters an empty channel, Services sends an |
| 1465 |
<tt>SJOIN</tt> message to the network with the altered channel creation |
| 1466 |
time, including the newly-joining user in the user list; this results in |
| 1467 |
the channel creation time being updated without any other changes being |
| 1468 |
made to the channel.</p> |
| 1469 |
|
| 1470 |
<p>Unfortunately, both of the major IRC servers using <tt>SJOIN</tt>, |
| 1471 |
Bahamut and Unreal, have idiosyncrasies that prevent this behavior from |
| 1472 |
working exactly as designed; Bahamut ignores any channel user modes set on |
| 1473 |
clients who are not behind the sending server, causing the client to lose |
| 1474 |
channel operator privileges, while Unreal interprets an empty mode string |
| 1475 |
(a single "<tt>+</tt>") to mean "clear all channel modes". To work around |
| 1476 |
this, if the module defines the preprocessor symbol <tt>BAHAMUT_HACK</tt> |
| 1477 |
before including this source file, this processing will be modified to set |
| 1478 |
<tt>+o</tt> again on the newly-joining client if it was <tt>+o</tt> before |
| 1479 |
the Services <tt>SJOIN</tt> was sent; this restores the original channel |
| 1480 |
state, at the cost of having an unsightly <tt>MODE -o</tt> and |
| 1481 |
<tt>MODE +o</tt> in quick succession when a user first enters a |
| 1482 |
registered channel. Likewise, defining <tt>UNREAL_HACK</tt> will work |
| 1483 |
around the Unreal problem by using the channel mode parameter to set |
| 1484 |
<tt>+o</tt> on the user rather than listing the user in the final |
| 1485 |
parameter.</p> |
| 1486 |
|
| 1487 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1488 |
|
| 1489 |
|
| 1490 |
<h4 class="subsubsection-title" id="s7-6">5-7-6. <tt>svsnick.c</tt>, <tt>svsnick.h</tt></h4> |
| 1491 |
|
| 1492 |
<p>The <tt>svsnick.c</tt> source file implements support for forced |
| 1493 |
changing of clients' nicknames; this is used, for example, by NickServ to |
| 1494 |
change a client's nickname to a "guest" nickname rather than disconnecting |
| 1495 |
the client outright. The implementation itself simply consists of setting |
| 1496 |
the <tt>PF_CHANGENICK</tt> protocol feature flag and assigning a function |
| 1497 |
to the <tt>send_nickchange_remote()</tt> function pointer. However, unlike |
| 1498 |
most other auxiliary source files, the initialization function |
| 1499 |
<tt>init_svsnick()</tt> takes a parameter; this is so that the protocol |
| 1500 |
module can specify the name of the message used, in case it is not |
| 1501 |
<tt>SVSNICK</tt>.</p> |
| 1502 |
|
| 1503 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1504 |
|
| 1505 |
|
| 1506 |
<h4 class="subsubsection-title" id="s7-7">5-7-7. <tt>token.c</tt>, <tt>token.h</tt></h4> |
| 1507 |
|
| 1508 |
<p>The <tt>token.c</tt> source file implements the use of one- or |
| 1509 |
two-character <i>tokens</i> to substitute for full message names in |
| 1510 |
server-to-server communications. The mapping of tokens to message names |
| 1511 |
is given by a <tt>TokenInfo</tt> array passed to <tt>init_tokens()</tt>, |
| 1512 |
terminated by an entry with the <tt>token</tt> field of the structure set |
| 1513 |
to <tt>NULL</tt>. The initialization routine uses this mapping array to |
| 1514 |
generate a 65,536-entry lookup table, indexed by the two characters of the |
| 1515 |
token taken as a 16-bit value with the first character in the high eight |
| 1516 |
bits (a value of zero is used for the second character in the case of a |
| 1517 |
one-character token). The values in the lookup table point directly to |
| 1518 |
the handler functions; this eliminates the necessity to search through |
| 1519 |
the message table, but also means that any later changes to the message |
| 1520 |
table will not be seen.</p> |
| 1521 |
|
| 1522 |
<p>The actual processing of the tokens is done by a callback function added |
| 1523 |
to the "<tt>receive message</tt>" callback. The function checks |
| 1524 |
whether the message name is two characters long or less and whether there |
| 1525 |
is a function in the table corresponding to the one- or two-character |
| 1526 |
message name; if so, that function is called, and the ordinary message |
| 1527 |
processing is skipped.</p> |
| 1528 |
|
| 1529 |
|
| 1530 |
<p class="backlink"><a href="#top">Back to top</a></p> |
| 1531 |
|
| 1532 |
<!------------------------------------------------------------------------> |
| 1533 |
<hr/> |
| 1534 |
|
| 1535 |
<p class="backlink"><a href="4.html">Previous section: The module system</a> | |
| 1536 |
<a href="index.html">Table of Contents</a> | |
| 1537 |
<a href="6.html">Next section: Database handling</a></p> |
| 1538 |
|
| 1539 |
</body> |
| 1540 |
</html> |