diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Ice/PropertyNames.cpp | 3 | ||||
-rw-r--r-- | cpp/src/Ice/PropertyNames.h | 2 | ||||
-rw-r--r-- | cpp/src/IceBT/AcceptorI.cpp | 10 | ||||
-rw-r--r-- | cpp/src/IceBT/DBus.cpp | 64 | ||||
-rw-r--r-- | cpp/src/IceBT/EndpointI.cpp | 54 | ||||
-rw-r--r-- | cpp/src/IceBT/Engine.cpp | 86 | ||||
-rw-r--r-- | cpp/src/IceBT/TransceiverI.cpp | 2 | ||||
-rw-r--r-- | cpp/src/IceBT/Util.cpp | 2 | ||||
-rw-r--r-- | cpp/src/Makefile | 7 |
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 |