
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.
