⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qunixsocket.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qunixsocket_p.h"// #define QUNIXSOCKET_DEBUG 1#include <QtCore/qsocketnotifier.h>#include <QtCore/qqueue.h>#include <QtCore/qdatetime.h>#ifdef QUNIXSOCKET_DEBUG#include <QtCore/qdebug.h>#endifextern "C" {#include <unistd.h>#include <string.h>#include <errno.h>#include <sys/socket.h>#include <sys/un.h>};#define UNIX_PATH_MAX 108 // From unix(7)#ifdef QT_LSB// LSB doesn't declare ucredstruct ucred{    pid_t pid;                    /* PID of sending process.  */    uid_t uid;                    /* UID of sending process.  */    gid_t gid;                    /* GID of sending process.  */};// LSB doesn't define the ones below#ifndef SO_PASSCRED#  define SO_PASSCRED   16#endif#ifndef SCM_CREDENTIALS#  define SCM_CREDENTIALS 0x02#endif#ifndef MSG_DONTWAIT#  define MSG_DONTWAIT 0x40#endif#ifndef MSG_NOSIGNAL#  define MSG_NOSIGNAL 0x4000#endif#endif // QT_LSB///////////////////////////////////////////////////////////////////////////////// class QUnixSocketRights////////////////////////////////////////////////////////////////////////////////*!  \class QUnixSocketRights  \internal  \brief The QUnixSocketRights class encapsulates QUnixSocket rights data.  \omit  \ingroup Platform::DeviceSpecific  \ingroup Platform::OS  \ingroup Platform::Communications  \endomit  \ingroup qws  \l QUnixSocket allows you to transfer Unix file descriptors between processes.  A file descriptor is referred to as "rights data" as it allows one process to  transfer its right to access a resource to another.  The Unix system verifies resource permissions only when the resource is first  opened.  For example, consider a file on disk readable only by the user "qt".  A process running as user "qt" will be able to open this file for reading.  If, while the process was still reading from the file, the ownership was  changed from user "qt" to user "root", the process would be allowed to  continue reading from the file, even though attempting to reopen the file  would be denied.  Permissions are associated with special descriptors called  file descriptors which are returned to a process after it initially opens a  resource.  File descriptors can be duplicated within a process through the dup(2) system  call.  File descriptors can be passed between processes using the  \l QUnixSocket class in the same way.  Even though the receiving process never  opened the resource directly, it has the same permissions to access it as the  process that did.  \sa QUnixSocket */struct QUnixSocketRightsPrivate : public QSharedData{    virtual ~QUnixSocketRightsPrivate() {#ifdef QUNIXSOCKET_DEBUG        int closerv =#endif            ::close(fd);#ifdef QUNIXSOCKET_DEBUG        if(0 != closerv) {            qDebug() << "QUnixSocketRightsPrivate: Unable to close managed"                        " file descriptor (" << ::strerror(errno) << ")";        }#endif    }    int fd;};/*!  Create a new QUnixSocketRights instance containing the file descriptor \a fd.  \a fd will be dup(2)'d internally, so the application is free to close \a fd  following this call.  If the dup(2) fails, or you pass an invalid \a fd, an  \l {QUnixSocketRights::isValid()}{invalid } object will be  constructed.  QUnixSocketRights instances are immutable and the internal file descriptor  will be shared between any copies made of this object.  The system will  close(2) the file descriptor once it is no longer needed.  */QUnixSocketRights::QUnixSocketRights(int fd){    d = new QUnixSocketRightsPrivate();    if(-1 == fd) {        d->fd = -1;    } else {        d->fd = ::dup(fd);#ifdef QUNIXSOCKET_DEBUG        if(-1 == d->fd) {            qDebug() << "QUnixSocketRights: Unable to duplicate fd "                     << fd << " (" << ::strerror(errno) << ")";        }#endif    }}/*!  \internal  Construct a QUnixSocketRights instance on \a fd without dup(2)'ing the file  descriptor.  */QUnixSocketRights::QUnixSocketRights(int fd,int){    Q_ASSERT(-1 != fd);    d = new QUnixSocketRightsPrivate();    d->fd = fd;}/*!  Destroys the QUnixSocketRights instance.  */QUnixSocketRights::~QUnixSocketRights(){}/*!  Create a copy of \a other.  */QUnixSocketRights &QUnixSocketRights::operator=(const QUnixSocketRights & other){    d = other.d;    return *this;}/*!  Create a copy of \a other.  */QUnixSocketRights::QUnixSocketRights(const QUnixSocketRights & other): d(other.d){}/*!  Returns true if this QUnixSocketRights instance is managing a valid file  descriptor.  This method is equivalent to (-1 != peekFd()).  \sa QUnixSocketRights::peekFd()  */bool QUnixSocketRights::isValid() const{    return d->fd != -1;}/*!  Return a duplicate of the file descriptor contained in this object.  If this  is an \l {QUnixSocketRights::isValid()}{invalid } object, or the  dup(2) call fails, an invalid file descriptor (-1) will be returned.  \sa QUnixSocketRights::peekFd()  */int QUnixSocketRights::dupFd() const{    if(-1 == d->fd) return -1;    int rv = ::dup(d->fd);#ifdef QUNIXSOCKET_DEBUG    if(-1 == rv)        qDebug() << "QUnixSocketRights: Unable to duplicate managed file "                    "descriptor (" << ::strerror(errno) << ")";#endif    return rv;}/*!  Returns the file descriptor contained in this object.  If this  is an \l {QUnixSocketRights::isValid()}{invalid } object an invalid  file descriptor (-1) will be returned.  The lifetime of this file descriptor is tied to the lifetime of the  QUnixSocketRights instance.  The file descriptor returned by this method  \e may be close(2)'d when the QUnixSocketRights instance is destroyed.  If  you want to continue to use the file descriptor use  \l QUnixSocketRights::dupFd() instead.  \sa QUnixSocketRights::dupFd()  */int QUnixSocketRights::peekFd() const{    return d->fd;}///////////////////////////////////////////////////////////////////////////////// class QUnixSocketMessage///////////////////////////////////////////////////////////////////////////////struct QUnixSocketMessagePrivate : public QSharedData{    QUnixSocketMessagePrivate()    : state(Default), vec(0), iovecLen(0), dataSize(0) {}    QUnixSocketMessagePrivate(const QByteArray & b)    : bytes(b), state(Default), vec(0), iovecLen(0), dataSize(0) {}    QUnixSocketMessagePrivate(const QByteArray & b,                              const QList<QUnixSocketRights> & r)    : bytes(b), rights(r), state(Default), vec(0), iovecLen(0), dataSize(0) {}    int size() const { return vec ? dataSize : bytes.size(); }    void removeBytes( unsigned int );    QByteArray bytes;    QList<QUnixSocketRights> rights;    enum AncillaryDataState {        Default = 0x00,        Truncated = 0x01,        Credential = 0x02    };    AncillaryDataState state;    pid_t pid;    gid_t gid;    uid_t uid;    ::iovec *vec;    int iovecLen;  // number of vectors in array    int dataSize;  // total size of vectors = payload};/*!  \internal  Remove \a bytesToDequeue bytes from the front of this message*/void QUnixSocketMessagePrivate::removeBytes( unsigned int bytesToDequeue ){    if ( vec )    {        ::iovec *vecPtr = vec;        if ( bytesToDequeue > (unsigned int)dataSize ) bytesToDequeue = dataSize;        while ( bytesToDequeue > 0 && iovecLen > 0 )        {            if ( vecPtr->iov_len > bytesToDequeue )            {                // dequeue the bytes by taking them off the front of the                // current vector.  since we don't own the iovec, its okay                // to "leak" this away by pointing past it                char **base = reinterpret_cast<char**>(&(vecPtr->iov_base));                *base += bytesToDequeue;                vecPtr->iov_len -= bytesToDequeue;                bytesToDequeue = 0;            }            else            {                // dequeue bytes by skipping a whole vector.  again, its ok                // to lose the pointers to this data                bytesToDequeue -= vecPtr->iov_len;                iovecLen--;                vecPtr++;            }        }        dataSize -= bytesToDequeue;        if ( iovecLen == 0 ) vec = 0;    }    else    {        bytes.remove(0, bytesToDequeue );    }}/*!  \class QUnixSocketMessage  \internal  \brief The QUnixSocketMessage class encapsulates a message sent or received  through the QUnixSocket class.  \omit  \ingroup Platform::DeviceSpecific  \ingroup Platform::OS  \ingroup Platform::Communications  \endomit  \ingroup qws  In addition to transmitting regular byte stream data, messages sent over Unix  domain sockets may have special ancillary properties.  QUnixSocketMessage  instances allow programmers to retrieve and control these properties.  Every QUnixSocketMessage sent has an associated set of credentials.  A  message's credentials consist of the process id, the user id and the group id  of the sending process.  Normally these credentials are set automatically for  you by the QUnixSocketMessage class and can be queried by the receiving  process using the \l QUnixSocketMessage::processId(),  \l QUnixSocketMessage::userId() and \l QUnixSocketMessage::groupId() methods  respectively.  Advanced applications may wish to change the credentials that their message  is sent with, and may do so though the \l QUnixSocketMessage::setProcessId(),  \l QUnixSocketMessage::setUserId() and \l QUnixSocketMessage::setGroupId()  methods.  The validity of these credentials is verified by the system kernel.  Only the root user can send messages with credentials that are not his own.  Sending of the message will fail for any non-root user who attempts to  fabricate credentials.  Note that this failure is enforced by the system  kernel - receivers can trust the accuracy of credential data!  Unix domain socket messages may also be used to transmit Unix file descriptors  between processes.  In this context, file descriptors are known as rights data  and are encapsulated by the \l QUnixSocketRights class.  Senders can set the  file descriptors to transmit using the \l QUnixSocketMessage::setRights() and  receivers can retrieve this data through a call to  \l QUnixSocketMessage::rights().  \l QUnixSocket and \l QUnixSocketRights  discuss the specific copy and ordering semantic associated with rights data.  QUnixSocketMessage messages are sent by the \l QUnixSocket::write() method.  Like any normal network message, attempting to transmit an empty  QUnixSocketMessage will succeed, but result in a no-op.  Limitations in the  Unix domain protocol semantic will cause a transmission of a  QUnixSocketMessage with rights data, but no byte data portion, to fail.  \sa QUnixSocket QUnixSocketRights  *//*!  Construct an empty QUnixSocketMessage.  This instance will have not data and  no rights information.  The message's credentials will be set to the  application's default credentials.  */QUnixSocketMessage::QUnixSocketMessage(): d(new QUnixSocketMessagePrivate()){}/*!  Construct a QUnixSocketMessage with an initial data payload of \a bytes.  The  message's credentials will be set to the application's default credentials.  */QUnixSocketMessage::QUnixSocketMessage(const QByteArray & bytes): d(new QUnixSocketMessagePrivate(bytes)){}/*!  Construct a QUnixSocketMessage with an initial data payload of \a bytes and  an initial rights payload of \a rights.  The message's credentials will be set  to the application's default credentials.  A message with rights data but an empty data payload cannot be transmitted  by the system.  */QUnixSocketMessage::QUnixSocketMessage(const QByteArray & bytes,                                       const QList<QUnixSocketRights> & rights): d(new QUnixSocketMessagePrivate(bytes, rights)){}/*!  Create a copy of \a other.  */QUnixSocketMessage::QUnixSocketMessage(const QUnixSocketMessage & other): d(other.d){}/*!  \fn  QUnixSocketMessage::QUnixSocketMessage(const iovec* data, int vecLen)  Construct a QUnixSocketMessage with an initial data payload of \a  data which points to an array of \a vecLen iovec structures.  The  message's credentials will be set to the application's default  credentials.  This method can be used to avoid the overhead of copying buffers of data  and will directly send the data pointed to by \a data on the socket.  It also  avoids the syscall overhead of making a number of small socket write calls,  if a number of data items can be delivered with one write.  Caller must ensure the iovec * \a data remains valid until the message

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -