author | Eric Chou <echou@mozilla.com> |
Tue, 09 Oct 2012 13:56:17 +0800 | |
changeset 109724 | dd61540f237caed9b66e05419ecc200ef6f1f51d |
parent 109723 | 66f9632e35390f9037ebdba9e6c386ad1ca468c9 |
child 109725 | 22d192c5d1fd86f86bfe680bf78dc938df79bd31 |
child 109728 | b992224cdd55d70e0bec80c68da428eeb7d3688e |
push id | 23648 |
push user | emorley@mozilla.com |
push date | Tue, 09 Oct 2012 14:23:49 +0000 |
treeherder | mozilla-central@dd61540f237c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | qdot |
bugs | 799138 |
milestone | 19.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/bluetooth/BluetoothOppManager.cpp | file | annotate | diff | comparison | revisions | |
dom/bluetooth/BluetoothOppManager.h | file | annotate | diff | comparison | revisions |
--- a/dom/bluetooth/BluetoothOppManager.cpp +++ b/dom/bluetooth/BluetoothOppManager.cpp @@ -90,16 +90,17 @@ BluetoothOppManager::BluetoothOppManager , mConnectionId(1) , mLastCommand(0) , mBlob(nullptr) , mRemoteObexVersion(0) , mRemoteConnectionFlags(0) , mRemoteMaxPacketLength(0) , mAbortFlag(false) , mReadFileThread(nullptr) + , mPacketLeftLength(0) { } BluetoothOppManager::~BluetoothOppManager() { } //static @@ -183,22 +184,30 @@ BluetoothOppManager::StopSendingFile(Blu return true; } // Virtual function of class SocketConsumer void BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage) { - uint8_t responseCode = aMessage->mData[0]; - int packetLength = (((int)aMessage->mData[1]) << 8) | aMessage->mData[2]; + uint8_t opCode; + int packetLength; int receivedLength = aMessage->mSize; + if (mPacketLeftLength > 0) { + opCode = ObexRequestCode::Put; + packetLength = mPacketLeftLength; + } else { + opCode = aMessage->mData[0]; + packetLength = (((int)aMessage->mData[1]) << 8) | aMessage->mData[2]; + } + if (mLastCommand == ObexRequestCode::Connect) { - if (responseCode == ObexResponseCode::Success) { + if (opCode == ObexResponseCode::Success) { mConnected = true; // Keep remote information mRemoteObexVersion = aMessage->mData[3]; mRemoteConnectionFlags = aMessage->mData[4]; mRemoteMaxPacketLength = (((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]); @@ -231,26 +240,27 @@ BluetoothOppManager::ReceiveSocketData(U sUpdateProgressCounter = 1; sSentFileLength = 0; mAbortFlag = false; sInstance->SendPutHeaderRequest(sFileName, sFileLength); } } } else if (mLastCommand == ObexRequestCode::Disconnect) { - if (responseCode != ObexResponseCode::Success) { + if (opCode != ObexResponseCode::Success) { // FIXME: Needs error handling here NS_WARNING("[OPP] Disconnect failed"); } else { mConnected = false; + mLastCommand = 0; mBlob = nullptr; mReadFileThread = nullptr; } } else if (mLastCommand == ObexRequestCode::Put) { - if (responseCode != ObexResponseCode::Continue) { + if (opCode != ObexResponseCode::Continue) { // FIXME: Needs error handling here NS_WARNING("[OPP] Put failed"); } else { if (mAbortFlag || mReadFileThread == nullptr) { SendAbortRequest(); } else { // Sending system message "bluetooth-opp-update-progress" every 50kb, if (kUpdateProgressBase * sUpdateProgressCounter < sSentFileLength) { @@ -261,40 +271,75 @@ BluetoothOppManager::ReceiveSocketData(U nsRefPtr<ReadFileTask> task = new ReadFileTask(mBlob); if (NS_FAILED(mReadFileThread->Dispatch(task, NS_DISPATCH_NORMAL))) { NS_WARNING("Cannot dispatch ring task!"); } } } } else if (mLastCommand == ObexRequestCode::PutFinal) { - if (responseCode != ObexResponseCode::Success) { + if (opCode != ObexResponseCode::Success) { // FIXME: Needs error handling here NS_WARNING("[OPP] PutFinal failed"); } else { FileTransferComplete(true, false, sFileName, sSentFileLength); SendDisconnectRequest(); } } else if (mLastCommand == ObexRequestCode::Abort) { - if (responseCode != ObexResponseCode::Success) { + if (opCode != ObexResponseCode::Success) { NS_WARNING("[OPP] Abort failed"); } FileTransferComplete(false, false, sFileName, sSentFileLength); SendDisconnectRequest(); + } else { + // Remote request or unknown mLastCommand + if (opCode == ObexRequestCode::Connect) { + ReplyToConnect(); + } else if (opCode == ObexRequestCode::Disconnect) { + ReplyToDisconnect(); + } else if (opCode == ObexRequestCode::Put || + opCode == ObexRequestCode::PutFinal) { + /* + * A PUT request from remote devices may be divided into multiple parts. + * In other words, one request may need to be received multiple times, + * so here we keep a variable mPacketLeftLength to indicate if current + * PUT request is done. + */ + bool final = (opCode == ObexRequestCode::PutFinal); + + if (mPacketLeftLength == 0) { + if (receivedLength < packetLength) { + mPacketLeftLength = packetLength - receivedLength; + } else { + ReplyToPut(final); + } + } else { + NS_ASSERTION(mPacketLeftLength < receivedLength, + "Invalid packet length"); + + if (mPacketLeftLength <= receivedLength) { + ReplyToPut(final); + mPacketLeftLength = 0; + } else { + mPacketLeftLength -= receivedLength; + } + } + } } } void BluetoothOppManager::SendConnectRequest() { if (mConnected) return; // Section 3.3.1 "Connect", IrOBEX 1.2 - // [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2][Headers:var] + // [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2] + // [Headers:var] uint8_t req[255]; int index = 7; req[3] = 0x10; // version=1.0 req[4] = 0x00; // flag=0x00 req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8; req[6] = BluetoothOppManager::MAX_PACKET_LENGTH; @@ -303,17 +348,18 @@ BluetoothOppManager::SendConnectRequest( mLastCommand = ObexRequestCode::Connect; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); SendSocketData(s); } void -BluetoothOppManager::SendPutHeaderRequest(const nsAString& aFileName, int aFileSize) +BluetoothOppManager::SendPutHeaderRequest(const nsAString& aFileName, + int aFileSize) { uint8_t* req = new uint8_t[mRemoteMaxPacketLength]; const PRUnichar* fileNamePtr = aFileName.BeginReading(); uint32_t len = aFileName.Length(); uint8_t* fileName = new uint8_t[(len + 1) * 2]; for (int i = 0; i < len; i++) { fileName[i * 2] = (uint8_t)(fileNamePtr[i] >> 8); @@ -349,17 +395,17 @@ BluetoothOppManager::SendPutRequest(uint int packetLeftSpace = mRemoteMaxPacketLength - index - 3; if (!mConnected) return; if (aFileBodyLength > packetLeftSpace) { NS_WARNING("Not allowed such a small MaxPacketLength value"); return; } - // IrOBEX 1.2 3.3.3 + // Section 3.3.3 "Put", IrOBEX 1.2 // [opcode:1][length:2][Headers:var] uint8_t* req = new uint8_t[mRemoteMaxPacketLength]; index += AppendHeaderBody(&req[index], aFileBody, aFileBodyLength); if (aFinal) { SetObexPacketInfo(req, ObexRequestCode::PutFinal, index); mLastCommand = ObexRequestCode::PutFinal; @@ -373,17 +419,17 @@ BluetoothOppManager::SendPutRequest(uint SendSocketData(s); delete [] req; } void BluetoothOppManager::SendDisconnectRequest() { - // IrOBEX 1.2 3.3.2 + // Section 3.3.2 "Disconnect", IrOBEX 1.2 // [opcode:1][length:2][Headers:var] uint8_t req[255]; int index = 3; SetObexPacketInfo(req, ObexRequestCode::Disconnect, index); mLastCommand = ObexRequestCode::Disconnect; UnixSocketRawData* s = new UnixSocketRawData(index); @@ -403,16 +449,79 @@ BluetoothOppManager::SendAbortRequest() mLastCommand = ObexRequestCode::Abort; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); SendSocketData(s); } void +BluetoothOppManager::ReplyToConnect() +{ + if (mConnected) return; + mConnected = true; + + // Section 3.3.1 "Connect", IrOBEX 1.2 + // [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2] + // [Headers:var] + uint8_t req[255]; + int index = 7; + + req[3] = 0x10; // version=1.0 + req[4] = 0x00; // flag=0x00 + req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8; + req[6] = BluetoothOppManager::MAX_PACKET_LENGTH; + + SetObexPacketInfo(req, ObexResponseCode::Success, index); + + UnixSocketRawData* s = new UnixSocketRawData(index); + memcpy(s->mData, req, s->mSize); + SendSocketData(s); +} + +void +BluetoothOppManager::ReplyToDisconnect() +{ + if (!mConnected) return; + mConnected = false; + + // Section 3.3.2 "Disconnect", IrOBEX 1.2 + // [opcode:1][length:2][Headers:var] + uint8_t req[255]; + int index = 3; + + SetObexPacketInfo(req, ObexResponseCode::Success, index); + + UnixSocketRawData* s = new UnixSocketRawData(index); + memcpy(s->mData, req, s->mSize); + SendSocketData(s); +} + +void +BluetoothOppManager::ReplyToPut(bool aFinal) +{ + if (!mConnected) return; + + // Section 3.3.2 "Disconnect", IrOBEX 1.2 + // [opcode:1][length:2][Headers:var] + uint8_t req[255]; + int index = 3; + + if (aFinal) { + SetObexPacketInfo(req, ObexResponseCode::Success, index); + } else { + SetObexPacketInfo(req, ObexResponseCode::Continue, index); + } + + UnixSocketRawData* s = new UnixSocketRawData(index); + memcpy(s->mData, req, s->mSize); + SendSocketData(s); +} + +void BluetoothOppManager::FileTransferComplete(bool aSuccess, bool aReceived, const nsString& aFileName, uint32_t aFileLength) { nsString type, name; BluetoothValue v; InfallibleTArray<BluetoothNamedValue> parameters;
--- a/dom/bluetooth/BluetoothOppManager.h +++ b/dom/bluetooth/BluetoothOppManager.h @@ -57,24 +57,28 @@ public: void SendDisconnectRequest(); void SendAbortRequest(); private: BluetoothOppManager(); void FileTransferComplete(bool aSuccess, bool aReceived, const nsString& aFileName, uint32_t aFileLength); void UpdateProgress(uint32_t aProcessed, uint32_t aFileLength); + void ReplyToConnect(); + void ReplyToDisconnect(); + void ReplyToPut(bool aFinal); bool mConnected; int mConnectionId; int mLastCommand; uint8_t mRemoteObexVersion; uint8_t mRemoteConnectionFlags; int mRemoteMaxPacketLength; bool mAbortFlag; + int mPacketLeftLength; nsCOMPtr<nsIDOMBlob> mBlob; nsCOMPtr<nsIThread> mReadFileThread; }; END_BLUETOOTH_NAMESPACE #endif