2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * Please read the file COPYING, README and AUTHORS for more information.
16 * Sending IRC commands over the network
30 #include "conn-func.h"
34 #include "irc-write.h"
36 #define SEND_TO_USER 1
37 #define SEND_TO_SERVER 2
39 static const char *Get_Prefix PARAMS((CLIENT *Target, CLIENT *Client));
40 static void cb_writeStrServersPrefixFlag PARAMS((CLIENT *Client,
41 CLIENT *Prefix, void *Buffer));
42 static void Send_Marked_Connections PARAMS((CLIENT *Prefix, const char *Buffer));
45 * Send a message to a client.
47 * @param Client The target client.
48 * @param Format Format string.
49 * @return CONNECTED or DISCONNECTED.
53 IRC_WriteStrClient( CLIENT *Client, const char *Format, ... )
56 IRC_WriteStrClient( Client, Format, va_alist )
65 assert(Client != NULL);
66 assert(Format != NULL);
73 vsnprintf(buffer, 1000, Format, ap);
76 return IRC_WriteStrClientPrefix(Client, Client_ThisServer(),
81 * Send a message to a client using a specific prefix.
83 * @param Client The target client.
84 * @param Prefix The prefix to use.
85 * @param Format Format string.
86 * @return CONNECTED or DISCONNECTED.
90 IRC_WriteStrClientPrefix(CLIENT *Client, CLIENT *Prefix, const char *Format, ...)
93 IRC_WriteStrClientPrefix(Client, Prefix, Format, va_alist)
100 /* send text to local and remote clients */
105 assert( Client != NULL );
106 assert( Format != NULL );
107 assert( Prefix != NULL );
110 va_start( ap, Format );
114 vsnprintf( buffer, 1000, Format, ap );
117 return Conn_WriteStr(Client_Conn(Client_NextHop(Client)), ":%s %s",
118 Get_Prefix(Client_NextHop(Client), Prefix), buffer);
122 * Send a message to all client in a channel.
124 * The message is only sent once per remote server.
126 * @param Client The sending client, excluded while forwarding the message.
127 * @param Channel The target channel.
128 * @param Remote If not set, the message is sent to local clients only.
129 * @param Format Format string.
133 IRC_WriteStrChannel(CLIENT *Client, CHANNEL *Chan, bool Remote,
134 const char *Format, ...)
137 IRC_WriteStrChannel(Client, Chan, Remote, Format, va_alist)
148 assert( Client != NULL );
149 assert( Format != NULL );
152 va_start( ap, Format );
156 vsnprintf( buffer, 1000, Format, ap );
159 IRC_WriteStrChannelPrefix(Client, Chan, Client_ThisServer(),
160 Remote, "%s", buffer);
164 * Send a message to all client in a channel using a specific prefix.
166 * The message is only sent once per remote server.
168 * @param Client The sending client, excluded while forwarding the message.
169 * @param Channel The target channel.
170 * @param Prefix The prefix to use.
171 * @param Remote If not set, the message is sent to local clients only.
172 * @param Format Format string.
176 IRC_WriteStrChannelPrefix(CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix,
177 bool Remote, const char *Format, ...)
180 IRC_WriteStrChannelPrefix(Client, Chan, Prefix, Remote, Format, va_alist)
195 assert( Client != NULL );
196 assert( Chan != NULL );
197 assert( Prefix != NULL );
198 assert( Format != NULL );
201 va_start( ap, Format );
205 vsnprintf( buffer, 1000, Format, ap );
210 cl2chan = Channel_FirstMember( Chan );
212 c = Channel_GetClient( cl2chan );
214 if (Client_Conn(c) <= NONE)
216 else if(Client_Type(c) == CLIENT_SERVER)
220 c = Client_NextHop(c);
222 if(c && c != Client) {
223 /* Ok, another Client */
224 conn = Client_Conn(c);
225 if (Client_Type(c) == CLIENT_SERVER)
226 Conn_SetFlag(conn, SEND_TO_SERVER);
228 Conn_SetFlag(conn, SEND_TO_USER);
230 cl2chan = Channel_NextMember(Chan, cl2chan);
232 Send_Marked_Connections(Prefix, buffer);
236 * Send a message to all the servers in the network.
238 * @param Client The sending client, excluded while forwarding the message.
239 * @param Format Format string.
243 IRC_WriteStrServers(CLIENT *ExceptOf, const char *Format, ...)
246 IRC_WriteStrServers(ExceptOf, Format, va_alist)
255 assert( Format != NULL );
258 va_start( ap, Format );
262 vsnprintf( buffer, 1000, Format, ap );
265 IRC_WriteStrServersPrefix(ExceptOf, Client_ThisServer(), "%s", buffer);
269 * Send a message to all the servers in the network using a specific prefix.
271 * @param Client The sending client, excluded while forwarding the message.
272 * @param Prefix The prefix to use.
273 * @param Format Format string.
277 IRC_WriteStrServersPrefix(CLIENT *ExceptOf, CLIENT *Prefix,
278 const char *Format, ...)
281 IRC_WriteStrServersPrefix(ExceptOf, Prefix, Format, va_alist)
291 assert( Format != NULL );
292 assert( Prefix != NULL );
295 va_start( ap, Format );
299 vsnprintf( buffer, 1000, Format, ap );
302 IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
306 * Send a message to all the servers in the network using a specific prefix
307 * and matching a "client flag".
309 * @param Client The sending client, excluded while forwarding the message.
310 * @param Prefix The prefix to use.
311 * @param Flag Client flag that must be set on the target.
312 * @param Format Format string.
316 IRC_WriteStrServersPrefixFlag(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
317 const char *Format, ...)
320 IRC_WriteStrServersPrefixFlag(ExceptOf, Prefix, Flag, Format, va_alist)
331 assert( Format != NULL );
332 assert( Prefix != NULL );
335 va_start( ap, Format );
339 vsnprintf( buffer, 1000, Format, ap );
342 IRC_WriteStrServersPrefixFlag_CB(ExceptOf, Prefix, Flag,
343 cb_writeStrServersPrefixFlag, buffer);
347 * Send a message to all the servers in the network using a specific prefix
348 * and matching a "client flag" using a callback function.
350 * @param Client The sending client, excluded while forwarding the message.
351 * @param Prefix The prefix to use.
352 * @param Flag Client flag that must be set on the target.
353 * @param callback Callback function.
354 * @param Format Format string.
357 IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
358 void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data)
364 if (Client_Type(c) == CLIENT_SERVER && Client_Conn(c) > NONE &&
365 c != Client_ThisServer() && c != ExceptOf) {
366 /* Found a target server, do the flags match? */
367 if (Flag == '\0' || Client_HasFlag(c, Flag))
368 callback(c, Prefix, cb_data);
375 * Send a message to all "related" clients.
377 * Related clients are the one that share one ore more channels with the client
378 * sending this message.
380 * The message is only sent once per remote server.
382 * @param Client The sending client, excluded while forwarding the message.
383 * @param Prefix The prefix to use.
384 * @param Remote If not set, the message is sent to local clients only.
385 * @param Format Format string.
389 IRC_WriteStrRelatedPrefix(CLIENT *Client, CLIENT *Prefix, bool Remote,
390 const char *Format, ...)
393 IRC_WriteStrRelatedPrefix(Client, Prefix, Remote, Format, va_alist)
401 CL2CHAN *chan_cl2chan, *cl2chan;
408 assert( Client != NULL );
409 assert( Prefix != NULL );
410 assert( Format != NULL );
413 va_start( ap, Format );
417 vsnprintf( buffer, 1000, Format, ap );
422 chan_cl2chan = Channel_FirstChannelOf( Client );
423 while( chan_cl2chan )
425 chan = Channel_GetChannel( chan_cl2chan );
426 cl2chan = Channel_FirstMember( chan );
429 c = Channel_GetClient( cl2chan );
432 if( Client_Conn( c ) <= NONE ) c = NULL;
433 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
435 if( c ) c = Client_NextHop( c );
437 if( c && ( c != Client ))
439 conn = Client_Conn( c );
440 if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
441 else Conn_SetFlag( conn, SEND_TO_USER );
443 cl2chan = Channel_NextMember( chan, cl2chan );
446 chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
448 Send_Marked_Connections(Prefix, buffer);
449 } /* IRC_WriteStrRelatedPrefix */
452 * Send WALLOPS message.
454 * @param Client The sending client, excluded while forwarding the message.
455 * @param From The (remote) sender of the message.
456 * @param Format Format string.
460 IRC_SendWallops(CLIENT *Client, CLIENT *From, const char *Format, ...)
463 IRC_SendWallops(Client, From, Format, va_alist )
475 va_start(ap, Format);
479 vsnprintf(msg, 1000, Format, ap);
482 for (to=Client_First(); to != NULL; to=Client_Next(to)) {
483 if (Client_Conn(to) == NONE) /* no local connection */
486 switch (Client_Type(to)) {
488 if (Client_HasMode(to, 'w'))
489 IRC_WriteStrClientPrefix(to, From,
494 IRC_WriteStrClientPrefix(to, From,
499 } /* IRC_SendWallops */
502 * Set a "penalty time" for an IRC client.
504 * Note: penalty times are never set for server links!
506 * @param Client The client.
507 * @param Seconds The additional "penalty time" to enforce.
510 IRC_SetPenalty( CLIENT *Client, time_t Seconds )
514 assert( Client != NULL );
515 assert( Seconds > 0 );
517 if( Client_Type( Client ) == CLIENT_SERVER ) return;
519 c = Client_Conn( Client );
521 Conn_SetPenalty(c, Seconds);
522 } /* IRC_SetPenalty */
525 Get_Prefix(CLIENT *Target, CLIENT *Client)
527 assert (Target != NULL);
528 assert (Client != NULL);
530 if (Client_Type(Target) == CLIENT_SERVER)
531 return Client_ID(Client);
533 return Client_MaskCloaked(Client);
537 cb_writeStrServersPrefixFlag(CLIENT *Client, CLIENT *Prefix, void *Buffer)
539 IRC_WriteStrClientPrefix(Client, Prefix, "%s", Buffer);
540 } /* cb_writeStrServersPrefixFlag */
543 * Send a message to all marked connections using a specific prefix.
545 * @param Prefix The prefix to use.
546 * @param Buffer The message to send.
549 Send_Marked_Connections(CLIENT *Prefix, const char *Buffer)
553 assert(Prefix != NULL);
554 assert(Buffer != NULL);
557 while (conn != NONE) {
558 if (Conn_Flag(conn) == SEND_TO_SERVER)
559 Conn_WriteStr(conn, ":%s %s",
560 Client_ID(Prefix), Buffer);
561 else if (Conn_Flag(conn) == SEND_TO_USER)
562 Conn_WriteStr(conn, ":%s %s",
563 Client_MaskCloaked(Prefix), Buffer);
564 conn = Conn_Next(conn);