summaryrefslogtreecommitdiffstats
path: root/src/gui/embedded/qwssocket_qws.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/embedded/qwssocket_qws.cpp')
-rw-r--r--src/gui/embedded/qwssocket_qws.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/gui/embedded/qwssocket_qws.cpp b/src/gui/embedded/qwssocket_qws.cpp
new file mode 100644
index 0000000000..463af6c336
--- /dev/null
+++ b/src/gui/embedded/qwssocket_qws.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qwssocket_qws.h"
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+#include <fcntl.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/un.h>
+
+#ifdef __MIPSEL__
+# ifndef SOCK_DGRAM
+# define SOCK_DGRAM 1
+# endif
+# ifndef SOCK_STREAM
+# define SOCK_STREAM 2
+# endif
+#endif
+
+#if defined(Q_OS_SOLARIS) || defined (QT_LINUXBASE)
+// uff-da apparently Solaris doesn't have the SUN_LEN macro, here is
+// an implementation of it...
+# ifndef SUN_LEN
+# define SUN_LEN(su) \
+ sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)
+# endif
+
+// nor the POSIX names of UNIX domain sockets *sigh*
+# ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+# endif
+# ifndef PF_LOCAL
+# define PF_LOCAL PF_UNIX
+# endif
+#endif // Q_OS_SOLARIS || QT_LINUXBASE
+
+QT_BEGIN_NAMESPACE
+
+/***********************************************************************
+ *
+ * QWSSocket
+ *
+ **********************************************************************/
+QWSSocket::QWSSocket(QObject *parent)
+ : QWS_SOCK_BASE(parent)
+{
+#ifndef QT_NO_SXE
+ QObject::connect( this, SIGNAL(stateChanged(SocketState)),
+ this, SLOT(forwardStateChange(SocketState)));
+#endif
+}
+
+QWSSocket::~QWSSocket()
+{
+}
+
+#ifndef QT_NO_SXE
+QString QWSSocket::errorString()
+{
+ switch (QUnixSocket::error()) {
+ case NoError:
+ return QString();
+ case InvalidPath:
+ case NonexistentPath:
+ return QLatin1String("Bad path"); // NO_TR
+ default:
+ return QLatin1String("Bad socket"); // NO TR
+ }
+}
+
+void QWSSocket::forwardStateChange(QUnixSocket::SocketState st )
+{
+ switch ( st )
+ {
+ case ConnectedState:
+ emit connected();
+ break;
+ case ClosingState:
+ break;
+ case UnconnectedState:
+ emit disconnected();
+ break;
+ default:
+ // nothing
+ break;
+ }
+ if ( QUnixSocket::error() != NoError )
+ emit error((QAbstractSocket::SocketError)0);
+}
+#endif
+
+bool QWSSocket::connectToLocalFile(const QString &file)
+{
+#ifndef QT_NO_SXE
+ bool result = QUnixSocket::connect( file.toLocal8Bit() );
+ if ( !result )
+ {
+ perror( "QWSSocketAuth::connectToLocalFile could not connect:" );
+ emit error(QAbstractSocket::ConnectionRefusedError);
+ return false;
+ }
+ return true;
+#else
+ // create socket
+ int s = ::socket(PF_LOCAL, SOCK_STREAM, 0);
+
+ // connect to socket
+ struct sockaddr_un a;
+ memset(&a, 0, sizeof(a));
+ a.sun_family = PF_LOCAL;
+ strncpy(a.sun_path, file.toLocal8Bit().constData(), sizeof(a.sun_path) - 1);
+ int r = ::connect(s, (struct sockaddr*)&a, SUN_LEN(&a));
+ if (r == 0) {
+ setSocketDescriptor(s);
+ } else {
+ perror("QWSSocket::connectToLocalFile could not connect:");
+ ::close(s);
+ emit error(ConnectionRefusedError);
+ return false;
+ }
+#endif
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * QWSServerSocket
+ *
+ **********************************************************************/
+QWSServerSocket::QWSServerSocket(const QString& file, QObject *parent)
+#ifndef QT_NO_SXE
+ : QUnixSocketServer(parent)
+#else
+ : QTcpServer(parent)
+#endif
+{
+ init(file);
+}
+
+void QWSServerSocket::init(const QString &file)
+{
+#ifndef QT_NO_SXE
+ QByteArray fn = file.toLocal8Bit();
+ bool result = QUnixSocketServer::listen( fn );
+ if ( !result )
+ {
+ QUnixSocketServer::ServerError err = serverError();
+ switch ( err )
+ {
+ case InvalidPath:
+ qWarning("QWSServerSocket:: invalid path %s", qPrintable(file));
+ break;
+ case ResourceError:
+ case BindError:
+ case ListenError:
+ qWarning("QWSServerSocket:: could not listen on path %s", qPrintable(file));
+ break;
+ default:
+ break;
+ }
+ }
+#else
+ int backlog = 16; //#####
+
+// create socket
+ int s = ::socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (s == -1) {
+ perror("QWSServerSocket::init");
+ qWarning("QWSServerSocket: unable to create socket.");
+ return;
+ }
+
+ QByteArray fn = file.toLocal8Bit();
+ unlink(fn.constData()); // doesn't have to succeed
+
+ // bind socket
+ struct sockaddr_un a;
+ memset(&a, 0, sizeof(a));
+ a.sun_family = PF_LOCAL;
+ strncpy(a.sun_path, fn.constData(), sizeof(a.sun_path) - 1);
+ int r = ::bind(s, (struct sockaddr*)&a, SUN_LEN(&a));
+ if (r < 0) {
+ perror("QWSServerSocket::init");
+ qWarning("QWSServerSocket: could not bind to file %s", fn.constData());
+ ::close(s);
+ return;
+ }
+
+ if (chmod(fn.constData(), 0600) < 0) {
+ perror("QWSServerSocket::init");
+ qWarning("Could not set permissions of %s", fn.constData());
+ ::close(s);
+ return;
+ }
+
+ // listen
+ if (::listen(s, backlog) == 0) {
+ if (!setSocketDescriptor(s))
+ qWarning( "QWSServerSocket could not set descriptor %d : %s", s, errorString().toLatin1().constData());
+ } else {
+ perror("QWSServerSocket::init");
+ qWarning("QWSServerSocket: could not listen to file %s", fn.constData());
+ ::close(s);
+ }
+#endif
+}
+
+QWSServerSocket::~QWSServerSocket()
+{
+}
+
+#ifndef QT_NO_SXE
+
+void QWSServerSocket::incomingConnection(int socketDescriptor)
+{
+ inboundConnections.append( socketDescriptor );
+ emit newConnection();
+}
+
+
+QWSSocket *QWSServerSocket::nextPendingConnection()
+{
+ QMutexLocker locker( &ssmx );
+ if ( inboundConnections.count() == 0 )
+ return 0;
+ QWSSocket *s = new QWSSocket();
+ s->setSocketDescriptor( inboundConnections.takeFirst() );
+ return s;
+}
+
+#endif // QT_NO_SXE
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_QWS_MULTIPROCESS