/************************************************************************
* IRC - Internet Relay Chat, src/packet.c
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Computing Center
*
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: packet.c,v 1.2 2006/01/07 22:13:26 trystanscott Exp $ */
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "msg.h"
#include "h.h"
#include "dh.h"
#include "zlink.h"
/*
* * dopacket
* cptr - pointer to client structure for which the buffer
* data applies.
* buffer - pointr to the buffer containing the newly read data
* length - number of valid bytes of data in the buffer
*
* Note:
* It is implicitly assumed that dopacket is called only
* with cptr of "local" variation, which contains all the
* necessary fields (buffer etc..)
*/
int dopacket(aClient *cptr, char *buffer, int length)
{
char *ch1;
char *ch2;
char *cptrbuf = cptr->buffer;
aListener *lptr = cptr->lstn;
char *nbuf = NULL;
int nlen;
#ifdef HAVE_ENCRYPTION_ON
if(IsRC4IN(cptr))
rc4_process_stream(cptr->serv->rc4_in, (unsigned char *) buffer, length);
#endif
me.receiveB += length; /* Update bytes received */
cptr->receiveB += length;
if (cptr->receiveB & 0x0400)
{
cptr->receiveK += (cptr->receiveB >> 10);
cptr->receiveB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */
}
if (lptr)
{
lptr->receiveB += length;
if (lptr->receiveB & 0x0400)
{
lptr->receiveK += (lptr->receiveB >> 10);
lptr->receiveB &= 0x03ff;
}
}
else if (me.receiveB & 0x0400)
{
me.receiveK += (me.receiveB >> 10);
me.receiveB &= 0x03ff;
}
zcontinue:
ch1 = cptrbuf + cptr->count;
ch2 = buffer;
if(ZipIn(cptr))
{
int err;
ch2 = zip_input(cptr->serv->zip_in, ch2, &length, &err, &nbuf, &nlen);
if(length == -1)
{
sendto_realops("Zipin error for %s: (%d) %s\n", cptr->name,
err, ch2);
return exit_client(cptr, cptr, &me, "fatal error in zip_input!");
}
}
while (--length >= 0)
{
char g;
g = (*ch1 = *ch2++);
/*
* Yuck. Stuck. To make sure we stay backward compatible, we
* must assume that either CR or LF terminates the message and
* not CR-LF. By allowing CR or LF (alone) into the body of
* messages, backward compatibility is lost and major problems
* will arise. - Avalon
*/
if (g < '\16' && (g == '\n' || g == '\r')) {
if (ch1 == cptrbuf)
continue; /* Skip extra LF/CR's */
*ch1 = '\0';
me.receiveM += 1; /* Update messages received */
cptr->receiveM += 1;
if (lptr)
lptr->receiveM += 1;
cptr->count = 0; /*
* ...just in case parse returns with
* FLUSH_BUFFER without removing the
* structure pointed by cptr... --msa
*/
switch (parse(cptr, cptr->buffer, ch1))
{
case FLUSH_BUFFER:
return FLUSH_BUFFER;
case ZIP_NEXT_BUFFER:
if(length)
{
int err;
ch2 = zip_input(cptr->serv->zip_in, ch2, &length,
&err, &nbuf, &nlen);
if(length == -1)
{
sendto_realops("Zipin error for %s: (%d) %s\n",
cptr->name, err, ch2);
return exit_client(cptr, cptr, &me,
"fatal error in zip_input!");
}
}
break;
#ifdef HAVE_ENCRYPTION_ON
case RC4_NEXT_BUFFER:
if(length)
rc4_process_stream(cptr->serv->rc4_in, (unsigned char *) ch2, length);
break;
#endif
default:
break;
}
/*
* Socket is dead so exit (which always returns with *
* FLUSH_BUFFER here). - avalon
*/
if (cptr->flags & FLAGS_DEADSOCKET)
return exit_client(cptr, cptr, &me,
(cptr->flags & FLAGS_SENDQEX) ?
"SendQ exceeded" : "Dead socket");
ch1 = cptrbuf;
}
else if (ch1 < cptrbuf + (sizeof(cptr->buffer) - 1))
ch1++; /* There is always room for the null */
}
cptr->count = ch1 - cptrbuf;
if(nbuf)
{
#if 0 /* this message is annoying and not quite that useful */
static time_t last_complain = 0;
static int numrepeat = 0;
numrepeat++;
if(NOW > (last_complain + 300)) /* if more than 5 mins have elapsed */
{
if(last_complain == 0)
{
sendto_realops("Overflowed zipInBuf! "
"If you see this a lot, you should increase "
"zipInBufSize in src/zlink.c.");
}
else
{
sendto_realops("Overflowed zipInBuf %d time%s in the "
"last %d minutes. If you see this a lot, you "
"should increase zipInBufSize in src/zlink.c.",
numrepeat, numrepeat == 1 ? "" : "s",
(NOW - last_complain) / 60);
}
last_complain = NOW;
numrepeat = 0;
}
#endif
buffer = nbuf;
length = nlen;
nbuf = NULL;
goto zcontinue; /* gross, but it should work.. */
}
return 0;
}
int client_dopacket(aClient *cptr, char *buffer, int length)
{
strncpy(cptr->buffer, buffer, BUFSIZE);
length = strlen(cptr->buffer);
/* Update messages received */
++me.receiveM;
++cptr->receiveM;
/* Update bytes received */
cptr->receiveB += length;
if (cptr->receiveB > 1023)
{
cptr->receiveK += (cptr->receiveB >> 10);
cptr->receiveB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */
}
me.receiveB += length;
if (me.receiveB > 1023)
{
me.receiveK += (me.receiveB >> 10);
me.receiveB &= 0x03ff;
}
cptr->count = 0; /* ...just in case parse returns with */
if (FLUSH_BUFFER == parse(cptr, cptr->buffer, cptr->buffer + length))
{
/*
* CLIENT_EXITED means actually that cptr
* structure *does* not exist anymore!!! --msa
*/
return FLUSH_BUFFER;
}
else if (cptr->flags & FLAGS_DEADSOCKET)
{
/*
* Socket is dead so exit (which always returns with
* CLIENT_EXITED here). - avalon
*/
return exit_client(cptr, cptr, &me,
(cptr->flags & FLAGS_SENDQEX) ?
"SendQ exceeded" : "Dead socket");
}
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1