-//
-// $Id: socket.cc,v 1.3 1999/01/19 11:00:50 voeckler Exp $
-//
-// Author: Jens-S. Vöckler <voeckler@rvs.uni-hannover.de>
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+// Author: Jens-S. V?ckler <voeckler@rvs.uni-hannover.de>
//
// File: socket.hh
// Sun May 3 1998
//
// (c) 1998 Lehrgebiet Rechnernetze und Verteilte Systeme
-// Universität Hannover, Germany
+// Universit?t Hannover, Germany
//
// Books: W. Richard Steven, "Advanced Programming in the UNIX Environment",
// Addison-Wesley, 1992.
// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
// SOFTWARE.
//
-// $Log: socket.cc,v $
// Revision 1.3 1999/01/19 11:00:50 voeckler
// Linux glibc2 fixes for socket size parameters.
//
// Revision 1.1 1998/08/13 21:52:55 voeckler
// Initial revision
//
-//
-#if defined(__GNUC__) || defined(__GNUG__)
-#pragma implementation
-#endif
+#include "squid.h"
#include "socket.hh"
+
+#include <cerrno>
+#include <cstring>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
#include <unistd.h>
#include "convert.hh"
-static const char* RCS_ID =
-"$Id: socket.cc,v 1.3 1999/01/19 11:00:50 voeckler Exp $";
-
int
setSocketBuffers( int sockfd, int size )
- // purpose: set socket buffers for both directions to the specified size
- // paramtr: sockfd (IN): socket file descriptor
- // size (IN): new socket buffer size
- // returns: -1 on setsockopt() errors, 0 otherwise
- // warning: prints error message on stderr, errno will be changed
+// purpose: set socket buffers for both directions to the specified size
+// paramtr: sockfd (IN): socket file descriptor
+// size (IN): new socket buffer size
+// returns: -1 on setsockopt() errors, 0 otherwise
+// warning: prints error message on stderr, errno will be changed
{
- if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF,
- (char*) &size, sizeof(size) ) == -1 ) {
- perror( "setsockopt( SO_RCVBUF )" );
- return -1;
- }
+ if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF,
+ (char*) &size, sizeof(size) ) == -1 ) {
+ perror( "setsockopt( SO_RCVBUF )" );
+ return -1;
+ }
- if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF,
- (char*) &size, sizeof(size) ) == -1 ) {
- perror( "setsockopt( SO_SNDBUF )" );
- return -1;
- }
+ if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF,
+ (char*) &size, sizeof(size) ) == -1 ) {
+ perror( "setsockopt( SO_SNDBUF )" );
+ return -1;
+ }
- return 0;
+ return 0;
}
int
getSocketNoDelay( int sockfd )
- // purpose: get state of the TCP_NODELAY of the socket
- // paramtr: sockfd (IN): socket descriptor
- // returns: 1, if TCP_NODELAY is set,
- // 0, if TCP_NODELAY is not set,
- // -1, if an error occurred (e.g. datagram socket)
+// purpose: get state of the TCP_NODELAY of the socket
+// paramtr: sockfd (IN): socket descriptor
+// returns: 1, if TCP_NODELAY is set,
+// 0, if TCP_NODELAY is not set,
+// -1, if an error occurred (e.g. datagram socket)
{
- int delay = 0;
- SOCKLEN len = sizeof(delay);
- if ( getsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
- (char*) &delay, &len ) == -1 ) {
- perror( "# getsockopt( TCP_NODELAY ) failed" );
- return -1;
- } else
- return ( delay ? 1 : 0 );
+ int delay = 0;
+ socklen_t len = sizeof(delay);
+ if ( getsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
+ (char*) &delay, &len ) == -1 ) {
+ perror( "# getsockopt( TCP_NODELAY ) failed" );
+ return -1;
+ } else
+ return ( delay ? 1 : 0 );
}
int
-setSocketNoDelay( int sockfd, bool nodelay )
- // purpose: get state of the TCP_NODELAY of the socket
- // paramtr: sockfd (IN): socket descriptor
- // nodelay (IN): true, if TCP_NODELAY is to be set, false otherwise.
- // returns: 0, if everything worked out o.k.
- // -1, if an error occurred (e.g. datagram socket)
+setSocketNoDelay( int sockfd, bool)
+// purpose: get state of the TCP_NODELAY of the socket
+// paramtr: sockfd (IN): socket descriptor
+// nodelay (IN): true, if TCP_NODELAY is to be set, false otherwise.
+// returns: 0, if everything worked out o.k.
+// -1, if an error occurred (e.g. datagram socket)
{
- const int delay = 1;
- if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
- (const char*) &delay, sizeof(delay) ) == -1 ) {
- perror( "setsockopt( TCP_NODELAY ) failed" );
- return -1;
- } else
- return 0;
+ const int delay = 1;
+ if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
+ (const char*) &delay, sizeof(delay) ) == -1 ) {
+ perror( "setsockopt( TCP_NODELAY ) failed" );
+ return -1;
+ } else
+ return 0;
}
-
int
commonCode( int& sockfd, bool nodelay, int sendBufferSize, int recvBufferSize )
- // purpose: common code in server sockets and client sockets
- // paramtr: sockfd (IO): socket filedescriptor
- // nodelay (IN): true=set TCP_NODELAY option.
- // sendBufferSize (IN): don't set (use sys defaults) if < 0
- // recvBufferSize (IN): don't set (use sys defaults) if < 0
- // returns: 0 == if everthing went ok, -1 otherwise
- // warning: sockfd will be closed, if -1 is returned!
+// purpose: common code in server sockets and client sockets
+// paramtr: sockfd (IO): socket filedescriptor
+// nodelay (IN): true=set TCP_NODELAY option.
+// sendBufferSize (IN): don't set (use sys defaults) if < 0
+// recvBufferSize (IN): don't set (use sys defaults) if < 0
+// returns: 0 == if everthing went ok, -1 otherwise
+// warning: sockfd will be closed, if -1 is returned!
{
- // set TCP_NODELAY option, if that is wanted.
- // The socket API default is unset.
- if ( nodelay ) {
- const int delay = 1;
- if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
- (const char*) &delay, sizeof(delay) ) == -1 ) {
- perror( "setsockopt( TCP_NODELAY ) failed" );
- close(sockfd);
- return -1;
+ // set TCP_NODELAY option, if that is wanted.
+ // The socket API default is unset.
+ if ( nodelay ) {
+ const int delay = 1;
+ if ( setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
+ (const char*) &delay, sizeof(delay) ) == -1 ) {
+ perror( "setsockopt( TCP_NODELAY ) failed" );
+ close(sockfd);
+ return -1;
+ }
}
- }
- // set the socket send buffer size explicitly, or use the system default
- if ( sendBufferSize >= 0 ) {
- if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF, (char*) &sendBufferSize,
- sizeof(sendBufferSize) ) == -1 ) {
- perror( "setsockopt( SO_SNDBUF )" );
- close(sockfd);
- return -1;
+ // set the socket send buffer size explicitly, or use the system default
+ if ( sendBufferSize >= 0 ) {
+ if ( setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF, (char*) &sendBufferSize,
+ sizeof(sendBufferSize) ) == -1 ) {
+ perror( "setsockopt( SO_SNDBUF )" );
+ close(sockfd);
+ return -1;
+ }
}
- }
- // set the socket recv buffer size explicitly, or use the system default
- if ( recvBufferSize >= 0 ) {
- if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF, (char*) &recvBufferSize,
- sizeof(recvBufferSize) ) == -1 ) {
- perror( "setsockopt( SO_RCVBUF )" );
- close(sockfd);
- return -1;
+ // set the socket recv buffer size explicitly, or use the system default
+ if ( recvBufferSize >= 0 ) {
+ if ( setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF, (char*) &recvBufferSize,
+ sizeof(recvBufferSize) ) == -1 ) {
+ perror( "setsockopt( SO_RCVBUF )" );
+ close(sockfd);
+ return -1;
+ }
}
- }
- return 0;
+ return 0;
}
int
connectTo( struct in_addr host, unsigned short port, bool nodelay,
- int sendBufferSize, int recvBufferSize )
- // purpose: connect to a server as a client
- // paramtr: host (IN): address describing the server
- // port (IN): port to connect at the server
- // nodelay (IN): true=set TCP_NODELAY option.
- // sendBufferSize (IN): don't set (use sys defaults) if < 0
- // recvBufferSize (IN): don't set (use sys defaults) if < 0
- // returns: >=0 is the descriptor of the opened, connected socket,
- // -1 is an indication of an error (errno may have been reset).
+ int sendBufferSize, int recvBufferSize )
+// purpose: connect to a server as a client
+// paramtr: host (IN): address describing the server
+// port (IN): port to connect at the server
+// nodelay (IN): true=set TCP_NODELAY option.
+// sendBufferSize (IN): don't set (use sys defaults) if < 0
+// recvBufferSize (IN): don't set (use sys defaults) if < 0
+// returns: >=0 is the descriptor of the opened, connected socket,
+// -1 is an indication of an error (errno may have been reset).
{
- int sockfd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
- if ( sockfd == -1 ) {
- perror( "socket() failed" );
- return -1;
- }
+ int sockfd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
+ if ( sockfd == -1 ) {
+ perror( "socket() failed" );
+ return -1;
+ }
+
+ if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
+ return -1;
- if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
- return -1;
-
- struct sockaddr_in server;
- memset( &server, 0, sizeof(server) );
- server.sin_family = AF_INET;
- server.sin_addr = host;
- server.sin_port = port;
- if ( connect( sockfd, (struct sockaddr*) &server, sizeof(server) ) == -1 ) {
- perror( "connect() failure" );
- close(sockfd);
- return -1;
- }
-
- return sockfd;
+ struct sockaddr_in server;
+ memset( &server, 0, sizeof(server) );
+ server.sin_family = AF_INET;
+ server.sin_addr = host;
+ server.sin_port = port;
+ if ( connect( sockfd, (struct sockaddr*) &server, sizeof(server) ) == -1 ) {
+ perror( "connect() failure" );
+ close(sockfd);
+ return -1;
+ }
+
+ return sockfd;
}
int
serverSocket( struct in_addr host, unsigned short port,
- int backlog, bool reuse, bool nodelay,
- int sendBufferSize, int recvBufferSize )
- // purpose: open a server socket for listening
- // paramtr: host (IN): host to bind locally to, use INADDRY_ANY for *
- // port (IN): port to bind to, use 0 for system assigned
- // backlog (IN): listen backlog queue length
- // reuse (IN): set SO_REUSEADDR option - default usefully
- // nodelay (IN): true=set TCP_NODELAY option.
- // SETTING TCP_NODELAY ON A SERVER SOCKET DOES NOT MAKE SENSE!
- // sendBufferSize (IN): don't set (use sys defaults) if < 0
- // recvBufferSize (IN): don't set (use sys defaults) if < 0
- // returns: opened listening fd, or -1 on error.
- // warning: error message will be printed on stderr and errno reset.
+ int backlog, bool reuse, bool nodelay,
+ int sendBufferSize, int recvBufferSize )
+// purpose: open a server socket for listening
+// paramtr: host (IN): host to bind locally to, use INADDRY_ANY for *
+// port (IN): port to bind to, use 0 for system assigned
+// backlog (IN): listen backlog queue length
+// reuse (IN): set SO_REUSEADDR option - default usefully
+// nodelay (IN): true=set TCP_NODELAY option.
+// SETTING TCP_NODELAY ON A SERVER SOCKET DOES NOT MAKE SENSE!
+// sendBufferSize (IN): don't set (use sys defaults) if < 0
+// recvBufferSize (IN): don't set (use sys defaults) if < 0
+// returns: opened listening fd, or -1 on error.
+// warning: error message will be printed on stderr and errno reset.
{
- int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
- if ( sockfd == -1 ) {
- perror( "socket" );
- return -1;
- }
+ int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
+ if ( sockfd == -1 ) {
+ perror( "socket" );
+ return -1;
+ }
- if ( reuse ) {
- int reuse = 1;
- if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
- (char*) &reuse, sizeof(int) ) == -1) {
- perror( "setsockopt( SO_REUSEADDR )" );
- close( sockfd );
- return -1;
+ if ( reuse ) {
+ int opt = 1;
+ if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
+ (char*) &opt, sizeof(int) ) == -1) {
+ perror( "setsockopt( SO_REUSEADDR )" );
+ close( sockfd );
+ return -1;
+ }
}
- }
- if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
- return -1;
+ if ( commonCode( sockfd, nodelay, sendBufferSize, recvBufferSize ) == -1 )
+ return -1;
- struct sockaddr_in server;
- memset( &server, 0, sizeof(server) );
- server.sin_family = AF_INET;
- server.sin_port = port;
- server.sin_addr = host;
- if ( bind( sockfd, (SA*) &server, sizeof(server) ) == -1 ) {
- SockAddress socket;
- fprintf( stderr, "bind(%s): %s\n",
- my_sock_ntoa(server,socket), strerror(errno) );
- close(sockfd);
- return -1;
- }
+ struct sockaddr_in server;
+ memset( &server, 0, sizeof(server) );
+ server.sin_family = AF_INET;
+ server.sin_port = port;
+ server.sin_addr = host;
+ if ( bind( sockfd, (SA*) &server, sizeof(server) ) == -1 ) {
+ SockAddress socket;
+ fprintf( stderr, "bind(%s): %s\n",
+ my_sock_ntoa(server,socket), strerror(errno) );
+ close(sockfd);
+ return -1;
+ }
- if ( listen( sockfd, backlog ) == -1 ) {
- perror( "listen" );
- close(sockfd);
- return -1;
- }
+ if ( listen( sockfd, backlog ) == -1 ) {
+ perror( "listen" );
+ close(sockfd);
+ return -1;
+ }
- return sockfd;
+ return sockfd;
}
+