$Revision: 1.1.2.10 $
$Date: 2003/10/05 02:11:08 $
Abstract
This documentation is a draft. It is full of typo's and grammar errors. It might be unclear at some points.
Future versions of ctrlproxy will include an improved version of this document.
Meanwhile, all comments, questions and updates are welcome at jelmer@vernstok.nl.
Table of Contents
Table of Contents
CtrlProxy is a project I started because I got bored with running irssi in screen on my server. My server isn't very fast and that meant when it was on high load ircing was getting pretty hard. I could of course run irssi on my workstation, but my workstation isn't on 24/7 and some people depend on the channel logs I generate.
The structure of ctrlproxy is very modular and it is easily extendible.
Ctrlproxy is a so-called IRC proxy or BNC (bouncer). It keeps a permanent connection to one or more IRC servers. The user can then connect and disconnect his/her IRC client to the bouncer without actually disconnecting from the 'real' IRC server.
Connect to one server with many clients under one nick transparently
Connect to multiple servers using only one process
CTCP support when no client is attached
irssi-style logging support
Transparent detaching and attaching of clients
Password support
Replication support (from memory)
Auto-Away support
Keeping track of events occuring
Direct, inetd-style interfacing with local IRC servers (such as bitlbee)
Responses to queries are only sent to the originator of the query
SSL support
Table of Contents
Table of Contents
Some distributions come with a packaged version of ctrlproxy. Wilmer van der Gaast is maintaining the debian ctrlproxy package and Aron Griffis maintains the gentoo package of ctrlproxy.
If you already have a packaged version of ctrlproxy installed, you can skip this chapter.
The source of ctrlproxy can be downloaded from the ctrlproxy homepage. The source files available there can be unpacked using tar and gzip:
$ tar xvgz ctrlproxy-2.5.tar.gz ctrlproxy-2.5/AUTHORS ...
If you wish to use the bleeding-edge version of ctrlproxy, you can download the sources from CVS.
Ctrlproxy CVS can be accessed by doing:
$ cvs -d :pserver:anonymous@cvs.vernstok.nl:/cvs login
(when asked for a password, press enter)
$ cvs -d :pserver:anonymous@cvs.vernstok.nl:/cvs co -r UNSTABLE ctrlproxy ctrlproxy ctrlproxy/AUTHORS ctrlproxy/README ...
Make sure you run aclocal, autoheader and autoconf in the source directory (ctrlproxy/) so that the configure script is generated correctly.
You have to use at least autoconf/autoheader 2.50!
First, run the configure script:
$ ./configure
If this script does not detect all libraries and headers, while they are present, specify the locations using command line arguments to configure. Run ./configure --help for details.
After configure has finished, run make.
Now that ctrlproxy has been built, find your system administrator or become root yourself and (get him/her to) run make install.
Ctrlproxy uses a XML as it's RC file. The syntax of XML files is described much better in other documents on the web and is beyond the scope of this document.
Take a look at the ctrlproxyrc.example file that is distributed with ctrlproxy. It should give you a good impression of what a ctrlproxyrc file is supposed to look like.
The root element contains 2 elements: plugins and networks. These are discssed below.
Contains various <plugin> elements, which each represent a plugin that can be loaded. When the autoload attribute is set, the plugin will be loaded when ctrlproxy starts.
The file attribute is required and should specify either an absolute path to a plugin or the name of a plugin in the default modules dir (something like /usr/lib/ctrlproxy).
The <plugin> element should contain plugin-specific elements. See the documentation for the individual plugins for details.
The <networks> element contains several <network> elements, each representing an IRC network.
Attributes that can be specified on a network element are:
Name of the network. Something like “OPN”, “OFTC” or “IRCNet”. The name of the first server is used if this is not specified.
Password a client should use to authenticate when it connects. Defaults to empty string, in which case authentication will be disabled.
Initial nick name to use on this network. Defaults to UNIX user name.
User name to report in hostmask. Defaults to UNIX user name.
IRC clients always send a NICK command to the IRC server after they have connected. Ctrlproxy happily passes this new nick name on to the real server. If you want ctrlproxy to ignore the first nick change that a client sends, add this attribute.
Full name to report (for example in /WHOIS information). Defaults to the full name specified in the gecos field of your NSS passwd backend (usually the file /etc/passwd.
Specifies whether to connect to this network at start-up.
Clients need to be able to connect to ctrlproxy. This is done using so-called 'listeners'. The element <listen> can contain several elements from transports that ctrlproxy should listen on.
For a description of the configuration of the various avaiable transports that can be used for listening, read their chapter in modules part.
Example:
<ctrlproxy> <plugins> <plugin autoload="1" file="socket"/> </plugins> <networks> <network name="OPN" autoconnect="1"> <listen> <ipv4 port="6667"/> </listen> </network> </networks> </ctrlproxy>
A <network> element can also contain several <channel> elements. Each channel should have a “name” attribute which should contain the name of the channel.
The “autojoin” attribute is voluntary and specifies whether the channel should be joined automatically when ctrlproxy connects to the network.
Example:
<ctrlproxy> <networks> <network name="OPN"> <channel name="#samba"/> <channel name="#samba-technical" autojoin="1"/> </network> </networks> </ctrlproxy>
Similar to the <listen> element is the <servers> element. It contains possible transport configuration that is used to connect to the network.
Note that ctrlproxy always only connects to exactly one server at once. It starts by connecting to the first server and tries the others in the list if that one fails.
Again, see the documentation for the specific transport plugins for details.
Example:
<ctrlproxy> <plugins> <plugin autoload="1" file="socket"/> </plugins> <networks> <network name="OPN" autoconnect="1"> <servers> <ipv4 host="irc.freenode.net"/> <ipv6 host="irc.ipv6.freenode.net"/> <ipv4 host="irc.nl.linux.org"/> </servers> </network> </networks> </ctrlproxy>
A network element can contain one or more <autosend> elements. These should contain raw IRC commands that are sent to the server after ctrlproxy has connected to it.
Example
<ctrlproxy> <networks> <network name="OPN"> <autosend>PRIVMSG nickserv :identify mysecretpassword</autosend> <autosend>PRIVMSG ctrlsoft :Hi! I'm using ctrlproxy!</autosend> </network> </networks> </ctrlproxy>
Table of Contents
Table of Contents
Remote administration
0.1
This module provides a simple interface for remote administration of ControlProxy. Commands can be executed by sending them to the nick ctrlproxy on a network.
The syntax for the commands is very simple: the command should be followed by one or arguments, seperated by spaces. Quoting is not supported.
The following commands are supported:
Adds a new network with the specified name.
Adds a new 'listener' to the specified network with the specified type and options.
Example: addlisten OPN ipv4 port=6676
Adds a new server to the specified network with the specified type and options.
Example: addserver OPN ipv4 host=irc.freenode.net
Connect to the specifed network. Ctrlproxy will connect to the first known server for this network.
Disconnect all clients and servers and exit ctrlproxy.
Disconnect from the specified network.
Prints out a list of all networks ctrlproxy is connected to at the moment.
Load DSO module (aka 'plugin') from the specified location.
Reload the DSO module at the specified location. This does the same as doing a UNLOADMODULE followed by a LOADMODULE.
Unload the DSO module which was loaded from the specified location. This may or may not work correctly, depending on the plugin you are trying to unload.
Prints out a list of all currently loaded plugins.
Prints out the current configuration file XML data.
Save the (updated) XML configuration file to the location it was loaded from (usually $HOME/.ctrlproxyrc).
Prints out list of available commands.
Table of Contents
Automagic away
0.1
This module sets your IRC status to 'away' after you have been inactive('idle') for a certain period of time.
The following XML elements are supported:
Message to set AWAY mode to when idle for too long.
Number of seconds you have to be idle before setting AWAY.
<ctrlproxy> <plugins> <plugin autoload="1" file="auto-away"> <message time="600">I've been idle for 10 minutes, so I'm probably away. Please leave me a message. Thanks!</message> </plugin> <plugin autoload="1" file="socket"/> </plugins> <networks> <network name="OFTC"> <servers><ipv4 host="irc.oftc.net"/></servers> <channel name="#flood.nl" autojoin="1"/> </network> </networks> </ctrlproxy>
Table of Contents
Standard CTCP module
0.1
Simple CTCP module that implements some basic CTCP commands. Use for this module is having CTCP support available when there is no client connected that can answer CTCP queries and providing the ability to detect ctrlproxy.
The following CTCP commands are supported:
VERSION |
TIME |
FINGER |
SOURCE |
CLIENTINFO |
PING |
Table of Contents
Irssi-style log files
0.1
Module that logs IRC data to the specified file in the same format that the irssi(1) IRC client uses.
Each channel or nick gets it's own seperate log file, which is located in a directory with the name of the IRC network.
The following XML elements are supported:
Should specify a base path that log files are to be generated in. For each network, a subdirectory will be created in this directory.
<ctrlproxy> <plugins> <plugin autoload="1" file="log_irssi"> <logfile>/home/jelmer/log/ctrlproxy</logfile> </plugin> <plugin autoload="1" file="socket"/> </plugins> <networks> <network name="OFTC"> <servers><ipv4 host="irc.oftc.net"/></servers> <channel name="#flood"/> </network> </networks> </ctrlproxy>
Table of Contents
Replication from memory
0.1
Table of Contents
Support for IPv4, IPv6 and pipes
0.1
This module provides support for connecting to remote servers using IPv4, IPv6 and unix pipes, as well as listening for client connections using these connection types.
As this module is currently the only module providing connection support, it is essential for basic use of ctrlproxy.
Connecting or listening using SSL over IPv4 or IPv6 is supported when a SSL library was found at configure time.
When acting as a SSL server (e.g. waiting for connections from clients and communicating with them using SSL), ctrlproxy needs to have a certificate file and a private key file. This can be generated using the mksslcert.sh script distributed with ctrlproxy.
The following XML elements are supported:
Name of file to load private SSL key from. Only required when acting as a server
Name of file to load certificate from. Only required when acting as a server
After this module is loaded, the following three new elements are supported in <listen> and <servers>:
ipv4 |
ipv6 |
pipe |
ipv4 and ipv6 support the following attributes:
Enable SSL
Host name or IP address to connect to.
Port to connect to or listen on.
When connecting, the pipe element can contain one member element <path> and several <arg> elements. These should contain a program with arguments to execute.
In listen mode, a file attribute (attribute, not element!) should be specified, containing the file name of the unix socket to create. If no file name is specified, one will be generated.
<ctrlproxy> <plugins> <plugin autoload="1" file="socket"> <sslcertfile>ctrlproxy.pem</sslcertfile> <sslkeyfile>ctrlproxy.pem</sslkeyfile> </plugin> </plugins> <networks> <network name="BEE"> <servers> <pipe> <path>/usr/sbin/bitlbee</path> </pipe> <ipv4 host="localhost"/> </servers> <listen> <ipv4 ssl="1" port="6667"/> </network> <network name="DSR"> <servers> <ipv6 host="irc.ipv6.distributed.net"/> <ipv4 host="irc.distributed.net" port="994" ssl="1"/> </servers> <listen> <ipv4 port="6668"/> <ipv6 port="6669" ssl="1"/> </listen> </network> </networks> </ctrlproxy>
Table of Contents
Logging ctrlproxy messages via IRC
0.1
Table of Contents
Stats generation
0.1
tdb, pcre(optional)
This module keeps track of the number of times a certain expression is used and stores that data in a TDB-file. This TDB file can be read later with the printstats utility.
Expressions should be Perl-compatible regexes whenever pcre is found, normal regular expressions when only the POSIX regex functions are found. If no regex functionality was found, just 'plain' text should be specified.
The following XML elements are supported:
Location of TDB file to store statistics in. $HOME/.ctrlproxy-stats.tdb is used when none is specified.
Pattern to search for and keep track of.
'Variable' to add up to whenever this pattern is used
<ctrlproxy> <plugin autoload="1" file="stats"> <tdbfile>/home/jelmer/.ctrlproxy-stats.tdb</tdbfile> <pattern type="happy">[:;]([-]*)[\)D]</pattern> <pattern type="unhappy">[:;]([-]*)[\/\(]</pattern> <pattern type="foul">(shit|damn|fuck)</pattern> <pattern type="question">\?([^ ]*)$</pattern> <pattern type="exclamation">!([^ ]*)$</pattern> <pattern type="lines">(.*)</pattern> <pattern type="word">([^ ]+)</pattern> <pattern type="caps">^([^a-z]+)$</pattern> <pattern type="action">.ACTION .</pattern> <pattern type="violent">.ACTION .*(mept|slaat|kickt|kicks|duwt|slaps)</pattern> </plugin> <plugin autoload="1" file="socket"/> </plugins> <networks> <network autoconnect="1"> <servers><ipv4 host="irc.freenode.net"/></servers> <channel name="#flood" autojoin="1"/> </network> </networks> </ctrlproxy>
Table of Contents
Strip query answers for other clients
0.1
One problem with ctrlproxy's multi-client support is the fact that when one client does a query (such as a WHOIS), all other clients get the answer. This module fixes that problem.
The following queries are intercepted by this module:
WHOIS
WHO
NAMES
LIST
TOPIC
WHOWAS
STATS
VERSION
LINKS
TIME
SUMMON
USERS
USERHOST
ISON
Table of Contents
Logging in a predefined format
0.1
Module that writes logs to one or more files using a defined format.
This module may be used to write out log files that can be parsed by scripts or bots or logs in the same format as your favorite IRC client.
The configuration values define the syntax that is used to write out log file lines. In these configuration values, values beginning with a '%' can be substituted.
The following characters are allowed after a percent sign for all types of lines:
Current time of day, hours field.
Current time of day, number of minutes.
Current time of day, number of seconds.
Nick originating the line (saying the message, doing the kick, quitting, joining, etc).
Hostmask of the user originating the line.
Name of the current IRC network.
Name of the server (as set by the transport).
Percent sign
Substituted with the respective argument in the IRC line.
Replaced by channel name if the message is directed to a channel, the nick name to which the message is being sent, or the name of the sender of the message when the receiver is the user running ctrlproxy.
This substitute will be the name of the first channel on which the user is active if the line type is NICK or QUIT.
Each type of line also has some variables of it's own that it substitutes.
Nick of the user that is being kicked.
Channel the user is being kicked from.
Reason the user is being kicked.
Name of the channel of which the topic is being changed.
The new topic. Only set for 'topic', not for 'notopic'.
Name of user or channel of which the mode is being changed.
Change in the mode, e.g. +oie
Target of which the mode is being changed.
To retrieve any additional arguments for a MODE command, use %1, %2, etc.
Name of channel or nickname of user to which the notice/privmsg/ or action is being sent.
Message that is being sent.
The following XML elements are supported:
Path to the logfile that will be written. Supports substitution depending on the type of line that is being parsed.
Format to use for lines where a user joins a channel.
Format to use for lines where a user leaves a channel.
Format to use for 'regular' messages - when a user says something.
Format to use for notices.
Format to use for CTCP actions (e.g. /me ...)
Format to use for MODE changes (including bans)
Format to use for quit lines.
Format to use for kicks.
Format to use for topic changes to a valid topic
Format to use when the topic is unset.
Format to use when a user changes his/her nick name.
<ctrlproxy> <plugins> <plugin autoload="1" file="log_custom"> <logfile>/home/jelmer/log/ctrlproxy/%@</logfile> <join>%h%M%s -!- User %n [%u] has joined %c</join> <part>%h%M%s -!- User %n [%u] has left %c [%m]</part> <quit>%h%M%s -!- User %n [%u] has quit [%m]</quit> <action>%h%M%s * %n %m</action> </plugin> <plugin autoload="1" file="socket"/> </plugins> <networks> <network name="OFTC"> <servers><ipv4 host="irc.oftc.net"/></servers> <channel name="#flood"/> </network> </networks> </ctrlproxy>
Table of Contents
NickServ
0.1
<ctrlproxy> <plugins> <plugin autoload="1" file="nickserv"/> <plugin autoload="1" file="socket"/> </plugins> <networks> <network name="OFTC"> <servers><ipv4 host="irc.oftc.net"/></servers> <channel name="#flood.nl" autojoin="1"/> <nickserv> <nick name="foo" password="secret"/> </nickserv> </network> </networks> </ctrlproxy>
Table of Contents
Flood protection module
0.1
This module makes sure at most 1 message is sent to the server in a certain period of time.
A child element of a server element named "queue_speed" contains the number of milliseconds the client has to wait before sending a new message.
<ctrlproxy> <plugins> <plugin autoload="1" file="antiflood"/> <plugin autoload="1" file="socket"/> </plugins> <networks> <network name="OFTC"> <queuespeed>2200</queuespeed> <servers><ipv4 host="irc.oftc.net"/></servers> <channel name="#flood"/> </network> </networks> </ctrlproxy>
Table of Contents
Table of Contents
As has been said in the introduction, ctrlproxy is easily extendible. At the time of writing, there are nine modules available.
The simplest possible module would be:
#include <ctrlproxy.h> gboolean init_plugin(struct plugin *p) { /* Do something */ return TRUE; } gboolean fini_plugin(struct plugin *p) { /* Free my structures here */ return TRUE; }
The init_plugin function is called when the module is loaded. In this function, you should register whatever functions the module provides, such as a 'message handler' or a transport. You can use the data member of the plugin struct to store data for your plugin. This function should return a boolean: false when initialisation failed or true when it succeeded.
THe fini_plugin function is called before the module is unloaded. In this function, you should free the data structures your module is using and make sure there are no other pointers in ctrlproxy pointing to functions or data structures from your module. For example, unregister transports or hooks.
The fini_plugin should return a boolean as well. This value should be true if the unloading may preceed, or false if there are reasons ctrlproxy should not attempt to unload the module (such as resources that are currently in use, etc).
A module is in fact a shared library that's loaded at run-time, when the program is already running. The .so file can compiled with a command like:
$ gcc -shared -o foo.so input1.c input2.o input3.c
A message handling function is a function that is called whenever ctrlproxy receives an IRC message. The only argument this function should have would be a line struct.
Flags can be set on the line (the field in the struct to use is called 'options') to influence the handling of the packet by the rest of ctrlproxy. At the time of writing, the following two flags are available:
Continue processing, but do not send this line.
Immediately stop processing the line (passing it to other message handlers). Implemented as of version 2.5.
There is one other option that can be specified, but is only useful when sending your own messages:
Do not send this line to other clients currently connected.
All IRC lines that ctrlproxy receives and sends are passed thru so-called 'filter functions'. These functions can do things based on the contents of these lines, change the lines or stop further processing of these lines.
To add a filter function, call 'add_filter'. To remove the filter function again (usually when your plugin is being unloaded) call 'del_filter'.
Example:
... add_filter("my_module", my_message_handler); ...
The prototype for the message handling function in the example above would look something like this:
static gboolean my_message_handler(struct line *l);
Your message handler should return TRUE if the rest of the filter functions should also see the message and FALSE if ctrlproxy should stop running filter functions on the given line struct.
These hooks are executed before the data as returned by find_channel() and find_nick() is updated
Ctrlproxy uses GLib's logging functions. Read the related section in the GLib documentation for details.
The default replication function (default_replicate_function) of ctrlproxy is very basic. It only makes sure the client knows on which channels the user is, but does not do any replication of the messages that have been received.
To use your own replicate function instead, set the function pointer replicate_function to your replicate function.
The prototype for a replicate function is:
void replicatef(struct network *s, struct transport_context *c);
The replication data should be sent to the specified transport_context.
Table of Contents
This chapter describes the functions that are available for third-party plugin writers.
struct client { struct network *network; char authenticated; struct transport_context *incoming; time_t connect_time; };
Describes one single client connection to ctrlproxy.
Pointer to network struct this client belongs to.
Indicates whether the client has been authenticated by ctrlproxy. (By sending the correct “PASS ...” line). If set to 0, the client has not been authenticated, if set to 1, the client has been successfully authenticated. A value of 2 means the client has disconnected.
Transport context to be used to communicate with the client.
Contains unix timestamp of the moment the client did its initial connect. This field is used to kick clients that have not authenticated after one minute.
struct network { xmlNodePtr xmlConf; char modes[255]; xmlNodePtr servers; char *hostmask; GList *channels; char authenticated; GList *clients; xmlNodePtr current_server; xmlNodePtr listen; char *supported_modes[2]; char **features; struct transport_context *outgoing; struct transport_context **incoming; };
Describes an IRC network that ctrlproxy is connected to.
Points to XML node with configuration for this network.
Array with modes of the user on this network. For modes that have been set, the index in this array has been set to 1. The rest of the array is set to 0.
For example, if mode “i”(invisible) is set on this user, “modes['i']” is set to 1.
Pointer to XML node <servers> for this server.
Hostmask that ctrlproxy uses to communicate to the server.
List of “struct channel” pointers with channels the user has joined on this network.
Indicates whether the connection to this network is established. It is set to true after a 004 message has been received.
List of “struct client” pointers with all the clients that have connected to ctrlproxy for this network.
Pointer to XML node that contains the configuration data of the current server ctrlproxy is connected to for this network.
Pointer to XML node <listen>.
Contains 2 arrays of modes that is supported by the remote server. This list is sent by the server after the connection has just been set-up.
Array of options supported by the server. Same format as unix environment variables, though a value is not required.
Transport context to use to communicate with the remote server.
List with transport contexts for the clients that are currently connected to ctrlproxy for this server.
This section covers everything related to the current (known) state information of the network the user is on.
struct nick { char *name; char mode; };
Covers one nick in a certain channel. Mode is either a space, indicating the user has no special rights, a '@' if the user is an operator or a '+' if the user has voice.
struct channel { xmlNodePtr xmlConf; char *topic; char mode; char *modes[255]; char introduced; long limit; char *key; GList *nicks; };
Covers one channel at a certain network that the user is currently on. Here is a small list with explanation of the various fields.
Pointer to XML node describing this channel.
Indicates whether the channel is private or secret.
Pointer to string containing the topic of this channel. NULL if no topic has been set or if the topic is unknown.
Modes that have been set on this channel. FIXME
Reserved for use by replication functions. Private. Do not use.
Maximum number of users on the channel. 0 means no limit has been set.
Key users have to enter to enter the channel. If no key is required, this field is set to NULL.
List of “struct nick”, one for each user that is joined to the channel.
struct channel *find_channel(struct network *st, char *name);
Returns a pointer to the struct of the channel with the specified name on the specified network. Returns NULL if no channel struct was found.
Note that this function only works for channels the user has currently used.
struct nick *find_nick(struct channel *c, char *name);
Find data pointer to “struct nick” of the user with the specified name on the specified channel.
If the user was not found, NULL is returned.
GSList *gen_replication(struct network *s);
Generates double-linked list of strings that need to be send to a client to give it a good view of the channels that have been joined, the users on those channels and the modes of those channels.
void default_replicate_function (struct network *, struct transport_context *); extern void (*replicate_function) (struct network *, struct transport_context *);
Default replication function. What this basically does is sending the strings returned by gen_replication() to the specified transport_context.
extern GList *networks; extern xmlNodePtr xmlNode_networks, xmlNode_plugins; extern GList *plugins; extern xmlDocPtr configuration; extern GHookList data_hook;
Pointers to various useful varables. The xmlNode_* variables point to the <networks> and <plugins> elements in the rc file.
configuration points to the top level XML document.
data_hook can be used to register a function that should be called whenever ctrlproxy receives or sends IRC messages.
plugins and networks contain lists to all “struct plugin”s and “struct network”s, respectively.
void network_add_listen(struct network *, xmlNodePtr);
Add listener to specified network with configuration specified in xmlNodePtr.
void save_configuration();
Save the current state of the XML configuration of ctrlproxy to the same file it was loaded from.
void load_plugin(xmlNodePtr);
Load plugin with specified configuration. xmlNodePtr should point to a <plugin> element.
struct transport; struct transport_context;
void register_transport(struct transport *);
Register the specified transport. See the next chapter for details.
struct transport_context *transport_connect(const char *name, xmlNodePtr p, receive_handler, disconnect_handler, void *data);
Connect using the transport with name name and configuration p.
The receive_handler and disconnect_handler will be called when new data is received and when the remote has disconnected, respectively. The data pointer will be passed to the disconnect and receive handlers.
struct transport_context *transport_listen(const char *name, xmlNodePtr p, newclient_handler, void *data);
Listen for incoming connections using the transport with name name, which has configuration p.
The newclient_handler will be called whenever a new client connects to the transport. data will be passed to it.
void transport_free(struct transport_context *);
Disconnect the specified transport and free all data associated with it.
int transport_write(struct transport_context *, char *l);
Write specified line to the transport. l has to be null-terminated!
void transport_set_disconnect_handler(struct transport_context *, disconnect_handler); typedef void (*disconnect_handler) (struct transport_context *, void *data);
Set function to call when the remote closes the transport.
void transport_set_receive_handler(struct transport_context *, receive_handler); typedef void (*receive_handler) (struct transport_context *, char *l, void *data);
Set function to call when new data is received on the socket. l will be a null-terminated string.
typedef void (*newclient_handler) (struct transport_context *, struct transport_context *, void *data); void transport_set_newclient_handler(struct transport_context *, newclient_handler);
Set function to call whenever a new client connects to the specified (listening) transport context.
These functions all have to do with manipulating line structs. Pretty much all internal functions of ctrlproxy work with these instead of manipulating plain strings.
struct line { enum data_direction direction; int options; struct network *network; struct client *client; const char *origin; char **args; /* NULL terminated */ size_t argc; }; /* for the options fields */ #define LINE_IS_PRIVATE 1 #define LINE_DONT_SEND 2 #define LINE_STOP_PROCESSING 4 enum data_direction { UNKNOWN = 0, TO_SERVER = 1, FROM_SERVER = 2 };
Direction of this line. A value of TO_SERVER means it's going to the server, FROM_SERVER means it's coming from a remote IRC server. UNKNOWN is used in cases where the direction is not known.
Sum of one of LINE_IS_PRIVATE, LINE_DONT_SEND and LINE_STOP_PROCESSING. LINE_IS_PRIVATE means this line was send by a client and should not be sent to the other clients. LINE_DONT_SEND should be used to tell ctrlproxy to not send this line to its destination (either client or server). LINE_STOP_PROCESSING will stop further filtering of the line.
Points to the network this line came from or is going to.
Points to the client this line came from, if any. Set to NULL if unknown.
Hostmask of the user who sent the message. NULL if unknown.
IRC arguments/commands in an array. Last element is set to NULL.
Contains number of arguments/commands in args.
struct line * irc_parse_line(char *data);
Takes a string as sent by an IRC client or an IRC server and generates a struct line.
struct line * virc_parse_line(char *origin, va_list ap); struct line *irc_parse_line_args( char *origin, ... ); gboolean irc_send_args(struct transport_context *, ...);
Generates a line struct with the hostmask specified in origin or NULL if none should be set.
For virc_parse_line(), the ap should be a list of strings that are each that are a seperate part of the IRC line. The last argument should be NULL to indicate the end of the list.
irc_parse_line_args() is similar to virc_parse_line(), except that now the commands don't need to be passed in a va_list, but can be passed as arguments.
irc_send_args() sends the specified commands, terminated by a NULL to the specified transport_context.
char *irc_line_string(struct line *l); char *irc_line_string_nl(struct line *l);
Generate a string representation of a line struct in the format used by IRC clients and servers.
irc_Line_string_nl() is similar to irc_line_string(), except that it adds a newline and a carriage-return to the string (\r\n).
char *line_get_nick(struct line *l);
Get the nick name of the user that sent l or NULL if the nick name was unknown.
gboolean irc_sendf(struct transport_context *, char *fmt, ...); struct line *irc_parse_linef( char *fmt, ... );
irc_sendf() sends the specified transport_context a IRC line. fmt is a printf-like string and the remaining arguments correspond to the data in fmt. See the printf manpage for details.
irc_parse_linef() is similar, but instead of sending the string it generates a struct line and returns it.
int irc_send_line(struct transport_context *, struct line *l);
Send the specified line to the specified transport_context.
char *list_make_string(char **l);
Creates a string with all the elements in string array l, seperated by spaces. The last element in l should be NULL.
Table of Contents
Transports are ctrlproxy's own layer for sending and receiving data in a way that is independant of the implementation underneath (IP, UNIX sockets, etc). Since transports are aimed at IRC-only data, they work with lines (char *) and not with lengths, etc. Data is only passed to the main process when a complete line is in, not parts of it.
Implementors of a certain transport backend should call register_transport() with a pointer to a struct transport.
The following struct is passed to all transport functions.
struct transport_context { struct transport *functions; xmlNodePtr configuration; void *data; void *caller_data; disconnect_handler on_disconnect; receive_handler on_receive; newclient_handler on_new_client; };
The configuration xmlNodePtr contains configuration for this specific instance of the transport. The data pointer can be used by the transport to store instance-specific data. The three 'handler' functions should be called whenever one of these events occur. Please note that you have to check for available data yourself. See the documentation about the main context in GLib for details on registering polling and idle functions.
A transport struct should contain function pointers to the following functions:
This function should connect to a IRC server.
This function should make the transport waiting for incoming connections.
Function to write/send the specified line using the transport.
Close (if necessary) any outstanding ports, file handles, etc. This function is always called before a transport is freed.
Each of the function pointers listed above can be set to NULL, to indicate that the function is not implemented.
The following callbacks, which are listed in transport_context should be called by your transport. The “data” argument in all of these calls should be the “callerdata” member field of the struct transport_context.
Called when the remote host closes the connection.
Called when a new line with contents “l” has arrived.
Function to be called when a new client has connected to the transport. The second argument contains a pointer to a new transport_context which can be used to talk to the new client.