diff options
Diffstat (limited to 'cpp/src/IceBT/EndpointI.cpp')
-rw-r--r-- | cpp/src/IceBT/EndpointI.cpp | 732 |
1 files changed, 732 insertions, 0 deletions
diff --git a/cpp/src/IceBT/EndpointI.cpp b/cpp/src/IceBT/EndpointI.cpp new file mode 100644 index 00000000000..9efdd46656b --- /dev/null +++ b/cpp/src/IceBT/EndpointI.cpp @@ -0,0 +1,732 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 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 <IceBT/EndpointI.h> +#include <IceBT/AcceptorI.h> +#include <IceBT/ConnectorI.h> +#include <IceBT/Engine.h> +#include <IceBT/Instance.h> +#include <IceBT/Util.h> + +#include <Ice/BasicStream.h> +#include <Ice/LocalException.h> +#include <Ice/DefaultsAndOverrides.h> +#include <Ice/HashUtil.h> +#include <Ice/Object.h> +#include <Ice/Properties.h> +#include <IceUtil/StringUtil.h> + +using namespace std; +using namespace Ice; +using namespace IceBT; + +IceUtil::Shared* IceBT::upCast(EndpointI* p) { return p; } + +IceBT::EndpointI::EndpointI(const InstancePtr& instance, const string& addr, const string& uuid, const string& name, + Int channel, Int timeout, const string& connectionId, bool compress) : + _instance(instance), + _addr(addr), + _uuid(uuid), + _name(name), + _channel(channel), + _timeout(timeout), + _connectionId(connectionId), + _compress(compress), + _hashValue(0), + _connectPending(false) +{ + hashInit(); +} + +IceBT::EndpointI::EndpointI(const InstancePtr& instance) : + _instance(instance), + _channel(0), + _timeout(instance->defaultTimeout()), + _compress(false), + _hashValue(0), + _connectPending(false) +{ +} + +IceBT::EndpointI::EndpointI(const InstancePtr& instance, IceInternal::BasicStream* s) : + _instance(instance), + _channel(0), + _timeout(-1), + _compress(false), + _hashValue(0), + _connectPending(false) +{ + // + // _name and _channel are not marshaled. + // + s->read(const_cast<string&>(_addr), false); + s->read(const_cast<string&>(_uuid), false); + s->read(const_cast<Int&>(_timeout)); + s->read(const_cast<bool&>(_compress)); + hashInit(); +} + +void +IceBT::EndpointI::streamWrite(IceInternal::BasicStream* s) const +{ + // + // _name and _channel are not marshaled. + // + s->startWriteEncaps(); + s->write(_addr, false); + s->write(_uuid, false); + s->write(_timeout); + s->write(_compress); + s->endWriteEncaps(); +} + +Ice::Short +IceBT::EndpointI::type() const +{ + return _instance->type(); +} + +const string& +IceBT::EndpointI::protocol() const +{ + return _instance->protocol(); +} + +Int +IceBT::EndpointI::timeout() const +{ + return _timeout; +} + +IceInternal::EndpointIPtr +IceBT::EndpointI::timeout(Int timeout) const +{ + if(timeout == _timeout) + { + return const_cast<EndpointI*>(this); + } + else + { + return new EndpointI(_instance, _addr, _uuid, _name, _channel, timeout, _connectionId, _compress); + } +} + +const string& +IceBT::EndpointI::connectionId() const +{ + return _connectionId; +} + +IceInternal::EndpointIPtr +IceBT::EndpointI::connectionId(const string& connectionId) const +{ + if(connectionId == _connectionId) + { + return const_cast<EndpointI*>(this); + } + else + { + return new EndpointI(_instance, _addr, _uuid, _name, _channel, _timeout, connectionId, _compress); + } +} + +bool +IceBT::EndpointI::compress() const +{ + return _compress; +} + +IceInternal::EndpointIPtr +IceBT::EndpointI::compress(bool compress) const +{ + if(compress == _compress) + { + return const_cast<EndpointI*>(this); + } + else + { + return new EndpointI(_instance, _addr, _uuid, _name, _channel, _timeout, _connectionId, compress); + } +} + +bool +IceBT::EndpointI::datagram() const +{ + return false; +} + +bool +IceBT::EndpointI::secure() const +{ + return _instance->secure(); +} + +IceInternal::TransceiverPtr +IceBT::EndpointI::transceiver() const +{ + return 0; +} + +void +IceBT::EndpointI::connectors_async(EndpointSelectionType selType, const IceInternal::EndpointI_connectorsPtr& cb) const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_lock); + + if(!_connectPending) + { + assert(_callbacks.empty()); + _instance->engine()->connect(_addr, _uuid, new ConnectCallbackI(const_cast<EndpointI*>(this))); + const_cast<bool&>(_connectPending) = true; + } + + const_cast<vector<IceInternal::EndpointI_connectorsPtr>&>(_callbacks).push_back(cb); +} + +IceInternal::AcceptorPtr +IceBT::EndpointI::acceptor(const string& adapterName) const +{ + return new AcceptorI(const_cast<EndpointI*>(this), _instance, adapterName, _addr, _uuid, _name, _channel); +} + +vector<IceInternal::EndpointIPtr> +IceBT::EndpointI::expand() const +{ + // + // Nothing to do here. + // + vector<IceInternal::EndpointIPtr> endps; + endps.push_back(const_cast<EndpointI*>(this)); + return endps; +} + +bool +IceBT::EndpointI::equivalent(const IceInternal::EndpointIPtr& endpoint) const +{ + const EndpointI* btEndpointI = dynamic_cast<const EndpointI*>(endpoint.get()); + if(!btEndpointI) + { + return false; + } + return btEndpointI->type() == type() && btEndpointI->_addr == _addr && btEndpointI->_uuid == _uuid; +} + +bool +IceBT::EndpointI::operator==(const Ice::LocalObject& r) const +{ + const EndpointI* p = dynamic_cast<const EndpointI*>(&r); + if(!p) + { + return false; + } + + if(this == p) + { + return true; + } + + if(_addr != p->_addr) + { + return false; + } + + if(_uuid != p->_uuid) + { + return false; + } + + if(_connectionId != p->_connectionId) + { + return false; + } + + if(_channel != p->_channel) + { + return false; + } + + if(_timeout != p->_timeout) + { + return false; + } + + if(_compress != p->_compress) + { + return false; + } + + return true; +} + +bool +IceBT::EndpointI::operator<(const Ice::LocalObject& r) const +{ + const EndpointI* p = dynamic_cast<const EndpointI*>(&r); + if(!p) + { + const IceInternal::EndpointI* e = dynamic_cast<const IceInternal::EndpointI*>(&r); + if(!e) + { + return false; + } + return type() < e->type(); + } + + if(this == p) + { + return false; + } + + if(type() < p->type()) + { + return true; + } + else if(p->type() < type()) + { + return false; + } + + if(_addr < p->_addr) + { + return true; + } + else if(p->_addr < _addr) + { + return false; + } + + if(_uuid < p->_uuid) + { + return true; + } + else if(p->_uuid < _uuid) + { + return false; + } + + if(_connectionId < p->_connectionId) + { + return true; + } + else if(p->_connectionId < _connectionId) + { + return false; + } + + if(_channel < p->_channel) + { + return true; + } + else if(p->_channel < _channel) + { + return false; + } + + if(_timeout < p->_timeout) + { + return true; + } + else if(p->_timeout < _timeout) + { + return false; + } + + if(!_compress && p->_compress) + { + return true; + } + else if(p->_compress < _compress) + { + return false; + } + + return false; +} + +Ice::Int +IceBT::EndpointI::hash() const +{ + return _hashValue; +} + +string +IceBT::EndpointI::options() const +{ + // + // WARNING: Certain features, such as proxy validation in Glacier2, + // depend on the format of proxy strings. Changes to toString() and + // methods called to generate parts of the reference string could break + // these features. Please review for all features that depend on the + // format of proxyToString() before changing this and related code. + // + ostringstream s; + + if(!_addr.empty()) + { + s << " -a "; + bool addQuote = _addr.find(':') != string::npos; + if(addQuote) + { + s << "\""; + } + s << _addr; + if(addQuote) + { + s << "\""; + } + } + + if(!_uuid.empty()) + { + s << " -u "; + bool addQuote = _uuid.find(':') != string::npos; + if(addQuote) + { + s << "\""; + } + s << _uuid; + if(addQuote) + { + s << "\""; + } + } + + if(_channel != 0) + { + s << " -c " << _channel; + } + + if(_timeout == -1) + { + s << " -t infinite"; + } + else + { + s << " -t " << _timeout; + } + + if(_compress) + { + s << " -z"; + } + + return s.str(); +} + +Ice::EndpointInfoPtr +IceBT::EndpointI::getInfo() const +{ + EndpointInfoPtr info = new EndpointInfoI(const_cast<EndpointI*>(this)); + info->addr = _addr; + info->uuid = _uuid; + return info; +} + +void +IceBT::EndpointI::initWithOptions(vector<string>& args, bool oaEndpoint) +{ + IceInternal::EndpointI::initWithOptions(args); + + if(_addr.empty()) + { + const_cast<string&>(_addr) = _instance->properties()->getProperty("IceBT.DefaultAddress"); + } + + if(oaEndpoint && _addr.empty()) + { + // + // getDefaultDeviceAddress can throw BluetoothException. + // + const_cast<string&>(_addr) = _instance->engine()->getDefaultDeviceAddress(); + } + + if(!oaEndpoint && _addr.empty()) + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "a device address must be specified using the -a option or IceBT.DefaultAddress"; + throw ex; + } + + if(_name.empty()) + { + const_cast<string&>(_name) = "Ice Service"; + } + + if(_uuid.empty()) + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "a UUID must be specified using the -u option"; + throw ex; + } + + if(_channel < 0) + { + const_cast<Int&>(_channel) = 0; + } + + if(!oaEndpoint && _channel != 0) + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "the -c option can only be used for object adapter endpoints"; + throw ex; + } + + hashInit(); +} + +IceBT::EndpointIPtr +IceBT::EndpointI::endpoint(const AcceptorIPtr& acceptor) const +{ + return new EndpointI(_instance, _addr, _uuid, _name, acceptor->effectiveChannel(), _timeout, _connectionId, + _compress); +} + +void +IceBT::EndpointI::hashInit() +{ + Int h = 5381; + IceInternal::hashAdd(h, type()); + IceInternal::hashAdd(h, _addr); + IceInternal::hashAdd(h, _uuid); + IceInternal::hashAdd(h, _connectionId); + const_cast<Int&>(_hashValue) = h; +} + +bool +IceBT::EndpointI::checkOption(const string& option, const string& argument, const string& endpoint) +{ + string arg = IceUtilInternal::trim(argument); + if(option == "-a") + { + if(arg.empty()) + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "no argument provided for -a option in endpoint " + endpoint; + throw ex; + } + if(!isValidDeviceAddress(arg)) + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "invalid argument provided for -a option in endpoint " + endpoint; + throw ex; + } + const_cast<string&>(_addr) = arg; + } + else if(option == "-u") + { + if(arg.empty()) + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "no argument provided for -u option in endpoint " + endpoint; + throw ex; + } + const_cast<string&>(_uuid) = arg; + } + else if(option == "-c") + { + if(arg.empty()) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "no argument provided for -c option in endpoint " + endpoint; + throw ex; + } + + istringstream t(argument); + if(!(t >> const_cast<Int&>(_channel)) || !t.eof() || _channel > 30) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "invalid channel value `" + arg + "' in endpoint " + endpoint; + throw ex; + } + } + else if(option == "-t") + { + if(arg.empty()) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "no argument provided for -t option in endpoint " + endpoint; + throw ex; + } + + if(arg == "infinite") + { + const_cast<Int&>(_timeout) = -1; + } + else + { + istringstream t(argument); + if(!(t >> const_cast<Int&>(_timeout)) || !t.eof() || _timeout < 1) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "invalid timeout value `" + arg + "' in endpoint " + endpoint; + throw ex; + } + } + } + else if(option == "-z") + { + if(!arg.empty()) + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "unexpected argument `" + arg + "' provided for -z option in " + endpoint; + throw ex; + } + const_cast<bool&>(_compress) = true; + } + else if(option == "--name") + { + if(arg.empty()) + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "no argument provided for --name option in endpoint " + endpoint; + throw ex; + } + const_cast<string&>(_name) = arg; + } + else + { + return false; + } + return true; +} + +void +IceBT::EndpointI::connectCompleted(int fd, const ConnectionPtr& conn) +{ + // + // We are responsible for closing the given file descriptor and connection. + // + + vector<IceInternal::ConnectorPtr> connectors; + + if(fd != -1) + { + connectors.push_back(new ConnectorI(_instance, fd, conn, _addr, _uuid, _timeout, _connectionId)); + } + + vector<IceInternal::EndpointI_connectorsPtr> callbacks; + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_lock); + assert(!_callbacks.empty()); + callbacks.swap(_callbacks); + _connectPending = false; + } + + for(vector<IceInternal::EndpointI_connectorsPtr>::iterator p = callbacks.begin(); p != callbacks.end(); ++p) + { + (*p)->connectors(connectors); + } +} + +void +IceBT::EndpointI::connectFailed(const Ice::LocalException& ex) +{ + vector<IceInternal::EndpointI_connectorsPtr> callbacks; + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_lock); + assert(!_callbacks.empty()); + callbacks.swap(_callbacks); + _connectPending = false; + } + + // + // NoEndpointException means the device address was unknown, so we just return an empty list of + // connectors (similar to a DNS lookup failure). + // + try + { + ex.ice_throw(); + } + catch(const Ice::NoEndpointException&) + { + vector<IceInternal::ConnectorPtr> connectors; + for(vector<IceInternal::EndpointI_connectorsPtr>::iterator p = callbacks.begin(); p != callbacks.end(); ++p) + { + (*p)->connectors(connectors); + } + } + catch(...) + { + for(vector<IceInternal::EndpointI_connectorsPtr>::iterator p = callbacks.begin(); p != callbacks.end(); ++p) + { + (*p)->exception(ex); + } + } +} + +IceBT::EndpointInfoI::EndpointInfoI(const EndpointIPtr& endpoint) : _endpoint(endpoint) +{ +} + +IceBT::EndpointInfoI::~EndpointInfoI() +{ +} + +Ice::Short +IceBT::EndpointInfoI::type() const +{ + return _endpoint->type(); +} + +bool +IceBT::EndpointInfoI::datagram() const +{ + return _endpoint->datagram(); +} + +bool +IceBT::EndpointInfoI::secure() const +{ + return _endpoint->secure(); +} + +IceBT::EndpointFactoryI::EndpointFactoryI(const InstancePtr& instance) : _instance(instance) +{ +} + +IceBT::EndpointFactoryI::~EndpointFactoryI() +{ +} + +Short +IceBT::EndpointFactoryI::type() const +{ + return _instance->type(); +} + +string +IceBT::EndpointFactoryI::protocol() const +{ + return _instance->protocol(); +} + +IceInternal::EndpointIPtr +IceBT::EndpointFactoryI::create(vector<string>& args, bool oaEndpoint) const +{ + EndpointIPtr endpt = new EndpointI(_instance); + endpt->initWithOptions(args, oaEndpoint); + return endpt; +} + +IceInternal::EndpointIPtr +IceBT::EndpointFactoryI::read(IceInternal::BasicStream* s) const +{ + return new EndpointI(_instance, s); +} + +void +IceBT::EndpointFactoryI::destroy() +{ + _instance = 0; +} + +IceInternal::EndpointFactoryPtr +IceBT::EndpointFactoryI::clone(const IceInternal::ProtocolInstancePtr& instance) const +{ + return new EndpointFactoryI(new Instance(_instance->engine(), instance->type(), instance->protocol())); +} |