src/gui/embedded/qwssocket_qws.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/embedded/qwssocket_qws.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 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