summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorkumpf <kumpf>2005-08-19 00:24:32 +0000
committerkumpf <kumpf>2005-08-19 00:24:32 +0000
commit2e5d48f220d45a1d1186dad53b36ba56cb9d8210 (patch)
treeca8ca6edd9477d28d5bcddc351b6dc81fc971932 /src
parent0ada80d3bf1bd9a5e9b646f8ea8078fd3596911f (diff)
downloadtog-pegasus-2e5d48f220d45a1d1186dad53b36ba56cb9d8210.zip
tog-pegasus-2e5d48f220d45a1d1186dad53b36ba56cb9d8210.tar.gz
tog-pegasus-2e5d48f220d45a1d1186dad53b36ba56cb9d8210.tar.xz
BUG#: 4115
TITLE: HTTPConnection _handleReadEvent should complete connection setup DESCRIPTION: Finish connection setup in the HTTPConnection::_handleReadEvent method, when necessary. Also move the SSLContext mutex locking responsibility to the SSLSocket class, which contains the protected logic.
Diffstat (limited to 'src')
-rw-r--r--src/Pegasus/Common/HTTPAcceptor.cpp36
-rw-r--r--src/Pegasus/Common/HTTPConnection.cpp44
-rw-r--r--src/Pegasus/Common/HTTPConnection.h5
-rw-r--r--src/Pegasus/Common/HTTPConnector.cpp2
-rw-r--r--src/Pegasus/Common/TLS.cpp40
-rw-r--r--src/Pegasus/Common/TLS.h23
6 files changed, 117 insertions, 33 deletions
diff --git a/src/Pegasus/Common/HTTPAcceptor.cpp b/src/Pegasus/Common/HTTPAcceptor.cpp
index 2ad52cb..7d97a69 100644
--- a/src/Pegasus/Common/HTTPAcceptor.cpp
+++ b/src/Pegasus/Common/HTTPAcceptor.cpp
@@ -734,27 +734,18 @@ void HTTPAcceptor::_acceptConnection()
"HTTPAcceptor - accept() success. Socket: $1"
,socket);
- // Create a new conection and add it to the connection list:
+ AutoPtr<MP_Socket> mp_socket(new MP_Socket(
+ socket, _sslcontext, _sslContextObjectLock, _exportConnection));
- AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, _sslcontext, _exportConnection));
+ // Perform the SSL handshake, if applicable. Make the socket non-blocking
+ // for this operation so we can send it back to the Monitor's select() loop
+ // if it takes a while.
- Sint32 retVal;
+ mp_socket->disableBlocking();
+ Sint32 socketAcceptStatus = mp_socket->accept();
+ mp_socket->enableBlocking();
- if (_sslcontext)
- {
- //
- // For SSL connections, obtain read lock to SSLContext object before
- // calling the accept() method of MP_Socket.
- //
- ReadLock rlock(*_sslContextObjectLock);
- retVal = mp_socket->accept();
- }
- else
- {
- retVal = mp_socket->accept();
- }
-
- if (retVal < 0)
+ if (socketAcceptStatus < 0)
{
PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
"HTTPAcceptor: SSL_accept() failed");
@@ -762,9 +753,18 @@ void HTTPAcceptor::_acceptConnection()
return;
}
+ // Create a new connection and add it to the connection list:
+
HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
+ if (socketAcceptStatus == 0)
+ {
+ PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
+ "HTTPAcceptor: SSL_accept() pending");
+ connection->_acceptPending = true;
+ }
+
// Solicit events on this new connection's socket:
int index;
diff --git a/src/Pegasus/Common/HTTPConnection.cpp b/src/Pegasus/Common/HTTPConnection.cpp
index eb8b5ad..c27c2bb 100644
--- a/src/Pegasus/Common/HTTPConnection.cpp
+++ b/src/Pegasus/Common/HTTPConnection.cpp
@@ -226,7 +226,8 @@ HTTPConnection::HTTPConnection(
_outputMessageQueue(outputMessageQueue),
_contentOffset(-1),
_contentLength(-1),
- _connectionClosePending(false)
+ _connectionClosePending(false),
+ _acceptPending(false)
{
PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnection::HTTPConnection");
@@ -1643,6 +1644,47 @@ void HTTPConnection::_handleReadEvent()
static const char func[] = "HTTPConnection::_handleReadEvent()";
PEG_METHOD_ENTER(TRC_HTTP, func);
+ if (_acceptPending)
+ {
+ PEGASUS_ASSERT(!_isClient());
+
+ Sint32 socketAcceptStatus = _socket->accept();
+
+ if (socketAcceptStatus < 0)
+ {
+ PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
+ "HTTPConnection: SSL_accept() failed");
+ _closeConnection();
+ PEG_METHOD_EXIT();
+ return;
+ }
+ else if (socketAcceptStatus == 0)
+ {
+ // Not enough data yet to complete the SSL handshake
+ PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
+ "HTTPConnection: SSL_accept() pending");
+ PEG_METHOD_EXIT();
+ return;
+ }
+ else
+ {
+ // Add SSL verification information to the authentication info
+ if (_socket->isSecure() &&
+ _socket->isPeerVerificationEnabled() &&
+ _socket->isCertificateVerified())
+ {
+ _authInfo->setAuthStatus(AuthenticationInfoRep::AUTHENTICATED);
+ _authInfo->setAuthType(AuthenticationInfoRep::AUTH_TYPE_SSL);
+ _authInfo->setClientCertificate(_socket->getPeerCertificate());
+ }
+
+ // Go back to the select() and wait for data on the connection
+ _acceptPending = false;
+ PEG_METHOD_EXIT();
+ return;
+ }
+ }
+
// -- Append all data waiting on socket to incoming buffer:
String httpStatus;
diff --git a/src/Pegasus/Common/HTTPConnection.h b/src/Pegasus/Common/HTTPConnection.h
index a27ca3a..9197d8a 100644
--- a/src/Pegasus/Common/HTTPConnection.h
+++ b/src/Pegasus/Common/HTTPConnection.h
@@ -201,6 +201,11 @@ private:
// returning control of the connection to the Monitor.
Boolean _connectionClosePending;
+ // The _acceptPending flag is set to true if a server-side
+ // connection is accepted but an SSL handshake has not been
+ // completed.
+ Boolean _acceptPending;
+
int _entry_index;
// When used by the client, it is an offset (from start of http message)
diff --git a/src/Pegasus/Common/HTTPConnector.cpp b/src/Pegasus/Common/HTTPConnector.cpp
index fb93b45..bee79fd 100644
--- a/src/Pegasus/Common/HTTPConnector.cpp
+++ b/src/Pegasus/Common/HTTPConnector.cpp
@@ -350,7 +350,7 @@ HTTPConnection* HTTPConnector::connect(
// Create HTTPConnection object:
- AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, sslContext, false));
+ AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, sslContext, 0, false));
if (mp_socket->connect() < 0) {
char portStr [32];
sprintf (portStr, "%u", portNumber);
diff --git a/src/Pegasus/Common/TLS.cpp b/src/Pegasus/Common/TLS.cpp
index 2f310f9..be1f703 100644
--- a/src/Pegasus/Common/TLS.cpp
+++ b/src/Pegasus/Common/TLS.cpp
@@ -59,11 +59,16 @@ PEGASUS_NAMESPACE_BEGIN
// Basic SSL socket
//
-SSLSocket::SSLSocket(Sint32 socket, SSLContext * sslcontext, Boolean exportConnection)
+SSLSocket::SSLSocket(
+ Sint32 socket,
+ SSLContext * sslcontext,
+ ReadWriteSem * sslContextObjectLock,
+ Boolean exportConnection)
:
_SSLConnection(0),
_socket(socket),
_SSLContext(sslcontext),
+ _sslContextObjectLock(sslContextObjectLock),
_SSLCallbackInfo(0),
_certificateVerified(false),
_exportConnection(exportConnection)
@@ -213,7 +218,9 @@ Sint32 SSLSocket::accept()
//SSL_do_handshake(_SSLConnection);
//SSL_set_accept_state(_SSLConnection);
-redo_accept:
+ // Make sure the SSLContext object is not updated during this operation.
+ ReadLock rlock(*_sslContextObjectLock);
+
ssl_rc = SSL_accept(_SSLConnection);
if (ssl_rc < 0)
@@ -224,7 +231,8 @@ redo_accept:
if ((ssl_rsn == SSL_ERROR_WANT_READ) ||
(ssl_rsn == SSL_ERROR_WANT_WRITE))
{
- goto redo_accept;
+ PEG_METHOD_EXIT();
+ return 0;
}
else
{
@@ -314,7 +322,7 @@ redo_accept:
}
PEG_METHOD_EXIT();
- return ssl_rc;
+ return 1;
}
Sint32 SSLSocket::connect()
@@ -426,13 +434,18 @@ Boolean SSLSocket::isCertificateVerified()
MP_Socket::MP_Socket(Uint32 socket)
: _socket(socket), _isSecure(false) {}
-MP_Socket::MP_Socket(Uint32 socket, SSLContext * sslcontext, Boolean exportConnection)
+MP_Socket::MP_Socket(
+ Uint32 socket,
+ SSLContext * sslcontext,
+ ReadWriteSem * sslContextObjectLock,
+ Boolean exportConnection)
{
PEG_METHOD_ENTER(TRC_SSL, "MP_Socket::MP_Socket()");
if (sslcontext != NULL)
{
_isSecure = true;
- _sslsock = new SSLSocket(socket, sslcontext, exportConnection);
+ _sslsock = new SSLSocket(
+ socket, sslcontext, sslContextObjectLock, exportConnection);
}
else
{
@@ -524,8 +537,10 @@ void MP_Socket::disableBlocking()
Sint32 MP_Socket::accept()
{
if (_isSecure)
- if (_sslsock->accept() < 0) return -1;
- return 0;
+ {
+ return (_sslsock->accept());
+ }
+ return 1;
}
Sint32 MP_Socket::connect()
@@ -572,8 +587,11 @@ PEGASUS_NAMESPACE_BEGIN
MP_Socket::MP_Socket(Uint32 socket)
: _socket(socket), _isSecure(false) {}
-MP_Socket::MP_Socket(Uint32 socket, SSLContext * sslcontext,
- Boolean exportConnection)
+MP_Socket::MP_Socket(
+ Uint32 socket,
+ SSLContext * sslcontext,
+ ReadWriteSem * sslContextObjectLock,
+ Boolean exportConnection)
: _socket(socket), _isSecure(false) {}
MP_Socket::~MP_Socket() {}
@@ -615,7 +633,7 @@ void MP_Socket::disableBlocking()
Socket::disableBlocking(_socket);
}
-Sint32 MP_Socket::accept() { return 0; }
+Sint32 MP_Socket::accept() { return 1; }
Sint32 MP_Socket::connect() { return 0; }
diff --git a/src/Pegasus/Common/TLS.h b/src/Pegasus/Common/TLS.h
index bc350ba..ad78855 100644
--- a/src/Pegasus/Common/TLS.h
+++ b/src/Pegasus/Common/TLS.h
@@ -71,7 +71,10 @@ class PEGASUS_COMMON_LINKAGE SSLSocket
{
public:
- SSLSocket(Sint32 socket, SSLContext * sslcontext,
+ SSLSocket(
+ Sint32 socket,
+ SSLContext * sslcontext,
+ ReadWriteSem * sslContextObjectLock,
Boolean exportConnection = false);
~SSLSocket();
@@ -94,6 +97,12 @@ public:
Sint32 getSocket() {return _socket;}
+ /**
+ Accepts the connection, performing the necessary SSL handshake.
+
+ @return Returns -1 on failure, 0 if not enough data is available to
+ complete the operation (retry needed), and 1 on success.
+ */
Sint32 accept();
Sint32 connect();
@@ -109,6 +118,7 @@ private:
SSL * _SSLConnection;
Sint32 _socket;
SSLContext * _SSLContext;
+ ReadWriteSem * _sslContextObjectLock;
AutoPtr<SSLCallbackInfo> _SSLCallbackInfo;
Boolean _certificateVerified;
@@ -131,7 +141,10 @@ class MP_Socket {
public:
MP_Socket(Uint32 socket); // "normal" socket
- MP_Socket(Uint32 socket, SSLContext * sslcontext,
+ MP_Socket(
+ Uint32 socket,
+ SSLContext * sslcontext,
+ ReadWriteSem * sslContextObjectLock,
Boolean exportConnection = false); // secure socket
~MP_Socket();
@@ -152,6 +165,12 @@ public:
void disableBlocking();
+ /**
+ Accepts the connection, performing an SSL handshake if applicable.
+
+ @return Returns -1 on failure, 0 if not enough data is available to
+ complete the operation (retry needed), and 1 on success.
+ */
Sint32 accept();
Sint32 connect();