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