Make QLocalSocket connectable with open()

Add getter and setter for handling the server QLocalSocket connects to.

Move the connectServer() implementation to QLocalSocket::open
so the local socket can be handled transparently as a QIODevice

Add a convenient connectToServer(OpenMode) method

Change-Id: Ibc8dc33f79903f92daf2d1ca2e64ead2ce39f33e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Corentin Jabot 2012-11-25 17:30:15 +01:00 committed by The Qt Project
parent 866a5d0c28
commit 953255abab
5 changed files with 94 additions and 37 deletions

View File

@ -71,18 +71,17 @@ QT_BEGIN_NAMESPACE
*/ */
/*! /*!
\fn void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) \fn void QLocalSocket::open(OpenMode openMode)
Attempts to make a connection to \a name. Equivalent to connectToServer(OpenMode mode).
The socket is opened in the given \a openMode to the server defined by setServerName().
The socket is opened in the given \a openMode and first enters ConnectingState. Note that unlike in most other QIODevice subclasses, open() may not open the device directly.
It then attempts to connect to the address or addresses returned by the lookup. The function return false if the socket was already connected or if the server to connect
Finally, if a connection is established, QLocalSocket enters ConnectedState to was not defined and true in any other case. The connected() or error() signals will be
and emits connected(). emitted once the device is actualy open (or the connection failed).
At any point, the socket can emit error() to signal that an error occurred. See connectToServer() for more details.
See also state(), serverName(), and waitForConnected().
*/ */
/*! /*!
@ -354,8 +353,62 @@ QLocalSocket::~QLocalSocket()
} }
/*! /*!
Returns the name of the peer as specified by connectToServer(), or an \since 5.1
empty QString if connectToServer() has not been called or it failed.
Attempts to make a connection to serverName().
setServerName() must be called before you open the connection.
Alternatively you can use connectToServer(const QString &name, OpenMode openMode);
The socket is opened in the given \a openMode and first enters ConnectingState.
If a connection is established, QLocalSocket enters ConnectedState and emits connected().
After calling this function, the socket can emit error() to signal that an error occurred.
\sa state(), serverName(), waitForConnected()
*/
void QLocalSocket::connectToServer(OpenMode openMode)
{
open(openMode);
}
/*! \overload
Set the server \a name and attempts to make a connection to it.
The socket is opened in the given \a openMode and first enters ConnectingState.
If a connection is established, QLocalSocket enters ConnectedState and emits connected().
After calling this function, the socket can emit error() to signal that an error occurred.
\sa state(), serverName(), waitForConnected()
*/
void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
{
setServerName(name);
open(openMode);
}
/*!
\since 5.1
Set the \a name of the peer to connect to.
On Windows name is the name of a named pipe; on Unix name is the name of a local domain socket.
This function must be called when the socket is not connected.
*/
void QLocalSocket::setServerName(const QString & name)
{
Q_D(QLocalSocket);
if (d->state != UnconnectedState) {
qWarning("QLocalSocket::setServerName() called while not in unconnected state");
return;
}
d->serverName = name;
}
/*!
Returns the name of the peer as specified by setServerName(), or an
empty QString if setServerName() has not been called or connectToServer() failed.
\sa connectToServer(), fullServerName() \sa connectToServer(), fullServerName()

View File

@ -84,9 +84,11 @@ public:
QLocalSocket(QObject *parent = 0); QLocalSocket(QObject *parent = 0);
~QLocalSocket(); ~QLocalSocket();
void connectToServer(OpenMode openMode = ReadWrite);
void connectToServer(const QString &name, OpenMode openMode = ReadWrite); void connectToServer(const QString &name, OpenMode openMode = ReadWrite);
void disconnectFromServer(); void disconnectFromServer();
void setServerName(const QString &name);
QString serverName() const; QString serverName() const;
QString fullServerName() const; QString fullServerName() const;
@ -95,6 +97,7 @@ public:
virtual qint64 bytesAvailable() const; virtual qint64 bytesAvailable() const;
virtual qint64 bytesToWrite() const; virtual qint64 bytesToWrite() const;
virtual bool canReadLine() const; virtual bool canReadLine() const;
virtual bool open(OpenMode openMode = ReadWrite) Q_DECL_OVERRIDE;
virtual void close(); virtual void close();
LocalSocketError error() const; LocalSocketError error() const;
bool flush(); bool flush();

View File

@ -214,29 +214,28 @@ void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, co
q->emit stateChanged(state); q->emit stateChanged(state);
} }
void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) bool QLocalSocket::open(OpenMode openMode)
{ {
Q_D(QLocalSocket); Q_D(QLocalSocket);
if (state() == ConnectedState if (state() == ConnectedState || state() == ConnectingState) {
|| state() == ConnectingState) return false;
return; }
d->errorString.clear(); d->errorString.clear();
d->state = ConnectingState; d->state = ConnectingState;
emit stateChanged(d->state); emit stateChanged(d->state);
if (name.isEmpty()) { if (d->serverName.isEmpty()) {
d->errorOccurred(ServerNotFoundError, d->errorOccurred(ServerNotFoundError,
QLatin1String("QLocalSocket::connectToServer")); QLatin1String("QLocalSocket::connectToServer"));
return; return false;
} }
d->serverName = name;
const QLatin1String prefix("QLocalServer/"); const QLatin1String prefix("QLocalServer/");
if (name.startsWith(prefix)) if (name.startsWith(prefix))
d->fullServerName = name; d->fullServerName = d->serverName;
else else
d->fullServerName = prefix + name; d->fullServerName = prefix + d->serverName;
QSettings settings(QLatin1String("QtProject"), QLatin1String("Qt")); QSettings settings(QLatin1String("QtProject"), QLatin1String("Qt"));
bool ok; bool ok;
@ -244,10 +243,11 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
if (!ok) { if (!ok) {
d->errorOccurred(ServerNotFoundError, d->errorOccurred(ServerNotFoundError,
QLatin1String("QLocalSocket::connectToServer")); QLatin1String("QLocalSocket::connectToServer"));
return; return false;
} }
d->tcpSocket->connectToHost(QHostAddress::LocalHost, port, openMode); d->tcpSocket->connectToHost(QHostAddress::LocalHost, port, openMode);
QIODevice::open(openMode); QIODevice::open(openMode);
return true;
} }
bool QLocalSocket::setSocketDescriptor(qintptr socketDescriptor, bool QLocalSocket::setSocketDescriptor(qintptr socketDescriptor,

View File

@ -221,14 +221,14 @@ void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, co
q->emit stateChanged(state); q->emit stateChanged(state);
} }
void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) bool QLocalSocket::open(OpenMode openMode)
{ {
Q_D(QLocalSocket); Q_D(QLocalSocket);
if (state() == ConnectedState || state() == ConnectingState) { if (state() == ConnectedState || state() == ConnectingState) {
QString errorString = d->generateErrorString(QLocalSocket::OperationError, QLatin1String("QLocalSocket::connectToserver")); QString errorString = d->generateErrorString(QLocalSocket::OperationError, QLatin1String("QLocalSocket::connectToserver"));
setErrorString(errorString); setErrorString(errorString);
emit error(QLocalSocket::OperationError); emit error(QLocalSocket::OperationError);
return; return false;
} }
d->errorString.clear(); d->errorString.clear();
@ -236,17 +236,17 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
d->state = ConnectingState; d->state = ConnectingState;
emit stateChanged(d->state); emit stateChanged(d->state);
if (name.isEmpty()) { if (d->serverName.isEmpty()) {
d->errorOccurred(ServerNotFoundError, d->errorOccurred(ServerNotFoundError,
QLatin1String("QLocalSocket::connectToServer")); QLatin1String("QLocalSocket::connectToServer"));
return; return false;
} }
// create the socket // create the socket
if (-1 == (d->connectingSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0))) { if (-1 == (d->connectingSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0))) {
d->errorOccurred(UnsupportedSocketOperationError, d->errorOccurred(UnsupportedSocketOperationError,
QLatin1String("QLocalSocket::connectToServer")); QLatin1String("QLocalSocket::connectToServer"));
return; return false;
} }
// set non blocking so we can try to connect and it won't wait // set non blocking so we can try to connect and it won't wait
int flags = fcntl(d->connectingSocket, F_GETFL, 0); int flags = fcntl(d->connectingSocket, F_GETFL, 0);
@ -254,13 +254,14 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
|| -1 == (fcntl(d->connectingSocket, F_SETFL, flags | O_NONBLOCK))) { || -1 == (fcntl(d->connectingSocket, F_SETFL, flags | O_NONBLOCK))) {
d->errorOccurred(UnknownSocketError, d->errorOccurred(UnknownSocketError,
QLatin1String("QLocalSocket::connectToServer")); QLatin1String("QLocalSocket::connectToServer"));
return; return false;
} }
// _q_connectToSocket does the actual connecting // _q_connectToSocket does the actual connecting
d->connectingName = name; d->connectingName = d->serverName;
d->connectingOpenMode = openMode; d->connectingOpenMode = openMode;
d->_q_connectToSocket(); d->_q_connectToSocket();
return true;
} }
/*! /*!

View File

@ -128,33 +128,33 @@ void QLocalSocketPrivate::destroyPipeHandles()
} }
} }
void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) bool QLocalSocket::open(OpenMode openMode)
{ {
Q_D(QLocalSocket); Q_D(QLocalSocket);
if (state() == ConnectedState || state() == ConnectingState) { if (state() == ConnectedState || state() == ConnectingState) {
setErrorString(tr("Trying to connect while connection is in progress")); setErrorString(tr("Trying to connect while connection is in progress"));
emit error(QLocalSocket::OperationError); emit error(QLocalSocket::OperationError);
return; return false;
} }
d->error = QLocalSocket::UnknownSocketError; d->error = QLocalSocket::UnknownSocketError;
d->errorString = QString(); d->errorString = QString();
d->state = ConnectingState; d->state = ConnectingState;
emit stateChanged(d->state); emit stateChanged(d->state);
if (name.isEmpty()) { if (d->serverName.isEmpty()) {
d->error = QLocalSocket::ServerNotFoundError; d->error = QLocalSocket::ServerNotFoundError;
setErrorString(QLocalSocket::tr("%1: Invalid name").arg(QLatin1String("QLocalSocket::connectToServer"))); setErrorString(QLocalSocket::tr("%1: Invalid name").arg(QLatin1String("QLocalSocket::connectToServer")));
d->state = UnconnectedState; d->state = UnconnectedState;
emit error(d->error); emit error(d->error);
emit stateChanged(d->state); emit stateChanged(d->state);
return; return false;
} }
QString pipePath = QLatin1String("\\\\.\\pipe\\"); QString pipePath = QLatin1String("\\\\.\\pipe\\");
if (name.startsWith(pipePath)) if (d->serverName.startsWith(pipePath))
d->fullServerName = name; d->fullServerName = d->serverName;
else else
d->fullServerName = pipePath + name; d->fullServerName = pipePath + d->serverName;
// Try to open a named pipe // Try to open a named pipe
HANDLE localSocket; HANDLE localSocket;
forever { forever {
@ -184,15 +184,15 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
if (localSocket == INVALID_HANDLE_VALUE) { if (localSocket == INVALID_HANDLE_VALUE) {
d->setErrorString(QLatin1String("QLocalSocket::connectToServer")); d->setErrorString(QLatin1String("QLocalSocket::connectToServer"));
d->fullServerName = QString(); d->fullServerName = QString();
return; return false;
} }
// we have a valid handle // we have a valid handle
d->serverName = name;
if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode)) { if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode)) {
d->handle = localSocket; d->handle = localSocket;
emit connected(); emit connected();
} }
return true;
} }
// This is reading from the buffer // This is reading from the buffer