2 MiddleMan filtering proxy server
3 Copyright (C) 2002 Jason McLaughlin
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 SOCKET *sock_new(int fd)
30 ret = xmalloc(sizeof(SOCKET));
34 ret->inbuf_len = ret->outbuf_len = 0;
35 ret->inbuf_reallen = ret->outbuf_reallen = 0;
36 ret->inbuf = ret->outbuf = NULL;
41 void sock_close(SOCKET * sock)
47 FREE_AND_NULL(sock->inbuf);
48 FREE_AND_NULL(sock->outbuf);
53 int sock_read(SOCKET * sock, void *buf, int len)
58 if (sock->inbuf_len != 0 && len != -1) {
59 memcpy(buf, sock->inbuf, (sock->inbuf_len < len) ? sock->inbuf_len : len);
60 if (sock->inbuf_len <= len) {
61 /* all buffered data used up, clear it */
62 pos = sock->inbuf_len;
66 /* buffer is exact size of requested read size, no need to do any network IO */
70 /* buffer larger than requested read size, no need to do any network IO */
71 /* chop off used part of buffer */
72 memcpy(sock->inbuf, sock->inbuf + len, sock->inbuf_len - len);
73 sock_resize(sock, sock->inbuf_len - len, IN);
79 x = read(sock->fd, b, BLOCKSIZE);
83 sock_resize(sock, sock->inbuf_len + x, IN);
84 memcpy(sock->inbuf + sock->inbuf_len - x, b, x);
86 memcpy(buf + pos, b, (x > len - pos) ? len - pos : x);
89 sock_resize(sock, x - (len - pos), IN);
90 memcpy(sock->inbuf, &b[len - pos], x - (len - pos));
93 pos += (x > len - pos) ? len - pos : x;
97 return (pos != 0) ? pos : x;
100 int sock_write(SOCKET * sock, void *buf, int len)
104 if (sock->outbuf_len != 0 && sock->frozen == FALSE) {
105 x = write(sock->fd, sock->outbuf, sock->outbuf_len);
107 if (x == sock->outbuf_len) {
108 /* successfully wrote everything */
109 sock_clear(sock, OUT);
112 memcpy(sock->outbuf, sock->outbuf + x, sock->outbuf_len - x);
113 sock_resize(sock, sock->outbuf_len - x, OUT);
121 if (sock->outbuf_len == 0 && sock->frozen == FALSE)
122 x = write(sock->fd, buf, len);
124 /* buffer data that couldn't be written immediately */
125 tmp = sock->outbuf_len;
126 sock_resize(sock, sock->outbuf_len + len - ((x != -1) ? x : 0), OUT);
127 memcpy(sock->outbuf + tmp, buf + ((x != -1) ? x : 0), len - ((x != -1) ? x : 0));
134 int sock_getline(SOCKET * sock, char *buf, int len)
140 if (sock->inbuf_len != 0 && ((ptr = memchr(sock->inbuf + pos, '\n', sock->inbuf_len - pos)))) {
141 /* if len is -1, just discard the line */
143 x = ((ptr - sock->inbuf) + 1 < len) ? (ptr - sock->inbuf) + 1 : len;
145 memcpy(buf, sock->inbuf, x);
146 buf[(x != len) ? x : x - 1] = '\0';
149 if (ptr - sock->inbuf == sock->inbuf_len || ptr - sock->inbuf + 1 == sock->inbuf_len) {
150 /* used up all buffered data */
151 sock_clear(sock, IN);
153 /* remove entire line from buffer, even if it's larger than requested read size */
154 memcpy(sock->inbuf, ptr + 1, sock->inbuf_len - (ptr - sock->inbuf) - 1);
155 sock_resize(sock, sock->inbuf_len - (ptr - sock->inbuf) - 1, IN);
160 pos = sock->inbuf_len;
161 } while ((x = sock_read(sock, NULL, -1)) > 0);
166 void sock_flush(SOCKET * sock)
168 sock->frozen = FALSE;
170 while (sock->outbuf_len > 0 && sock_write(sock, NULL, -1) != -1);
172 sock_resize(sock, 0, OUT);
173 sock_resize(sock, 0, IN);
176 void sock_resize(SOCKET * sock, int newsize, int which)
179 if (sock->inbuf != NULL && sock->inbuf_reallen >= newsize && sock->inbuf_reallen < newsize + FILEBUF_ALIGNMENT)
180 sock->inbuf_len = newsize;
181 else if (newsize == 0)
182 sock_clear(sock, IN);
184 sock->inbuf_reallen = ALIGN2(newsize, FILEBUF_ALIGNMENT);
185 sock->inbuf = xrealloc(sock->inbuf, sock->inbuf_reallen);
186 sock->inbuf_len = newsize;
189 if (sock->outbuf != NULL && sock->outbuf_reallen >= newsize && sock->outbuf_reallen < newsize + FILEBUF_ALIGNMENT)
190 sock->outbuf_len = newsize;
191 else if (newsize == 0)
192 sock_clear(sock, OUT);
194 sock->outbuf_reallen = ALIGN2(newsize, FILEBUF_ALIGNMENT);
195 sock->outbuf = xrealloc(sock->outbuf, sock->outbuf_reallen);
196 sock->outbuf_len = newsize;
201 void sock_clear(SOCKET * sock, int which)
204 if (sock->inbuf_reallen > FILEBUF_ALIGNMENT) {
205 FREE_AND_NULL(sock->inbuf);
206 sock->inbuf_reallen = 0;
211 if (sock->outbuf_reallen > FILEBUF_ALIGNMENT) {
212 FREE_AND_NULL(sock->outbuf);
213 sock->outbuf_reallen = 0;
216 sock->outbuf_len = 0;