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