author | Eric Chou <echou@mozilla.com> |
Fri, 28 Sep 2012 20:03:36 +0800 | |
changeset 108726 | 5b799e7132346d8cf4cde4c1738fdfb4f5edb2d6 |
parent 108725 | 02747dcace863372fef293993a714720af1b8763 |
child 108727 | d4355e045ea76e8bd1f473bdae0e52194e11a4f3 |
child 108733 | aade44131d6c270a90faca358e1734709d51f74b |
push id | 23585 |
push user | emorley@mozilla.com |
push date | Mon, 01 Oct 2012 13:02:21 +0000 |
treeherder | mozilla-central@d4355e045ea7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | qdot |
bugs | 795410 |
milestone | 18.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 @@ -8,26 +8,94 @@ #include "BluetoothOppManager.h" #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" #include "BluetoothServiceUuid.h" #include "ObexBase.h" #include "mozilla/RefPtr.h" -#include "nsIDOMFile.h" +#include "nsIInputStream.h" USING_BLUETOOTH_NAMESPACE using namespace mozilla::ipc; static mozilla::RefPtr<BluetoothOppManager> sInstance; +static nsCOMPtr<nsIInputStream> stream = nullptr; +static uint64_t sSentFileSize = 0; + +class ReadFileTask : public nsRunnable +{ +public: + ReadFileTask(nsIDOMBlob* aBlob) : mBlob(aBlob) + { + MOZ_ASSERT(NS_IsMainThread()); + } + + NS_IMETHOD Run() + { + if (NS_IsMainThread()) { + NS_WARNING("Can't read file from main thread"); + return NS_ERROR_FAILURE; + } + + uint64_t fileSize; + nsresult rv = mBlob->GetSize(&fileSize); + if (NS_FAILED(rv)) { + NS_WARNING("Can't get file size"); + return NS_ERROR_FAILURE;; + } + + if (stream == nullptr) { + rv = mBlob->GetInternalStream(getter_AddRefs(stream)); + if (NS_FAILED(rv)) { + NS_WARNING("Can't get internal stream of blob"); + return NS_ERROR_FAILURE; + } + } + + /* + * 255 is the Minimum OBEX Packet Length (See section 3.3.1.4, + * IrOBEX ver 1.2) + */ + char buf[255]; + uint32_t numRead; + int offset = 0; + + // function inputstream->Read() only works on non-main thread + rv = stream->Read(buf, sizeof(buf), &numRead); + if (NS_FAILED(rv)) { + // Needs error handling here + return NS_ERROR_FAILURE; + } + + if (numRead > 0) { + if (sSentFileSize + numRead >= fileSize) { + sInstance->SendPutRequest((uint8_t*)buf, numRead, true); + } else { + sInstance->SendPutRequest((uint8_t*)buf, numRead, false); + } + + sSentFileSize += numRead; + } + + return NS_OK; + }; + +private: + nsCOMPtr<nsIDOMBlob> mBlob; +}; BluetoothOppManager::BluetoothOppManager() : mConnected(false) , mConnectionId(1) , mLastCommand(0) + , mBlob(nullptr) + , mRemoteObexVersion(0) + , mRemoteConnectionFlags(0) + , mRemoteMaxPacketLength(0) { } BluetoothOppManager::~BluetoothOppManager() { } //static @@ -77,58 +145,217 @@ BluetoothOppManager::Disconnect() { CloseSocket(); } bool BluetoothOppManager::SendFile(BlobParent* aActor, BluetoothReplyRunnable* aRunnable) { - // will implement in another patch. + if (mBlob) { + // Means there's a sending process. Reply error. + return false; + } + + /* + * Process of sending a file: + * - Keep blob because OPP connection has not been established yet. + * - Create an OPP connection by SendConnectRequest() + * - After receiving the response, start to read file and send. + */ + mBlob = aActor->GetBlob(); + + SendConnectRequest(); + return true; } bool BluetoothOppManager::StopSendingFile(BluetoothReplyRunnable* aRunnable) { // will implement in another patch. 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]; + int receivedLength = aMessage->mSize; if (mLastCommand == ObexRequestCode::Connect) { if (responseCode == ObexResponseCode::Success) { mConnected = true; + + // Keep remote information + mRemoteObexVersion = aMessage->mData[3]; + mRemoteConnectionFlags = aMessage->mData[4]; + mRemoteMaxPacketLength = + (((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]); + + if (mBlob) { + /* + * Before sending content, we have to send a header including + * information such as file name, file length and content type. + */ + nsresult rv; + nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob); + nsString fileName; + if (file) { + rv = file->GetName(fileName); + } + + if (!file || fileName.IsEmpty()) { + fileName.AssignLiteral("Unknown"); + } + + uint64_t fileSize; + rv = mBlob->GetSize(&fileSize); + if (NS_FAILED(rv)) { + NS_WARNING("Can't get file size"); + return; + } + + sSentFileSize = 0; + sInstance->SendPutHeaderRequest(fileName, fileSize); + } } } else if (mLastCommand == ObexRequestCode::Disconnect) { - if (responseCode == ObexResponseCode::Success) { + if (responseCode != ObexResponseCode::Success) { + // FIXME: Needs error handling here + NS_WARNING("[OPP] Disconnect failed"); + } else { mConnected = false; + mBlob = nullptr; + } + } else if (mLastCommand == ObexRequestCode::Put) { + if (responseCode != ObexResponseCode::Continue) { + // FIXME: Needs error handling here + NS_WARNING("[OPP] Put failed"); + } else { + nsCOMPtr<nsIThread> t; + NS_NewThread(getter_AddRefs(t)); + + nsRefPtr<ReadFileTask> task = new ReadFileTask(mBlob); + + if (NS_FAILED(t->Dispatch(task, NS_DISPATCH_NORMAL))) { + NS_WARNING("Cannot dispatch ring task!"); + } + } + } else if (mLastCommand == ObexRequestCode::PutFinal) { + if (responseCode != ObexResponseCode::Success) { + // FIXME: Needs error handling here + NS_WARNING("[OPP] PutFinal failed"); + } else { + SendDisconnectRequest(); } } } void -BluetoothOppManager::SendConnectReqeust() +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] 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; - index += AppendHeaderConnectionId(&req[index], mConnectionId++); + index += AppendHeaderConnectionId(&req[index], mConnectionId); SetObexPacketInfo(req, ObexRequestCode::Connect, index); mLastCommand = ObexRequestCode::Connect; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); SendSocketData(s); } +void +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); + fileName[i * 2 + 1] = (uint8_t)fileNamePtr[i]; + } + + fileName[len * 2] = 0x00; + fileName[len * 2 + 1] = 0x00; + + int index = 3; + index += AppendHeaderConnectionId(&req[index], mConnectionId); + index += AppendHeaderName(&req[index], (char*)fileName, (len + 1) * 2); + index += AppendHeaderLength(&req[index], aFileSize); + + SetObexPacketInfo(req, ObexRequestCode::Put, index); + mLastCommand = ObexRequestCode::Put; + + UnixSocketRawData* s = new UnixSocketRawData(index); + memcpy(s->mData, req, s->mSize); + SendSocketData(s); + + delete [] fileName; + delete [] req; +} + +void +BluetoothOppManager::SendPutRequest(uint8_t* aFileBody, + int aFileBodyLength, + bool aFinal) +{ + int sentFileBodyLength = 0; + int index = 3; + 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 + // [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; + } else { + SetObexPacketInfo(req, ObexRequestCode::Put, index); + mLastCommand = ObexRequestCode::Put; + } + + UnixSocketRawData* s = new UnixSocketRawData(index); + memcpy(s->mData, req, s->mSize); + SendSocketData(s); + + delete [] req; +} + +void +BluetoothOppManager::SendDisconnectRequest() +{ + // IrOBEX 1.2 3.3.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); + memcpy(s->mData, req, s->mSize); + SendSocketData(s); +}
--- a/dom/bluetooth/BluetoothOppManager.h +++ b/dom/bluetooth/BluetoothOppManager.h @@ -5,16 +5,17 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_bluetooth_bluetoothoppmanager_h__ #define mozilla_dom_bluetooth_bluetoothoppmanager_h__ #include "BluetoothCommon.h" #include "mozilla/dom/ipc/Blob.h" #include "mozilla/ipc/UnixSocket.h" +#include "nsIDOMFile.h" BEGIN_BLUETOOTH_NAMESPACE class BluetoothReplyRunnable; class BluetoothOppManager : public mozilla::ipc::UnixSocketConsumer { public: @@ -45,20 +46,31 @@ public: BluetoothReplyRunnable* aRunnable); void Disconnect(); bool SendFile(BlobParent* aBlob, BluetoothReplyRunnable* aRunnable); bool StopSendingFile(BluetoothReplyRunnable* aRunnable); + // xxx For runnable use + void SendConnectRequest(); + void SendPutHeaderRequest(const nsAString& aFileName, int aFileSize); + void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength, + bool aFinal); + void SendDisconnectRequest(); + private: BluetoothOppManager(); - void SendConnectReqeust(); bool mConnected; int mConnectionId; int mLastCommand; + uint8_t mRemoteObexVersion; + uint8_t mRemoteConnectionFlags; + int mRemoteMaxPacketLength; + + nsCOMPtr<nsIDOMBlob> mBlob; }; END_BLUETOOTH_NAMESPACE #endif