]> git.ipfire.org Git - thirdparty/squid.git/blob - tools/purge/socket.cc
Merge from trunk
[thirdparty/squid.git] / tools / purge / socket.cc
1 //
2 // $Id: socket.cc,v 1.3 1999/01/19 11:00:50 voeckler Exp $
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 // $Log: socket.cc,v $
38 // Revision 1.3 1999/01/19 11:00:50 voeckler
39 // Linux glibc2 fixes for socket size parameters.
40 //
41 // Revision 1.2 1998/08/27 15:23:39 voeckler
42 // added TCP_NODELAY options at several places.
43 //
44 // Revision 1.1 1998/08/13 21:52:55 voeckler
45 // Initial revision
46 //
47 //
48 #if defined(__GNUC__) || defined(__GNUG__)
49 #pragma implementation
50 #endif
51
52 #include "socket.hh"
53 #include <netinet/tcp.h>
54 #include <arpa/inet.h>
55 #include <netdb.h>
56
57 #include <errno.h>
58 #include <stdio.h>
59 #include <string.h>
60 #include <unistd.h>
61
62 #include "convert.hh"
63
64 static const char* RCS_ID =
65 "$Id: socket.cc,v 1.3 1999/01/19 11:00:50 voeckler Exp $";
66
67 int
68 setSocketBuffers( int sockfd, int size )
69 // purpose: set socket buffers for both directions to the specified size
70 // paramtr: sockfd (IN): socket file descriptor
71 // size (IN): new socket buffer size
72 // returns: -1 on setsockopt() errors, 0 otherwise
73 // warning: prints error message on stderr, errno will be changed
74 {
75 if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF,
76 (char*) &size, sizeof(size) ) == -1 ) {
77 perror( "setsockopt( SO_RCVBUF )" );
78 return -1;
79 }
80
81 if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF,
82 (char*) &size, sizeof(size) ) == -1 ) {
83 perror( "setsockopt( SO_SNDBUF )" );
84 return -1;
85 }
86
87 return 0;
88 }
89
90 int
91 getSocketNoDelay( int sockfd )
92 // purpose: get state of the TCP_NODELAY of the socket
93 // paramtr: sockfd (IN): socket descriptor
94 // returns: 1, if TCP_NODELAY is set,
95 // 0, if TCP_NODELAY is not set,
96 // -1, if an error occurred (e.g. datagram socket)
97 {
98 int delay = 0;
99 SOCKLEN len = sizeof(delay);
100 if ( getsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
101 (char*) &delay, &len ) == -1 ) {
102 perror( "# getsockopt( TCP_NODELAY ) failed" );
103 return -1;
104 } else
105 return ( delay ? 1 : 0 );
106 }
107
108 int
109 setSocketNoDelay( int sockfd, bool nodelay )
110 // purpose: get state of the TCP_NODELAY of the socket
111 // paramtr: sockfd (IN): socket descriptor
112 // nodelay (IN): true, if TCP_NODELAY is to be set, false otherwise.
113 // returns: 0, if everything worked out o.k.
114 // -1, if an error occurred (e.g. datagram socket)
115 {
116 const int delay = 1;
117 if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
118 (const char*) &delay, sizeof(delay) ) == -1 ) {
119 perror( "setsockopt( TCP_NODELAY ) failed" );
120 return -1;
121 } else
122 return 0;
123 }
124
125
126 int
127 commonCode( int& sockfd, bool nodelay, int sendBufferSize, int recvBufferSize )
128 // purpose: common code in server sockets and client sockets
129 // paramtr: sockfd (IO): socket filedescriptor
130 // nodelay (IN): true=set TCP_NODELAY option.
131 // sendBufferSize (IN): don't set (use sys defaults) if < 0
132 // recvBufferSize (IN): don't set (use sys defaults) if < 0
133 // returns: 0 == if everthing went ok, -1 otherwise
134 // warning: sockfd will be closed, if -1 is returned!
135 {
136 // set TCP_NODELAY option, if that is wanted.
137 // The socket API default is unset.
138 if ( nodelay ) {
139 const int delay = 1;
140 if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
141 (const char*) &delay, sizeof(delay) ) == -1 ) {
142 perror( "setsockopt( TCP_NODELAY ) failed" );
143 close(sockfd);
144 return -1;
145 }
146 }
147
148 // set the socket send buffer size explicitly, or use the system default
149 if ( sendBufferSize >= 0 ) {
150 if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF, (char*) &sendBufferSize,
151 sizeof(sendBufferSize) ) == -1 ) {
152 perror( "setsockopt( SO_SNDBUF )" );
153 close(sockfd);
154 return -1;
155 }
156 }
157
158 // set the socket recv buffer size explicitly, or use the system default
159 if ( recvBufferSize >= 0 ) {
160 if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF, (char*) &recvBufferSize,
161 sizeof(recvBufferSize) ) == -1 ) {
162 perror( "setsockopt( SO_RCVBUF )" );
163 close(sockfd);
164 return -1;
165 }
166 }
167 return 0;
168 }
169
170 int
171 connectTo( struct in_addr host, unsigned short port, bool nodelay,
172 int sendBufferSize, int recvBufferSize )
173 // purpose: connect to a server as a client
174 // paramtr: host (IN): address describing the server
175 // port (IN): port to connect at the server
176 // nodelay (IN): true=set TCP_NODELAY option.
177 // sendBufferSize (IN): don't set (use sys defaults) if < 0
178 // recvBufferSize (IN): don't set (use sys defaults) if < 0
179 // returns: >=0 is the descriptor of the opened, connected socket,
180 // -1 is an indication of an error (errno may have been reset).
181 {
182 int sockfd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
183 if ( sockfd == -1 ) {
184 perror( "socket() failed" );
185 return -1;
186 }
187
188 if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
189 return -1;
190
191 struct sockaddr_in server;
192 memset( &server, 0, sizeof(server) );
193 server.sin_family = AF_INET;
194 server.sin_addr = host;
195 server.sin_port = port;
196 if ( connect( sockfd, (struct sockaddr*) &server, sizeof(server) ) == -1 ) {
197 perror( "connect() failure" );
198 close(sockfd);
199 return -1;
200 }
201
202 return sockfd;
203 }
204
205 int
206 serverSocket( struct in_addr host, unsigned short port,
207 int backlog, bool reuse, bool nodelay,
208 int sendBufferSize, int recvBufferSize )
209 // purpose: open a server socket for listening
210 // paramtr: host (IN): host to bind locally to, use INADDRY_ANY for *
211 // port (IN): port to bind to, use 0 for system assigned
212 // backlog (IN): listen backlog queue length
213 // reuse (IN): set SO_REUSEADDR option - default usefully
214 // nodelay (IN): true=set TCP_NODELAY option.
215 // SETTING TCP_NODELAY ON A SERVER SOCKET DOES NOT MAKE SENSE!
216 // sendBufferSize (IN): don't set (use sys defaults) if < 0
217 // recvBufferSize (IN): don't set (use sys defaults) if < 0
218 // returns: opened listening fd, or -1 on error.
219 // warning: error message will be printed on stderr and errno reset.
220 {
221 int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
222 if ( sockfd == -1 ) {
223 perror( "socket" );
224 return -1;
225 }
226
227 if ( reuse ) {
228 int reuse = 1;
229 if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
230 (char*) &reuse, sizeof(int) ) == -1) {
231 perror( "setsockopt( SO_REUSEADDR )" );
232 close( sockfd );
233 return -1;
234 }
235 }
236
237 if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
238 return -1;
239
240 struct sockaddr_in server;
241 memset( &server, 0, sizeof(server) );
242 server.sin_family = AF_INET;
243 server.sin_port = port;
244 server.sin_addr = host;
245 if ( bind( sockfd, (SA*) &server, sizeof(server) ) == -1 ) {
246 SockAddress socket;
247 fprintf( stderr, "bind(%s): %s\n",
248 my_sock_ntoa(server,socket), strerror(errno) );
249 close(sockfd);
250 return -1;
251 }
252
253 if ( listen( sockfd, backlog ) == -1 ) {
254 perror( "listen" );
255 close(sockfd);
256 return -1;
257 }
258
259 return sockfd;
260 }