134 lines
6.6 KiB
ReStructuredText
134 lines
6.6 KiB
ReStructuredText
|
||
Frequently asked questions
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
.. _faq_err_socket:
|
||
|
||
Why do I get a LIBIRC_ERR_SOCKET error under Win32 when using a static library?
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
Because on Win32 you have to initialize the Winsock API before using it:
|
||
|
||
.. sourcecode:: c
|
||
|
||
WSADATA wsaData;
|
||
|
||
if ( WSAStartup ( MAKEWORD (2, 2), &wsaData) != 0 )
|
||
// report an error
|
||
|
||
// Now you can use libircclient
|
||
|
||
|
||
You have to do it ONCE in your application, and since libircclient does not know whether you already initialized it or not, it does not contain any Winsock initialization code.
|
||
|
||
|
||
What does it mean that the IRC protocol is event-based?
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
The IRC protocol itself is asynchronous and server-driven. For you, this means the following:
|
||
|
||
- For any IRC command, it is not possible to obtain an immediate response whether the command succeed
|
||
or not. Instead the server will send the reply in a short (or long) period of time.
|
||
|
||
- For some IRC command there is no ‘success’ response at all. For example, when you send a text
|
||
message, IRC server will not send anything to confirm that the message is already sent.
|
||
|
||
- You can send several commands to the IRC server, and then receive several replies regarding every
|
||
command. The order of the replies you receive is generally undefined.
|
||
|
||
- A lot of IRC events sent to you is generated by other users, or the IRC server itself, and are
|
||
sent to you just when they are generated.
|
||
|
||
- Long lists (for example, channel lists) are also sent as events. Moreover, these events could be
|
||
separated by other events (message or notices). And it is your responsibility to separate the data
|
||
(using event codes), and use some sort of data structure that will hold it until the data is complete.
|
||
It is not possible to simply query the list of channels, and expect that its content will immediately arrive.
|
||
|
||
- You may send the request, and not receive a response in case of success (such as when you send a message).
|
||
You may send the request and it will only succeed when you receive a response (which may be after you receive
|
||
ten more unrelated events). Or you can receive a response without even sending a request, as it is the case
|
||
with JOIN - it is possible for the server to JOIN you to a specific channel implicitly.
|
||
|
||
- You should be prepared to expect the unexpected from the IRC server. For example, the server can change your
|
||
nick (seen on most servers, which use nickserv authentication. You can be “forced” to join the channel, to
|
||
say something, to leave a channel, to change your usermode and so on. Listen what IRC server tells you, and do so.
|
||
|
||
|
||
Why the irc_cmd_join function does not return an error?
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
A typical example is the :c:func:`irc_cmd_join` call always returns success even when you attempt to join a password-protected
|
||
channel. Then some time later the IRC server returns an error. This is because the irc_cmd family of functions return
|
||
success when the command is sent to the IRC server. The asynchronous nature of IRC makes it impossible to obtain the
|
||
command result immediately. Please read the question above.
|
||
|
||
|
||
How to register/auth with NICKSERV?
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
There is no ‘standard’ way. NICKSERV, CHANSERV and so on are not specified by the RFC. They are IRC extensions which
|
||
behave exactly like the other IRC users but with more power. Typically their messages are sent via Notice events, so
|
||
you can use following algorithm to handle Nickserv registration:
|
||
|
||
.. sourcecode:: c
|
||
|
||
static void event_notice (irc_session_t * session, const char * event,
|
||
const char * origin, const char ** params, unsigned int count)
|
||
{
|
||
char buf[256];
|
||
|
||
if ( !origin )
|
||
return;
|
||
|
||
if ( strcasecmp (origin, "nickserv") )
|
||
return;
|
||
|
||
if ( strstr (params[1], "This nick is not registered") == params[1] )
|
||
{
|
||
sprintf (buf, "REGISTER %s NOMAIL", gCfg.irc_nickserv_password);
|
||
irc_cmd_msg(session, "nickserv", buf);
|
||
}
|
||
else if ( strstr (params[1], "This nickname is registered and protected") == params[1] )
|
||
{
|
||
sprintf (buf, "IDENTIFY %s", gCfg.irc_nickserv_password);
|
||
irc_cmd_msg(session, "nickserv", buf);
|
||
}
|
||
else if ( strstr (params[1], "Password accepted - you are now recognized") == params[1] )
|
||
printf ("Nickserv authentication succeed.");
|
||
}
|
||
|
||
The idea is to parse the messages sent from NICKSERV, and if they’re matched the specific patterns, react on them appropriately.
|
||
|
||
What is CTCP?
|
||
^^^^^^^^^^^^^
|
||
|
||
CTCP abbreviature is deciphered as “Client-to-Client Protocol”. It is used between the IRC clients to query the
|
||
remote client for some data, or to send some information – for example, /me messages are sent via CTCP.
|
||
|
||
There is no standard list of possible CTCP requests, and different IRC clients often add their own CTCP codes.
|
||
The built-in handler reacts on TIME, VERSION, PING and FINGER CTCP queries. If you need to react on other requests,
|
||
you’ll have to write your own CTCP handler. See the source code of libirc_event_ctcp_internal function to get an
|
||
idea how to write it.
|
||
|
||
|
||
When I am made a chanop (+o) why do I not receive the event_umode?
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
Becoming a channel operator channes the **channel mode**, not user mode. Therefore you will receive :c:member:`event_mode` and not :c:member:`event_umode`
|
||
|
||
If you receive the event_umode with +o this means your user is an IRC server operator.
|
||
|
||
|
||
.. _faq_epoll:
|
||
|
||
What if my application uses epoll?
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
The library only directly supports the select()-based loops for historic reasons, so epoll and other polling methods are not supported directly by the library.
|
||
However but if necessart, it could be emulated by converting descriptors between select and epoll as following:
|
||
* Call irc_add_select_descriptors with an empty FD_SET
|
||
* Extract the descriptors from the fd_set arrays (remember fd_array is a bitarray, not the value array). There may be more than one descriptor in case there are DCC sessions.
|
||
* Pass those descriptors to poll/epoll using relevant events (i.e. use the EPOLLIN for the descriptors in the *in_set*)
|
||
* For those descriptors which triggered the events, fill up the relevant in_set and out_set structures (again, remember the bitmasks!) and pass them to :c:func:`irc_process_select_descriptors`
|
||
|
||
While this is cumbersome, the operations are very simple (basically bitmask operations on a small structure) and will not add any significant slowdown to your application.
|