
send.c re-work

PREFIXES
========

  Server prefixes are the ":%s" strings at the beginning of messages.
They are used by servers to route the message properly and by servers to
local clients to update their idea of who is whom.

":nick!user@host" is a prefix ":name" where name is either a nick
or name of a server is another valid prefix.

Typical prefix for a local client to a channel:

":Dianora!db@irc.db.net"

for a prefix to a remote server:
":Dianora"

e.g. as seen locally on a channel:

":Dianora!db@irc.db.net PRIVMSG #us-opers :ON TOP OF ...\r\n"

e.g. as seen sent to a remote server:
":Dianora PRIVMSG #us-opers :ON TOP OF ...\r\n"

  It has been argued that full prefixes sent locally are a waste of bandwidth
(Isomer from Undernet has argued this). i.e. instead of sending:
":nick!user@host" for a local prefix, one could just send ":nick"..
Unfortunately, this breaks many clients badly. Personally I feel that
until clients are updated to understand that a full prefix isn't always
going to be sent, that this should be held off on.

  As much as possible, prefix generation is now moved "upstairs" as
much as possible. i.e. if its known its a local client only, then the
onus of the prefix generation, is the users, not hidden in send.c
This allows somewhat faster code to be written, as the prefix doesn't
have to be regenerated over and over again.

  Prefixes aren't sent in all cases, such as a new user using NICK
A prefix is needed when it must be routed.

i.e.

NICK newnick

  There is obviously no prefix needed from a locally connected client.



FUNCTIONS
=========

sendto_one()    - Should be used for _local_ clients only
                  it expects the prefix to be pre-built by user.
		  
                  usage - sendto_one(struct Client *to, char *pattern, ...);

                  typical use:

                  sendto_one(acptr,":%s NOTICE %s :I'm tired", me.name);
                  Note: This was from a server "me" hence only one
                  name in prefix.

                  This would be an example of a client sptr, noticing
                  acptr IF acptr is known to be a local client:

                  sendto_one(acptr,":%s!%s@%s NOTICE %s :You there?",
                             sptr->name,
                             sptr->username,
                             sptr->host,
                             acptr->name);

sendto_channel_butone()
                - This function sends a var args message to a channel globally,
                  except to the client specified as "one", the prefix
                  is built by this function on the fly as it has to
                  be sent both to local clients on this server and to
                  remote servers. 

                  usage - sendto_channel_butone(struct Client *one,
                                                struct Client *from,
                                                struct Channel *chptr,
                                                const char *pattern, ... );

                  sendto_channel_butone(cptr, sptr, chptr
                                        "PRIVMSG %s :HI!",
                                        chptr->chname);

                  e.g. if channel message is coming from "cptr"
                  it must not be sent back to cptr.


sendto_ll_serv_butone(struct Client *one, struct Client *sptr, int add,
		      const char *pattern, ...)

                - This function is almost identical to sendto_channel_butone
                  however, it will also not send on a nick as given by sptr,
                  if target server does not "know" about it.
                  As the name implies, it is used for "lazylinks"

sendto_serv_butone()
                - This function sends specified var args message
                  to all connected servers except the client "one"
	
                  usage - sendto_serv_butone(struct Client *one,
                                           const char *pattern, ... );  

sendto_cap_serv_butone()
                - This function sends specified var args message
                  to all connected servers except the client "one"
                  with capability specified. 
                  NOTE: sendto_serv_butone() could be replaced with 
                  a generalized version of this function. i.e.
                  CAP_ALL

                  usage - sendto_cap_serv_butone(int cap,
                                               struct Client *one,
                                               const char *pattern, ... );  

sendto_common_channels_local()
                - This function is used only by m_nick and exit_one_client
                  its used to propagate nick changes to all channels user
                  is in, and QUIT messages to all channels user is in.
                  As it only sends to local clients, prefix generation
                  is left to the user. It also sends the message to the
                  user if the user isn't on any channels.

                  usage - sendto_common_channels_local(struct Client *user,
                                                       const char *pattern,
                                                       ...);

sendto_channel_local()
                - This function is used only to send locally, never
                  to remote servers. This is useful when removing
                  local chanops, or adding a local chanop. MODE/SJOIN
                  sent to remote server allows that server to propagate
                  mode changes to its clients locally.

                  usage - sendto_channel_local(type,
                                               struct Channel *chptr,
                                               const char *pattern, ... );


                  prefix must be pre-built. type is a flag
                  denoting ONE of 
                  ALL_MEMBERS		- all members locally are sent to
                  NON_CHANOPS		- only non-chanops see this
                  ONLY_CHANOPS_VOICED	- both chanops and voiced see this
                  ONLY_CHANOPS		- only chanops see this


sendto_match_butone()
match_it()      - both only used for the old style oper masking
                  i.e. /msg #hostmask which in hyb7 is /msg $#hostmask
                  or  /msg $servermask in hyb7 /msg $$servermask

                  usage - match_it(struct Client *one,
                                   const char *mask,
                                   int what);

                  one is the client to match on either hostmask or servermask
                  mask is the actual mask
                  what is either MATCH_HOST or MATCH_SERVER

                  usage - sendto_match_butone(struct Client *one,
                                              struct Client *from,
                                              char *mark,
                                              int what,
                                              const char *pattern, ... );

sendto_channel_remote()
                - Is only used to send a message to a remote server


sendto_match_cap_servs()
                - Is used only to send MODE lists to remote server
                  who are capable of it. i.e. MODE #channel +e nick!user@host

sendto_match_noncap_servs()
		- Is used only to send MODE lists to remote servers that
		  are not capable of it. i.e. MODE #channel +o nick
		- This allows you to send a MODE #channel +h nick via 
                  sendto_match_cap_servs and MODE #channel +o nick to 
                  servers which dont support it.

sendto_anywhere()
                - Allows the sending of a message to any client on the net
                  without knowing whether its local or remote. The penalty
                  is the calculation of a run-time prefix.
                  It is less efficient then sendto_one()

                  usage - sendto_anywhere(struct Client *to,
                                          struct Client *from,
                                          const char *pattern, ...);

                  e.g.
                  sendto_anywhere(acptr, sptr,
                                  "PRIVMSG Larz :Hi, Where ever you are");

sendto_realops_flags()
                - combines old sendto_realops and sendto_realops_flags
                  sends specified message to opers locally only
                  depending on flags. FLAGS_ALL is a special case
                  to send to any oper.

                  usage - sendto_realops_flags(int flags,
                                               const char *pattern, ... );

                  e.g.
                  sendto_realops_flags(FLAGS_ALL,
                                 "Don't eat the yellow snow");

sendto_wallops_flags()
                - sends specified message to opers locally, 
                  depending on flags.  used for messages that need
                  to be in wallops form

                  usage - sendto_wall_flags(int flags,
                                    struct Client *, const char *patterm ...);

                  e.g.
                  sendto_wallops_flags(FLAGS_LOCOPS,
                                      sptr, "Message");

ts_warn()       - Only used to send warning messages to all opers
                  without flooding them with warnings.
                  It limits the number of warnings to no more than 5
                  every 5 seconds. It probably can go away now.
 
                  usage - ts_warn(const char *pattern, ... );

*** LOCAL HELPER FUNCTIONS (static) ***

sendto_format() - Used to format a varargs buffer into given buffer
                  returns length of buffer built, enforces RFC1459 length
                  limits and appends \r\n as per rfc.

                  usage - sendto_format(char *sendbuf,
                                        const char *pattern, ... );

send_trim()     - This local function simply trims a char string
                  to fit inside 512 bytes as per rfc1459, adding
                  a cr/lf pair as needed. It does not check to make
                  sure original string has a cr/lf.
    
                  usage - int send_trim(char buffer, int len);
                  returns length as modified or not,
                  modifies buffer in-place.

sendto_list_local()
                - This local function sends given message to given dlink_list
                  with data == a local client. This is used by
                  sendto_common_channels_local() and by
                  sendto_channel_local() 
 
                  It could easily be extended to sendto "groups" of
                  otherwise unrelated users, not just channel groups.

                  usage - sendto_list_local(dlink_list *list,
                                            const char *sendbuf,
                                            int len);


sendto_list_anywhere()
                - This local function sends a message to all members
                  as given in a dlink_list, whether they are remote or local
                  clients. It is used by sendto_channel_butone()

                  It could easily be extended to sendto "groups" of
                  otherwise unrelated users, not just channel groups.

                  usage: sendto_list_anywhere(struct Client *one,
                                              struct Client *from,
                                              dlink_list *list,
                                              const char *local_sendbuf,
                                              int local_len,
                                              const char *remote_sendbuf,
                                              int remote_len);


send_message()
                - This local function does the actual send of message
                  
                  usage: send_message(struct Client *to, char *msg, int len);

                  The message has to be pre-formatted and the length
                  must be pre-calculated. 

-- Diane Bruce 

$Id: send.txt 23020 2006-09-01 18:20:19Z androsyn $
