version 1.72, 2005/08/19 00:24:32
|
version 1.82, 2006/06/26 22:23:29
|
|
|
//%2005//////////////////////////////////////////////////////////////////////// |
//%2006//////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development | // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. | // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
|
|
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. | // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; | // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
// EMC Corporation; VERITAS Software Corporation; The Open Group. | // EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy | // Permission is hereby granted, free of charge, to any person obtaining a copy |
// of this software and associated documentation files (the "Software"), to | // of this software and associated documentation files (the "Software"), to |
|
|
// Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) | // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
// Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com) | // Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com) |
// Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2065 | // Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2065 |
// David Dillard, VERITAS Software Corp. |
// David Dillard, Symantec Corp. (david_dillard@symantec.com) |
// (david.dillard@veritas.com) |
|
// John Alex, IBM (johnalex@us.ibm.com) for Bug#3312 | // John Alex, IBM (johnalex@us.ibm.com) for Bug#3312 |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
|
|
#include "Config.h" | #include "Config.h" |
#include "Constants.h" | #include "Constants.h" |
#include <iostream> | #include <iostream> |
#include "Socket.h" |
|
|
|
#ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC |
|
#include <windows.h> |
|
#else |
|
# include <cctype> |
|
# include <cstdlib> |
|
# include <errno.h> |
|
# include <fcntl.h> |
|
# include <netdb.h> |
|
# include <netinet/in.h> |
|
# include <arpa/inet.h> |
|
# include <sys/socket.h> |
|
# ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET |
|
# include <unistd.h> |
|
# include <sys/un.h> |
|
# endif |
|
#endif |
|
| |
|
#include "Network.h" |
#include "Socket.h" | #include "Socket.h" |
#include "TLS.h" | #include "TLS.h" |
#include "HTTPAcceptor.h" | #include "HTTPAcceptor.h" |
|
|
#include "OS400ConvertChar.h" | #include "OS400ConvertChar.h" |
#endif | #endif |
| |
|
|
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
| |
// |
|
// Determine the correct type to use for the length passed to getsockname(). |
|
// The default is to use the 'socklen_t'. |
|
// |
|
|
|
#if defined(PEGASUS_OS_TYPE_WINDOWS) || defined(PEGASUS_OS_OS400) |
|
#define PEGASUS_SOCKLEN_T int |
|
#endif |
|
|
|
#if defined(PEGASUS_OS_HPUX) && !defined(_XOPEN_SOURCE_EXTENDED) |
|
#define PEGASUS_SOCKLEN_T int |
|
#endif |
|
|
|
|
|
#if defined(PEGASUS_OS_VMS) || defined(PEGASUS_OS_ZOS) |
|
#define PEGASUS_SOCKLEN_T unsigned |
|
#endif |
|
|
|
#ifndef PEGASUS_SOCKLEN_T |
|
#define PEGASUS_SOCKLEN_T socklen_t |
|
#endif |
|
|
|
static int MAX_CONNECTION_QUEUE_LENGTH = -1; | static int MAX_CONNECTION_QUEUE_LENGTH = -1; |
| |
|
|
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// | // |
// HTTPAcceptorRep | // HTTPAcceptorRep |
|
|
} | } |
struct sockaddr* address; | struct sockaddr* address; |
| |
#if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined(PEGASUS_OS_VMS) |
|
size_t address_size; |
|
#elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC) && !defined(SUNOS_5_6)) |
|
socklen_t address_size; | socklen_t address_size; |
#else |
|
int address_size; |
|
#endif |
|
Mutex _connection_mut; | Mutex _connection_mut; |
| |
Sint32 socket; |
SocketHandle socket; |
Array<HTTPConnection*> connections; | Array<HTTPConnection*> connections; |
}; | }; |
| |
|
//------------------------------------------------------------------------------ |
|
// |
|
// _setTCPNoDelay() |
|
// |
|
//------------------------------------------------------------------------------ |
|
|
|
inline void _setTCPNoDelay(SocketHandle socket) |
|
{ |
|
// This function disables "Nagle's Algorithm" also known as "the TCP delay |
|
// algorithm", which causes read operations to obtain whatever data is |
|
// already in the input queue and then wait a little longer to see if |
|
// more data arrives. This algorithm optimizes the case in which data is |
|
// sent in only one direction but severely impairs performance of round |
|
// trip servers. Disabling TCP delay is a standard technique for round |
|
// trip servers. |
|
|
|
int opt = 1; |
|
setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt)); |
|
} |
|
|
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// | // |
// HTTPAcceptor | // HTTPAcceptor |
|
|
for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) | for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) |
{ | { |
HTTPConnection* connection = _rep->connections[i]; | HTTPConnection* connection = _rep->connections[i]; |
Sint32 socket = connection->getSocket(); |
SocketHandle socket = connection->getSocket(); |
| |
if (socket == closeConnectionMessage->socket) | if (socket == closeConnectionMessage->socket) |
{ | { |
|
|
else | else |
{ | { |
_rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); | _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); |
|
|
|
_setTCPNoDelay(_rep->socket); |
} | } |
| |
if (_rep->socket < 0) | if (_rep->socket < 0) |
|
|
| |
// set the close-on-exec bit for this file handle. | // set the close-on-exec bit for this file handle. |
// any unix that forks needs this bit set. | // any unix that forks needs this bit set. |
#if !defined PEGASUS_PLATFORM_WIN32_IX86_MSVC && !defined(PEGASUS_OS_VMS) |
#if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS) |
int sock_flags; | int sock_flags; |
if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0) | if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0) |
{ | { |
|
|
if ( _portNumber == 0 ) | if ( _portNumber == 0 ) |
{ | { |
sockaddr_in buf; | sockaddr_in buf; |
PEGASUS_SOCKLEN_T bufSize = sizeof(buf); |
socklen_t bufSize = sizeof(buf); |
if ( getsockname(_rep->socket, reinterpret_cast<sockaddr *>(&buf), &bufSize) == 0 ) | if ( getsockname(_rep->socket, reinterpret_cast<sockaddr *>(&buf), &bufSize) == 0 ) |
{ | { |
_portNumber = ntohs(buf.sin_port); | _portNumber = ntohs(buf.sin_port); |
|
|
for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) | for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) |
{ | { |
HTTPConnection* connection = _rep->connections[i]; | HTTPConnection* connection = _rep->connections[i]; |
Sint32 socket = connection->getSocket(); |
SocketHandle socket = connection->getSocket(); |
| |
// Unsolicit SocketMessages: | // Unsolicit SocketMessages: |
| |
|
|
| |
// Destroy the connection (causing it to close): | // Destroy the connection (causing it to close): |
| |
while (connection->refcount.value()) { } |
while (connection->refcount.get()) { } |
delete connection; | delete connection; |
} | } |
| |
|
|
// Accept the connection (populate the address): | // Accept the connection (populate the address): |
| |
struct sockaddr* accept_address; | struct sockaddr* accept_address; |
#if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined(PEGASUS_OS_VMS) |
|
size_t address_size; |
|
#elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_OS_SOLARIS) && !defined(SUNOS_5_6)) |
|
socklen_t address_size; | socklen_t address_size; |
#else |
|
int address_size; |
|
#endif |
|
| |
if (_localConnection) | if (_localConnection) |
{ | { |
|
|
address_size = sizeof(struct sockaddr_in); | address_size = sizeof(struct sockaddr_in); |
} | } |
| |
Sint32 socket = accept(_rep->socket, accept_address, &address_size); |
SocketHandle socket = accept(_rep->socket, accept_address, &address_size); |
| |
delete accept_address; | delete accept_address; |
| |
|
|
} | } |
| |
// set the close on exec flag | // set the close on exec flag |
#if !defined PEGASUS_PLATFORM_WIN32_IX86_MSVC && !defined(PEGASUS_OS_VMS) |
#if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS) |
int sock_flags; | int sock_flags; |
if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0) | if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0) |
{ | { |
|
|
#endif | #endif |
| |
| |
Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE, |
PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0, |
"HTTPAcceptor - accept() success. Socket: $1" |
"HTTPAcceptor - accept() success. Socket: $1" ,socket)); |
,socket); |
|
| |
AutoPtr<MP_Socket> mp_socket(new MP_Socket( | AutoPtr<MP_Socket> mp_socket(new MP_Socket( |
socket, _sslcontext, _sslContextObjectLock, _exportConnection)); | socket, _sslcontext, _sslContextObjectLock, _exportConnection)); |