diff options
author | Dwayne Boone <dwayne@zeroc.com> | 2005-06-20 16:43:38 +0000 |
---|---|---|
committer | Dwayne Boone <dwayne@zeroc.com> | 2005-06-20 16:43:38 +0000 |
commit | 8b0d67e9ad16a3b6bdfff6d9900ea009442249a0 (patch) | |
tree | d1cfce0274d58c377392d56f64d57b10d8a1c8fb /cppe/src | |
parent | Improved fix for bug #377 (diff) | |
download | ice-8b0d67e9ad16a3b6bdfff6d9900ea009442249a0.tar.bz2 ice-8b0d67e9ad16a3b6bdfff6d9900ea009442249a0.tar.xz ice-8b0d67e9ad16a3b6bdfff6d9900ea009442249a0.zip |
Separated TCP into separate transport library
Diffstat (limited to 'cppe/src')
-rw-r--r-- | cppe/src/Makefile | 3 | ||||
-rw-r--r-- | cppe/src/TcpTransport/.depend | 5 | ||||
-rw-r--r-- | cppe/src/TcpTransport/Acceptor.cpp | 142 | ||||
-rw-r--r-- | cppe/src/TcpTransport/Connector.cpp | 63 | ||||
-rw-r--r-- | cppe/src/TcpTransport/Endpoint.cpp | 377 | ||||
-rw-r--r-- | cppe/src/TcpTransport/EndpointFactory.cpp | 82 | ||||
-rw-r--r-- | cppe/src/TcpTransport/Makefile | 53 | ||||
-rw-r--r-- | cppe/src/TcpTransport/Transceiver.cpp | 469 |
8 files changed, 1193 insertions, 1 deletions
diff --git a/cppe/src/Makefile b/cppe/src/Makefile index 5975862445e..4c1a7c1b216 100644 --- a/cppe/src/Makefile +++ b/cppe/src/Makefile @@ -11,7 +11,8 @@ top_srcdir = .. include $(top_srcdir)/config/Make.rules -SUBDIRS = Ice +SUBDIRS = Ice \ + TcpTransport $(EVERYTHING):: @for subdir in $(SUBDIRS); \ diff --git a/cppe/src/TcpTransport/.depend b/cppe/src/TcpTransport/.depend new file mode 100644 index 00000000000..11c5c9215c1 --- /dev/null +++ b/cppe/src/TcpTransport/.depend @@ -0,0 +1,5 @@ +Acceptor.o: Acceptor.cpp ../../include/Ice/Acceptor.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/Ice/TransceiverF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/Ice/Config.h ../../include/Ice/InstanceF.h ../Ice/TraceLevelsF.h ../../include/Ice/LoggerF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/Ice/UndefSysMacros.h ../../include/Ice/AcceptorF.h ../../include/Ice/Transceiver.h ../Ice/Instance.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/RecMutex.h ../../include/Ice/CommunicatorF.h ../../include/Ice/PropertiesF.h ../Ice/DefaultsAndOverridesF.h ../Ice/RouterInfoF.h ../Ice/LocatorInfoF.h ../Ice/ReferenceFactoryF.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionFactoryF.h ../../include/Ice/ObjectAdapterFactoryF.h ../../include/Ice/EndpointFactoryF.h ../Ice/TraceLevels.h ../../include/Ice/LoggerUtil.h ../Ice/Network.h +Connector.o: Connector.cpp ../../include/Ice/Connector.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/Ice/TransceiverF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/Ice/Config.h ../../include/Ice/InstanceF.h ../Ice/TraceLevelsF.h ../../include/Ice/LoggerF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/Ice/UndefSysMacros.h ../../include/Ice/ConnectorF.h ../../include/Ice/Transceiver.h ../Ice/Instance.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/RecMutex.h ../../include/Ice/CommunicatorF.h ../../include/Ice/PropertiesF.h ../Ice/DefaultsAndOverridesF.h ../Ice/RouterInfoF.h ../Ice/LocatorInfoF.h ../Ice/ReferenceFactoryF.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionFactoryF.h ../../include/Ice/ObjectAdapterFactoryF.h ../../include/Ice/EndpointFactoryF.h ../Ice/TraceLevels.h ../../include/Ice/LoggerUtil.h ../Ice/Network.h +EndpointFactory.o: EndpointFactory.cpp ../../include/Ice/EndpointFactory.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/Ice/EndpointF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/Ice/Config.h ../../include/Ice/InstanceF.h ../../include/Ice/EndpointFactoryF.h ../../include/Ice/Endpoint.h ../../include/Ice/AcceptorF.h ../../include/Ice/ConnectorF.h ../../include/Ice/TransceiverF.h ../../include/Ice/LocalException.h ../../include/Ice/LocalObjectF.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionIF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/UndefSysMacros.h ../../include/Ice/ReferenceF.h ../../include/Ice/Current.h ../../include/Ice/ConnectionF.h ../../include/Ice/Identity.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/BasicStream.h ../../include/Ice/Buffer.h +Endpoint.o: Endpoint.cpp ../../include/Ice/Endpoint.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/Ice/EndpointF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/Ice/Config.h ../../include/Ice/AcceptorF.h ../../include/Ice/ConnectorF.h ../../include/Ice/TransceiverF.h ../../include/Ice/InstanceF.h ../Ice/Network.h ../../include/Ice/Acceptor.h ../Ice/TraceLevelsF.h ../../include/Ice/LoggerF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/Ice/UndefSysMacros.h ../../include/Ice/Connector.h ../../include/Ice/Transceiver.h ../../include/Ice/BasicStream.h ../../include/Ice/Buffer.h ../../include/Ice/LocalException.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionIF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/Current.h ../../include/Ice/ConnectionF.h ../../include/Ice/Identity.h ../../include/Ice/BuiltinSequences.h ../Ice/Instance.h ../../include/IceUtil/RecMutex.h ../../include/Ice/CommunicatorF.h ../../include/Ice/PropertiesF.h ../Ice/DefaultsAndOverridesF.h ../Ice/RouterInfoF.h ../Ice/LocatorInfoF.h ../Ice/ReferenceFactoryF.h ../../include/Ice/ConnectionFactoryF.h ../../include/Ice/ObjectAdapterFactoryF.h ../../include/Ice/EndpointFactoryF.h ../Ice/DefaultsAndOverrides.h ../../include/IceUtil/SafeStdio.h +Transceiver.o: Transceiver.cpp ../../include/Ice/Transceiver.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/Ice/InstanceF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/Ice/Config.h ../Ice/TraceLevelsF.h ../../include/Ice/LoggerF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/Ice/UndefSysMacros.h ../../include/Ice/TransceiverF.h ../Ice/Instance.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/RecMutex.h ../../include/Ice/CommunicatorF.h ../../include/Ice/PropertiesF.h ../Ice/DefaultsAndOverridesF.h ../Ice/RouterInfoF.h ../Ice/LocatorInfoF.h ../Ice/ReferenceFactoryF.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionFactoryF.h ../../include/Ice/ObjectAdapterFactoryF.h ../../include/Ice/EndpointFactoryF.h ../Ice/TraceLevels.h ../../include/Ice/LoggerUtil.h ../../include/Ice/Buffer.h ../Ice/Network.h ../../include/Ice/LocalException.h ../../include/Ice/Proxy.h ../../include/Ice/ConnectionIF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/Current.h ../../include/Ice/ConnectionF.h ../../include/Ice/Identity.h ../../include/Ice/BuiltinSequences.h ../../include/IceUtil/SafeStdio.h diff --git a/cppe/src/TcpTransport/Acceptor.cpp b/cppe/src/TcpTransport/Acceptor.cpp new file mode 100644 index 00000000000..14725d5f774 --- /dev/null +++ b/cppe/src/TcpTransport/Acceptor.cpp @@ -0,0 +1,142 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Acceptor.h> +#include <Ice/Transceiver.h> +#include <Ice/Instance.h> +#include <Ice/TraceLevels.h> +#include <Ice/LoggerUtil.h> +#include <Ice/Network.h> +#include <Ice/Exception.h> + +using namespace std; +using namespace Ice; +using namespace IceInternal; + +void IceInternal::incRef(Acceptor* p) { p->__incRef(); } +void IceInternal::decRef(Acceptor* p) { p->__decRef(); } + +SOCKET +IceInternal::Acceptor::fd() +{ + return _fd; +} + +void +IceInternal::Acceptor::close() +{ + if(_traceLevels->network >= 1) + { + Trace out(_logger, _traceLevels->networkCat); + out << "stopping to accept tcp connections at " << toString(); + } + + SOCKET fd = _fd; + _fd = INVALID_SOCKET; + closeSocket(fd); +} + +void +IceInternal::Acceptor::listen() +{ + try + { + doListen(_fd, _backlog); + } + catch(...) + { + _fd = INVALID_SOCKET; + throw; + } + + if(_traceLevels->network >= 1) + { + Trace out(_logger, _traceLevels->networkCat); + out << "accepting tcp connections at " << toString(); + } +} + +TransceiverPtr +IceInternal::Acceptor::accept(int timeout) +{ + SOCKET fd = doAccept(_fd, timeout); + setBlock(fd, false); + + if(_traceLevels->network >= 1) + { + Trace out(_logger, _traceLevels->networkCat); + out << "accepted tcp connection\n" << fdToString(fd); + } + + return new Transceiver(_instance, fd); +} + +void +IceInternal::Acceptor::connectToSelf() +{ + SOCKET fd = createSocket(); + setBlock(fd, false); + doConnect(fd, _addr, -1); + closeSocket(fd); +} + +string +IceInternal::Acceptor::toString() const +{ + return addrToString(_addr); +} + +bool +IceInternal::Acceptor::equivalent(const string& host, int port) const +{ + struct sockaddr_in addr; + getAddress(host, port, addr); + return compareAddress(addr, _addr); +} + +int +IceInternal::Acceptor::effectivePort() +{ + return ntohs(_addr.sin_port); +} + +IceInternal::Acceptor::Acceptor(const InstancePtr& instance, const string& host, int port) : + _instance(instance), + _traceLevels(instance->traceLevels()), + _logger(instance->logger()), + _backlog(0) +{ + if(_backlog <= 0) + { + _backlog = 5; + } + + try + { + _fd = createSocket(); + setBlock(_fd, false); + getAddress(host, port, _addr); + if(_traceLevels->network >= 2) + { + Trace out(_logger, _traceLevels->networkCat); + out << "attempting to bind to tcp socket " << toString(); + } + doBind(_fd, _addr); + } + catch(...) + { + _fd = INVALID_SOCKET; + throw; + } +} + +IceInternal::Acceptor::~Acceptor() +{ + assert(_fd == INVALID_SOCKET); +} diff --git a/cppe/src/TcpTransport/Connector.cpp b/cppe/src/TcpTransport/Connector.cpp new file mode 100644 index 00000000000..cee89eb201e --- /dev/null +++ b/cppe/src/TcpTransport/Connector.cpp @@ -0,0 +1,63 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Connector.h> +#include <Ice/Transceiver.h> +#include <Ice/Instance.h> +#include <Ice/TraceLevels.h> +#include <Ice/LoggerUtil.h> +#include <Ice/Network.h> +#include <Ice/Exception.h> + +using namespace std; +using namespace Ice; +using namespace IceInternal; + +void IceInternal::incRef(Connector* p) { p->__incRef(); } +void IceInternal::decRef(Connector* p) { p->__decRef(); } + +TransceiverPtr +Connector::connect(int timeout) +{ + if(_traceLevels->network >= 2) + { + Trace out(_logger, _traceLevels->networkCat); + out << "trying to establish tcp connection to " << toString(); + } + + SOCKET fd = createSocket(); + setBlock(fd, false); + doConnect(fd, _addr, timeout); + + if(_traceLevels->network >= 1) + { + Trace out(_logger, _traceLevels->networkCat); + out << "tcp connection established\n" << fdToString(fd); + } + + return new Transceiver(_instance, fd); +} + +string +Connector::toString() const +{ + return addrToString(_addr); +} + +Connector::Connector(const InstancePtr& instance, const string& host, int port) : + _instance(instance), + _traceLevels(instance->traceLevels()), + _logger(instance->logger()) +{ + getAddress(host, port, _addr); +} + +Connector::~Connector() +{ +} diff --git a/cppe/src/TcpTransport/Endpoint.cpp b/cppe/src/TcpTransport/Endpoint.cpp new file mode 100644 index 00000000000..dc02bf4a9a0 --- /dev/null +++ b/cppe/src/TcpTransport/Endpoint.cpp @@ -0,0 +1,377 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Endpoint.h> +#include <Ice/Network.h> +#include <Ice/Acceptor.h> +#include <Ice/Connector.h> +#include <Ice/Transceiver.h> +#include <Ice/BasicStream.h> +#include <Ice/LocalException.h> +#include <Ice/Instance.h> +#include <Ice/DefaultsAndOverrides.h> +#include <IceUtil/SafeStdio.h> + +using namespace std; +using namespace Ice; +using namespace IceInternal; + +void IceInternal::incRef(Endpoint* p) { p->__incRef(); } +void IceInternal::decRef(Endpoint* p) { p->__decRef(); } + +IceInternal::Endpoint::Endpoint(const InstancePtr& instance, const string& ho, Int po, Int ti) : + _instance(instance), + _host(ho), + _port(po), + _timeout(ti) +{ +} + +IceInternal::Endpoint::Endpoint(const InstancePtr& instance, const string& str) : + _instance(instance), + _port(0), + _timeout(-1) +{ + const string delim = " \t\n\r"; + + string::size_type beg; + string::size_type end = 0; + + while(true) + { + beg = str.find_first_not_of(delim, end); + if(beg == string::npos) + { + break; + } + + end = str.find_first_of(delim, beg); + if(end == string::npos) + { + end = str.length(); + } + + string option = str.substr(beg, end - beg); + if(option.length() != 2 || option[0] != '-') + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "tcp " + str; + throw ex; + } + + string argument; + string::size_type argumentBeg = str.find_first_not_of(delim, end); + if(argumentBeg != string::npos && str[argumentBeg] != '-') + { + beg = argumentBeg; + end = str.find_first_of(delim, beg); + if(end == string::npos) + { + end = str.length(); + } + argument = str.substr(beg, end - beg); + } + + switch(option[1]) + { + case 'h': + { + if(argument.empty()) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "tcp " + str; + throw ex; + } + const_cast<string&>(_host) = argument; + break; + } + + case 'p': + { + const_cast<Int&>(_port) = atoi(argument.c_str()); + if(_port == 0) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "tcp " + str; + throw ex; + } + break; + } + + case 't': + { + const_cast<Int&>(_timeout) = atoi(argument.c_str()); + if(_timeout == 0) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "tcp " + str; + throw ex; + } + break; + } + + case 'z': + { + // Ignore compression flag. + break; + } + + default: + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "tcp " + str; + throw ex; + } + } + } + + if(_host.empty()) + { + const_cast<string&>(_host) = _instance->defaultsAndOverrides()->defaultHost; + } +} + +IceInternal::Endpoint::Endpoint(BasicStream* s) : + _instance(s->instance()), + _port(0), + _timeout(-1) +{ + bool dummy; + + s->startReadEncaps(); + s->read(const_cast<string&>(_host)); + s->read(const_cast<Int&>(_port)); + s->read(const_cast<Int&>(_timeout)); + s->read(const_cast<bool&>(dummy)); + s->endReadEncaps(); +} + +void +IceInternal::Endpoint::streamWrite(BasicStream* s) const +{ + s->write(TcpEndpointType); + s->startWriteEncaps(); + s->write(_host); + s->write(_port); + s->write(_timeout); + s->write(false); + s->endWriteEncaps(); +} + +string +IceInternal::Endpoint::toString() const +{ + string s; + s += "tcp -h "; + s += _host; + + s += IceUtil::printfToString(" -p %d", _port); + + if(_timeout != -1) + { + s += IceUtil::printfToString(" -t %d", _timeout); + } + return s; +} + +Short +IceInternal::Endpoint::type() const +{ + return TcpEndpointType; +} + +Int +IceInternal::Endpoint::timeout() const +{ + return _timeout; +} + +EndpointPtr +IceInternal::Endpoint::timeout(Int timeout) const +{ + if(timeout == _timeout) + { + return const_cast<Endpoint*>(this); + } + else + { + return new Endpoint(_instance, _host, _port, timeout); + } +} + +bool +IceInternal::Endpoint::unknown() const +{ + return false; +} + +TransceiverPtr +IceInternal::Endpoint::clientTransceiver() const +{ + return 0; +} + +TransceiverPtr +IceInternal::Endpoint::serverTransceiver(EndpointPtr& endp) const +{ + endp = const_cast<Endpoint*>(this); + return 0; +} + +ConnectorPtr +IceInternal::Endpoint::connector() const +{ + return new Connector(_instance, _host, _port); +} + +AcceptorPtr +IceInternal::Endpoint::acceptor(EndpointPtr& endp) const +{ + Acceptor* p = new Acceptor(_instance, _host, _port); + endp = new Endpoint(_instance, _host, p->effectivePort(), _timeout); + return p; +} + +bool +IceInternal::Endpoint::equivalent(const TransceiverPtr&) const +{ + return false; +} + +bool +IceInternal::Endpoint::equivalent(const AcceptorPtr& acceptor) const +{ + const Acceptor* tcpAcceptor = dynamic_cast<const Acceptor*>(acceptor.get()); + if(!tcpAcceptor) + { + return false; + } + return tcpAcceptor->equivalent(_host, _port); +} + +bool +IceInternal::Endpoint::operator==(const Endpoint& r) const +{ + const Endpoint* p = dynamic_cast<const Endpoint*>(&r); + if(!p) + { + return false; + } + + if(this == p) + { + return true; + } + + if(_port != p->_port) + { + return false; + } + + if(_timeout != p->_timeout) + { + return false; + } + + if(_host != p->_host) + { + // + // We do the most time-consuming part of the comparison last. + // + struct sockaddr_in laddr; + struct sockaddr_in raddr; + try + { + getAddress(_host, _port, laddr); + getAddress(p->_host, p->_port, raddr); + } + catch(const DNSException&) + { + return false; + } + + return compareAddress(laddr, raddr); + } + + return true; +} + +bool +IceInternal::Endpoint::operator!=(const Endpoint& r) const +{ + return !operator==(r); +} + +bool +IceInternal::Endpoint::operator<(const Endpoint& r) const +{ + const Endpoint* p = dynamic_cast<const Endpoint*>(&r); + if(!p) + { + return type() < r.type(); + } + + if(this == p) + { + return false; + } + + if(_port < p->_port) + { + return true; + } + else if(p->_port < _port) + { + return false; + } + + if(_timeout < p->_timeout) + { + return true; + } + else if(p->_timeout < _timeout) + { + return false; + } + + if(_host != p->_host) + { + // + // We do the most time-consuming part of the comparison last. + // + struct sockaddr_in laddr; + try + { + getAddress(_host, _port, laddr); + } + catch(const DNSException&) + { + } + + struct sockaddr_in raddr; + try + { + getAddress(p->_host, p->_port, raddr); + } + catch(const DNSException&) + { + } + + if(laddr.sin_addr.s_addr < raddr.sin_addr.s_addr) + { + return true; + } + else if(raddr.sin_addr.s_addr < laddr.sin_addr.s_addr) + { + return false; + } + } + + return false; +} diff --git a/cppe/src/TcpTransport/EndpointFactory.cpp b/cppe/src/TcpTransport/EndpointFactory.cpp new file mode 100644 index 00000000000..d7a0a61525a --- /dev/null +++ b/cppe/src/TcpTransport/EndpointFactory.cpp @@ -0,0 +1,82 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/EndpointFactory.h> +#include <Ice/Endpoint.h> +#include <Ice/LocalException.h> +#include <Ice/BasicStream.h> + +using namespace std; +using namespace Ice; +using namespace IceInternal; + +void IceInternal::incRef(EndpointFactory* p) { p->__incRef(); } +void IceInternal::decRef(EndpointFactory* p) { p->__decRef(); } + +IceInternal::EndpointFactory::EndpointFactory(const InstancePtr& instance) + : _instance(instance) +{ +} + +IceInternal::EndpointFactory::~EndpointFactory() +{ +} + +EndpointPtr +IceInternal::EndpointFactory::create(const std::string& str) const +{ + const string delim = " \t\n\r"; + + string::size_type beg = str.find_first_not_of(delim); + if(beg == string::npos) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = str; + throw ex; + } + + string::size_type end = str.find_first_of(delim, beg); + if(end == string::npos) + { + end = str.length(); + } + + string protocol = str.substr(beg, end - beg); + + if(protocol == "default" || protocol == "tcp") + { + return new Endpoint(_instance, str.substr(end)); + } + + EndpointParseException ex(__FILE__, __LINE__); +} + +EndpointPtr +IceInternal::EndpointFactory::read(BasicStream* s) const +{ + Short type; + s->read(type); + + if(type == TcpEndpointType) + { + return new Endpoint(s); + } + + // + // XXX: What should this do? Old code returned UnknownEndpoint. Maybe that needs + // to be added back? + // + return 0; +} + +void +IceInternal::EndpointFactory::destroy() +{ + _instance = 0; +} diff --git a/cppe/src/TcpTransport/Makefile b/cppe/src/TcpTransport/Makefile new file mode 100644 index 00000000000..ae1b5b07bd2 --- /dev/null +++ b/cppe/src/TcpTransport/Makefile @@ -0,0 +1,53 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +LIBFILENAME = $(call mklibfilename,IceETCP,$(VERSION)) +SONAME = $(call mksoname,IceETCP,$(SOVERSION)) +LIBNAME = $(call mklibname,IceETCP) + +TARGETS = $(call mklibtargets,$(libdir)/$(LIBFILENAME),$(libdir)/$(SONAME),$(libdir)/$(LIBNAME)) + +OBJS = Acceptor.o \ + Connector.o \ + EndpointFactory.o \ + Endpoint.o \ + Transceiver.o + +SRCS = $(OBJS:.o=.cpp) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I.. $(CPPFLAGS) -DICE_TRANSPORT_API_EXPORTS + +LINKWITH := $(ICE_OS_LIBS) + +ifeq ($(STATICLIBS),yes) +$(libdir)/$(LIBNAME): $(OBJS) + rm -f $@ + $(call mklib,$@,$(OBJS)) +else +$(libdir)/$(LIBFILENAME): $(OBJS) + rm -f $@ + $(call mkshlib,$@,$(SONAME),$(OBJS),$(LINKWITH)) + +$(libdir)/$(SONAME): $(libdir)/$(LIBFILENAME) + rm -f $@ + ln -s $(LIBFILENAME) $@ + +$(libdir)/$(LIBNAME): $(libdir)/$(SONAME) + rm -f $@ + ln -s $(SONAME) $@ +endif + +install:: all + $(call installlib,$(install_libdir),$(libdir),$(LIBFILENAME),$(SONAME),$(LIBNAME)) + +include .depend diff --git a/cppe/src/TcpTransport/Transceiver.cpp b/cppe/src/TcpTransport/Transceiver.cpp new file mode 100644 index 00000000000..7709777fc87 --- /dev/null +++ b/cppe/src/TcpTransport/Transceiver.cpp @@ -0,0 +1,469 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Transceiver.h> +#include <Ice/Instance.h> +#include <Ice/TraceLevels.h> +#include <Ice/LoggerUtil.h> +#include <Ice/Buffer.h> +#include <Ice/Network.h> +#include <Ice/LocalException.h> +#include <IceUtil/SafeStdio.h> + +using namespace std; +using namespace Ice; +using namespace IceInternal; + +void IceInternal::incRef(Transceiver* p) { p->__incRef(); } +void IceInternal::decRef(Transceiver* p) { p->__decRef(); } + + +SOCKET +IceInternal::Transceiver::fd() +{ + assert(_fd != INVALID_SOCKET); + return _fd; +} + +void +IceInternal::Transceiver::close() +{ + if(_traceLevels->network >= 1) + { + Trace out(_logger, _traceLevels->networkCat); + out << "closing tcp connection\n" << toString(); + } + +#ifdef _WIN32_WCE + assert(_event != 0); + WSACloseEvent(_event); + _event = 0; +#endif + + assert(_fd != INVALID_SOCKET); + try + { + closeSocket(_fd); + _fd = INVALID_SOCKET; + } + catch(const SocketException&) + { + _fd = INVALID_SOCKET; + throw; + } +} + +void +IceInternal::Transceiver::shutdownWrite() +{ + if(_traceLevels->network >= 2) + { + Trace out(_logger, _traceLevels->networkCat); + out << "shutting down tcp connection for writing\n" << toString(); + } + + assert(_fd != INVALID_SOCKET); + shutdownSocketWrite(_fd); +} + +void +IceInternal::Transceiver::shutdownReadWrite() +{ + if(_traceLevels->network >= 2) + { + Trace out(_logger, _traceLevels->networkCat); + out << "shutting down tcp connection for reading and writing\n" << toString(); + } + + assert(_fd != INVALID_SOCKET); + shutdownSocketReadWrite(_fd); +} + +void +IceInternal::Transceiver::write(Buffer& buf, int timeout) +{ + Buffer::Container::difference_type packetSize = + static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); + +#ifdef _WIN32 + // + // Limit packet size to avoid performance problems on WIN32 + // + if(packetSize > 64 * 1024) + { + packetSize = 64 * 1024; + } +#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) + { +#ifdef _WIN32_WCE
+ repeatError: +#endif
+ if(interrupted()) + { + continue; + } + + if(noBuffers() && packetSize > 1024) + { + packetSize /= 2; + continue; + } + + if(wouldBlock()) + { +#ifdef _WIN32_WCE + WSAEVENT events[1]; + events[0] = _event; + long tout = (timeout >= 0) ? timeout : WSA_INFINITE; + DWORD rc = WSAWaitForMultipleEvents(1, events, FALSE, tout, FALSE); + if(rc == WSA_WAIT_FAILED) + { + // + // This an error from WSAWaitForMultipleEvents + // itself (similar to an error from select). None + // of these errors are recoverable (such as + // EINTR). + // + SocketException ex(__FILE__, __LINE__); + ex.error = WSAGetLastError(); + throw ex; + } + + if(rc == WSA_WAIT_TIMEOUT) + { + assert(timeout >= 0); + throw TimeoutException(__FILE__, __LINE__); + } + assert(rc == WSA_WAIT_EVENT_0); + + WSANETWORKEVENTS nevents; + if(WSAEnumNetworkEvents(_fd, _event, &nevents) == SOCKET_ERROR) + { + SocketException ex(__FILE__, __LINE__); + ex.error = WSAGetLastError(); + throw ex; + } + // + // This checks for an error on the fd (this would be + // same as recv itself returning an error). + // + // In the event of an error we set the error code, and + // // repeat the error handling. + // + if(nevents.lNetworkEvents & FD_READ && nevents.iErrorCode[FD_READ_BIT] != 0) + { + WSASetLastError(nevents.iErrorCode[FD_READ_BIT]); + goto repeatError; + } + if(nevents.lNetworkEvents & FD_CLOSE && nevents.iErrorCode[FD_CLOSE_BIT] != 0) + { + WSASetLastError(nevents.iErrorCode[FD_CLOSE_BIT]); + goto repeatError; + } +#else + repeatSelect: + int rs; + assert(_fd != INVALID_SOCKET); + FD_SET(_fd, &_wFdSet); + + if(timeout >= 0) + { + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000; + rs = ::select(_fd + 1, 0, &_wFdSet, 0, &tv); + } + else + { + rs = ::select(_fd + 1, 0, &_wFdSet, 0, 0); + } + + if(rs == SOCKET_ERROR) + { + if(interrupted()) + { + goto repeatSelect; + } + + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + + if(rs == 0) + { + throw TimeoutException(__FILE__, __LINE__); + } +#endif + continue; + } + + if(connectionLost()) + { + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + else + { + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + } + + if(_traceLevels->network >= 3) + { + Trace out(_logger, _traceLevels->networkCat); + out << IceUtil::printfToString("sent %d of %d", ret, packetSize) << " bytes via tcp\n" << toString(); + } + + buf.i += ret; + + if(packetSize > buf.b.end() - buf.i) + { + packetSize = static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); + } + } +} + +void +IceInternal::Transceiver::read(Buffer& buf, int timeout) +{ + Buffer::Container::difference_type packetSize = + static_cast<Buffer::Container::difference_type>(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) + { + // + // 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; + } + + if(ret == SOCKET_ERROR) + { +#ifdef _WIN32_WCE
+ repeatError: +#endif
+ if(interrupted()) + { + continue; + } + + if(noBuffers() && packetSize > 1024) + { + packetSize /= 2; + continue; + } + + if(wouldBlock()) + { +#ifdef _WIN32_WCE + // + // This code is basically the same as the code in + // ::send above. Check that for detailed comments. + // + WSAEVENT events[1]; + events[0] = _event; + long tout = (timeout >= 0) ? timeout : WSA_INFINITE; + DWORD rc = WSAWaitForMultipleEvents(1, events, FALSE, tout, FALSE); + if(rc == WSA_WAIT_FAILED) + { + SocketException ex(__FILE__, __LINE__); + ex.error = WSAGetLastError(); + throw ex; + } + if(rc == WSA_WAIT_TIMEOUT) + { + assert(timeout >= 0); + throw TimeoutException(__FILE__, __LINE__); + } + assert(rc == WSA_WAIT_EVENT_0); + + WSANETWORKEVENTS nevents; + if(WSAEnumNetworkEvents(_fd, _event, &nevents) == SOCKET_ERROR) + { + SocketException ex(__FILE__, __LINE__); + ex.error = WSAGetLastError(); + throw ex; + } + + if(nevents.lNetworkEvents & FD_READ && nevents.iErrorCode[FD_READ_BIT] != 0) + { + WSASetLastError(nevents.iErrorCode[FD_READ_BIT]); + goto repeatError; + } + if(nevents.lNetworkEvents & FD_CLOSE && nevents.iErrorCode[FD_CLOSE_BIT] != 0) + { + WSASetLastError(nevents.iErrorCode[FD_CLOSE_BIT]); + goto repeatError; + } +#else + repeatSelect: + + int rs; + assert(_fd != INVALID_SOCKET); + FD_SET(_fd, &_rFdSet); + + if(timeout >= 0) + { + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000; + rs = ::select(_fd + 1, &_rFdSet, 0, 0, &tv); + } + else + { + rs = ::select(_fd + 1, &_rFdSet, 0, 0, 0); + } + + if(rs == SOCKET_ERROR) + { + if(interrupted()) + { + goto repeatSelect; + } + + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + + if(rs == 0) + { + throw TimeoutException(__FILE__, __LINE__); + } +#endif + continue; + } + + if(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 = getSocketErrno(); + throw ex; + } + else + { + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + } + + if(_traceLevels->network >= 3) + { + Trace out(_logger, _traceLevels->networkCat); + out << IceUtil::printfToString("received %d of %d", ret, packetSize) << " bytes via tcp\n" << toString(); + } + + buf.i += ret; + + if(packetSize > buf.b.end() - buf.i) + { + packetSize = static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); + } + } +} + +string +IceInternal::Transceiver::type() const +{ + return "tcp"; +} + +string +IceInternal::Transceiver::toString() const +{ + return _desc; +} + +IceInternal::Transceiver::Transceiver(const InstancePtr& instance, SOCKET fd) : + _traceLevels(instance->traceLevels()), + _logger(instance->logger()), + _fd(fd), + _desc(fdToString(fd)) +{ +#ifdef _WIN32_WCE + _event = WSACreateEvent(); + if(_event == 0) + { + closeSocket(_fd); + + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + + // + // Create a WSAEVENT which selects read/write and close for + // trigging. + // + if(WSAEventSelect(_fd, _event, FD_READ|FD_WRITE|FD_CLOSE) == SOCKET_ERROR) + { + int error = WSAGetLastError(); + + WSACloseEvent(_event); + closeSocket(_fd); + + SocketException ex(__FILE__, __LINE__); + ex.error = error; + throw ex; + } +#else + FD_ZERO(&_wFdSet); + FD_ZERO(&_rFdSet); +#endif +} + +IceInternal::Transceiver::~Transceiver() +{ + assert(_fd == INVALID_SOCKET); +#ifdef _WIN32_WCE + assert(_event == 0); +#endif +} |