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

📄 qunixsocket.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
  is flushed.  Caller retains ownership of the iovec structs.  */QUnixSocketMessage::QUnixSocketMessage(const ::iovec* data, int vecLen ): d(new QUnixSocketMessagePrivate()){    for ( int v = 0; v < vecLen; v++ )        d->dataSize += data[v].iov_len;    d->vec = const_cast<iovec*>(data);    d->iovecLen = vecLen;}/*!  Assign the contents of \a other to this object.  */QUnixSocketMessage & QUnixSocketMessage::operator=(const QUnixSocketMessage & other){    d = other.d;    return *this;}/*!  Destroy this instance.  */QUnixSocketMessage::~QUnixSocketMessage(){}/*!  Set the data portion of the message to \a bytes.  \sa QUnixSocketMessage::bytes()  */void QUnixSocketMessage::setBytes(const QByteArray & bytes){    d.detach();    d->bytes = bytes;}/*!  Set the rights portion of the message to \a rights.  A message with rights data but an empty byte data payload cannot be  transmitted by the system.  \sa QUnixSocketMessage::rights()  */void QUnixSocketMessage::setRights(const QList<QUnixSocketRights> & rights){    d.detach();    d->rights = rights;}/*!  Return the rights portion of the message.  \sa QUnixSocketMessage::setRights()  */const QList<QUnixSocketRights> & QUnixSocketMessage::rights() const{    return d->rights;}/*!  Returns true if the rights portion of the message was truncated on reception  due to insufficient buffer size.  The rights buffer size can be adjusted  through calls to the \l QUnixSocket::setRightsBufferSize() method.  \l QUnixSocket contains a discussion of the buffering and truncation  characteristics of the Unix domain protocol.  \sa QUnixSocket QUnixSocket::setRightsBufferSize()  */bool QUnixSocketMessage::rightsWereTruncated() const{    return d->state & QUnixSocketMessagePrivate::Truncated;}/*!  Return the data portion of the message.  \sa QUnixSocketMessage::setBytes()  */const QByteArray & QUnixSocketMessage::bytes() const{    return d->bytes;}/*!  Returns the process id credential associated with this message.  \sa QUnixSocketMessage::setProcessId()  */pid_t QUnixSocketMessage::processId() const{    if(QUnixSocketMessagePrivate::Credential & d->state)        return d->pid;    else        return ::getpid();}/*!  Returns the user id credential associated with this message.  \sa QUnixSocketMessage::setUserId()  */uid_t QUnixSocketMessage::userId() const{    if(QUnixSocketMessagePrivate::Credential & d->state)        return d->uid;    else        return ::geteuid();}/*!  Returns the group id credential associated with this message.  \sa QUnixSocketMessage::setGroupId()  */gid_t QUnixSocketMessage::groupId() const{    if(QUnixSocketMessagePrivate::Credential & d->state)        return d->gid;    else        return ::getegid();}/*!  Set the process id credential associated with this message to \a pid.  Unless  you are the root user, setting a fraudulant credential will cause this message  to fail.  \sa QUnixSocketMessage::processId() */void QUnixSocketMessage::setProcessId(pid_t pid){    if(!(d->state & QUnixSocketMessagePrivate::Credential)) {        d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );        d->uid = ::geteuid();        d->gid = ::getegid();    }    d->pid = pid;}/*!  Set the user id credential associated with this message to \a uid.  Unless  you are the root user, setting a fraudulant credential will cause this message  to fail.  \sa QUnixSocketMessage::userId() */void QUnixSocketMessage::setUserId(uid_t uid){    if(!(d->state & QUnixSocketMessagePrivate::Credential)) {        d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );        d->pid = ::getpid();        d->gid = ::getegid();    }    d->uid = uid;}/*!  Set the group id credential associated with this message to \a gid.  Unless  you are the root user, setting a fraudulant credential will cause this message  to fail.  \sa QUnixSocketMessage::groupId() */void QUnixSocketMessage::setGroupId(gid_t gid){    if(!(d->state & QUnixSocketMessagePrivate::Credential)) {        d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );        d->pid = ::getpid();        d->uid = ::geteuid();    }    d->gid = gid;}/*!  Return true if this message is valid.  A message with rights data but an empty  byte data payload cannot be transmitted by the system and is marked as  invalid.  */bool QUnixSocketMessage::isValid() const{    return d->rights.isEmpty() || !d->bytes.isEmpty();}///////////////////////////////////////////////////////////////////////////////// class QUnixSocket///////////////////////////////////////////////////////////////////////////////#define QUNIXSOCKET_DEFAULT_READBUFFER 1024#define QUNIXSOCKET_DEFAULT_ANCILLARYBUFFER 0/*!  \class QUnixSocket  \internal  \brief The QUnixSocket class provides a Unix domain socket.  \omit  \ingroup Platform::DeviceSpecific  \ingroup Platform::OS  \ingroup Platform::Communications  \endomit  \ingroup qws  Unix domain sockets provide an efficient mechanism for communications between  Unix processes on the same machine.  Unix domain sockets support a reliable,  stream-oriented, connection-oriented transport protocol, much like TCP  sockets.  Unlike IP based sockets, the connection endpoint of a Unix domain  socket is a file on disk of type socket.  In addition to transporting raw data bytes, Unix domain sockets are able to  transmit special ancillary data.  The two types of ancillary data supported  by the QUnixSocket class are:  \list  \o Credential Data - Allows a receiver  to reliably identify the process sending each message.  \o \l {QUnixSocketRights}{Rights Data } - Allows Unix file descriptors  to be transmitted between processes.  \endlist  Because of the need to support ancillary data, QUnixSocket is not a QIODevice,  like QTcpSocket and QUdpSocket.  Instead, QUnixSocket contains a number of  read and write methods that clients must invoke directly.  Rather than  returning raw data bytes, \l QUnixSocket::read() returns \l QUnixSocketMessage  instances that encapsulate the message's byte data and any other ancillary  data.  Ancillary data is transmitted "out of band".  Every \l QUnixSocketMessage  received will have credential data associated with it that the client can  access through calls to \l QUnixSocketMessage::processId(),  \l QUnixSocketMessage::groupId() and \l QUnixSocketMessage::userId().  Likewise, message creators can set the credential data to send through calls  to \l QUnixSocketMessage::setProcessId(), \l QUnixSocketMessage::setGroupId()  and \l QUnixSocketMessage::setUserId() respectively.  The authenticity of the  credential values is verified by the system kernel and cannot be fabricated  by unprivileged processes.  Only processes running as the root user can  specify credential data that does not match the sending process.  Unix file descriptors, known as "rights data", transmitted between processes  appear as though they had been dup(2)'d between the two.  As Unix  domain sockets present a continuous stream of bytes to the receiver, the  rights data - which is transmitted out of band - must be "slotted" in at some  point.  The rights data is logically associated with the first byte - called  the anchor byte - of the \l QUnixSocketMessage to which they are attached.  Received rights data will be available from the  \l QUnixSocketMessage::rights() method for the \l QUnixSocketMessage  instance that contains the anchor byte.  In addition to a \l QUnixSocket::write() that takes a \l QUnixSocketMessage  instance - allowing a client to transmit both byte and rights data - a  number of convenience overloads are provided for use when only transmitting  simple byte data.  Unix requires that at least one byte of raw data be  transmitted in order to send rights data.  A \l QUnixSocketMessage instance  with rights data, but no byte data, cannot be transmitted.  Unix sockets present a stream interface, such that, for example, a single  six byte transmission might be received as two three byte messages.  Rights  data, on the other hand, is conceptually transmitted as unfragmentable  datagrams.  If the receiving buffer is not large enough to contain all the  transmitted rights information, the data is truncated and irretreivably lost.  Users should use the \l QUnixSocket::setRightsBufferSize() method to control  the buffer size used for this data, and develop protocols that avoid the  problem.  If the buffer size is too small and rights data is truncated,  the \l QUnixSocketMessage::rightsWereTruncated() flag will be set.  \sa QUnixSocketMessage QUnixSocketRights*//*!  \enum QUnixSocket::SocketError  The SocketError enumeration represents the various errors that can occur on  a Unix domain socket.  The most recent error for the socket is available  through the \l QUnixSocket::error() method.  \value NoError No error has occurred.  \value InvalidPath An invalid path endpoint was passed to         \l QUnixSocket::connect().  As defined by unix(7), invalid paths         include an empty path, or what more than 107 characters long.  \value ResourceError An error acquiring or manipulating the system's socket         resources occurred.  For example, if the process runs out of available         socket descriptors, a ResourceError will occur.  \value NonexistentPath The endpoing passed to \l QUnixSocket::connect() does         not refer to a Unix domain socket entity on disk.  \value ConnectionRefused The connection to the specified endpoint was refused.         Generally this means that there is no server listening on that         endpoint.  \value UnknownError An unknown error has occurred.  \value ReadFailure An error occurred while reading bytes from the connection.  \value WriteFailure An error occurred while writing bytes into the connection.  *//*!  \enum QUnixSocket::SocketState  The SocketState enumeration represents the connection state of a QUnixSocket  instance.  \value UnconnectedState The connection is not established.  \value ConnectedState The connection is established.  \value ClosingState The connection is being closed, following a call to         \l QUnixSocket::close().  While closing, any pending data will be         transmitted, but further writes by the application will be refused.  *//*  \fn QUnixSocket::bytesWritten(qint64 bytes)  This signal is emitted every time a payload of data has been written to the  connection.  The \a bytes argument is set to the number of bytes that were  written in this payload.  \sa QUnixSocket::readyRead()*//*  \fn QUnixSocket::readyRead()  This signal is emitted once every time new data is available for reading from  the connection. It will only be emitted again once new data is available.  \sa QUnixSocket::bytesWritten()*//*!  \fn QUnixSocket::stateChanged(SocketState socketState)  This signal is emitted each time the socket changes connection state.  \a socketState will be set to the socket's new state.*/class QUnixSocketPrivate : public QObject {Q_OBJECTpublic:    QUnixSocketPrivate(QUnixSocket * _me)    : me(_me), fd(-1), readNotifier(0), writeNotifier(0),      state(QUnixSocket::UnconnectedState), error(QUnixSocket::NoError),      writeQueueBytes(0), messageValid(false), dataBuffer(0),      dataBufferLength(0), dataBufferCapacity(0), ancillaryBuffer(0),      ancillaryBufferCount(0), closingTimer(0) {          QObject::connect(this, SIGNAL(readyRead()), me, SIGNAL(readyRead()));          QObject::connect(this, SIGNAL(bytesWritten(qint64)),                           me, SIGNAL(bytesWritten(qint64)));      }    ~QUnixSocketPrivate()    {        if(dataBuffer)            delete [] dataBuffer;        if(ancillaryBuffer)            delete [] ancillaryBuffer;    }    enum { CausedAbort = 0x70000000 };    QUnixSocket * me;    int fd;    QSocketNotifier * readNotifier;    QSocketNotifier * writeNotifier;    QUnixSocket::SocketState state;    QUnixSocket::SocketError error;    QQueue<QUnixSocketMessage> writeQueue;    unsigned int writeQueueBytes;    bool messageValid;    ::msghdr message;    inline void flushAncillary()    {        if(!messageValid) return;        ::cmsghdr * h = (::cmsghdr *)CMSG_FIRSTHDR(&(message));        while(h) {            if(SCM_RIGHTS == h->cmsg_type) {                int * fds = (int *)CMSG_DATA(h);                int numFds = (h->cmsg_len - CMSG_LEN(0)) / sizeof(int);                for(int ii = 0; ii < numFds; ++ii)                    ::close(fds[ii]);            }            h = (::cmsghdr *)CMSG_NXTHDR(&(message), h);        }        messageValid = false;    }    char * dataBuffer;    unsigned int dataBufferLength;    unsigned int dataBufferCapacity;    char * ancillaryBuffer;    inline unsigned int ancillaryBufferCapacity()    {        return CMSG_SPACE(sizeof(::ucred)) + CMSG_SPACE(sizeof(int) * ancillaryBufferCount);    }    unsigned int ancillaryBufferCount;    QByteArray address;    int closingTimer;    virtual void timerEvent(QTimerEvent *)    {        me->abort();        killTimer(closingTimer);        closingTimer = 0;    }signals:    void readyRead();    void bytesWritten(qint64);public slots:    void readActivated();    void writeActivated();};/*!  Construct a QUnixSocket instance, with \a parent.  The read buffer is initially set to 1024 bytes, and the rights buffer to 0  entries.  \sa QUnixSocket::readBufferSize() QUnixSocket::rightsBufferSize()  */QUnixSocket::QUnixSocket(QObject * parent): QIODevice(parent), d(new QUnixSocketPrivate(this)){    setOpenMode(QIODevice::NotOpen);    setReadBufferSize(QUNIXSOCKET_DEFAULT_READBUFFER);    setRightsBufferSize(QUNIXSOCKET_DEFAULT_ANCILLARYBUFFER);}

⌨️ 快捷键说明

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