summaryrefslogtreecommitdiff
path: root/cpp/src/IceBT/EndpointI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceBT/EndpointI.cpp')
-rw-r--r--cpp/src/IceBT/EndpointI.cpp732
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()));
+}