summaryrefslogtreecommitdiff
path: root/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceSSL/OpenSSLTransceiverI.cpp')
-rw-r--r--cpp/src/IceSSL/OpenSSLTransceiverI.cpp356
1 files changed, 25 insertions, 331 deletions
diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
index 8df471c87eb..22f2412a845 100644
--- a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
+++ b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
@@ -68,98 +68,24 @@ Init init;
IceInternal::NativeInfoPtr
IceSSL::TransceiverI::getNativeInfo()
{
- return this;
+ return _stream;
}
IceInternal::SocketOperation
IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer, bool&)
{
- if(_state == StateNeedConnect)
+ IceInternal::SocketOperation status = _stream->connect(readBuffer, writeBuffer);
+ if(status != IceInternal::SocketOperationNone)
{
- _state = StateConnectPending;
- return IceInternal::SocketOperationConnect;
+ return status;
}
- else if(_state <= StateConnectPending)
- {
- IceInternal::doFinishConnect(_fd);
-
- _desc = IceInternal::fdToString(_fd, _proxy, _addr, true);
-
- if(_proxy)
- {
- //
- // Prepare the read & write buffers in advance.
- //
- _proxy->beginWriteConnectRequest(_addr, writeBuffer);
- _proxy->beginReadConnectRequestResponse(readBuffer);
-
- //
- // Write the proxy connection message using TCP.
- //
- if(writeRaw(writeBuffer))
- {
- //
- // Write completed without blocking.
- //
- _proxy->endWriteConnectRequest(writeBuffer);
-
- //
- // Try to read the response using TCP.
- //
- if(readRaw(readBuffer))
- {
- //
- // Read completed without blocking - fall through.
- //
- _proxy->endReadConnectRequestResponse(readBuffer);
- }
- else
- {
- //
- // Return SocketOperationRead to indicate we need to complete the read.
- //
- _state = StateProxyConnectRequestPending; // Wait for proxy response
- return IceInternal::SocketOperationRead;
- }
- }
- else
- {
- //
- // Return SocketOperationWrite to indicate we need to complete the write.
- //
- _state = StateProxyConnectRequest; // Send proxy connect request
- return IceInternal::SocketOperationWrite;
- }
- }
-
- _state = StateConnected;
- }
- else if(_state == StateProxyConnectRequest)
- {
- //
- // Write completed.
- //
- _proxy->endWriteConnectRequest(writeBuffer);
- _state = StateProxyConnectRequestPending; // Wait for proxy response
- return IceInternal::SocketOperationRead;
- }
- else if(_state == StateProxyConnectRequestPending)
- {
- //
- // Read completed.
- //
- _proxy->endReadConnectRequestResponse(readBuffer);
- _state = StateConnected;
- }
-
- assert(_state == StateConnected);
if(!_ssl)
{
//
// This static_cast is necessary due to 64bit windows. There SOCKET is a non-int type.
//
- BIO* bio = BIO_new_socket(static_cast<int>(_fd), 0);
+ BIO* bio = BIO_new_socket(static_cast<int>(_stream->fd()), 0);
if(!bio)
{
SecurityException ex(__FILE__, __LINE__);
@@ -205,8 +131,10 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
switch(SSL_get_error(_ssl, ret))
{
case SSL_ERROR_NONE:
+ {
assert(SSL_is_init_finished(_ssl));
break;
+ }
case SSL_ERROR_ZERO_RETURN:
{
ConnectionLostException ex(__FILE__, __LINE__);
@@ -266,7 +194,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
{
IceInternal::Address remoteAddr;
string desc = "<not available>";
- if(IceInternal::fdToRemoteAddress(_fd, remoteAddr))
+ if(IceInternal::fdToRemoteAddress(_stream->fd(), remoteAddr))
{
desc = IceInternal::addrToString(remoteAddr);
}
@@ -308,8 +236,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
throw ex;
}
}
- _engine->verifyPeer(_fd, _host, getNativeConnectionInfo());
- _state = StateHandshakeComplete;
+ _engine->verifyPeer(_stream->fd(), _host, getNativeConnectionInfo());
if(_engine->securityTraceLevel() >= 1)
{
@@ -348,12 +275,6 @@ IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
void
IceSSL::TransceiverI::close()
{
- if(_state == StateHandshakeComplete && _instance->traceLevel() >= 1)
- {
- Trace out(_instance->logger(), _instance->traceCategory());
- out << "closing " << _instance->protocol() << " connection\n" << toString();
- }
-
if(_ssl)
{
int err = SSL_shutdown(_ssl);
@@ -370,28 +291,15 @@ IceSSL::TransceiverI::close()
_ssl = 0;
}
- assert(_fd != INVALID_SOCKET);
- try
- {
- IceInternal::closeSocket(_fd);
- _fd = INVALID_SOCKET;
- }
- catch(const SocketException&)
- {
- _fd = INVALID_SOCKET;
- throw;
- }
+ _stream->close();
}
IceInternal::SocketOperation
IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
{
- if(_state == StateProxyConnectRequest)
+ if(!_stream->isConnected())
{
- //
- // We need to write the proxy message, but we have to use TCP and not SSL.
- //
- return writeRaw(buf) ? IceInternal::SocketOperationNone : IceInternal::SocketOperationWrite;
+ return _stream->write(buf);
}
if(buf.i == buf.b.end())
@@ -406,8 +314,6 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
while(buf.i != buf.b.end())
{
ERR_clear_error(); // Clear any spurious errors.
- assert(_fd != INVALID_SOCKET);
-
int ret = SSL_write(_ssl, reinterpret_cast<const void*>(&*buf.i), packetSize);
if(ret <= 0)
{
@@ -479,12 +385,6 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
}
}
- if(_instance->traceLevel() >= 3)
- {
- Trace out(_instance->logger(), _instance->traceCategory());
- out << "sent " << ret << " of " << packetSize << " bytes via " << protocol() << "\n" << toString();
- }
-
buf.i += ret;
if(packetSize > buf.b.end() - buf.i)
@@ -499,6 +399,11 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
IceInternal::SocketOperation
IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool&)
{
+ if(!_stream->isConnected())
+ {
+ return _stream->read(buf);
+ }
+
//
// Note: we don't set the hasMoreData flag in this implementation.
// We assume that OpenSSL doesn't read more SSL records than
@@ -506,14 +411,6 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool&)
// Ice messages in individual SSL records.
//
- if(_state == StateProxyConnectRequestPending)
- {
- //
- // We need to read the proxy reply, but we have to use TCP and not SSL.
- //
- return readRaw(buf) ? IceInternal::SocketOperationNone : IceInternal::SocketOperationRead;
- }
-
if(buf.i == buf.b.end())
{
return IceInternal::SocketOperationNone;
@@ -526,7 +423,6 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool&)
while(buf.i != buf.b.end())
{
ERR_clear_error(); // Clear any spurious errors.
- assert(_fd != INVALID_SOCKET);
int ret = SSL_read(_ssl, reinterpret_cast<void*>(&*buf.i), packetSize);
if(ret <= 0)
{
@@ -539,17 +435,6 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool&)
}
case SSL_ERROR_ZERO_RETURN:
{
- //
- // If the connection is lost when reading data, we shut
- // down the write end of the socket. This helps to unblock
- // threads that are stuck in send() or select() while
- // sending data. Note: I don't really understand why
- // send() or select() sometimes don't detect a connection
- // loss. Therefore this helper to make them detect it.
- //
- //assert(_fd != INVALID_SOCKET);
- //shutdownSocketReadWrite(_fd);
-
ConnectionLostException ex(__FILE__, __LINE__);
ex.error = 0;
throw ex;
@@ -586,14 +471,6 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool&)
if(IceInternal::connectionLost())
{
- //
- // See the commment above about shutting down the
- // socket if the connection is lost while reading
- // data.
- //
- //assert(_fd != INVALID_SOCKET);
- //shutdownSocketReadWrite(_fd);
-
ConnectionLostException ex(__FILE__, __LINE__);
ex.error = IceInternal::getSocketErrno();
throw ex;
@@ -644,12 +521,6 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool&)
}
}
- if(_instance->traceLevel() >= 3)
- {
- Trace out(_instance->logger(), _instance->traceCategory());
- out << "received " << ret << " of " << packetSize << " bytes via " << protocol() << "\n" << toString();
- }
-
buf.i += ret;
if(packetSize > buf.b.end() - buf.i)
@@ -670,7 +541,7 @@ IceSSL::TransceiverI::protocol() const
string
IceSSL::TransceiverI::toString() const
{
- return _desc;
+ return _stream->toString();
}
string
@@ -694,64 +565,28 @@ IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer& buf, size_t messa
}
}
-IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, SOCKET fd, const IceInternal::NetworkProxyPtr& proxy,
- const string& host, const IceInternal::Address& addr,
- const IceInternal::Address& sourceAddr) :
- IceInternal::NativeInfo(fd),
+IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, const IceInternal::StreamSocketPtr& stream,
+ const string& host, const std::string& adapterName) :
_instance(instance),
_engine(OpenSSLEnginePtr::dynamicCast(instance->engine())),
- _proxy(proxy),
_host(host),
- _addr(addr),
- _sourceAddr(sourceAddr),
- _incoming(false),
- _ssl(0),
- _state(StateNeedConnect)
-{
- IceInternal::setBlock(fd, false);
- IceInternal::setTcpBufSize(fd, _instance->properties(), _instance->logger());
-
- IceInternal::Address connectAddr = proxy ? proxy->getAddress() : addr;
- if(IceInternal::doConnect(_fd, connectAddr, _sourceAddr))
- {
- _state = StateConnected;
- _desc = IceInternal::fdToString(_fd, _proxy, _addr, true);
- if(_instance->traceLevel() >= 1)
- {
- Trace out(_instance->logger(), _instance->traceCategory());
- out << _instance->protocol() << " connection established\n" << _desc;
- }
- }
- else
- {
- _desc = IceInternal::fdToString(_fd, _proxy, _addr, true);
- }
-}
-
-IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, SOCKET fd, const string& adapterName) :
- IceInternal::NativeInfo(fd),
- _instance(instance),
- _engine(OpenSSLEnginePtr::dynamicCast(instance->engine())),
_adapterName(adapterName),
- _incoming(true),
- _ssl(0),
- _state(StateConnected),
- _desc(IceInternal::fdToString(fd))
+ _incoming(_host.empty()),
+ _stream(stream),
+ _ssl(0)
{
- IceInternal::setBlock(fd, false);
- IceInternal::setTcpBufSize(fd, _instance->properties(), _instance->logger());
}
IceSSL::TransceiverI::~TransceiverI()
{
- assert(_fd == INVALID_SOCKET);
}
NativeConnectionInfoPtr
IceSSL::TransceiverI::getNativeConnectionInfo() const
{
NativeConnectionInfoPtr info = new NativeConnectionInfo();
- IceInternal::fdToAddressAndPort(_fd, info->localAddress, info->localPort, info->remoteAddress, info->remotePort);
+ IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress,
+ info->remotePort);
if(_ssl != 0)
{
@@ -797,145 +632,4 @@ IceSSL::TransceiverI::getNativeConnectionInfo() const
return info;
}
-bool
-IceSSL::TransceiverI::writeRaw(IceInternal::Buffer& buf)
-{
- //
- // It's impossible for packetSize to be more than an Int.
- //
- int packetSize = static_cast<int>(buf.b.end() - buf.i);
-#ifdef ICE_USE_IOCP
- //
- // Limit packet size to avoid performance problems on WIN32
- //
- if(_maxSendPacketSize > 0 && packetSize > _maxSendPacketSize)
- {
- packetSize = _maxSendPacketSize;
- }
-#endif
- while(buf.i != buf.b.end())
- {
- assert(_fd != INVALID_SOCKET);
-
- ssize_t ret = ::send(_fd, reinterpret_cast<const char*>(&*buf.i), packetSize, 0);
- if(ret == 0)
- {
- ConnectionLostException ex(__FILE__, __LINE__);
- ex.error = 0;
- throw ex;
- }
-
- if(ret == SOCKET_ERROR)
- {
- if(IceInternal::interrupted())
- {
- continue;
- }
-
- if(IceInternal::noBuffers() && packetSize > 1024)
- {
- packetSize /= 2;
- continue;
- }
-
- if(IceInternal::wouldBlock())
- {
- return false;
- }
-
- if(IceInternal::connectionLost())
- {
- ConnectionLostException ex(__FILE__, __LINE__);
- ex.error = IceInternal::getSocketErrno();
- throw ex;
- }
- else
- {
- SocketException ex(__FILE__, __LINE__);
- ex.error = IceInternal::getSocketErrno();
- throw ex;
- }
- }
-
- if(_instance->traceLevel() >= 3)
- {
- Trace out(_instance->logger(), _instance->traceCategory());
- out << "sent " << ret << " of " << packetSize << " bytes via " << protocol() << "\n" << toString();
- }
-
- buf.i += ret;
-
- if(packetSize > buf.b.end() - buf.i)
- {
- packetSize = static_cast<int>(buf.b.end() - buf.i);
- }
- }
-
- return true;
-}
-
-bool
-IceSSL::TransceiverI::readRaw(IceInternal::Buffer& buf)
-{
- //
- // It's impossible for packetSize to be more than an Int.
- //
- int packetSize = static_cast<int>(buf.b.end() - buf.i);
- while(buf.i != buf.b.end())
- {
- assert(_fd != INVALID_SOCKET);
- ssize_t ret = ::recv(_fd, reinterpret_cast<char*>(&*buf.i), packetSize, 0);
-
- if(ret == 0)
- {
- ConnectionLostException ex(__FILE__, __LINE__);
- ex.error = 0;
- throw ex;
- }
-
- if(ret == SOCKET_ERROR)
- {
- if(IceInternal::interrupted())
- {
- continue;
- }
-
- if(IceInternal::noBuffers() && packetSize > 1024)
- {
- packetSize /= 2;
- continue;
- }
-
- if(IceInternal::wouldBlock())
- {
- return false;
- }
-
- if(IceInternal::connectionLost())
- {
- ConnectionLostException ex(__FILE__, __LINE__);
- ex.error = IceInternal::getSocketErrno();
- throw ex;
- }
- else
- {
- SocketException ex(__FILE__, __LINE__);
- ex.error = IceInternal::getSocketErrno();
- throw ex;
- }
- }
-
- if(_instance->traceLevel() >= 3)
- {
- Trace out(_instance->logger(), _instance->traceCategory());
- out << "received " << ret << " of " << packetSize << " bytes via " << protocol() << "\n" << toString();
- }
-
- buf.i += ret;
-
- packetSize = static_cast<int>(buf.b.end() - buf.i);
- }
-
- return true;
-}
#endif