/******************************************************************************** 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_LINUXBASEQT_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_SXEQString 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);}#endifbool 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_SXEvoid 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_SXEQT_END_NAMESPACE#endif //QT_NO_QWS_MULTIPROCESS