nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut) { // We get a pointer to the first character in the PDU, a length // of 1 ensures we consume the \0 byte. With 'str' pointing to // the string in the PDU, we can copy the actual bytes. const char* str = reinterpret_cast<const char*>(aPDU.Consume(1)); if (NS_WARN_IF(!str)) { return NS_ERROR_ILLEGAL_VALUE; // end of PDU } const char* end = static_cast<char*>(memchr(str, '\0', aPDU.GetSize())); if (NS_WARN_IF(!end)) { return NS_ERROR_ILLEGAL_VALUE; // no string terminator } ptrdiff_t len = end - str; const uint8_t* rest = aPDU.Consume(len); if (NS_WARN_IF(!rest)) { // We couldn't consume bytes that should have been there. return NS_ERROR_ILLEGAL_VALUE; } aOut.Rebind(str, len); return NS_OK; }
nsresult BluetoothDaemonConnectionIO::SendPendingData(int aFd) { while (HasPendingData()) { BluetoothDaemonPDU* outgoing = mOutgoingQ.ElementAt(0); MOZ_ASSERT(outgoing); ssize_t res = outgoing->Send(aFd); if (res < 0) { /* an I/O error occured */ return NS_ERROR_FAILURE; } else if (!res) { /* I/O is currently blocked; try again later */ return NS_OK; } MOZ_ASSERT(!outgoing->GetSize()); mOutgoingQ.RemoveElementAt(0); delete outgoing; } return NS_OK; }
nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothServiceRecord& aOut) { /* unpack UUID */ nsresult rv = UnpackPDU(aPDU, aOut.mUuid); if (NS_FAILED(rv)) { return rv; } /* unpack channel */ rv = UnpackPDU(aPDU, aOut.mChannel); if (NS_FAILED(rv)) { return rv; } /* unpack name */ return aPDU.Read(aOut.mName, sizeof(aOut.mName)); }
nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut) { nsresult rv = UnpackPDU(aPDU, aOut.mType); if (NS_FAILED(rv)) { return rv; } uint16_t len; rv = UnpackPDU(aPDU, len); if (NS_FAILED(rv)) { return rv; } switch (aOut.mType) { case PROPERTY_BDNAME: /* fall through */ case PROPERTY_REMOTE_FRIENDLY_NAME: { const uint8_t* data = aPDU.Consume(len); if (NS_WARN_IF(!data)) { return NS_ERROR_ILLEGAL_VALUE; } // We construct an nsCString here because the string // returned from the PDU is not 0-terminated. aOut.mString = NS_ConvertUTF8toUTF16( nsCString(reinterpret_cast<const char*>(data), len)); } break; case PROPERTY_BDADDR: rv = UnpackPDU<BluetoothAddress>( aPDU, UnpackConversion<BluetoothAddress, nsAString>(aOut.mString)); break; case PROPERTY_UUIDS: { size_t numUuids = len / MAX_UUID_SIZE; aOut.mUuidArray.SetLength(numUuids); rv = UnpackPDU(aPDU, aOut.mUuidArray); } break; case PROPERTY_CLASS_OF_DEVICE: /* fall through */ case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: rv = UnpackPDU(aPDU, aOut.mUint32); break; case PROPERTY_TYPE_OF_DEVICE: rv = UnpackPDU(aPDU, aOut.mTypeOfDevice); break; case PROPERTY_SERVICE_RECORD: rv = UnpackPDU(aPDU, aOut.mServiceRecord); break; case PROPERTY_ADAPTER_SCAN_MODE: rv = UnpackPDU(aPDU, aOut.mScanMode); break; case PROPERTY_ADAPTER_BONDED_DEVICES: { /* unpack addresses */ size_t numAddresses = len / BLUETOOTH_ADDRESS_BYTES; nsAutoArrayPtr<BluetoothAddress> addresses; UnpackArray<BluetoothAddress> addressArray(addresses, numAddresses); rv = UnpackPDU(aPDU, addressArray); if (NS_FAILED(rv)) { return rv; } /* convert addresses to strings */ aOut.mStringArray.SetLength(numAddresses); ConvertArray<BluetoothAddress> convertArray(addressArray.mData, addressArray.mLength); rv = Convert(convertArray, aOut.mStringArray); } break; case PROPERTY_REMOTE_RSSI: { int8_t rssi; rv = UnpackPDU(aPDU, rssi); aOut.mInt32 = rssi; } break; case PROPERTY_REMOTE_VERSION_INFO: rv = UnpackPDU(aPDU, aOut.mRemoteInfo); break; case PROPERTY_REMOTE_DEVICE_TIMESTAMP: /* nothing to do */ break; default: break; } return rv; }