diff options
Diffstat (limited to 'src/bluetooth/qbluetoothsocket_win.cpp')
-rw-r--r-- | src/bluetooth/qbluetoothsocket_win.cpp | 168 |
1 files changed, 89 insertions, 79 deletions
diff --git a/src/bluetooth/qbluetoothsocket_win.cpp b/src/bluetooth/qbluetoothsocket_win.cpp index 781decad..83855323 100644 --- a/src/bluetooth/qbluetoothsocket_win.cpp +++ b/src/bluetooth/qbluetoothsocket_win.cpp @@ -57,6 +57,8 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) QBluetoothSocketPrivateWin::QBluetoothSocketPrivateWin() : QBluetoothSocketBasePrivate() { + WSAData wsadata = {}; + ::WSAStartup(MAKEWORD(2, 0), &wsadata); } QBluetoothSocketPrivateWin::~QBluetoothSocketPrivateWin() @@ -73,20 +75,17 @@ bool QBluetoothSocketPrivateWin::ensureNativeSocket(QBluetoothServiceInfo::Proto return true; abort(); } - socketType = type; - switch (type) { - case QBluetoothServiceInfo::RfcommProtocol: - socket = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); - break; - default: - socket = INVALID_SOCKET; + if (type != QBluetoothServiceInfo::RfcommProtocol) { + socket = int(INVALID_SOCKET); errorString = QBluetoothSocket::tr("Unsupported protocol. Win32 only supports RFCOMM sockets"); q->setSocketError(QBluetoothSocket::UnsupportedProtocolError); return false; } + socket = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); + if (static_cast<SOCKET>(socket) == INVALID_SOCKET) { const int error = ::WSAGetLastError(); qCWarning(QT_BT_WINDOWS) << "Failed to create socket:" << error << qt_error_string(error); @@ -157,27 +156,14 @@ void QBluetoothSocketPrivateWin::connectToService( // we are checking the service protocol and not socketType() // socketType will change in ensureNativeSocket() - if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) { - qCWarning(QT_BT_WINDOWS) << "QBluetoothSocket::connectToService cannot " - "connect with 'UnknownProtocol' (type provided by given service)"; + if (service.socketProtocol() != QBluetoothServiceInfo::RfcommProtocol) { + qCWarning(QT_BT_WINDOWS) << "QBluetoothSocket::connectToService called with unsupported protocol"; errorString = QBluetoothSocket::tr("Socket type not supported"); q->setSocketError(QBluetoothSocket::UnsupportedProtocolError); return; } - if (service.protocolServiceMultiplexer() > 0) { - Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol); - - if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) { - errorString = QBluetoothSocket::tr("Unknown socket error"); - q->setSocketError(QBluetoothSocket::UnknownSocketError); - return; - } - connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(), - openMode); - } else if (service.serverChannel() > 0) { - Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol); - + if (service.serverChannel() > 0) { if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) { errorString = QBluetoothSocket::tr("Unknown socket error"); q->setSocketError(QBluetoothSocket::UnknownSocketError); @@ -195,14 +181,13 @@ void QBluetoothSocketPrivateWin::connectToService( q->doDeviceDiscovery(service, openMode); } } + void QBluetoothSocketPrivateWin::_q_writeNotify() { Q_Q(QBluetoothSocket); if (state == QBluetoothSocket::ConnectingState) { - updateAddressesAndPorts(); q->setSocketState(QBluetoothSocket::ConnectedState); - emit q->connected(); connectWriteNotifier->setEnabled(false); } else { if (txBuffer.isEmpty()) { @@ -220,7 +205,7 @@ void QBluetoothSocketPrivateWin::_q_writeNotify() q->setSocketError(QBluetoothSocket::NetworkError); } else if (writtenBytes <= size) { // add remainder back to buffer - char *remainder = &buf[writtenBytes]; + const char *remainder = &buf[writtenBytes]; txBuffer.ungetBlock(remainder, size - writtenBytes); if (writtenBytes > 0) emit q->bytesWritten(writtenBytes); @@ -264,6 +249,9 @@ void QBluetoothSocketPrivateWin::_q_readNotify() } q->disconnectFromService(); + } else if (bytesRead == 0) { + q->setSocketError(QBluetoothSocket::RemoteHostClosedError); + q->setSocketState(QBluetoothSocket::UnconnectedState); } else { const int unusedBytes = QPRIVATELINEARBUFFER_BUFFERSIZE - bytesRead; buffer.chop(unusedBytes); @@ -280,11 +268,8 @@ void QBluetoothSocketPrivateWin::_q_exceptNotify() errorString = qt_error_string(error); q->setSocketError(QBluetoothSocket::UnknownSocketError); - if (state == QBluetoothSocket::ConnectingState) { + if (state == QBluetoothSocket::ConnectingState) abort(); - q->setSocketState(QBluetoothSocket::UnconnectedState); - emit q->disconnected(); - } } void QBluetoothSocketPrivateWin::connectToService( @@ -348,55 +333,104 @@ void QBluetoothSocketPrivateWin::abort() delete exceptNotifier; exceptNotifier = nullptr; - m_localAddress.clear(); - m_localPort = 0; - m_peerAddress.clear(); - m_peerPort = 0; - // We don't transition through Closing for abort, so // we don't call disconnectFromService or QBluetoothSocket::close ::closesocket(socket); - socket = INVALID_SOCKET; + socket = int(INVALID_SOCKET); + + Q_Q(QBluetoothSocket); + + const bool wasConnected = q->state() == QBluetoothSocket::ConnectedState; + q->setSocketState(QBluetoothSocket::UnconnectedState); + if (wasConnected) { + q->setOpenMode(QIODevice::NotOpen); + emit q->readChannelFinished(); + } } QString QBluetoothSocketPrivateWin::localName() const { - const QBluetoothLocalDevice device(m_localAddress); + const QBluetoothAddress localAddr = localAddress(); + if (localAddr == QBluetoothAddress()) + return {}; + const QBluetoothLocalDevice device(localAddr); return device.name(); } QBluetoothAddress QBluetoothSocketPrivateWin::localAddress() const { - return m_localAddress; + if (static_cast<SOCKET>(socket) == INVALID_SOCKET) + return {}; + SOCKADDR_BTH localAddr = {}; + int localAddrLength = sizeof(localAddr); + const int localResult = ::getsockname(socket, reinterpret_cast<sockaddr *>(&localAddr), &localAddrLength); + if (localResult == SOCKET_ERROR) { + const int error = ::WSAGetLastError(); + qCWarning(QT_BT_WINDOWS) << "Error getting local address" << error << qt_error_string(error); + return {}; + } + return QBluetoothAddress(localAddr.btAddr); } quint16 QBluetoothSocketPrivateWin::localPort() const { - return m_localPort; + if (static_cast<SOCKET>(socket) == INVALID_SOCKET) + return {}; + SOCKADDR_BTH localAddr = {}; + int localAddrLength = sizeof(localAddr); + const int localResult = ::getsockname(socket, reinterpret_cast<sockaddr *>(&localAddr), &localAddrLength); + if (localResult == SOCKET_ERROR) { + const int error = ::WSAGetLastError(); + qCWarning(QT_BT_WINDOWS) << "Error getting local port" << error << qt_error_string(error); + return {}; + } + return localAddr.port; } QString QBluetoothSocketPrivateWin::peerName() const { - if (static_cast<SOCKET>(socket) == INVALID_SOCKET) + const QBluetoothAddress peerAddr = peerAddress(); + if (peerAddr == QBluetoothAddress()) return {}; BLUETOOTH_DEVICE_INFO bdi = {}; bdi.dwSize = sizeof(bdi); - bdi.Address.ullLong = m_peerAddress.toUInt64(); + bdi.Address.ullLong = peerAddr.toUInt64(); const DWORD res = ::BluetoothGetDeviceInfo(nullptr, &bdi); - if (res == ERROR_SUCCESS) - return QString::fromWCharArray(&bdi.szName[0]); - qCWarning(QT_BT_WINDOWS) << "Error calling BluetoothGetDeviceInfo" << res << qt_error_string(res); - return {}; + if (res != ERROR_SUCCESS) { + qCWarning(QT_BT_WINDOWS) << "Error calling BluetoothGetDeviceInfo" << res << qt_error_string(res); + return {}; + } + return QString::fromWCharArray(&bdi.szName[0]); } QBluetoothAddress QBluetoothSocketPrivateWin::peerAddress() const { - return m_peerAddress; + if (static_cast<SOCKET>(socket) == INVALID_SOCKET) + return {}; + SOCKADDR_BTH peerAddr = {}; + int peerAddrLength = sizeof(peerAddr); + const int peerResult = ::getpeername(socket, reinterpret_cast<sockaddr *>(&peerAddr), &peerAddrLength); + if (peerResult == SOCKET_ERROR) { + const int error = ::WSAGetLastError(); + qCWarning(QT_BT_WINDOWS) << "Error getting peer address and port" << error << qt_error_string(error); + return {}; + } + return QBluetoothAddress(peerAddr.btAddr); } quint16 QBluetoothSocketPrivateWin::peerPort() const { - return m_peerPort; + if (static_cast<SOCKET>(socket) == INVALID_SOCKET) + return {}; + SOCKADDR_BTH peerAddr = {}; + int peerAddrLength = sizeof(peerAddr); + const int peerResult = ::getpeername(socket, reinterpret_cast<sockaddr *>(&peerAddr), &peerAddrLength); + if (peerResult == SOCKET_ERROR) { + const int error = ::WSAGetLastError(); + qCWarning(QT_BT_WINDOWS) << "Error getting peer address and port" << error << qt_error_string(error); + return {}; + } + return peerAddr.port; } qint64 QBluetoothSocketPrivateWin::writeData(const char *data, qint64 maxSize) @@ -427,8 +461,10 @@ qint64 QBluetoothSocketPrivateWin::writeData(const char *data, qint64 maxSize) if (!connectWriteNotifier) return -1; - if (txBuffer.isEmpty()) + if (txBuffer.isEmpty()) { connectWriteNotifier->setEnabled(true); + QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection); + } char *txbuf = txBuffer.reserve(maxSize); ::memcpy(txbuf, data, maxSize); @@ -459,19 +495,20 @@ void QBluetoothSocketPrivateWin::close() connectWriteNotifier->setEnabled(true); } -bool QBluetoothSocketPrivateWin::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_, - QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +bool QBluetoothSocketPrivateWin::setSocketDescriptor(int socketDescriptor, + QBluetoothServiceInfo::Protocol protocol, + QBluetoothSocket::SocketState socketState, + QBluetoothSocket::OpenMode openMode) { Q_Q(QBluetoothSocket); abort(); - socketType = socketType_; + socketType = protocol; socket = socketDescriptor; if (!createNotifiers()) return false; - updateAddressesAndPorts(); q->setSocketState(socketState); q->setOpenMode(openMode); if (socketState == QBluetoothSocket::ConnectedState) { @@ -526,33 +563,6 @@ bool QBluetoothSocketPrivateWin::createNotifiers() return true; } -void QBluetoothSocketPrivateWin::updateAddressesAndPorts() -{ - SOCKADDR_BTH localAddr = {}; - int localAddrLength = sizeof(localAddr); - const int localResult = ::getsockname(socket, reinterpret_cast<sockaddr *>(&localAddr), &localAddrLength); - if (localResult != SOCKET_ERROR) { - m_localAddress = QBluetoothAddress(localAddr.btAddr); - m_localPort = localAddr.port; - } else { - const int error = ::WSAGetLastError(); - qCWarning(QT_BT_WINDOWS) << "Error getting local address and port" << error << qt_error_string(error); - errorString = QBluetoothSocket::tr("Cannot get socket's local address and port"); - } - - SOCKADDR_BTH peerAddr = {}; - int peerAddrLength = sizeof(peerAddr); - const int peerResult = ::getpeername(socket, reinterpret_cast<sockaddr *>(&peerAddr), &peerAddrLength); - if (peerResult != SOCKET_ERROR) { - m_peerAddress = QBluetoothAddress(peerAddr.btAddr); - m_peerPort = peerAddr.port; - } else { - const int error = ::WSAGetLastError(); - qCWarning(QT_BT_WINDOWS) << "Error getting peer address and port" << error << qt_error_string(error); - errorString = QBluetoothSocket::tr("Cannot get socket's peer address and port"); - } -} - bool QBluetoothSocketPrivateWin::configureSecurity() { Q_Q(QBluetoothSocket); |