зеркало из https://github.com/mozilla/gecko-dev.git
Bug 799452 - patch 2: Parse PUT request header, r=qdot
This commit is contained in:
Родитель
6db58f3fe4
Коммит
2c2ebffe1b
|
@ -27,7 +27,7 @@ static mozilla::RefPtr<BluetoothOppManager> sInstance;
|
|||
static nsCOMPtr<nsIInputStream> stream = nullptr;
|
||||
static uint32_t sSentFileLength = 0;
|
||||
static nsString sFileName;
|
||||
static uint64_t sFileLength = 0;
|
||||
static uint32_t sFileLength = 0;
|
||||
static nsString sContentType;
|
||||
static int sUpdateProgressCounter = 0;
|
||||
|
||||
|
@ -98,6 +98,8 @@ BluetoothOppManager::BluetoothOppManager() : mConnected(false)
|
|||
, mAbortFlag(false)
|
||||
, mReadFileThread(nullptr)
|
||||
, mPacketLeftLength(0)
|
||||
, mReceiving(false)
|
||||
, mPutFinal(false)
|
||||
{
|
||||
// FIXME / Bug 800249:
|
||||
// mConnectedDeviceAddress is Bluetooth address of connected device,
|
||||
|
@ -222,7 +224,7 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
int receivedLength = aMessage->mSize;
|
||||
|
||||
if (mPacketLeftLength > 0) {
|
||||
opCode = ObexRequestCode::Put;
|
||||
opCode = mPutFinal ? ObexRequestCode::PutFinal : ObexRequestCode::Put;
|
||||
packetLength = mPacketLeftLength;
|
||||
} else {
|
||||
opCode = aMessage->mData[0];
|
||||
|
@ -254,18 +256,32 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
sFileName.AssignLiteral("Unknown");
|
||||
}
|
||||
|
||||
rv = mBlob->GetSize(&sFileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
return;
|
||||
}
|
||||
|
||||
rv = mBlob->GetType(sContentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get content type");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t fileLength;
|
||||
rv = mBlob->GetSize(&fileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently we keep the size of files which were sent/received via
|
||||
// Bluetooth not exceed UINT32_MAX because the Length header in OBEX
|
||||
// is only 4-byte long. Although it is possible to transfer a file
|
||||
// larger than UINT32_MAX, it needs to parse another OBEX Header
|
||||
// and I would like to leave it as a feature.
|
||||
if (fileLength <= UINT32_MAX) {
|
||||
NS_WARNING("The file size is too large for now");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sFileLength = fileLength;
|
||||
|
||||
if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
|
||||
NS_WARNING("Can't create thread");
|
||||
SendDisconnectRequest();
|
||||
|
@ -286,6 +302,7 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
NS_WARNING("[OPP] Disconnect failed");
|
||||
} else {
|
||||
mConnected = false;
|
||||
mReceiving = false;
|
||||
mLastCommand = 0;
|
||||
mBlob = nullptr;
|
||||
mReadFileThread = nullptr;
|
||||
|
@ -330,35 +347,53 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
SendDisconnectRequest();
|
||||
} else {
|
||||
// Remote request or unknown mLastCommand
|
||||
ObexHeaderSet pktHeaders(opCode);
|
||||
|
||||
if (opCode == ObexRequestCode::Connect) {
|
||||
ParseHeaders(&aMessage->mData[7], receivedLength - 7, &pktHeaders);
|
||||
ReplyToConnect();
|
||||
} else if (opCode == ObexRequestCode::Disconnect) {
|
||||
ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders);
|
||||
ReplyToDisconnect();
|
||||
} else if (opCode == ObexRequestCode::Put ||
|
||||
opCode == ObexRequestCode::PutFinal) {
|
||||
if (!mReceiving) {
|
||||
MOZ_ASSERT(mPacketLeftLength == 0);
|
||||
ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders);
|
||||
|
||||
pktHeaders.GetName(sFileName);
|
||||
pktHeaders.GetContentType(sContentType);
|
||||
pktHeaders.GetLength(&sFileLength);
|
||||
|
||||
ReceivingFileConfirmation(mConnectedDeviceAddress, sFileName, sFileLength, sContentType);
|
||||
mReceiving = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
mPutFinal = (opCode == ObexRequestCode::PutFinal);
|
||||
|
||||
if (mPacketLeftLength == 0) {
|
||||
if (receivedLength < packetLength) {
|
||||
mPacketLeftLength = packetLength - receivedLength;
|
||||
} else {
|
||||
ReplyToPut(final);
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(mPacketLeftLength < receivedLength,
|
||||
NS_ASSERTION(mPacketLeftLength >= receivedLength,
|
||||
"Invalid packet length");
|
||||
mPacketLeftLength = packetLength - receivedLength;
|
||||
} else {
|
||||
NS_ASSERTION(mPacketLeftLength >= receivedLength,
|
||||
"Invalid packet length");
|
||||
mPacketLeftLength -= receivedLength;
|
||||
}
|
||||
|
||||
if (mPacketLeftLength <= receivedLength) {
|
||||
ReplyToPut(final);
|
||||
mPacketLeftLength = 0;
|
||||
} else {
|
||||
mPacketLeftLength -= receivedLength;
|
||||
if (mPacketLeftLength == 0) {
|
||||
ReplyToPut(mPutFinal);
|
||||
|
||||
if (mPutFinal) {
|
||||
mReceiving = false;
|
||||
FileTransferComplete(mConnectedDeviceAddress, true, true, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -668,21 +703,6 @@ BluetoothOppManager::UpdateProgress(const nsString& aDeviceAddress,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::OnConnectSuccess()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::OnConnectError()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::OnDisconnect()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::ReceivingFileConfirmation(const nsString& aAddress,
|
||||
const nsString& aFileName,
|
||||
|
@ -715,3 +735,18 @@ BluetoothOppManager::ReceivingFileConfirmation(const nsString& aAddress,
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::OnConnectSuccess()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::OnConnectError()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::OnDisconnect()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -96,6 +96,8 @@ private:
|
|||
bool mAbortFlag;
|
||||
int mPacketLeftLength;
|
||||
nsString mConnectedDeviceAddress;
|
||||
bool mReceiving;
|
||||
bool mPutFinal;
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> mBlob;
|
||||
nsCOMPtr<nsIThread> mReadFileThread;
|
||||
|
|
|
@ -75,7 +75,7 @@ ParseHeaders(uint8_t* buf, int totalLength, ObexHeaderSet* retHandlerSet)
|
|||
|
||||
while (ptr - buf < totalLength) {
|
||||
ObexHeaderId headerId = (ObexHeaderId)*ptr++;
|
||||
int headerLength = 0;
|
||||
int contentLength = 0;
|
||||
uint8_t highByte, lowByte;
|
||||
|
||||
// Defined in 2.1 OBEX Headers, IrOBEX 1.2
|
||||
|
@ -87,26 +87,31 @@ ParseHeaders(uint8_t* buf, int totalLength, ObexHeaderSet* retHandlerSet)
|
|||
// byte sequence, length prefixed with 2 byte unsigned integer.
|
||||
highByte = *ptr++;
|
||||
lowByte = *ptr++;
|
||||
headerLength = ((int)highByte << 8) | lowByte;
|
||||
contentLength = (((int)highByte << 8) | lowByte) - 3;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
// 1 byte quantity
|
||||
headerLength = 1;
|
||||
contentLength = 1;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
// 4 byte quantity
|
||||
headerLength = 4;
|
||||
contentLength = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
// Content
|
||||
uint8_t* headerContent = new uint8_t[headerLength];
|
||||
memcpy(headerContent, ptr, headerLength);
|
||||
retHandlerSet->AddHeader(new ObexHeader(headerId, headerLength, headerContent));
|
||||
// FIXME: This case should be happened when we are receiving header 'Body'
|
||||
// (file body). I will handle this in another bug.
|
||||
if (contentLength + (ptr - buf) > totalLength) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += headerLength;
|
||||
uint8_t* content = new uint8_t[contentLength];
|
||||
memcpy(content, ptr, contentLength);
|
||||
retHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, content));
|
||||
|
||||
ptr += contentLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,6 +139,56 @@ public:
|
|||
{
|
||||
mHeaders.AppendElement(aHeader);
|
||||
}
|
||||
|
||||
void GetName(nsString& aRetName)
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Name) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
int nameLength = mHeaders[i]->mDataLength / 2;
|
||||
|
||||
for (int j = 0; j < nameLength; ++j) {
|
||||
PRUnichar c = ((((uint32_t)ptr[j * 2]) << 8) | ptr[j * 2 + 1]);
|
||||
aRetName += c;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetContentType(nsString& aRetContentType)
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Type) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
aRetContentType.AssignASCII((const char*)ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @return file length, 0 means file length is unknown.
|
||||
void GetLength(uint32_t* aRetLength)
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
*aRetLength = 0;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Length) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
*aRetLength = ((uint32_t)ptr[0] << 24) |
|
||||
((uint32_t)ptr[1] << 16) |
|
||||
((uint32_t)ptr[2] << 8) |
|
||||
((uint32_t)ptr[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int AppendHeaderName(uint8_t* retBuf, const char* name, int length);
|
||||
|
|
Загрузка…
Ссылка в новой задаче