socket.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
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 
9 // Author: Jens-S. V?ckler <voeckler@rvs.uni-hannover.de>
10 //
11 // File: socket.hh
12 // Sun May 3 1998
13 //
14 // (c) 1998 Lehrgebiet Rechnernetze und Verteilte Systeme
15 // Universit?t Hannover, Germany
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 //
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 //
51 
52 #include "squid.h"
53 #include "socket.hh"
54 
55 #include <cerrno>
56 #include <cstring>
57 #include <netinet/tcp.h>
58 #include <arpa/inet.h>
59 #include <netdb.h>
60 
61 #include <unistd.h>
62 
63 #include "convert.hh"
64 
65 int
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
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
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 int
124 commonCode( int& sockfd, bool nodelay, int sendBufferSize, int recvBufferSize )
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!
132 {
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  }
143  }
144 
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  }
153  }
154 
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  }
163  }
164  return 0;
165 }
166 
167 int
168 connectTo( struct in_addr host, unsigned short port, bool nodelay,
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).
178 {
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  }
198 
199  return sockfd;
200 }
201 
202 int
203 serverSocket( struct in_addr host, unsigned short port,
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.
217 {
218  int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
219  if ( sockfd == -1 ) {
220  perror( "socket" );
221  return -1;
222  }
223 
224  if ( reuse ) {
225  int opt = 1;
226  if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
227  (char*) &opt, sizeof(int) ) == -1) {
228  perror( "setsockopt( SO_REUSEADDR )" );
229  close( sockfd );
230  return -1;
231  }
232  }
233 
234  if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
235  return -1;
236 
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  }
249 
250  if ( listen( sockfd, backlog ) == -1 ) {
251  perror( "listen" );
252  close(sockfd);
253  return -1;
254  }
255 
256  return sockfd;
257 }
258 
int socklen_t
Definition: types.h:158
int connectTo(struct in_addr host, unsigned short port, bool nodelay, int sendBufferSize, int recvBufferSize)
Definition: socket.cc:168
int setSocketNoDelay(int sockfd, bool)
Definition: socket.cc:107
char * strerror(int ern)
Definition: strerror.c:22
static int sockfd
int serverSocket(struct in_addr host, unsigned short port, int backlog, bool reuse, bool nodelay, int sendBufferSize, int recvBufferSize)
Definition: socket.cc:203
int setSocketBuffers(int sockfd, int size)
Definition: socket.cc:66
const char * my_sock_ntoa(const struct sockaddr_in &a, SockAddress buffer)
Definition: convert.cc:85
static int port
Definition: ldap_backend.cc:69
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
int getSocketNoDelay(int sockfd)
Definition: socket.cc:89
#define SA
Definition: convert.cc:59
int commonCode(int &sockfd, bool nodelay, int sendBufferSize, int recvBufferSize)
Definition: socket.cc:124
int size
Definition: ModDevPoll.cc:77

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors