]> git.ipfire.org Git - thirdparty/squid.git/blob - tools/purge/socket.cc
Remove diff-reducer hack in rev10754
[thirdparty/squid.git] / tools / purge / socket.cc
1 //
2 // $Id$
3 //
4 // Author: Jens-S. V?ckler <voeckler@rvs.uni-hannover.de>
5 //
6 // File: socket.hh
7 // Sun May 3 1998
8 //
9 // (c) 1998 Lehrgebiet Rechnernetze und Verteilte Systeme
10 // Universit?t Hannover, Germany
11 //
12 // Books: W. Richard Steven, "Advanced Programming in the UNIX Environment",
13 // Addison-Wesley, 1992.
14 //
15 // Permission to use, copy, modify, distribute, and sell this software
16 // and its documentation for any purpose is hereby granted without fee,
17 // provided that (i) the above copyright notices and this permission
18 // notice appear in all copies of the software and related documentation,
19 // and (ii) the names of the Lehrgebiet Rechnernetze und Verteilte
20 // Systeme and the University of Hannover may not be used in any
21 // advertising or publicity relating to the software without the
22 // specific, prior written permission of Lehrgebiet Rechnernetze und
23 // Verteilte Systeme and the University of Hannover.
24 //
25 // THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
27 // WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
28 //
29 // IN NO EVENT SHALL THE LEHRGEBIET RECHNERNETZE UND VERTEILTE SYSTEME OR
30 // THE UNIVERSITY OF HANNOVER BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
31 // INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
32 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
33 // ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
34 // ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
35 // SOFTWARE.
36 //
37 // Revision 1.3 1999/01/19 11:00:50 voeckler
38 // Linux glibc2 fixes for socket size parameters.
39 //
40 // Revision 1.2 1998/08/27 15:23:39 voeckler
41 // added TCP_NODELAY options at several places.
42 //
43 // Revision 1.1 1998/08/13 21:52:55 voeckler
44 // Initial revision
45 //
46 //
47 #if defined(__GNUC__) || defined(__GNUG__)
48 #pragma implementation
49 #endif
50
51 #include "socket.hh"
52 #include <netinet/tcp.h>
53 #include <arpa/inet.h>
54 #include <netdb.h>
55
56 #include <errno.h>
57 #include <stdio.h>
58 #include <string.h>
59 #include <unistd.h>
60
61 #include "convert.hh"
62
63 int
64 setSocketBuffers( int sockfd, int size )
65 // purpose: set socket buffers for both directions to the specified size
66 // paramtr: sockfd (IN): socket file descriptor
67 // size (IN): new socket buffer size
68 // returns: -1 on setsockopt() errors, 0 otherwise
69 // warning: prints error message on stderr, errno will be changed
70 {
71 if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF,
72 (char*) &size, sizeof(size) ) == -1 ) {
73 perror( "setsockopt( SO_RCVBUF )" );
74 return -1;
75 }
76
77 if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF,
78 (char*) &size, sizeof(size) ) == -1 ) {
79 perror( "setsockopt( SO_SNDBUF )" );
80 return -1;
81 }
82
83 return 0;
84 }
85
86 int
87 getSocketNoDelay( int sockfd )
88 // purpose: get state of the TCP_NODELAY of the socket
89 // paramtr: sockfd (IN): socket descriptor
90 // returns: 1, if TCP_NODELAY is set,
91 // 0, if TCP_NODELAY is not set,
92 // -1, if an error occurred (e.g. datagram socket)
93 {
94 int delay = 0;
95 socklen_t len = sizeof(delay);
96 if ( getsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
97 (char*) &delay, &len ) == -1 ) {
98 perror( "# getsockopt( TCP_NODELAY ) failed" );
99 return -1;
100 } else
101 return ( delay ? 1 : 0 );
102 }
103
104 int
105 setSocketNoDelay( int sockfd, bool nodelay )
106 // purpose: get state of the TCP_NODELAY of the socket
107 // paramtr: sockfd (IN): socket descriptor
108 // nodelay (IN): true, if TCP_NODELAY is to be set, false otherwise.
109 // returns: 0, if everything worked out o.k.
110 // -1, if an error occurred (e.g. datagram socket)
111 {
112 const int delay = 1;
113 if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
114 (const char*) &delay, sizeof(delay) ) == -1 ) {
115 perror( "setsockopt( TCP_NODELAY ) failed" );
116 return -1;
117 } else
118 return 0;
119 }
120
121
122 int
123 commonCode( int& sockfd, bool nodelay, int sendBufferSize, int recvBufferSize )
124 // purpose: common code in server sockets and client sockets
125 // paramtr: sockfd (IO): socket filedescriptor
126 // nodelay (IN): true=set TCP_NODELAY option.
127 // sendBufferSize (IN): don't set (use sys defaults) if < 0
128 // recvBufferSize (IN): don't set (use sys defaults) if < 0
129 // returns: 0 == if everthing went ok, -1 otherwise
130 // warning: sockfd will be closed, if -1 is returned!
131 {
132 // set TCP_NODELAY option, if that is wanted.
133 // The socket API default is unset.
134 if ( nodelay ) {
135 const int delay = 1;
136 if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
137 (const char*) &delay, sizeof(delay) ) == -1 ) {
138 perror( "setsockopt( TCP_NODELAY ) failed" );
139 close(sockfd);
140 return -1;
141 }
142 }
143
144 // set the socket send buffer size explicitly, or use the system default
145 if ( sendBufferSize >= 0 ) {
146 if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF, (char*) &sendBufferSize,
147 sizeof(sendBufferSize) ) == -1 ) {
148 perror( "setsockopt( SO_SNDBUF )" );
149 close(sockfd);
150 return -1;
151 }
152 }
153
154 // set the socket recv buffer size explicitly, or use the system default
155 if ( recvBufferSize >= 0 ) {
156 if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF, (char*) &recvBufferSize,
157 sizeof(recvBufferSize) ) == -1 ) {
158 perror( "setsockopt( SO_RCVBUF )" );
159 close(sockfd);
160 return -1;
161 }
162 }
163 return 0;
164 }
165
166 int
167 connectTo( struct in_addr host, unsigned short port, bool nodelay,
168 int sendBufferSize, int recvBufferSize )
169 // purpose: connect to a server as a client
170 // paramtr: host (IN): address describing the server
171 // port (IN): port to connect at the server
172 // nodelay (IN): true=set TCP_NODELAY option.
173 // sendBufferSize (IN): don't set (use sys defaults) if < 0
174 // recvBufferSize (IN): don't set (use sys defaults) if < 0
175 // returns: >=0 is the descriptor of the opened, connected socket,
176 // -1 is an indication of an error (errno may have been reset).
177 {
178 int sockfd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
179 if ( sockfd == -1 ) {
180 perror( "socket() failed" );
181 return -1;
182 }
183
184 if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
185 return -1;
186
187 struct sockaddr_in server;
188 memset( &server, 0, sizeof(server) );
189 server.sin_family = AF_INET;
190 server.sin_addr = host;
191 server.sin_port = port;
192 if ( connect( sockfd, (struct sockaddr*) &server, sizeof(server) ) == -1 ) {
193 perror( "connect() failure" );
194 close(sockfd);
195 return -1;
196 }
197
198 return sockfd;
199 }
200
201 int
202 serverSocket( struct in_addr host, unsigned short port,
203 int backlog, bool reuse, bool nodelay,
204 int sendBufferSize, int recvBufferSize )
205 // purpose: open a server socket for listening
206 // paramtr: host (IN): host to bind locally to, use INADDRY_ANY for *
207 // port (IN): port to bind to, use 0 for system assigned
208 // backlog (IN): listen backlog queue length
209 // reuse (IN): set SO_REUSEADDR option - default usefully
210 // nodelay (IN): true=set TCP_NODELAY option.
211 // SETTING TCP_NODELAY ON A SERVER SOCKET DOES NOT MAKE SENSE!
212 // sendBufferSize (IN): don't set (use sys defaults) if < 0
213 // recvBufferSize (IN): don't set (use sys defaults) if < 0
214 // returns: opened listening fd, or -1 on error.
215 // warning: error message will be printed on stderr and errno reset.
216 {
217 int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
218 if ( sockfd == -1 ) {
219 perror( "socket" );
220 return -1;
221 }
222
223 if ( reuse ) {
224 int reuse = 1;
225 if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
226 (char*) &reuse, sizeof(int) ) == -1) {
227 perror( "setsockopt( SO_REUSEADDR )" );
228 close( sockfd );
229 return -1;
230 }
231 }
232
233 if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
234 return -1;
235
236 struct sockaddr_in server;
237 memset( &server, 0, sizeof(server) );
238 server.sin_family = AF_INET;
239 server.sin_port = port;
240 server.sin_addr = host;
241 if ( bind( sockfd, (SA*) &server, sizeof(server) ) == -1 ) {
242 SockAddress socket;
243 fprintf( stderr, "bind(%s): %s\n",
244 my_sock_ntoa(server,socket), strerror(errno) );
245 close(sockfd);
246 return -1;
247 }
248
249 if ( listen( sockfd, backlog ) == -1 ) {
250 perror( "listen" );
251 close(sockfd);
252 return -1;
253 }
254
255 return sockfd;
256 }