summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/PropertyNames.cpp3
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/IceBT/AcceptorI.cpp10
-rw-r--r--cpp/src/IceBT/DBus.cpp64
-rw-r--r--cpp/src/IceBT/EndpointI.cpp54
-rw-r--r--cpp/src/IceBT/Engine.cpp86
-rw-r--r--cpp/src/IceBT/TransceiverI.cpp2
-rw-r--r--cpp/src/IceBT/Util.cpp2
-rw-r--r--cpp/src/Makefile7
9 files changed, 163 insertions, 67 deletions
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index 7011be23d06..8bf1cbef8b3 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Mon Nov 9 08:34:24 2015
+// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Nov 24 08:50:30 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -1055,7 +1055,6 @@ const IceInternal::PropertyArray
const IceInternal::Property IceBTPropsData[] =
{
- IceInternal::Property("IceBT.DefaultAddress", false, 0),
IceInternal::Property("IceBT.RcvSize", false, 0),
IceInternal::Property("IceBT.SndSize", false, 0),
};
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index e4c62ee27e9..8550cbeb155 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Mon Nov 9 08:34:24 2015
+// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Nov 24 08:50:30 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/IceBT/AcceptorI.cpp b/cpp/src/IceBT/AcceptorI.cpp
index 89532aee6f1..e24f4aee492 100644
--- a/cpp/src/IceBT/AcceptorI.cpp
+++ b/cpp/src/IceBT/AcceptorI.cpp
@@ -57,6 +57,10 @@ IceBT::AcceptorI::listen()
{
try
{
+ if(!_instance->engine()->adapterExists(_adapter))
+ {
+ throw SocketException(__FILE__, __LINE__, EADDRNOTAVAIL);
+ }
_addr = doBind(_fd, _addr);
IceInternal::doListen(_fd, _backlog);
}
@@ -158,12 +162,6 @@ IceBT::AcceptorI::AcceptorI(const EndpointIPtr& endpoint, const InstancePtr& ins
ex.str = "invalid address value `" + _adapter + "' in endpoint " + endpoint->toString();
throw ex;
}
- if(!_instance->engine()->adapterExists(_adapter))
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "no device found for `" + _adapter + "' in endpoint " + endpoint->toString();
- throw ex;
- }
_fd = createSocket();
IceInternal::setBlock(_fd, false);
diff --git a/cpp/src/IceBT/DBus.cpp b/cpp/src/IceBT/DBus.cpp
index 53b631a69d0..883f6fa16bd 100644
--- a/cpp/src/IceBT/DBus.cpp
+++ b/cpp/src/IceBT/DBus.cpp
@@ -810,7 +810,8 @@ private:
};
typedef IceUtil::Handle<MessageI> MessageIPtr;
-static void pendingCallback(DBusPendingCall*, void*);
+static void pendingCallCompletedCallback(DBusPendingCall*, void*);
+static void pendingCallFree(void*);
class AsyncResultI : public AsyncResult
{
@@ -821,14 +822,35 @@ public:
_callback(cb),
_status(StatusPending)
{
- if(!::dbus_pending_call_set_notify(_call, pendingCallback, this, 0))
+ //
+ // Bump our refcount to ensure this object lives until the reply is received.
+ // The pendingFree function will decrement the refcount.
+ //
+ __incRef();
+
+ if(!::dbus_pending_call_set_notify(_call, pendingCallCompletedCallback, this, pendingCallFree))
{
+ ::dbus_pending_call_cancel(_call);
+ ::dbus_pending_call_unref(_call);
throw ExceptionI("dbus_pending_call_set_notify failed");
}
+
//
- // Bump our refcount to ensure this object lives until the reply is received.
+ // There's a potential race condition with dbus_pending_call_set_notify. If the
+ // pending call is already completed when we call dbus_pending_call_set_notify,
+ // our callback will NOT be invoked. We manually check the completion status
+ // here and handle the reply if necessary.
//
- __incRef();
+ bool complete;
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_lock);
+ complete = (::dbus_pending_call_get_completed(_call) && _status == StatusPending);
+ }
+
+ if(complete)
+ {
+ replyReceived();
+ }
}
~AsyncResultI()
@@ -892,17 +914,24 @@ public:
void replyReceived()
{
assert(::dbus_pending_call_get_completed(_call));
- DBusMessage* m = ::dbus_pending_call_steal_reply(_call);
- assert(m);
AsyncCallbackPtr cb;
{
IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_lock);
- _reply = MessageI::adopt(m);
- _status = StatusComplete;
- cb = _callback;
- _lock.notifyAll();
+
+ //
+ // Make sure we haven't already handled the reply (see constructor).
+ //
+ if(_status == StatusPending)
+ {
+ DBusMessage* m = ::dbus_pending_call_steal_reply(_call);
+ assert(m);
+ _reply = MessageI::adopt(m);
+ _status = StatusComplete;
+ cb = _callback;
+ _lock.notifyAll();
+ }
}
if(cb)
@@ -915,11 +944,6 @@ public:
{
}
}
-
- //
- // Decrement our refcount (see constructor). This object may be destroyed immediately.
- //
- __decRef();
}
private:
@@ -935,13 +959,21 @@ private:
};
static void
-pendingCallback(DBusPendingCall*, void* userData)
+pendingCallCompletedCallback(DBusPendingCall*, void* userData)
{
AsyncResultI* r = static_cast<AsyncResultI*>(userData);
assert(r);
r->replyReceived();
}
+static void
+pendingCallFree(void* userData)
+{
+ AsyncResultI* r = static_cast<AsyncResultI*>(userData);
+ assert(r);
+ r->__decRef();
+}
+
static DBusHandlerResult filterCallback(DBusConnection*, DBusMessage*, void*);
static void freeConnection(void*);
diff --git a/cpp/src/IceBT/EndpointI.cpp b/cpp/src/IceBT/EndpointI.cpp
index bf1608a28e7..d69f8c0ac34 100644
--- a/cpp/src/IceBT/EndpointI.cpp
+++ b/cpp/src/IceBT/EndpointI.cpp
@@ -23,6 +23,7 @@
#include <Ice/Properties.h>
#include <IceUtil/Random.h>
#include <IceUtil/StringUtil.h>
+#include <IceUtil/UUID.h>
using namespace std;
using namespace Ice;
@@ -417,7 +418,7 @@ IceBT::EndpointI::options() const
}
}
- if(_channel != 0)
+ if(_channel > 0)
{
s << " -c " << _channel;
}
@@ -455,22 +456,24 @@ IceBT::EndpointI::initWithOptions(vector<string>& args, bool oaEndpoint)
if(_addr.empty())
{
- const_cast<string&>(_addr) = _instance->properties()->getProperty("IceBT.DefaultAddress");
+ const_cast<string&>(_addr) = _instance->defaultHost();
}
- if(oaEndpoint && _addr.empty())
+ if(_addr.empty() || _addr == "*")
{
- //
- // getDefaultAdapterAddress can throw BluetoothException.
- //
- const_cast<string&>(_addr) = _instance->engine()->getDefaultAdapterAddress();
- }
-
- 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(oaEndpoint)
+ {
+ //
+ // getDefaultAdapterAddress can throw BluetoothException.
+ //
+ const_cast<string&>(_addr) = _instance->engine()->getDefaultAdapterAddress();
+ }
+ else
+ {
+ Ice::EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "a device address must be specified using the -a option or Ice.Default.Host";
+ throw ex;
+ }
}
if(_name.empty())
@@ -480,9 +483,19 @@ IceBT::EndpointI::initWithOptions(vector<string>& args, bool oaEndpoint)
if(_uuid.empty())
{
- Ice::EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "a UUID must be specified using the -u option";
- throw ex;
+ if(oaEndpoint)
+ {
+ //
+ // Generate a UUID for object adapters that don't specify one.
+ //
+ const_cast<string&>(_uuid) = IceUtil::generateUUID();
+ }
+ else
+ {
+ Ice::EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "a UUID must be specified using the -u option";
+ throw ex;
+ }
}
if(_channel < 0)
@@ -511,10 +524,11 @@ void
IceBT::EndpointI::hashInit()
{
Int h = 5381;
- IceInternal::hashAdd(h, type());
IceInternal::hashAdd(h, _addr);
IceInternal::hashAdd(h, _uuid);
+ IceInternal::hashAdd(h, _timeout);
IceInternal::hashAdd(h, _connectionId);
+ IceInternal::hashAdd(h, _compress);
const_cast<Int&>(_hashValue) = h;
}
@@ -530,7 +544,7 @@ IceBT::EndpointI::checkOption(const string& option, const string& argument, cons
ex.str = "no argument provided for -a option in endpoint " + endpoint;
throw ex;
}
- if(!isValidDeviceAddress(arg))
+ if(arg != "*" && !isValidDeviceAddress(arg))
{
Ice::EndpointParseException ex(__FILE__, __LINE__);
ex.str = "invalid argument provided for -a option in endpoint " + endpoint;
@@ -558,7 +572,7 @@ IceBT::EndpointI::checkOption(const string& option, const string& argument, cons
}
istringstream t(argument);
- if(!(t >> const_cast<Int&>(_channel)) || !t.eof() || _channel > 30)
+ if(!(t >> const_cast<Int&>(_channel)) || !t.eof() || _channel < 0 || _channel > 30)
{
EndpointParseException ex(__FILE__, __LINE__);
ex.str = "invalid channel value `" + arg + "' in endpoint " + endpoint;
diff --git a/cpp/src/IceBT/Engine.cpp b/cpp/src/IceBT/Engine.cpp
index 46e67f47016..308bb52f478 100644
--- a/cpp/src/IceBT/Engine.cpp
+++ b/cpp/src/IceBT/Engine.cpp
@@ -76,12 +76,34 @@ public:
// Block while we establish a DBus connection.
//
_dbusConnection = DBus::Connection::getSystemBus();
- _dbusConnection->addFilter(this);
}
catch(const DBus::Exception& ex)
{
throw BluetoothException(__FILE__, __LINE__, ex.reason);
}
+
+ _dbusConnection->addFilter(this);
+
+ try
+ {
+ //
+ // Use a call DefaultAdapter() to verify that the Bluetooth daemon is present and
+ // uses the expected version (BlueZ 4). If the system is running BlueZ 5, this call
+ // will return the error org.freedesktop.DBus.Error.UnknownMethod.
+ //
+ call("/", "org.bluez.Manager", "DefaultAdapter");
+ }
+ catch(const DBus::Exception& ex)
+ {
+ if(ex.reason.find("UnknownMethod") != string::npos)
+ {
+ throw BluetoothException(__FILE__, __LINE__, "Bluetooth daemon uses an unsupported version");
+ }
+ else
+ {
+ throw BluetoothException(__FILE__, __LINE__, ex.reason);
+ }
+ }
}
//
@@ -392,26 +414,50 @@ public:
string getDefaultAdapter() const
{
- //
- // The call to DefaultAdapter returns OBJ_PATH.
- //
- DBus::MessagePtr reply = call("/", "org.bluez.Manager", "DefaultAdapter");
- DBus::ValuePtr v = reply->read();
- DBus::ObjectPathValuePtr path = DBus::ObjectPathValuePtr::dynamicCast(v);
- assert(path);
- return path->v;
+ try
+ {
+ //
+ // The call to DefaultAdapter returns OBJ_PATH.
+ //
+ DBus::MessagePtr reply = call("/", "org.bluez.Manager", "DefaultAdapter");
+ DBus::ValuePtr v = reply->read();
+ DBus::ObjectPathValuePtr path = DBus::ObjectPathValuePtr::dynamicCast(v);
+ assert(path);
+ return path->v;
+ }
+ catch(const DBus::Exception& ex)
+ {
+ if(ex.reason.find("NoSuchAdapter") == string::npos)
+ {
+ throw BluetoothException(__FILE__, __LINE__, ex.reason);
+ }
+ }
+
+ return string();
}
string findAdapter(const string& addr) const
{
- //
- // The call to FindAdapter returns OBJ_PATH.
- //
- DBus::MessagePtr reply = call("/", "org.bluez.Manager", "FindAdapter", new DBus::StringValue(addr));
- DBus::ValuePtr v = reply->read();
- DBus::ObjectPathValuePtr path = DBus::ObjectPathValuePtr::dynamicCast(v);
- assert(path);
- return path->v;
+ try
+ {
+ //
+ // The call to FindAdapter returns OBJ_PATH.
+ //
+ DBus::MessagePtr reply = call("/", "org.bluez.Manager", "FindAdapter", new DBus::StringValue(addr));
+ DBus::ValuePtr v = reply->read();
+ DBus::ObjectPathValuePtr path = DBus::ObjectPathValuePtr::dynamicCast(v);
+ assert(path);
+ return path->v;
+ }
+ catch(const DBus::Exception& ex)
+ {
+ if(ex.reason.find("NoSuchAdapter") == string::npos)
+ {
+ throw BluetoothException(__FILE__, __LINE__, ex.reason);
+ }
+ }
+
+ return string();
}
VariantMap getAdapterProperties(const string& path) const
@@ -794,7 +840,11 @@ public:
{
if(channels.empty())
{
- cb->exception(BluetoothException(__FILE__, __LINE__, "no service found for " + uuid + " at " + addr));
+ //
+ // No service found for the UUID at the remote address. We treat this as if the
+ // server is not running.
+ //
+ cb->exception(ConnectFailedException(__FILE__, __LINE__, ECONNREFUSED));
}
else
{
diff --git a/cpp/src/IceBT/TransceiverI.cpp b/cpp/src/IceBT/TransceiverI.cpp
index f4d06cf33ba..a528fb9386f 100644
--- a/cpp/src/IceBT/TransceiverI.cpp
+++ b/cpp/src/IceBT/TransceiverI.cpp
@@ -37,8 +37,6 @@ IceBT::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Bu
IceInternal::SocketOperation
IceBT::TransceiverI::closing(bool initiator, const Ice::LocalException&)
{
- ::shutdown(_stream->fd(), SHUT_RDWR);
-
//
// If we are initiating the connection closure, wait for the peer
// to close the TCP/IP connection. Otherwise, close immediately.
diff --git a/cpp/src/IceBT/Util.cpp b/cpp/src/IceBT/Util.cpp
index 8d5001d84fd..757561a8e50 100644
--- a/cpp/src/IceBT/Util.cpp
+++ b/cpp/src/IceBT/Util.cpp
@@ -227,7 +227,7 @@ IceBT::doBind(SOCKET fd, const SocketAddress& addr)
SocketAddress local;
socklen_t len = static_cast<socklen_t>(sizeof(SocketAddress));
# ifdef NDEBUG
- getsockname(fd, &local, &len);
+ getsockname(fd, reinterpret_cast<struct sockaddr*>(&local), &len);
# else
int ret = getsockname(fd, reinterpret_cast<struct sockaddr*>(&local), &len);
assert(ret != SOCKET_ERROR);
diff --git a/cpp/src/Makefile b/cpp/src/Makefile
index 4c9ac214b89..46517fbee9f 100644
--- a/cpp/src/Makefile
+++ b/cpp/src/Makefile
@@ -62,6 +62,11 @@ endif
IceDB \
IceStorm \
IceGrid
+
+ifneq ($(findstring Ubuntu,$(shell uname -a)),)
+ SUBDIRS := $(SUBDIRS) IceBT
+endif
+
endif
endif
@@ -77,7 +82,7 @@ slice2cpp slice2cs slice2java slice2js slice2php slice2html slice2objc: Slice
Ice: slice2cpp
-IceXML IceSSL IceBox Glacier2Lib IcePatch2Lib IceStormLib IceGridLib: Ice
+IceXML IceSSL IceBox Glacier2Lib IcePatch2Lib IceStormLib IceGridLib IceBT: Ice
Glacier2 IceGridLib Glacier2CryptPermissionsVerifier: Glacier2Lib