/*
* ----------------------------------------------------------------
* Night Light IRC Proxy - Connection SendQ Functions
* ----------------------------------------------------------------
* Copyright (C) 1997-2003 Jonas Kvinge <jonas@night-light.net>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Last modified by:
* Jonas Kvinge (07.07.2003)
*
*/
#define CONN_SENDQ_C
#define NEED_SYS_TYPES_H 1 /* Extra types */
#define NEED_SYS_PARAM_H 1 /* Some systems need this */
#define NEED_LIMITS_H 0 /* Kernel limits */
#define NEED_STDARG_H 1 /* va_list, etc */
#define NEED_ERRNO_H 1 /* errno */
#define NEED_CTYPE_H 1 /* isdigit(), etc */
#define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */
#define NEED_ARPA_INET_H 0 /* inet_ntoa(), inet_aton(), etc */
#define NEED_STDIO_H 1 /* Standard C UNIX functions */
#define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */
#define NEED_TIME_H 1 /* time(), etc */
#define NEED_SYSCTL_H 0 /* sysctl(), etc */
#define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */
#define NEED_SYS_UIO_H 0 /* iovec, etc */
#define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */
#define NEED_SYS_IOCTL_H 0 /* ioctl(), etc */
#define NEED_SYS_FILIO_H 0 /* Solaris need this for ioctl(), etc */
#define NEED_UNISTD_H 1 /* Unix standard functions */
#define NEED_STRING_H 1 /* C string functions */
#define NEED_SIGNAL_H 0 /* Signal functions */
#define NEED_SYS_SOCKET_H 0 /* Socket functions */
#define NEED_NETDB_H 0 /* Network database functions */
#define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */
#define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */
#define NEED_ARES 0 /* Functions needed for ares */
#define NEED_SSL 1 /* Needed for SSL support */
#include "includes.h"
#include "irc.h"
#include "conf.h"
#include "access_conf.h"
#include "conn.h"
#include "conn_connection.h"
#include "conn_sendq.h"
#include "client.h"
#include "client_connection.h"
#include "client_notice.h"
/* VARIABLES - JONAS (31.07.2001) */
extern struct Conf_Struct ConfS;
extern struct Client_Struct *Client_Head;
/* CONN_ADDSENDQ FUNCTION - JONAS (01.07.2000) */
void conn_addsendq(struct Conn_Struct *ConnS, const char *const LinePT, ...) {
char Line[IRCMSGLEN+1] = "";
va_list Args = { 0 };
struct SendQ_Struct *SendQ = NULL;
struct SendQ_Struct *SendQ_NEW = NULL;
struct SendQ_Struct *SendQ_PRV = NULL;
struct Client_Struct *ClientS = NULL;
assert(ConnS != NULL);
assert(LinePT != NULL);
va_start(Args, LinePT);
vsnprintf(Line, IRCMSGLEN+1, LinePT, Args);
va_end(Args);
if (!Conn_IsSocket(ConnS)) {
sysprint(BITMASK_ERROR, "conn_addsendq() called for connection %s without socket: %s.", ConnS->Name, Line);
return;
}
#if DEBUG
client_noticealluser(ConnS->User, "Connection %s: Adding line \"%s\" to sendQ.", ConnS->Name, Line);
client_noticealluser(ConnS->User, "Connection %s: Allowed buffer to be sent: %ld - Allowed number of lines to be sent: %ld.", ConnS->Name, ConnS->SendQMaxFlushBuffer, ConnS->SendQMaxFlushLines);
#endif
SendQ_NEW = malloc(sizeof(struct SendQ_Struct));
if (SendQ_NEW == NULL) { return; }
memset(SendQ_NEW, 0, sizeof(struct SendQ_Struct));
SendQ_NEW->Line = strdup(Line);
if (SendQ_NEW->Line == NULL) {
free(SendQ_NEW);
return;
}
SendQ_NEW->Time = NOW;
if (strncasecmp(Line, "PASS ", 5) == FALSE) { SendQ_NEW->Priority = 1; }
else if (strncasecmp(Line, "NICK ", 5) == FALSE) { SendQ_NEW->Priority = 1; }
else if (strncasecmp(Line, "USER ", 5) == FALSE) { SendQ_NEW->Priority = 1; }
else if (strncasecmp(Line, "PONG ", 5) == FALSE) { SendQ_NEW->Priority = 1; }
else if (strncasecmp(Line, "QUIT ", 5) == FALSE) { SendQ_NEW->Priority = 1; }
else if (strncasecmp(Line, "JOIN ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "PART ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "ISON ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "MODE ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "OPER ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "KILL ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "NAMES ", 6) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "LINKS ", 6) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "WHO ", 4) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "WHOIS ", 6) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "AWAY ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "PING ", 5) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "USERHOST ", 9) == FALSE) { SendQ_NEW->Priority = 2; }
else if (strncasecmp(Line, "KICK ", 5) == FALSE) { SendQ_NEW->Priority = 3; }
else if (strncasecmp(Line, "PRIVMSG ", 8) == FALSE) { SendQ_NEW->Priority = 4; }
else if (strncasecmp(Line, "NOTICE ", 7) == FALSE) { SendQ_NEW->Priority = 4; }
else if (strncasecmp(Line, "INVITE ", 7) == FALSE) { SendQ_NEW->Priority = 4; }
else if (strncasecmp(Line, "TOPIC ", 6) == FALSE) { SendQ_NEW->Priority = 4; }
else { SendQ_NEW->Priority = 4; }
if (ConnS->SendQ_Head == NULL) { ConnS->SendQ_Head = SendQ_NEW; }
else {
for (SendQ = ConnS->SendQ_Head ; SendQ != NULL ;) {
if (SendQ->Priority > SendQ_NEW->Priority) {
if (SendQ_PRV == NULL) {
ConnS->SendQ_Head = SendQ_NEW;
SendQ_NEW->Next = SendQ;
}
else {
SendQ_PRV->Next = SendQ_NEW;
SendQ_NEW->Next = SendQ;
}
break;
}
SendQ_PRV = SendQ;
SendQ = SendQ->Next;
}
if (SendQ == NULL) { SendQ_PRV->Next = SendQ_NEW; }
}
++ConnS->NumSendQs;
if (ConnS->NumSendQs >= ConfS.ClientMaxSendQ) {
#if 0
conn_quit(ConnS, ACCESS_CONF_SENDQFLOOD);
#endif
for (ClientS = Client_Head ; ClientS != NULL ; ClientS = ClientS->Next) {
if (!Client_IsVerified(ClientS)) { continue; }
if (ClientS->ConnS != ConnS) { continue; }
client_close(ClientS, ACCESS_CONF_SENDQFLOOD);
access_conf_adddeny(ClientS->HostName, ACCESS_CONF_SENDQFLOOD);
}
}
}
/* CONN_FLUSHSENDQ FUNCTION - JONAS (24.06.2001) */
void conn_flushsendq(struct Conn_Struct *ConnS) {
struct SendQ_Struct *SendQ = NULL;
struct FlushL_Struct *FlushL = NULL;
struct FlushB_Struct *FlushB = NULL;
unsigned long int Duration = 0;
unsigned short int Count = 0;
unsigned short int Len = 0;
unsigned short int FlushLen = 0;
assert(ConnS != NULL);
assert(ConnS->SendQ_Head != NULL);
while (ConnS->FlushL_Head != NULL) {
FlushL = ConnS->FlushL_Head;
Duration = (NOW - FlushL->Time);
if (Duration < ConnS->SendLineTime) { break; }
ConnS->SendQMaxFlushLines += FlushL->Lines;
ConnS->FlushL_Head = FlushL->Next;
if (FlushL->Next == NULL) { ConnS->FlushL_Tail = NULL; }
else { FlushL->Next->Prev = NULL; }
free(FlushL);
ConnS->NumFlushLs--;
}
while (ConnS->FlushB_Head != NULL) {
FlushB = ConnS->FlushB_Head;
Duration = (NOW - FlushB->Time);
if (Duration < ConnS->SendBufferTime) { break; }
ConnS->SendQMaxFlushBuffer += FlushB->Len;
ConnS->FlushB_Head = FlushB->Next;
if (FlushB->Next == NULL) { ConnS->FlushB_Tail = NULL; }
else { FlushB->Next->Prev = NULL; }
free(FlushB);
ConnS->NumFlushBs--;
}
while ((ConnS->SendQ_Head != NULL) && (ConnS->SendQMaxFlushLines > 0) && (ConnS->SendQMaxFlushBuffer > 0)) {
SendQ = ConnS->SendQ_Head;
Len = strlen(SendQ->Line) + 2;
if (Len > ConnS->SendQMaxFlushBuffer) { break; }
ConnS->NumSendQs--;
ConnS->SendQ_Head = ConnS->SendQ_Head->Next;
conn_addsend(ConnS, SendQ->Line);
ConnS->SendQMaxFlushLines--;
ConnS->SendQMaxFlushBuffer -= Len;
FlushLen += Len;
free(SendQ->Line);
free(SendQ);
Count++;
}
if (Count > 0) {
conn_addflushl(ConnS, Count);
conn_addflushb(ConnS, FlushLen);
}
}
/* CONN_INITSENDQ FUNCTION - JONAS (01.07.2000) */
void conn_initsendq(struct Conn_Struct *ConnS) {
struct SendQ_Struct *SendQ = NULL;
assert(ConnS != NULL);
conn_initflushl(ConnS);
conn_initflushb(ConnS);
while (ConnS->SendQ_Head != NULL) {
SendQ = ConnS->SendQ_Head;
ConnS->SendQ_Head = ConnS->SendQ_Head->Next;
free(SendQ->Line);
free(SendQ);
ConnS->NumSendQs--;
}
assert(ConnS->NumSendQs == 0);
ConnS->SendQMaxFlushLines = ConnS->SendMaxLines;
ConnS->SendQMaxFlushBuffer = ConnS->SendMaxBuffer;
}
/* CONN_ADDFLUSHL FUNCTION - JONAS (24.06.2001) */
void conn_addflushl(struct Conn_Struct *ConnS, const unsigned short int Lines) {
struct FlushL_Struct *FlushL = NULL;
struct FlushL_Struct *FlushL_NEW = NULL;
assert(ConnS != NULL);
FlushL_NEW = malloc(sizeof(struct FlushL_Struct));
if (FlushL_NEW == NULL) { return; }
memset(FlushL_NEW, 0, sizeof(struct FlushL_Struct));
FlushL_NEW->Lines = Lines;
FlushL_NEW->Time = NOW;
if (ConnS->FlushL_Head == NULL) {
ConnS->FlushL_Head = FlushL_NEW;
ConnS->FlushL_Tail = FlushL_NEW;
}
else {
FlushL = ConnS->FlushL_Tail;
FlushL->Next = FlushL_NEW;
FlushL_NEW->Prev = FlushL;
ConnS->FlushL_Tail = FlushL_NEW;
}
ConnS->NumFlushLs++;
}
/* CONN_INITFLUSHL FUNCTION - JONAS (24.06.2001) */
void conn_initflushl(struct Conn_Struct *ConnS) {
struct FlushL_Struct *FlushL = NULL;
assert(ConnS != NULL);
while (ConnS->FlushL_Head != NULL) {
FlushL = ConnS->FlushL_Head;
ConnS->FlushL_Head = ConnS->FlushL_Head->Next;
free(FlushL);
ConnS->NumFlushLs--;
}
ConnS->FlushL_Tail = NULL;
assert(ConnS->NumFlushLs == 0);
ConnS->SendQMaxFlushLines = ConnS->SendMaxLines;
}
/* CONN_ADDFLUSHB FUNCTION - JONAS (24.06.2001) */
void conn_addflushb(struct Conn_Struct *ConnS, const unsigned short int Len) {
struct FlushB_Struct *FlushB = NULL;
struct FlushB_Struct *FlushB_NEW = NULL;
assert(ConnS != NULL);
FlushB_NEW = malloc(sizeof(struct FlushB_Struct));
if (FlushB_NEW == NULL) { return; }
memset(FlushB_NEW, 0, sizeof(struct FlushB_Struct));
FlushB_NEW->Len = Len;
FlushB_NEW->Time = NOW;
if (ConnS->FlushB_Head == NULL) {
ConnS->FlushB_Head = FlushB_NEW;
ConnS->FlushB_Tail = FlushB_NEW;
}
else {
FlushB = ConnS->FlushB_Tail;
FlushB->Next = FlushB_NEW;
FlushB_NEW->Prev = FlushB;
ConnS->FlushB_Tail = FlushB_NEW;
}
ConnS->NumFlushBs++;
}
/* CONN_INITFLUSHB FUNCTION - JONAS (24.06.2001) */
void conn_initflushb(struct Conn_Struct *ConnS) {
struct FlushB_Struct *FlushB = NULL;
assert(ConnS != NULL);
while (ConnS->FlushB_Head != NULL) {
FlushB = ConnS->FlushB_Head;
ConnS->FlushB_Head = ConnS->FlushB_Head->Next;
free(FlushB);
ConnS->NumFlushBs--;
}
ConnS->FlushB_Tail = NULL;
assert(ConnS->NumFlushBs == 0);
ConnS->SendQMaxFlushBuffer = ConnS->SendMaxBuffer;
}
syntax highlighted by Code2HTML, v. 0.9.1