ViewVC logotype

Annotation of /vendor/ircservices-5.1.24/docs/tech/5.html

Parent Directory Parent Directory | Revision Log Revision Log

Revision 3389 - (hide annotations)
Fri Apr 25 14:12:15 2014 UTC (6 years, 3 months ago) by michael
File MIME type: application/xhtml+xml
File size: 82975 byte(s)
- Imported ircservices-5.1.24

1 michael 3389 <?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>
10     <body>
11     <h1 class="title" id="top">IRC Services Technical Reference Manual</h1>
13     <h2 class="section-title">5. IRC server interface</h2>
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/>&nbsp;&nbsp;&nbsp;&nbsp;5-3-1. <a href="#s3-1">Required functionality</a>
20     <br/>&nbsp;&nbsp;&nbsp;&nbsp;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/>&nbsp;&nbsp;&nbsp;&nbsp;5-4-1. <a href="#s4-1">Required functionality</a>
23     <br/>&nbsp;&nbsp;&nbsp;&nbsp;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/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-1. <a href="#s6-1"><tt>protocol/rfc1459</tt></a>
27     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-2. <a href="#s6-2"><tt>protocol/ts8</tt></a>
28     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-3. <a href="#s6-3"><tt>protocol/dalnet</tt></a>
29     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-4. <a href="#s6-4"><tt>protocol/dreamforge</tt></a>
30     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-5. <a href="#s6-5"><tt>protocol/bahamut</tt></a>
31     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-6. <a href="#s6-6"><tt>protocol/hybrid</tt></a>
32     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-7. <a href="#s6-7"><tt>protocol/inspircd</tt></a>
33     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-8. <a href="#s6-8"><tt>protocol/monkey</tt></a>
34     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-9. <a href="#s6-9"><tt>protocol/ptlink</tt></a>
35     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-10. <a href="#s6-10"><tt>protocol/ratbox</tt></a>
36     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-11. <a href="#s6-11"><tt>protocol/solidircd</tt></a>
37     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-12. <a href="#s6-12"><tt>protocol/trircd</tt></a>
38     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-13. <a href="#s6-13"><tt>protocol/undernet-p9</tt></a>
39     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-6-14. <a href="#s6-14"><tt>protocol/unreal</tt></a>
40     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5-6-14-1. <a href="#s6-14-1">Module prologue</a>
41     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5-6-14-2. <a href="#s6-14-2">Message receiving</a>
42     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5-6-14-3. <a href="#s6-14-3">Message sending</a>
43     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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/>&nbsp;&nbsp;&nbsp;&nbsp;5-7-1. <a href="#s7-1"><tt>banexcept.c</tt>, <tt>banexcept.h</tt></a>
46     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-7-2. <a href="#s7-2"><tt>chanprot.c</tt>, <tt>chanprot.h</tt></a>
47     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-7-3. <a href="#s7-3"><tt>halfop.c</tt>, <tt>halfop.h</tt></a>
48     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-7-4. <a href="#s7-4"><tt>invitemask.c</tt>, <tt>invitemask.h</tt></a>
49     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-7-5. <a href="#s7-5"><tt>sjoin.c</tt>, <tt>sjoin.h</tt></a>
50     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-7-6. <a href="#s7-6"><tt>svsnick.c</tt>, <tt>svsnick.h</tt></a>
51     <br/>&nbsp;&nbsp;&nbsp;&nbsp;5-7-7. <a href="#s7-7"><tt>token.c</tt>, <tt>token.h</tt></a>
52     </p>
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>
58     <!------------------------------------------------------------------------>
59     <hr/>
61     <h3 class="subsection-title" id="s1">5-1. Protocol modules: the IRC protocol bridge</h3>
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>
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&mdash;for
78     example, that the protocol uses lines of text terminated by a CR/LF
79     pair&mdash;most differences seen in current IRC servers can be handled by
80     protocol modules.</p>
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>
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>
105     <p class="backlink"><a href="#top">Back to top</a></p>
107     <!------------------------------------------------------------------------>
108     <hr/>
110     <h3 class="subsection-title" id="s2">5-2. Specifying protocol features</h3>
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>
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>
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>
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>
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>
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>
185     <p>There are also three variables which can be optionally set as needed:</p>
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>
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>
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>
211     <p class="backlink"><a href="#top">Back to top</a></p>
213     <!------------------------------------------------------------------------>
214     <hr/>
216     <h3 class="subsection-title" id="s3">5-3. Sending messages to the network</h3>
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>
222     <p class="backlink"><a href="#top">Back to top</a></p>
225     <h4 class="subsubsection-title" id="s3-1">5-3-1. Required functionality</h4>
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>
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>
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>
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>
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>
272     <p class="backlink"><a href="#top">Back to top</a></p>
275     <h4 class="subsubsection-title" id="s3-2">5-3-2. Optional functionality</h4>
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>
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>
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>
302     <p class="backlink"><a href="#top">Back to top</a></p>
304     <!------------------------------------------------------------------------>
305     <hr/>
307     <h3 class="subsection-title" id="s4">5-4. Receiving messages from the network</h3>
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>
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>
320     <p class="backlink"><a href="#top">Back to top</a></p>
323     <h4 class="subsubsection-title" id="s4-1">5-4-1. Required functionality</h4>
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>
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>
337     <p class="backlink"><a href="#top">Back to top</a></p>
340     <h4 class="subsubsection-title" id="s4-2">5-4-2. Optional functionality</h4>
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>
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>
355     <p class="backlink"><a href="#top">Back to top</a></p>
357     <!------------------------------------------------------------------------>
358     <hr/>
360     <h3 class="subsection-title" id="s5">5-5. Other functions of protocol modules</h3>
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>
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>
380     <p class="backlink"><a href="#top">Back to top</a></p>
382     <!------------------------------------------------------------------------>
383     <hr/>
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>
395     <p class="backlink"><a href="#top">Back to top</a></p>
398     <h4 class="subsubsection-title" id="s6-1">5-6-1. <tt>protocol/rfc1459</tt></h4>
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>
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>
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>
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>
441     <p>There is only one callback function defined by the module; it hooks into
442     the "<tt>set&nbsp;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>
447     <p>The module initialization routine sets the protocol-specific variables
448     (<tt>protocol_name</tt>, <tt>protocol_version</tt>, and so on&mdash;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&nbsp;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>
460     <p class="backlink"><a href="#top">Back to top</a></p>
463     <h4 class="subsubsection-title" id="s6-2">5-6-2. <tt>protocol/ts8</tt></h4>
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>
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&nbsp;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>
490     <p class="backlink"><a href="#top">Back to top</a></p>
493     <h4 class="subsubsection-title" id="s6-3">5-6-3. <tt>protocol/dalnet</tt></h4>
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>
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>
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>
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&nbsp;module"</tt> callback. An "<tt>unload&nbsp;module</tt>"
525     callback is also included for completeness, though it does nothing in this
526     module.</p>
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>[&nbsp;\&nbsp;]</tt> are to be interepreted as equivalent to
532     <tt>{&nbsp;|&nbsp;}</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>[&nbsp;\&nbsp;]</tt> as distinct from <tt>{&nbsp;|&nbsp;}</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>
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>
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>
567     <p class="backlink"><a href="#top">Back to top</a></p>
570     <h4 class="subsubsection-title" id="s6-4">5-6-4. <tt>protocol/dreamforge</tt></h4>
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>
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>
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>
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&nbsp;module</tt>" callback
612     function when the <tt>operserv/main</tt> module is loaded (and cleared
613     again by the "<tt>unload&nbsp;module</tt>" if <tt>operserv/main</tt> is
614     unloaded).</p>
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>
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>
636     <p class="backlink"><a href="#top">Back to top</a></p>
639     <h4 class="subsubsection-title" id="s6-5">5-6-5. <tt>protocol/bahamut</tt></h4>
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>
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>
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>
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&nbsp;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&nbsp;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>
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&nbsp;<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>
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>
711     <p class="backlink"><a href="#top">Back to top</a></p>
714     <h4 class="subsubsection-title" id="s6-6">5-6-6. <tt>protocol/hybrid</tt></h4>
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>
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>
733     <p class="backlink"><a href="#top">Back to top</a></p>
736     <h4 class="subsubsection-title" id="s6-7">5-6-7. <tt>protocol/inspircd</tt></h4>
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>
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>
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>
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>
771     <p class="backlink"><a href="#top">Back to top</a></p>
774     <h4 class="subsubsection-title" id="s6-8">5-6-8. <tt>protocol/monkey</tt></h4>
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>
783     <p class="backlink"><a href="#top">Back to top</a></p>
786     <h4 class="subsubsection-title" id="s6-9">5-6-9. <tt>protocol/ptlink</tt></h4>
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>
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>
806     <p class="backlink"><a href="#top">Back to top</a></p>
809     <h4 class="subsubsection-title" id="s6-10">5-6-10. <tt>protocol/ratbox</tt></h4>
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>
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>
823     <p class="backlink"><a href="#top">Back to top</a></p>
826     <h4 class="subsubsection-title" id="s6-11">5-6-11. <tt>protocol/solidircd</tt></h4>
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>
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>
845     <p class="backlink"><a href="#top">Back to top</a></p>
848     <h4 class="subsubsection-title" id="s6-12">5-6-12. <tt>protocol/trircd</tt></h4>
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>
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>
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&nbsp;message</tt>" callback to watch for
880     <tt>+L</tt> or <tt>-L</tt> messages for empty channels and process them
881     accordingly.</p>
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>
891     <p class="backlink"><a href="#top">Back to top</a></p>
894     <h4 class="subsubsection-title" id="s6-13">5-6-13. <tt>protocol/undernet-p9</tt></h4>
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>
903     <p class="backlink"><a href="#top">Back to top</a></p>
906     <h4 class="subsubsection-title" id="s6-14">5-6-14. <tt>protocol/unreal</tt></h4>
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>
918     <p class="backlink"><a href="#top">Back to top</a></p>
921     <h5 class="subsubsubsection-title" id="s6-14-1">5-6-14-1. Module prologue</h5>
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>
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>
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>
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>
977     <p class="backlink"><a href="#top">Back to top</a></p>
980     <h5 class="subsubsubsection-title" id="s6-14-2">5-6-14-2. Message receiving</h5>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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&nbsp;-</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>
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>
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>
1155     <p class="backlink"><a href="#top">Back to top</a></p>
1158     <h5 class="subsubsubsection-title" id="s6-14-3">5-6-14-3. Message sending</h5>
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>
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>
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>
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&nbsp;<i>stamp</i>" needs to be treated separately from other
1198     mode changes.</dd>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
1304     <p class="backlink"><a href="#top">Back to top</a></p>
1307     <h5 class="subsubsubsection-title" id="s6-14-4">5-6-14-4. Module initialization and cleanup</h5>
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>
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>
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>
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>
1337     <p class="backlink"><a href="#top">Back to top</a></p>
1339     <!------------------------------------------------------------------------>
1340     <hr/>
1342     <h3 class="subsection-title" id="s7">5-7. Auxiliary source file details</h3>
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>
1354     <p class="backlink"><a href="#top">Back to top</a></p>
1357     <h4 class="subsubsection-title" id="s7-1">5-7-1. <tt>banexcept.c</tt>, <tt>banexcept.h</tt></h4>
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>
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&nbsp;module</tt>" and
1371     "<tt>unload&nbsp;module</tt>" callbacks to watch for that module being
1372     loaded and unloaded.</p>
1374     <p class="backlink"><a href="#top">Back to top</a></p>
1377     <h4 class="subsubsection-title" id="s7-2">5-7-2. <tt>chanprot.c</tt>, <tt>chanprot.h</tt></h4>
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>
1386     <p class="backlink"><a href="#top">Back to top</a></p>
1389     <h4 class="subsubsection-title" id="s7-3">5-7-3. <tt>halfop.c</tt>, <tt>halfop.h</tt></h4>
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>
1402     <p class="backlink"><a href="#top">Back to top</a></p>
1405     <h4 class="subsubsection-title" id="s7-4">5-7-4. <tt>invitemask.c</tt>, <tt>invitemask.h</tt></h4>
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>
1414     <p class="backlink"><a href="#top">Back to top</a></p>
1417     <h4 class="subsubsection-title" id="s7-5">5-7-5. <tt>sjoin.c</tt>, <tt>sjoin.h</tt></h4>
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>
1423     <p>The basic idea of the <tt>SJOIN</tt> message is to condense several
1424     types of channel information&mdash;channel creation time, channel modes,
1425     and users on the channel&mdash;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>
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>
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>
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&nbsp;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>
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&nbsp;-o</tt> and
1481     <tt>MODE&nbsp;+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>
1487     <p class="backlink"><a href="#top">Back to top</a></p>
1490     <h4 class="subsubsection-title" id="s7-6">5-7-6. <tt>svsnick.c</tt>, <tt>svsnick.h</tt></h4>
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>
1503     <p class="backlink"><a href="#top">Back to top</a></p>
1506     <h4 class="subsubsection-title" id="s7-7">5-7-7. <tt>token.c</tt>, <tt>token.h</tt></h4>
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>
1522     <p>The actual processing of the tokens is done by a callback function added
1523     to the "<tt>receive&nbsp;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>
1530     <p class="backlink"><a href="#top">Back to top</a></p>
1532     <!------------------------------------------------------------------------>
1533     <hr/>
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>
1539     </body>
1540     </html>

ViewVC Help
Powered by ViewVC 1.1.28