Bug 1159709: Inherit |BluetoothDaemonConnection| from |DataSocket|, r=kmachulis

|BluetoothDaemonConnection| sends and receives data. With this patch
it inherits from |DataSocket|, which provides the respective abstract
interfaces.
This commit is contained in:
Thomas Zimmermann 2015-04-30 12:55:37 +02:00
Родитель ed796f72dc
Коммит 92706b5790
3 изменённых файлов: 187 добавлений и 213 удалений

Просмотреть файл

@ -1510,7 +1510,9 @@ BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData)
aPDU->SetConsumer(this);
aPDU->SetUserData(aUserData);
aPDU->UpdateHeader();
return mConnection->Send(aPDU); // Forward PDU to command channel
mConnection->SendSocketData(aPDU); // Forward PDU to command channel
return NS_OK;
}
void

Просмотреть файл

@ -200,7 +200,7 @@ BluetoothDaemonPDUConsumer::~BluetoothDaemonPDUConsumer()
//
class BluetoothDaemonConnectionIO final : public UnixSocketWatcher
, public SocketIOBase
, public DataSocketIO
, public ConnectionOrientedSocketIO
{
public:
@ -209,33 +209,12 @@ public:
BluetoothDaemonConnection* aConnection,
BluetoothDaemonPDUConsumer* aConsumer);
SocketBase* GetSocketBase();
// StreamSocketIOBase
//
nsresult Accept(int aFd,
const union sockaddr_any* aAddr, socklen_t aAddrLen);
// Shutdown state
//
bool IsShutdownOnMainThread() const;
void ShutdownOnMainThread();
bool IsShutdownOnIOThread() const;
void ShutdownOnIOThread();
// Task callback methods
//
void Connect(const char* aSocketName);
void Send(BluetoothDaemonPDU* aPDU);
void EnqueueData(BluetoothDaemonPDU* aPDU);
bool HasPendingData() const;
nsresult Receive(struct msghdr& msg);
void Send(UnixSocketIOBuffer* aBuffer);
void OnSocketCanReceiveWithoutBlocking() override;
void OnSocketCanSendWithoutBlocking() override;
@ -243,14 +222,35 @@ public:
void OnConnected() override;
void OnError(const char* aFunction, int aErrno) override;
private:
ssize_t ReceiveData(int aFd);
nsresult SendPendingData(int aFd);
// Methods for |ConnectionOrientedSocketIO|
//
nsresult Accept(int aFd,
const union sockaddr_any* aAddr,
socklen_t aAddrLen) override;
// Methods for |DataSocketIO|
//
nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override;
void ConsumeBuffer() override;
void DiscardBuffer() override;
// Methods for |SocketIOBase|
//
SocketBase* GetSocketBase() override;
bool IsShutdownOnMainThread() const override;
bool IsShutdownOnIOThread() const override;
void ShutdownOnMainThread() override;
void ShutdownOnIOThread() override;
private:
BluetoothDaemonConnection* mConnection;
BluetoothDaemonPDUConsumer* mConsumer;
nsAutoPtr<BluetoothDaemonPDU> mPDU;
nsTArray<BluetoothDaemonPDU*> mOutgoingQ;
bool mShuttingDownOnIOThread;
};
@ -266,72 +266,6 @@ BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
{
MOZ_ASSERT(mConnection);
MOZ_ASSERT(mConsumer);
/* There's only one PDU for receiving, which we reuse everytime */
mPDU = new BluetoothDaemonPDU(BluetoothDaemonPDU::MAX_PAYLOAD_LENGTH);
}
SocketBase*
BluetoothDaemonConnectionIO::GetSocketBase()
{
return mConnection;
}
bool
BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const
{
MOZ_ASSERT(NS_IsMainThread());
return mConnection == nullptr;
}
void
BluetoothDaemonConnectionIO::ShutdownOnMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdownOnMainThread());
mConnection = nullptr;
}
bool
BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const
{
return mShuttingDownOnIOThread;
}
void
BluetoothDaemonConnectionIO::ShutdownOnIOThread()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
mShuttingDownOnIOThread = true;
}
nsresult
BluetoothDaemonConnectionIO::Accept(int aFd,
const union sockaddr_any* aAddr,
socklen_t aAddrLen)
{
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
// File-descriptor setup
if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
OnError("fcntl", errno);
ScopedClose cleanupFd(aFd);
return NS_ERROR_FAILURE;
}
SetSocket(aFd, SOCKET_IS_CONNECTED);
// Signal success
OnConnected();
return NS_OK;
}
void
@ -379,57 +313,17 @@ BluetoothDaemonConnectionIO::Connect(const char* aSocketName)
}
void
BluetoothDaemonConnectionIO::Send(BluetoothDaemonPDU* aPDU)
BluetoothDaemonConnectionIO::Send(UnixSocketIOBuffer* aBuffer)
{
MOZ_ASSERT(mConsumer);
MOZ_ASSERT(aPDU);
MOZ_ASSERT(aBuffer);
EnqueueData(aPDU);
EnqueueData(aBuffer);
AddWatchers(WRITE_WATCHER, false);
}
void
BluetoothDaemonConnectionIO::EnqueueData(BluetoothDaemonPDU* aPDU)
{
MOZ_ASSERT(aPDU);
mOutgoingQ.AppendElement(aPDU);
}
bool
BluetoothDaemonConnectionIO::HasPendingData() const
{
return !mOutgoingQ.IsEmpty();
}
ssize_t
BluetoothDaemonConnectionIO::ReceiveData(int aFd)
{
MOZ_ASSERT(aFd >= 0);
ssize_t res = mPDU->Receive(aFd);
if (res < 0) {
/* an I/O error occured */
NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
return -1;
} else if (!res) {
/* EOF or peer shut down sending */
NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
return 0;
}
mConsumer->Handle(*mPDU);
return res;
}
void
BluetoothDaemonConnectionIO::OnSocketCanReceiveWithoutBlocking()
{
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
MOZ_ASSERT(!IsShutdownOnIOThread());
ssize_t res = ReceiveData(GetFd());
if (res < 0) {
/* I/O error */
@ -440,30 +334,6 @@ BluetoothDaemonConnectionIO::OnSocketCanReceiveWithoutBlocking()
}
}
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;
}
void
BluetoothDaemonConnectionIO::OnSocketCanSendWithoutBlocking()
{
@ -506,6 +376,103 @@ BluetoothDaemonConnectionIO::OnError(const char* aFunction, int aErrno)
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
}
// |ConnectionOrientedSocketIO|
nsresult
BluetoothDaemonConnectionIO::Accept(int aFd,
const union sockaddr_any* aAddr,
socklen_t aAddrLen)
{
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
// File-descriptor setup
if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
OnError("fcntl", errno);
ScopedClose cleanupFd(aFd);
return NS_ERROR_FAILURE;
}
SetSocket(aFd, SOCKET_IS_CONNECTED);
// Signal success
OnConnected();
return NS_OK;
}
// |DataSocketIO|
nsresult
BluetoothDaemonConnectionIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
{
MOZ_ASSERT(aBuffer);
if (!mPDU) {
/* There's only one PDU for receiving. We reuse it every time. */
mPDU = new BluetoothDaemonPDU(BluetoothDaemonPDU::MAX_PAYLOAD_LENGTH);
}
*aBuffer = mPDU.get();
return NS_OK;
}
void
BluetoothDaemonConnectionIO::ConsumeBuffer()
{
MOZ_ASSERT(mConsumer);
mConsumer->Handle(*mPDU);
}
void
BluetoothDaemonConnectionIO::DiscardBuffer()
{
// Nothing to do.
}
// |SocketIOBase|
SocketBase*
BluetoothDaemonConnectionIO::GetSocketBase()
{
return mConnection;
}
bool
BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const
{
MOZ_ASSERT(NS_IsMainThread());
return mConnection == nullptr;
}
bool
BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const
{
return mShuttingDownOnIOThread;
}
void
BluetoothDaemonConnectionIO::ShutdownOnMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdownOnMainThread());
mConnection = nullptr;
}
void
BluetoothDaemonConnectionIO::ShutdownOnIOThread()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
mShuttingDownOnIOThread = true;
}
//
// I/O helper tasks
//
@ -558,6 +525,49 @@ BluetoothDaemonConnection::ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer)
return NS_OK;
}
ConnectionOrientedSocketIO*
BluetoothDaemonConnection::PrepareAccept(BluetoothDaemonPDUConsumer* aConsumer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIO);
MOZ_ASSERT(aConsumer);
SetConnectionStatus(SOCKET_CONNECTING);
mIO = new BluetoothDaemonConnectionIO(
XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
this, aConsumer);
return mIO;
}
// |ConnectionOrientedSocket|
ConnectionOrientedSocketIO*
BluetoothDaemonConnection::GetIO()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mIO); // Call |PrepareAccept| before listening for connections
return mIO;
}
// |DataSocket|
void
BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mIO);
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
new SocketIOSendTask<BluetoothDaemonConnectionIO,
UnixSocketIOBuffer>(mIO, aBuffer));
}
// |SocketBase|
void
BluetoothDaemonConnection::CloseSocket()
{
@ -575,47 +585,5 @@ BluetoothDaemonConnection::CloseSocket()
NotifyDisconnect();
}
nsresult
BluetoothDaemonConnection::Send(BluetoothDaemonPDU* aPDU)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mIO) {
CHROMIUM_LOG("Bluetooth daemon already connecting/connected!");
return NS_ERROR_FAILURE;
}
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
new SocketIOSendTask<BluetoothDaemonConnectionIO,
BluetoothDaemonPDU>(mIO, aPDU));
return NS_OK;
}
ConnectionOrientedSocketIO*
BluetoothDaemonConnection::GetIO()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mIO); // Call |PrepareAccept| before listening for connections
return mIO;
}
ConnectionOrientedSocketIO*
BluetoothDaemonConnection::PrepareAccept(BluetoothDaemonPDUConsumer* aConsumer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIO);
MOZ_ASSERT(aConsumer);
SetConnectionStatus(SOCKET_CONNECTING);
mIO = new BluetoothDaemonConnectionIO(
XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
this, aConsumer);
return mIO;
}
}
}

Просмотреть файл

@ -10,7 +10,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/FileUtils.h"
#include "mozilla/ipc/ConnectionOrientedSocket.h"
#include "mozilla/ipc/SocketBase.h"
#include "mozilla/ipc/DataSocket.h"
#include "nsError.h"
#include "nsAutoPtr.h"
@ -112,26 +112,30 @@ protected:
* Bluetooth daemon. It offers connection establishment and sending
* PDUs. PDU receiving is performed by |BluetoothDaemonPDUConsumer|.
*/
class BluetoothDaemonConnection : public SocketBase
class BluetoothDaemonConnection : public DataSocket
, public ConnectionOrientedSocket
{
public:
BluetoothDaemonConnection();
virtual ~BluetoothDaemonConnection();
// SocketBase
//
nsresult ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer);
void CloseSocket();
nsresult Send(BluetoothDaemonPDU* aPDU);
// ConnectionOrientedSocket
// Methods for |ConnectionOrientedSocket|
//
virtual ConnectionOrientedSocketIO* GetIO() override;
// Methods for |DataSocket|
//
void SendSocketData(UnixSocketIOBuffer* aBuffer) override;
// Methods for |SocketBase|
//
void CloseSocket() override;
protected:
// Prepares an instance of |BluetoothDaemonConnection| in DISCONNECTED