/** Attempt to send data queued for a client. * @param[in] to Client to send data to. */ void send_queued(struct Client *to) { assert(0 != to); assert(0 != cli_local(to)); if (IsBlocked(to) || !can_send(to)) return; /* Don't bother */ while (MsgQLength(&(cli_sendQ(to))) > 0) { unsigned int len; if ((len = deliver_it(to, &(cli_sendQ(to))))) { msgq_delete(&(cli_sendQ(to)), len); cli_lastsq(to) = MsgQLength(&(cli_sendQ(to))) / 1024; if (IsBlocked(to)) { update_write(to); return; } } else { if (IsDead(to)) { char tmp[512]; sprintf(tmp,"Write error: %s", ((cli_sslerror(to)) ? (cli_sslerror(to)) : ((strerror(cli_error(to))) ? (strerror(cli_error(to))) : "Unknown error")) ); dead_link(to, tmp); } return; } } /* Ok, sendq is now empty... */ client_drop_sendq(cli_connect(to)); update_write(to); }
/** Try to send a buffer to a client, queueing it if needed. * @param[in,out] to Client to send message to. * @param[in] buf Message to send. * @param[in] prio If non-zero, send as high priority. */ void send_buffer(struct Client* to, struct MsgBuf* buf, int prio) { assert(0 != to); assert(0 != buf); if (cli_from(to)) to = cli_from(to); if (!can_send(to)) /* * This socket has already been marked as dead */ return; if (MsgQLength(&(cli_sendQ(to))) > get_sendq(to)) { if (IsServer(to)) sendto_opmask(0, SNO_OLDSNO, "Max SendQ limit exceeded for %C: %zu > %zu", to, MsgQLength(&(cli_sendQ(to))), get_sendq(to)); dead_link(to, "Max sendQ exceeded"); return; } Debug((DEBUG_SEND, "Sending [%p] to %s", buf, cli_name(to))); #if defined(USE_SSL) if (cli_socket(to).s_ssl) prio = 0; #endif msgq_add(&(cli_sendQ(to)), buf, prio); client_add_sendq(cli_connect(to), &send_queues); update_write(to); /* * Update statistics. The following is slightly incorrect * because it counts messages even if queued, but bytes * only really sent. Queued bytes get updated in SendQueued. */ ++(cli_sendM(to)); ++(cli_sendM(&me)); /* * This little bit is to stop the sendQ from growing too large when * there is no need for it to. Thus we call send_queued() every time * 2k has been added to the queue since the last non-fatal write. * Also stops us from deliberately building a large sendQ and then * trying to flood that link with data (possible during the net * relinking done by servers with a large load). */ if (MsgQLength(&(cli_sendQ(to))) / 1024 > cli_lastsq(to)) send_queued(to); }
/* * m_list - generic message handler * * parv[0] = sender prefix * parv[1] = channel list or user/time limit * parv[2...] = more user/time limits */ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Channel *chptr; char *name, *p = 0; int show_channels = 0, param; struct ListingArgs args; if (cli_listing(sptr)) /* Already listing ? */ { if (cli_listing(sptr)) MyFree(cli_listing(sptr)); cli_listing(sptr) = 0; send_reply(sptr, RPL_LISTEND); update_write(sptr); if (parc < 2 || 0 == ircd_strcmp("STOP", parv[1])) return 0; /* Let LIST or LIST STOP abort a listing. */ } if (parc < 2) /* No arguments given to /LIST ? */ args = la_default; else { args = la_init; /* initialize argument to blank slate */ for (param = 1; parv[param]; param++) { /* process each parameter */ switch (param_parse(sptr, parv[param], &args, parc == 2)) { case LPARAM_ERROR: /* error encountered, usage already sent, return */ return 0; break; case LPARAM_CHANNEL: /* show channel instead */ show_channels++; break; case LPARAM_SUCCESS: /* parse succeeded */ break; } } } send_reply(sptr, RPL_LISTSTART); if (!show_channels) { if (args.max_users > args.min_users + 1 && args.max_time > args.min_time && args.max_topic_time > args.min_topic_time) /* Sanity check */ { cli_listing(sptr) = (struct ListingArgs*) MyMalloc(sizeof(struct ListingArgs)); assert(0 != cli_listing(sptr)); memcpy(cli_listing(sptr), &args, sizeof(struct ListingArgs)); list_next_channels(sptr); return 0; } send_reply(sptr, RPL_LISTEND); return 0; } for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0) { chptr = FindChannel(name); if (!chptr) continue; if (ShowChannel(sptr, chptr) || (IsAnOper(sptr) && HasPriv(sptr, PRIV_LIST_CHAN))) send_reply(sptr, RPL_LIST, chptr->chname, chptr->users - number_of_zombies(chptr), chptr->topic); } send_reply(sptr, RPL_LISTEND); return 0; }