]> jfr.im git - irc.git/blame - software/ircd/www.irc.org/ftp/irc/server/irc2.11.2p3/common/packet.c
init
[irc.git] / software / ircd / www.irc.org / ftp / irc / server / irc2.11.2p3 / common / packet.c
CommitLineData
3bd189cb
JR
1/************************************************************************
2 * IRC - Internet Relay Chat, common/packet.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifndef lint
22static const volatile char rcsid[] = "@(#)$Id: packet.c,v 1.13 2004/10/01 20:22:12 chopin Exp $";
23#endif
24
25#include "os.h"
26#include "s_defines.h"
27#define PACKET_C
28#include "s_externs.h"
29#undef PACKET_C
30
31/*
32** dopacket
33** cptr - pointer to client structure for which the buffer data
34** applies.
35** buffer - pointr to the buffer containing the newly read data
36** length - number of valid bytes of data in the buffer
37**
38** The buffer might be partially or totally zipped.
39** At the beginning of the compressed flow, it is possible that
40** an uncompressed ERROR message will be found. This occurs when
41** the connection fails on the other server before switching
42** to compressed mode.
43**
44** Note:
45** It is implicitly assumed that dopacket is called only
46** with cptr of "local" variation, which contains all the
47** necessary fields (buffer etc..)
48*/
49int dopacket(aClient *cptr, char *buffer, int length)
50{
51 Reg char *ch1;
52 Reg char *ch2, *bufptr;
53 aClient *acpt = cptr->acpt;
54 int r = 1;
55#ifdef ZIP_LINKS
56 int unzipped = 0;
57#endif
58
59 me.receiveB += length; /* Update bytes received */
60 cptr->receiveB += length;
61 if (acpt != &me)
62 {
63 acpt->receiveB += length;
64 }
65
66 bufptr = cptr->buffer;
67 ch1 = bufptr + cptr->count;
68 ch2 = buffer;
69
70#ifdef ZIP_LINKS
71 while ((length > 0 && ch2) || ((cptr->flags & FLAGS_ZIP) &&
72 (cptr->zip->in->avail_in ||
73 !unzipped)))
74#else
75 while (length > 0 && ch2)
76#endif
77 {
78 Reg char c;
79
80#ifdef ZIP_LINKS
81 if (cptr->flags & FLAGS_ZIPSTART)
82 {
83 /*
84 ** beginning of server connection, the buffer
85 ** contained PASS/SERVER and is now zipped!
86 ** Ignore the '\n' that should be here.
87 */
88 if (*ch2 == '\n') /* also check \r ? */
89 {
90 ch2++;
91 length--;
92 cptr->flags &= ~FLAGS_ZIPSTART;
93 }
94 if (length == 0)
95 return 1;
96 }
97
98 if ((cptr->flags & FLAGS_ZIP) && !(unzipped && length))
99 {
100 /* uncompressed buffer first */
101 unzipped = length; /* length is register, store
102 temp in unzipped */
103 ch2 = unzip_packet(cptr, ch2, &unzipped);
104 length = unzipped;
105 unzipped = 1;
106 if (length == -1)
107 return exit_client(cptr, cptr, &me,
108 "fatal error in unzip_packet()");
109 if (length == 0 || *ch2 == '\0')
110 break;
111 }
112#endif
113 length--;
114 c = (*ch1 = *ch2++);
115 /*
116 * Yuck. Stuck. To make sure we stay backward compatible,
117 * we must assume that either CR or LF terminates the message
118 * and not CR-LF. By allowing CR or LF (alone) into the body
119 * of messages, backward compatibility is lost and major
120 * problems will arise. - Avalon
121 */
122 if ((c <= '\r') && (c == '\n' || c == '\r'))
123 {
124 if (ch1 == bufptr)
125 continue; /* Skip extra LF/CR's */
126 *ch1 = '\0';
127 me.receiveM += 1; /* Update messages received */
128 cptr->receiveM += 1;
129 if (cptr->acpt != &me)
130 cptr->acpt->receiveM += 1;
131 cptr->count = 0; /* ...just in case parse returns with
132 ** FLUSH_BUFFER without removing the
133 ** structure pointed by cptr... --msa
134 */
135 if ((r = parse(cptr, bufptr, ch1)) ==
136 FLUSH_BUFFER)
137 /*
138 ** FLUSH_BUFFER means actually that cptr
139 ** structure *does* not exist anymore!!! --msa
140 */
141 return FLUSH_BUFFER;
142 /*
143 ** Socket is dead so exit (which always returns with
144 ** FLUSH_BUFFER here). - avalon
145 */
146 if (IsDead(cptr))
147 {
148 if (cptr->exitc == EXITC_REG)
149 cptr->exitc = EXITC_DEAD;
150 return exit_client(cptr, cptr, &me,
151 (cptr->exitc == EXITC_SENDQ) ?
152 "Max SendQ exceeded" :
153 "Dead Socket");
154 }
155 /*
156 ** Something is wrong, really wrong, and nothing
157 ** else should be allowed to be parsed!
158 ** This covers a bug which is somewhere else,
159 ** since no decent server would send such thing
160 ** as an unknown command. -krys
161 */
162 if (IsServer(cptr) && (cptr->flags & FLAGS_UNKCMD))
163 break;
164 ch1 = bufptr;
165 }
166 else if (ch1 < bufptr + (sizeof(cptr->buffer)-1))
167 ch1++; /* There is always room for the null */
168 }
169 cptr->count = ch1 - bufptr;
170 return r;
171}
172