1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qunixsocket_p.h"
43 
44 // #define QUNIXSOCKET_DEBUG 1
45 
46 #include <QtCore/qsocketnotifier.h>
47 #include <QtCore/qqueue.h>
48 #include <QtCore/qdatetime.h>
49 #include "private/qcore_unix_p.h" // overrides QT_OPEN
50 
51 #ifdef QUNIXSOCKET_DEBUG
52 #include <QtCore/qdebug.h>
53 #endif
54 
55 extern "C" {
56 #include <unistd.h>
57 #include <string.h>
58 #include <errno.h>
59 #include <sys/socket.h>
60 #include <sys/un.h>
61 };
62 
63 #define UNIX_PATH_MAX 108 // From unix(7)
64 
65 #ifdef QT_LINUXBASE
66 // LSB doesn't declare ucred
67 struct ucred
68 {
69     pid_t pid;                    /* PID of sending process.  */
70     uid_t uid;                    /* UID of sending process.  */
71     gid_t gid;                    /* GID of sending process.  */
72 };
73 
74 // LSB doesn't define the ones below
75 #ifndef SO_PASSCRED
76 #  define SO_PASSCRED   16
77 #endif
78 #ifndef SCM_CREDENTIALS
79 #  define SCM_CREDENTIALS 0x02
80 #endif
81 #ifndef MSG_DONTWAIT
82 #  define MSG_DONTWAIT 0x40
83 #endif
84 #ifndef MSG_NOSIGNAL
85 #  define MSG_NOSIGNAL 0x4000
86 #endif
87 
88 #endif // QT_LINUXBASE
89 
90 QT_BEGIN_NAMESPACE
91 
92 ///////////////////////////////////////////////////////////////////////////////
93 // class QUnixSocketRights
94 ///////////////////////////////////////////////////////////////////////////////
95 /*!
96   \class QUnixSocketRights
97   \internal
98 
99   \brief The QUnixSocketRights class encapsulates QUnixSocket rights data.
100   \omit
101   \ingroup Platform::DeviceSpecific
102   \ingroup Platform::OS
103   \ingroup Platform::Communications
104   \endomit
105   \ingroup qws
106 
107   \l QUnixSocket allows you to transfer Unix file descriptors between processes.
108   A file descriptor is referred to as "rights data" as it allows one process to
109   transfer its right to access a resource to another.
110 
111   The Unix system verifies resource permissions only when the resource is first
112   opened.  For example, consider a file on disk readable only by the user "qt".
113   A process running as user "qt" will be able to open this file for reading.
114   If, while the process was still reading from the file, the ownership was
115   changed from user "qt" to user "root", the process would be allowed to
116   continue reading from the file, even though attempting to reopen the file
117   would be denied.  Permissions are associated with special descriptors called
118   file descriptors which are returned to a process after it initially opens a
119   resource.
120 
121   File descriptors can be duplicated within a process through the dup(2) system
122   call.  File descriptors can be passed between processes using the
123   \l QUnixSocket class in the same way.  Even though the receiving process never
124   opened the resource directly, it has the same permissions to access it as the
125   process that did.
126 
127   \sa QUnixSocket
128  */
129 struct QUnixSocketRightsPrivate : public QSharedData
130 {
~QUnixSocketRightsPrivateQUnixSocketRightsPrivate131     virtual ~QUnixSocketRightsPrivate() {
132 #ifdef QUNIXSOCKET_DEBUG
133         int closerv =
134 #endif
135             QT_CLOSE(fd);
136 #ifdef QUNIXSOCKET_DEBUG
137         if(0 != closerv) {
138             qDebug() << "QUnixSocketRightsPrivate: Unable to close managed"
139                         " file descriptor (" << ::strerror(errno) << ')';
140         }
141 #endif
142     }
143 
144     int fd;
145 };
146 
147 /*!
148   Create a new QUnixSocketRights instance containing the file descriptor \a fd.
149   \a fd will be dup(2)'d internally, so the application is free to close \a fd
150   following this call.
151 
152   If the dup(2) fails, or you pass an invalid \a fd, an
153   \l {QUnixSocketRights::isValid()}{invalid } object will be
154   constructed.
155 
156   QUnixSocketRights instances are immutable and the internal file descriptor
157   will be shared between any copies made of this object.  The system will
158   close(2) the file descriptor once it is no longer needed.
159   */
QUnixSocketRights(int fd)160 QUnixSocketRights::QUnixSocketRights(int fd)
161 {
162     d = new QUnixSocketRightsPrivate();
163     if(-1 == fd) {
164         d->fd = -1;
165     } else {
166         d->fd = qt_safe_dup(fd);
167 #ifdef QUNIXSOCKET_DEBUG
168         if(-1 == d->fd) {
169             qDebug() << "QUnixSocketRights: Unable to duplicate fd "
170                      << fd << " (" << ::strerror(errno) << ')';
171         }
172 #endif
173     }
174 }
175 
176 /*!
177   \internal
178 
179   Construct a QUnixSocketRights instance on \a fd without dup(2)'ing the file
180   descriptor.
181   */
QUnixSocketRights(int fd,int)182 QUnixSocketRights::QUnixSocketRights(int fd,int)
183 {
184     Q_ASSERT(-1 != fd);
185     d = new QUnixSocketRightsPrivate();
186     d->fd = fd;
187 }
188 
189 /*!
190   Destroys the QUnixSocketRights instance.
191   */
~QUnixSocketRights()192 QUnixSocketRights::~QUnixSocketRights()
193 {
194 }
195 
196 /*!
197   Create a copy of \a other.
198   */
199 QUnixSocketRights &
operator =(const QUnixSocketRights & other)200 QUnixSocketRights::operator=(const QUnixSocketRights & other)
201 {
202     d = other.d;
203     return *this;
204 }
205 
206 /*!
207   Create a copy of \a other.
208   */
QUnixSocketRights(const QUnixSocketRights & other)209 QUnixSocketRights::QUnixSocketRights(const QUnixSocketRights & other)
210 : d(other.d)
211 {
212 }
213 
214 /*!
215   Returns true if this QUnixSocketRights instance is managing a valid file
216   descriptor.  This method is equivalent to (-1 != peekFd()).
217 
218   \sa QUnixSocketRights::peekFd()
219   */
isValid() const220 bool QUnixSocketRights::isValid() const
221 {
222     return d->fd != -1;
223 }
224 
225 /*!
226   Return a duplicate of the file descriptor contained in this object.  If this
227   is an \l {QUnixSocketRights::isValid()}{invalid } object, or the
228   dup(2) call fails, an invalid file descriptor (-1) will be returned.
229 
230   \sa QUnixSocketRights::peekFd()
231   */
dupFd() const232 int QUnixSocketRights::dupFd() const
233 {
234     if(-1 == d->fd) return -1;
235 
236     int rv = qt_safe_dup(d->fd);
237 
238 #ifdef QUNIXSOCKET_DEBUG
239     if(-1 == rv)
240         qDebug() << "QUnixSocketRights: Unable to duplicate managed file "
241                     "descriptor (" << ::strerror(errno) << ')';
242 #endif
243 
244     return rv;
245 }
246 
247 /*!
248   Returns the file descriptor contained in this object.  If this
249   is an \l {QUnixSocketRights::isValid()}{invalid } object an invalid
250   file descriptor (-1) will be returned.
251 
252   The lifetime of this file descriptor is tied to the lifetime of the
253   QUnixSocketRights instance.  The file descriptor returned by this method
254   \e may be close(2)'d when the QUnixSocketRights instance is destroyed.  If
255   you want to continue to use the file descriptor use
256   \l QUnixSocketRights::dupFd() instead.
257 
258   \sa QUnixSocketRights::dupFd()
259   */
peekFd() const260 int QUnixSocketRights::peekFd() const
261 {
262     return d->fd;
263 }
264 
265 ///////////////////////////////////////////////////////////////////////////////
266 // class QUnixSocketMessage
267 ///////////////////////////////////////////////////////////////////////////////
268 struct QUnixSocketMessagePrivate : public QSharedData
269 {
QUnixSocketMessagePrivateQUnixSocketMessagePrivate270     QUnixSocketMessagePrivate()
271     : state(Default), vec(0), iovecLen(0), dataSize(0) {}
QUnixSocketMessagePrivateQUnixSocketMessagePrivate272     QUnixSocketMessagePrivate(const QByteArray & b)
273     : bytes(b), state(Default), vec(0), iovecLen(0), dataSize(0) {}
QUnixSocketMessagePrivateQUnixSocketMessagePrivate274     QUnixSocketMessagePrivate(const QByteArray & b,
275                               const QList<QUnixSocketRights> & r)
276     : bytes(b), rights(r), state(Default), vec(0), iovecLen(0), dataSize(0) {}
277 
sizeQUnixSocketMessagePrivate278     int size() const { return vec ? dataSize : bytes.size(); }
279     void removeBytes( unsigned int );
280 
281     QByteArray bytes;
282     QList<QUnixSocketRights> rights;
283 
284     enum AncillaryDataState {
285         Default = 0x00,
286         Truncated = 0x01,
287         Credential = 0x02
288     };
289     AncillaryDataState state;
290 
291     pid_t pid;
292     gid_t gid;
293     uid_t uid;
294 
295     ::iovec *vec;
296     int iovecLen;  // number of vectors in array
297     int dataSize;  // total size of vectors = payload
298 };
299 
300 /*!
301   \internal
302   Remove \a bytesToDequeue bytes from the front of this message
303 */
removeBytes(unsigned int bytesToDequeue)304 void QUnixSocketMessagePrivate::removeBytes( unsigned int bytesToDequeue )
305 {
306     if ( vec )
307     {
308         ::iovec *vecPtr = vec;
309         if ( bytesToDequeue > (unsigned int)dataSize ) bytesToDequeue = dataSize;
310         while ( bytesToDequeue > 0 && iovecLen > 0 )
311         {
312             if ( vecPtr->iov_len > bytesToDequeue )
313             {
314                 // dequeue the bytes by taking them off the front of the
315                 // current vector.  since we don't own the iovec, its okay
316                 // to "leak" this away by pointing past it
317                 char **base = reinterpret_cast<char**>(&(vecPtr->iov_base));
318                 *base += bytesToDequeue;
319                 vecPtr->iov_len -= bytesToDequeue;
320                 bytesToDequeue = 0;
321             }
322             else
323             {
324                 // dequeue bytes by skipping a whole vector.  again, its ok
325                 // to lose the pointers to this data
326                 bytesToDequeue -= vecPtr->iov_len;
327                 iovecLen--;
328                 vecPtr++;
329             }
330         }
331         dataSize -= bytesToDequeue;
332         if ( iovecLen == 0 ) vec = 0;
333     }
334     else
335     {
336         bytes.remove(0, bytesToDequeue );
337     }
338 }
339 
340 
341 /*!
342   \class QUnixSocketMessage
343   \internal
344 
345   \brief The QUnixSocketMessage class encapsulates a message sent or received
346   through the QUnixSocket class.
347   \omit
348   \ingroup Platform::DeviceSpecific
349   \ingroup Platform::OS
350   \ingroup Platform::Communications
351   \endomit
352   \ingroup qws
353 
354   In addition to transmitting regular byte stream data, messages sent over Unix
355   domain sockets may have special ancillary properties.  QUnixSocketMessage
356   instances allow programmers to retrieve and control these properties.
357 
358   Every QUnixSocketMessage sent has an associated set of credentials.  A
359   message's credentials consist of the process id, the user id and the group id
360   of the sending process.  Normally these credentials are set automatically for
361   you by the QUnixSocketMessage class and can be queried by the receiving
362   process using the \l QUnixSocketMessage::processId(),
363   \l QUnixSocketMessage::userId() and \l QUnixSocketMessage::groupId() methods
364   respectively.
365 
366   Advanced applications may wish to change the credentials that their message
367   is sent with, and may do so though the \l QUnixSocketMessage::setProcessId(),
368   \l QUnixSocketMessage::setUserId() and \l QUnixSocketMessage::setGroupId()
369   methods.  The validity of these credentials is verified by the system kernel.
370   Only the root user can send messages with credentials that are not his own.
371   Sending of the message will fail for any non-root user who attempts to
372   fabricate credentials.  Note that this failure is enforced by the system
373   kernel - receivers can trust the accuracy of credential data!
374 
375   Unix domain socket messages may also be used to transmit Unix file descriptors
376   between processes.  In this context, file descriptors are known as rights data
377   and are encapsulated by the \l QUnixSocketRights class.  Senders can set the
378   file descriptors to transmit using the \l QUnixSocketMessage::setRights() and
379   receivers can retrieve this data through a call to
380   \l QUnixSocketMessage::rights().  \l QUnixSocket and \l QUnixSocketRights
381   discuss the specific copy and ordering semantic associated with rights data.
382 
383   QUnixSocketMessage messages are sent by the \l QUnixSocket::write() method.
384   Like any normal network message, attempting to transmit an empty
385   QUnixSocketMessage will succeed, but result in a no-op.  Limitations in the
386   Unix domain protocol semantic will cause a transmission of a
387   QUnixSocketMessage with rights data, but no byte data portion, to fail.
388 
389   \sa QUnixSocket QUnixSocketRights
390   */
391 
392 /*!
393   Construct an empty QUnixSocketMessage.  This instance will have not data and
394   no rights information.  The message's credentials will be set to the
395   application's default credentials.
396   */
QUnixSocketMessage()397 QUnixSocketMessage::QUnixSocketMessage()
398 : d(new QUnixSocketMessagePrivate())
399 {
400 }
401 
402 /*!
403   Construct a QUnixSocketMessage with an initial data payload of \a bytes.  The
404   message's credentials will be set to the application's default credentials.
405   */
QUnixSocketMessage(const QByteArray & bytes)406 QUnixSocketMessage::QUnixSocketMessage(const QByteArray & bytes)
407 : d(new QUnixSocketMessagePrivate(bytes))
408 {
409 }
410 
411 /*!
412   Construct a QUnixSocketMessage with an initial data payload of \a bytes and
413   an initial rights payload of \a rights.  The message's credentials will be set
414   to the application's default credentials.
415 
416   A message with rights data but an empty data payload cannot be transmitted
417   by the system.
418   */
QUnixSocketMessage(const QByteArray & bytes,const QList<QUnixSocketRights> & rights)419 QUnixSocketMessage::QUnixSocketMessage(const QByteArray & bytes,
420                                        const QList<QUnixSocketRights> & rights)
421 : d(new QUnixSocketMessagePrivate(bytes, rights))
422 {
423 }
424 
425 /*!
426   Create a copy of \a other.
427   */
QUnixSocketMessage(const QUnixSocketMessage & other)428 QUnixSocketMessage::QUnixSocketMessage(const QUnixSocketMessage & other)
429 : d(other.d)
430 {
431 }
432 
433 /*!
434   \fn  QUnixSocketMessage::QUnixSocketMessage(const iovec* data, int vecLen)
435 
436   Construct a QUnixSocketMessage with an initial data payload of \a
437   data which points to an array of \a vecLen iovec structures.  The
438   message's credentials will be set to the application's default
439   credentials.
440 
441   This method can be used to avoid the overhead of copying buffers of data
442   and will directly send the data pointed to by \a data on the socket.  It also
443   avoids the syscall overhead of making a number of small socket write calls,
444   if a number of data items can be delivered with one write.
445 
446   Caller must ensure the iovec * \a data remains valid until the message
447   is flushed.  Caller retains ownership of the iovec structs.
448   */
QUnixSocketMessage(const::iovec * data,int vecLen)449 QUnixSocketMessage::QUnixSocketMessage(const ::iovec* data, int vecLen )
450 : d(new QUnixSocketMessagePrivate())
451 {
452     for ( int v = 0; v < vecLen; v++ )
453         d->dataSize += data[v].iov_len;
454     d->vec = const_cast<iovec*>(data);
455     d->iovecLen = vecLen;
456 }
457 
458 /*!
459   Assign the contents of \a other to this object.
460   */
operator =(const QUnixSocketMessage & other)461 QUnixSocketMessage & QUnixSocketMessage::operator=(const QUnixSocketMessage & other)
462 {
463     d = other.d;
464     return *this;
465 }
466 
467 /*!
468   Destroy this instance.
469   */
~QUnixSocketMessage()470 QUnixSocketMessage::~QUnixSocketMessage()
471 {
472 }
473 
474 /*!
475   Set the data portion of the message to \a bytes.
476 
477   \sa QUnixSocketMessage::bytes()
478   */
setBytes(const QByteArray & bytes)479 void QUnixSocketMessage::setBytes(const QByteArray & bytes)
480 {
481     d.detach();
482     d->bytes = bytes;
483 }
484 
485 /*!
486   Set the rights portion of the message to \a rights.
487 
488   A message with rights data but an empty byte data payload cannot be
489   transmitted by the system.
490 
491   \sa QUnixSocketMessage::rights()
492   */
setRights(const QList<QUnixSocketRights> & rights)493 void QUnixSocketMessage::setRights(const QList<QUnixSocketRights> & rights)
494 {
495     d.detach();
496     d->rights = rights;
497 }
498 
499 /*!
500   Return the rights portion of the message.
501 
502   \sa QUnixSocketMessage::setRights()
503   */
rights() const504 const QList<QUnixSocketRights> & QUnixSocketMessage::rights() const
505 {
506     return d->rights;
507 }
508 
509 /*!
510   Returns true if the rights portion of the message was truncated on reception
511   due to insufficient buffer size.  The rights buffer size can be adjusted
512   through calls to the \l QUnixSocket::setRightsBufferSize() method.
513   \l QUnixSocket contains a discussion of the buffering and truncation
514   characteristics of the Unix domain protocol.
515 
516   \sa QUnixSocket QUnixSocket::setRightsBufferSize()
517   */
rightsWereTruncated() const518 bool QUnixSocketMessage::rightsWereTruncated() const
519 {
520     return d->state & QUnixSocketMessagePrivate::Truncated;
521 }
522 
523 /*!
524   Return the data portion of the message.
525 
526   \sa QUnixSocketMessage::setBytes()
527   */
bytes() const528 const QByteArray & QUnixSocketMessage::bytes() const
529 {
530     return d->bytes;
531 }
532 
533 /*!
534   Returns the process id credential associated with this message.
535 
536   \sa QUnixSocketMessage::setProcessId()
537   */
processId() const538 pid_t QUnixSocketMessage::processId() const
539 {
540     if(QUnixSocketMessagePrivate::Credential & d->state)
541         return d->pid;
542     else
543         return ::getpid();
544 }
545 
546 /*!
547   Returns the user id credential associated with this message.
548 
549   \sa QUnixSocketMessage::setUserId()
550   */
userId() const551 uid_t QUnixSocketMessage::userId() const
552 {
553     if(QUnixSocketMessagePrivate::Credential & d->state)
554         return d->uid;
555     else
556         return ::geteuid();
557 }
558 
559 /*!
560   Returns the group id credential associated with this message.
561 
562   \sa QUnixSocketMessage::setGroupId()
563   */
groupId() const564 gid_t QUnixSocketMessage::groupId() const
565 {
566     if(QUnixSocketMessagePrivate::Credential & d->state)
567         return d->gid;
568     else
569         return ::getegid();
570 }
571 
572 /*!
573   Set the process id credential associated with this message to \a pid.  Unless
574   you are the root user, setting a fraudulant credential will cause this message
575   to fail.
576 
577   \sa QUnixSocketMessage::processId()
578  */
setProcessId(pid_t pid)579 void QUnixSocketMessage::setProcessId(pid_t pid)
580 {
581     if(!(d->state & QUnixSocketMessagePrivate::Credential)) {
582         d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );
583         d->uid = ::geteuid();
584         d->gid = ::getegid();
585     }
586     d->pid = pid;
587 }
588 
589 /*!
590   Set the user id credential associated with this message to \a uid.  Unless
591   you are the root user, setting a fraudulant credential will cause this message
592   to fail.
593 
594   \sa QUnixSocketMessage::userId()
595  */
setUserId(uid_t uid)596 void QUnixSocketMessage::setUserId(uid_t uid)
597 {
598     if(!(d->state & QUnixSocketMessagePrivate::Credential)) {
599         d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );
600         d->pid = ::getpid();
601         d->gid = ::getegid();
602     }
603     d->uid = uid;
604 }
605 
606 /*!
607   Set the group id credential associated with this message to \a gid.  Unless
608   you are the root user, setting a fraudulant credential will cause this message
609   to fail.
610 
611   \sa QUnixSocketMessage::groupId()
612  */
setGroupId(gid_t gid)613 void QUnixSocketMessage::setGroupId(gid_t gid)
614 {
615     if(!(d->state & QUnixSocketMessagePrivate::Credential)) {
616         d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );
617         d->pid = ::getpid();
618         d->uid = ::geteuid();
619     }
620     d->gid = gid;
621 }
622 
623 /*!
624   Return true if this message is valid.  A message with rights data but an empty
625   byte data payload cannot be transmitted by the system and is marked as
626   invalid.
627   */
isValid() const628 bool QUnixSocketMessage::isValid() const
629 {
630     return d->rights.isEmpty() || !d->bytes.isEmpty();
631 }
632 
633 ///////////////////////////////////////////////////////////////////////////////
634 // class QUnixSocket
635 ///////////////////////////////////////////////////////////////////////////////
636 #define QUNIXSOCKET_DEFAULT_READBUFFER 1024
637 #define QUNIXSOCKET_DEFAULT_ANCILLARYBUFFER 0
638 
639 /*!
640   \class QUnixSocket
641   \internal
642 
643   \brief The QUnixSocket class provides a Unix domain socket.
644 
645   \omit
646   \ingroup Platform::DeviceSpecific
647   \ingroup Platform::OS
648   \ingroup Platform::Communications
649   \endomit
650   \ingroup qws
651 
652   Unix domain sockets provide an efficient mechanism for communications between
653   Unix processes on the same machine.  Unix domain sockets support a reliable,
654   stream-oriented, connection-oriented transport protocol, much like TCP
655   sockets.  Unlike IP based sockets, the connection endpoint of a Unix domain
656   socket is a file on disk of type socket.
657 
658   In addition to transporting raw data bytes, Unix domain sockets are able to
659   transmit special ancillary data.  The two types of ancillary data supported
660   by the QUnixSocket class are:
661 
662   \list
663   \o Credential Data - Allows a receiver
664   to reliably identify the process sending each message.
665   \o \l {QUnixSocketRights}{Rights Data } - Allows Unix file descriptors
666   to be transmitted between processes.
667   \endlist
668 
669   Because of the need to support ancillary data, QUnixSocket is not a QIODevice,
670   like QTcpSocket and QUdpSocket.  Instead, QUnixSocket contains a number of
671   read and write methods that clients must invoke directly.  Rather than
672   returning raw data bytes, \l QUnixSocket::read() returns \l QUnixSocketMessage
673   instances that encapsulate the message's byte data and any other ancillary
674   data.
675 
676   Ancillary data is transmitted "out of band".  Every \l QUnixSocketMessage
677   received will have credential data associated with it that the client can
678   access through calls to \l QUnixSocketMessage::processId(),
679   \l QUnixSocketMessage::groupId() and \l QUnixSocketMessage::userId().
680   Likewise, message creators can set the credential data to send through calls
681   to \l QUnixSocketMessage::setProcessId(), \l QUnixSocketMessage::setGroupId()
682   and \l QUnixSocketMessage::setUserId() respectively.  The authenticity of the
683   credential values is verified by the system kernel and cannot be fabricated
684   by unprivileged processes.  Only processes running as the root user can
685   specify credential data that does not match the sending process.
686 
687   Unix file descriptors, known as "rights data", transmitted between processes
688   appear as though they had been dup(2)'d between the two.  As Unix
689   domain sockets present a continuous stream of bytes to the receiver, the
690   rights data - which is transmitted out of band - must be "slotted" in at some
691   point.  The rights data is logically associated with the first byte - called
692   the anchor byte - of the \l QUnixSocketMessage to which they are attached.
693   Received rights data will be available from the
694   \l QUnixSocketMessage::rights() method for the \l QUnixSocketMessage
695   instance that contains the anchor byte.
696 
697   In addition to a \l QUnixSocket::write() that takes a \l QUnixSocketMessage
698   instance - allowing a client to transmit both byte and rights data - a
699   number of convenience overloads are provided for use when only transmitting
700   simple byte data.  Unix requires that at least one byte of raw data be
701   transmitted in order to send rights data.  A \l QUnixSocketMessage instance
702   with rights data, but no byte data, cannot be transmitted.
703 
704   Unix sockets present a stream interface, such that, for example, a single
705   six byte transmission might be received as two three byte messages.  Rights
706   data, on the other hand, is conceptually transmitted as unfragmentable
707   datagrams.  If the receiving buffer is not large enough to contain all the
708   transmitted rights information, the data is truncated and irretreivably lost.
709   Users should use the \l QUnixSocket::setRightsBufferSize() method to control
710   the buffer size used for this data, and develop protocols that avoid the
711   problem.  If the buffer size is too small and rights data is truncated,
712   the \l QUnixSocketMessage::rightsWereTruncated() flag will be set.
713 
714   \sa QUnixSocketMessage QUnixSocketRights
715 */
716 
717 /*!
718   \enum QUnixSocket::SocketError
719 
720   The SocketError enumeration represents the various errors that can occur on
721   a Unix domain socket.  The most recent error for the socket is available
722   through the \l QUnixSocket::error() method.
723 
724   \value NoError No error has occurred.
725   \value InvalidPath An invalid path endpoint was passed to
726          \l QUnixSocket::connect().  As defined by unix(7), invalid paths
727          include an empty path, or what more than 107 characters long.
728   \value ResourceError An error acquiring or manipulating the system's socket
729          resources occurred.  For example, if the process runs out of available
730          socket descriptors, a ResourceError will occur.
731   \value NonexistentPath The endpoing passed to \l QUnixSocket::connect() does
732          not refer to a Unix domain socket entity on disk.
733   \value ConnectionRefused The connection to the specified endpoint was refused.
734          Generally this means that there is no server listening on that
735          endpoint.
736   \value UnknownError An unknown error has occurred.
737   \value ReadFailure An error occurred while reading bytes from the connection.
738   \value WriteFailure An error occurred while writing bytes into the connection.
739   */
740 
741 /*!
742   \enum QUnixSocket::SocketState
743 
744   The SocketState enumeration represents the connection state of a QUnixSocket
745   instance.
746 
747   \value UnconnectedState The connection is not established.
748   \value ConnectedState The connection is established.
749   \value ClosingState The connection is being closed, following a call to
750          \l QUnixSocket::close().  While closing, any pending data will be
751          transmitted, but further writes by the application will be refused.
752   */
753 
754 /*
755   \fn QUnixSocket::bytesWritten(qint64 bytes)
756 
757   This signal is emitted every time a payload of data has been written to the
758   connection.  The \a bytes argument is set to the number of bytes that were
759   written in this payload.
760 
761   \sa QUnixSocket::readyRead()
762 */
763 
764 /*
765   \fn QUnixSocket::readyRead()
766 
767   This signal is emitted once every time new data is available for reading from
768   the connection. It will only be emitted again once new data is available.
769 
770   \sa QUnixSocket::bytesWritten()
771 */
772 
773 /*!
774   \fn QUnixSocket::stateChanged(SocketState socketState)
775 
776   This signal is emitted each time the socket changes connection state.
777   \a socketState will be set to the socket's new state.
778 */
779 
780 class QUnixSocketPrivate : public QObject {
781 Q_OBJECT
782 public:
QUnixSocketPrivate(QUnixSocket * _me)783     QUnixSocketPrivate(QUnixSocket * _me)
784     : me(_me), fd(-1), readNotifier(0), writeNotifier(0),
785       state(QUnixSocket::UnconnectedState), error(QUnixSocket::NoError),
786       writeQueueBytes(0), messageValid(false), dataBuffer(0),
787       dataBufferLength(0), dataBufferCapacity(0), ancillaryBuffer(0),
788       ancillaryBufferCount(0), closingTimer(0) {
789           QObject::connect(this, SIGNAL(readyRead()), me, SIGNAL(readyRead()));
790           QObject::connect(this, SIGNAL(bytesWritten(qint64)),
791                            me, SIGNAL(bytesWritten(qint64)));
792       }
~QUnixSocketPrivate()793     ~QUnixSocketPrivate()
794     {
795         if(dataBuffer)
796             delete [] dataBuffer;
797         if(ancillaryBuffer)
798             delete [] ancillaryBuffer;
799     }
800 
801     enum { CausedAbort = 0x70000000 };
802 
803     QUnixSocket * me;
804 
805     int fd;
806 
807     QSocketNotifier * readNotifier;
808     QSocketNotifier * writeNotifier;
809 
810     QUnixSocket::SocketState state;
811     QUnixSocket::SocketError error;
812 
813     QQueue<QUnixSocketMessage> writeQueue;
814     unsigned int writeQueueBytes;
815 
816     bool messageValid;
817     ::msghdr message;
flushAncillary()818     inline void flushAncillary()
819     {
820         if(!messageValid) return;
821         ::cmsghdr * h = (::cmsghdr *)CMSG_FIRSTHDR(&(message));
822         while(h) {
823 
824             if(SCM_RIGHTS == h->cmsg_type) {
825                 int * fds = (int *)CMSG_DATA(h);
826                 int numFds = (h->cmsg_len - CMSG_LEN(0)) / sizeof(int);
827 
828                 for(int ii = 0; ii < numFds; ++ii)
829                     QT_CLOSE(fds[ii]);
830             }
831 
832             h = (::cmsghdr *)CMSG_NXTHDR(&(message), h);
833         }
834 
835         messageValid = false;
836     }
837 
838 
839     char * dataBuffer;
840     unsigned int dataBufferLength;
841     unsigned int dataBufferCapacity;
842 
843     char * ancillaryBuffer;
ancillaryBufferCapacity()844     inline unsigned int ancillaryBufferCapacity()
845     {
846         return CMSG_SPACE(sizeof(::ucred)) + CMSG_SPACE(sizeof(int) * ancillaryBufferCount);
847     }
848     unsigned int ancillaryBufferCount;
849 
850     QByteArray address;
851 
852     int closingTimer;
853 
timerEvent(QTimerEvent *)854     virtual void timerEvent(QTimerEvent *)
855     {
856         me->abort();
857         killTimer(closingTimer);
858         closingTimer = 0;
859     }
860 signals:
861     void readyRead();
862     void bytesWritten(qint64);
863 
864 public slots:
865     void readActivated();
866     qint64 writeActivated();
867 };
868 
869 /*!
870   Construct a QUnixSocket instance, with \a parent.
871 
872   The read buffer is initially set to 1024 bytes, and the rights buffer to 0
873   entries.
874 
875   \sa QUnixSocket::readBufferSize() QUnixSocket::rightsBufferSize()
876   */
QUnixSocket(QObject * parent)877 QUnixSocket::QUnixSocket(QObject * parent)
878 : QIODevice(parent), d(new QUnixSocketPrivate(this))
879 {
880     setOpenMode(QIODevice::NotOpen);
881     setReadBufferSize(QUNIXSOCKET_DEFAULT_READBUFFER);
882     setRightsBufferSize(QUNIXSOCKET_DEFAULT_ANCILLARYBUFFER);
883 }
884 
885 /*!
886   Construct a QUnixSocket instance, with \a parent.
887 
888   The read buffer is initially set to \a readBufferSize bytes, and the rights
889   buffer to \a rightsBufferSize entries.
890 
891   \sa QUnixSocket::readBufferSize() QUnixSocket::rightsBufferSize()
892   */
QUnixSocket(qint64 readBufferSize,qint64 rightsBufferSize,QObject * parent)893 QUnixSocket::QUnixSocket(qint64 readBufferSize, qint64 rightsBufferSize,
894                          QObject * parent)
895 : QIODevice(parent), d(new QUnixSocketPrivate(this))
896 {
897     Q_ASSERT(readBufferSize > 0 && rightsBufferSize >= 0);
898 
899     setOpenMode(QIODevice::NotOpen);
900     setReadBufferSize(readBufferSize);
901     setRightsBufferSize(rightsBufferSize);
902 }
903 
904 /*!
905   Destroys the QUnixSocket instance.  Any unsent data is discarded.
906   */
~QUnixSocket()907 QUnixSocket::~QUnixSocket()
908 {
909     abort();
910     delete d;
911 }
912 
913 /*!
914   Attempt to connect to \a path.
915 
916   This method is synchronous and will return true if the connection succeeds and
917   false otherwise.  In the case of failure, \l QUnixSocket::error() will be set
918   accordingly.
919 
920   Any existing connection will be aborted, and all pending data will be
921   discarded.
922 
923   \sa QUnixSocket::close() QUnixSocket::abort() QUnixSocket::error()
924   */
connect(const QByteArray & path)925 bool QUnixSocket::connect(const QByteArray & path)
926 {
927     int _true;
928     int crv;
929 #ifdef QUNIXSOCKET_DEBUG
930     qDebug() << "QUnixSocket: Connect requested to '"
931              << path << '\'';
932 #endif
933 
934     abort(); // Reset any existing connection
935 
936     if(UnconnectedState != d->state) // abort() caused a signal and someone messed
937                                  // with us.  We'll assume they know what
938                                  // they're doing and bail.  Alternative is to
939                                  // have a special "Connecting" state
940         return false;
941 
942 
943     if(path.isEmpty() || path.size() > UNIX_PATH_MAX) {
944         d->error = InvalidPath;
945         return false;
946     }
947 
948     // Create the socket
949     d->fd = ::socket(PF_UNIX, SOCK_STREAM, 0);
950     if(-1 == d->fd) {
951 #ifdef QUNIXSOCKET_DEBUG
952         qDebug() << "QUnixSocket: Unable to create socket ("
953                  << strerror(errno) << ')';
954 #endif
955         d->error = ResourceError;
956         goto connect_error;
957     }
958 
959     // Set socket options
960     _true = 1;
961     crv = ::setsockopt(d->fd, SOL_SOCKET, SO_PASSCRED, (void *)&_true,
962                        sizeof(int));
963     if(-1 == crv) {
964 #ifdef QUNIXSOCKET_DEBUG
965         qDebug() << "QUnixSocket: Unable to configure socket ("
966                  << ::strerror(errno) << ')';
967 #endif
968         d->error = ResourceError;
969 
970         goto connect_error;
971     }
972 
973     // Construct our unix address
974     struct ::sockaddr_un addr;
975     addr.sun_family = AF_UNIX;
976     ::memcpy(addr.sun_path, path.data(), path.size());
977     if(path.size() < UNIX_PATH_MAX)
978         addr.sun_path[path.size()] = '\0';
979 
980     // Attempt the connect
981     crv = ::connect(d->fd, (sockaddr *)&addr, sizeof(sockaddr_un));
982     if(-1 == crv) {
983 #ifdef QUNIXSOCKET_DEBUG
984         qDebug() << "QUnixSocket: Unable to connect ("
985                  << ::strerror(errno) << ')';
986 #endif
987         if(ECONNREFUSED == errno)
988             d->error = ConnectionRefused;
989         else if(ENOENT == errno)
990             d->error = NonexistentPath;
991         else
992             d->error = UnknownError;
993 
994         goto connect_error;
995     }
996 
997     // We're connected!
998     d->address = path;
999     d->state = ConnectedState;
1000     d->readNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, d);
1001     d->writeNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Write, d);
1002     QObject::connect(d->readNotifier, SIGNAL(activated(int)),
1003                      d, SLOT(readActivated()));
1004     QObject::connect(d->writeNotifier, SIGNAL(activated(int)),
1005                      d, SLOT(writeActivated()));
1006     d->readNotifier->setEnabled(true);
1007     d->writeNotifier->setEnabled(false);
1008     setOpenMode(QIODevice::ReadWrite);
1009     emit stateChanged(ConnectedState);
1010 
1011 #ifdef QUNIXSOCKET_DEBUG
1012     qDebug() << "QUnixSocket: Connected to " << path;
1013 #endif
1014     return true;
1015 
1016 connect_error: // Cleanup failed connection
1017     if(-1 != d->fd) {
1018 #ifdef QUNIXSOCKET_DEBUG
1019         int closerv =
1020 #endif
1021             QT_CLOSE(d->fd);
1022 #ifdef QUNIXSOCKET_DEBUG
1023         if(0 != closerv) {
1024             qDebug() << "QUnixSocket: Unable to close file descriptor after "
1025                         "failed connect (" << ::strerror(errno) << ')';
1026         }
1027 #endif
1028     }
1029     d->fd = -1;
1030     return false;
1031 }
1032 
1033 /*!
1034   Sets the socket descriptor to use to \a socketDescriptor, bypassing
1035   QUnixSocket's connection infrastructure, and return true on success and false
1036   on failure.  \a socketDescriptor must be in the connected state, and must be
1037   a Unix domain socket descriptor.  Following a successful call to this method,
1038   the QUnixSocket instance will be in the Connected state and will have assumed
1039   ownership of \a socketDescriptor.
1040 
1041   Any existing connection will be aborted, and all pending data will be
1042   discarded.
1043 
1044   \sa QUnixSocket::connect()
1045 */
setSocketDescriptor(int socketDescriptor)1046 bool QUnixSocket::setSocketDescriptor(int socketDescriptor)
1047 {
1048     abort();
1049 
1050     if(UnconnectedState != state()) // See QUnixSocket::connect()
1051         return false;
1052 
1053     // Attempt to set the socket options
1054     if(-1 == socketDescriptor) {
1055 #ifdef QUNIXSOCKET_DEBUG
1056         qDebug() << "QUnixSocket: User provided socket is invalid";
1057 #endif
1058         d->error = ResourceError;
1059         return false;
1060     }
1061 
1062     // Set socket options
1063     int _true = 1;
1064     int crv = ::setsockopt(socketDescriptor, SOL_SOCKET,
1065                            SO_PASSCRED, (void *)&_true, sizeof(int));
1066     if(-1 == crv) {
1067 #ifdef QUNIXSOCKET_DEBUG
1068         qDebug() << "QUnixSocket: Unable to configure client provided socket ("
1069                  << ::strerror(errno) << ')';
1070 #endif
1071         d->error = ResourceError;
1072 
1073         return false;
1074     }
1075 
1076     d->fd = socketDescriptor;
1077     d->state = ConnectedState;
1078     d->address = QByteArray();
1079     setOpenMode(QIODevice::ReadWrite);
1080     d->readNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, d);
1081     d->writeNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Write, d);
1082     QObject::connect(d->readNotifier, SIGNAL(activated(int)),
1083                      d, SLOT(readActivated()));
1084     QObject::connect(d->writeNotifier, SIGNAL(activated(int)),
1085                      d, SLOT(writeActivated()));
1086     d->readNotifier->setEnabled(true);
1087     d->writeNotifier->setEnabled(false);
1088     emit stateChanged(d->state);
1089 
1090     return true;
1091 }
1092 
1093 /*!
1094   Returns the socket descriptor currently in use.  This method will return -1
1095   if the QUnixSocket instance is in the UnconnectedState \l {QUnixSocket::state()}{state. }
1096 
1097   \sa QUnixSocket::setSocketDescriptor()
1098   */
socketDescriptor() const1099 int QUnixSocket::socketDescriptor() const
1100 {
1101     return d->fd;
1102 }
1103 
1104 /*!
1105   Abort the connection.  This will immediately disconnect (if connected) and
1106   discard any pending data.  Following a call to QUnixSocket::abort() the
1107   object will always be in the disconnected \link QUnixSocket::state() state.
1108   \endlink
1109 
1110   \sa QUnixSocket::close()
1111 */
abort()1112 void QUnixSocket::abort()
1113 {
1114     setOpenMode(QIODevice::NotOpen);
1115 
1116     // We want to be able to use QUnixSocket::abort() to cleanup our state but
1117     // also preserve the error message that caused the abort.  It is not
1118     // possible to reorder code to do this:
1119     //        abort();
1120     //        d->error = SomeError
1121     // as QUnixSocket::abort() might emit a signal and we need the error to be
1122     // set within that signal.  So, if we want an error message to be preserved
1123     // across a *single* call to abort(), we set the
1124     // QUnixSocketPrivate::CausedAbort flag in the error.
1125     if(d->error & QUnixSocketPrivate::CausedAbort)
1126         d->error = (QUnixSocket::SocketError)(d->error &
1127                                               ~QUnixSocketPrivate::CausedAbort);
1128     else
1129         d->error = NoError;
1130 
1131     if( UnconnectedState == d->state) return;
1132 
1133 #ifdef QUNIXSOCKET_DEBUG
1134     int closerv =
1135 #endif
1136         ::close(d->fd);
1137 #ifdef QUNIXSOCKET_DEBUG
1138     if(0 != closerv) {
1139         qDebug() << "QUnixSocket: Unable to close socket during abort ("
1140                  << strerror(errno) << ')';
1141     }
1142 #endif
1143 
1144     // Reset variables
1145     d->fd = -1;
1146     d->state = UnconnectedState;
1147     d->dataBufferLength = 0;
1148     d->flushAncillary();
1149     d->address = QByteArray();
1150     if(d->readNotifier) {
1151         d->readNotifier->setEnabled(false);
1152         d->readNotifier->deleteLater();
1153     }
1154     if(d->writeNotifier) {
1155         d->writeNotifier->setEnabled(false);
1156         d->writeNotifier->deleteLater();
1157     }
1158     d->readNotifier = 0;
1159     d->writeNotifier = 0;
1160     d->writeQueue.clear();
1161     d->writeQueueBytes = 0;
1162     if(d->closingTimer) {
1163         d->killTimer(d->closingTimer);
1164     }
1165     d->closingTimer = 0;
1166     emit stateChanged(d->state);
1167 }
1168 
1169 /*!
1170   Close the connection.  The instance will enter the Closing
1171   \l {QUnixSocket::state()}{state } until all pending data has been
1172   transmitted, at which point it will enter the Unconnected state.
1173 
1174   Even if there is no pending data for transmission, the object will never
1175   jump directly to Disconnect without first passing through the
1176   Closing state.
1177 
1178   \sa QUnixSocket::abort()
1179   */
close()1180 void QUnixSocket::close()
1181 {
1182     if(ConnectedState != state()) return;
1183 
1184     d->state = ClosingState;
1185     if(d->writeQueue.isEmpty()) {
1186         d->closingTimer = d->startTimer(0); // Start a timer to "fake"
1187                                             // completing writes
1188     }
1189     emit stateChanged(d->state);
1190 }
1191 
1192 /*!
1193     This function writes as much as possible from the internal write buffer to
1194     the underlying socket, without blocking. If any data was written, this
1195     function returns true; otherwise false is returned.
1196 */
1197 // Note! docs partially copied from QAbstractSocket::flush()
flush()1198 bool QUnixSocket::flush()
1199 {
1200     // This needs to have the same semantics as QAbstractSocket, if it is to
1201     // be used interchangeably with that class.
1202     if (d->writeQueue.isEmpty())
1203         return false;
1204 
1205     d->writeActivated();
1206     return true;
1207 }
1208 
1209 /*!
1210   Returns the last error to have occurred on this object.  This method is not
1211   destructive, so multiple calls to QUnixSocket::error() will return the same
1212   value.  The error is only reset by a call to \l QUnixSocket::connect() or
1213   \l QUnixSocket::abort()
1214   */
error() const1215 QUnixSocket::SocketError QUnixSocket::error() const
1216 {
1217     return (QUnixSocket::SocketError)
1218         (d->error & ~QUnixSocketPrivate::CausedAbort);
1219 }
1220 
1221 /*!
1222   Returns the connection state of this instance.
1223   */
state() const1224 QUnixSocket::SocketState QUnixSocket::state() const
1225 {
1226     return d->state;
1227 }
1228 
1229 /*!
1230   Returns the Unix path address passed to \l QUnixSocket::connect().  This
1231   method will return an empty path if the object is in the Unconnected
1232   \l {QUnixSocket::state()}{state } or was connected through a call
1233   to \l QUnixSocket::setSocketDescriptor()
1234 
1235   \sa QUnixSocket::connect() QUnixSocket::setSocketDescriptor()
1236   */
address() const1237 QByteArray QUnixSocket::address() const
1238 {
1239     return d->address;
1240 }
1241 
1242 /*!
1243   Returns the number of bytes available for immediate retrieval through a call
1244   to \l QUnixSocket::read().
1245   */
bytesAvailable() const1246 qint64 QUnixSocket::bytesAvailable() const
1247 {
1248     return QIODevice::bytesAvailable() + d->dataBufferLength;
1249 }
1250 
1251 /*!
1252   Returns the number of enqueued bytes still to be written to the socket.
1253   */
bytesToWrite() const1254 qint64 QUnixSocket::bytesToWrite() const
1255 {
1256     return d->writeQueueBytes;
1257 }
1258 
1259 /*!
1260   Returns the size of the read buffer in bytes.  The read buffer size
1261   determines the amount of byte data that can be read from the socket in one go.
1262   The read buffer size caps the maximum value that can be returned by
1263   \l QUnixSocket::bytesAvailable() and will always be greater than zero.  By
1264   default, the read buffer size is 1024 bytes.
1265 
1266   The size of the read buffer is independent of the rights buffer, which can be
1267   queried by \l QUnixSocket::rightsBufferSize().
1268 
1269   \sa QUnixSocket::setReadBufferSize()
1270   */
readBufferSize() const1271 qint64 QUnixSocket::readBufferSize() const
1272 {
1273     return d->dataBufferCapacity;
1274 }
1275 
1276 /*!
1277   Sets the \a size of the socket's read buffer in bytes.
1278 
1279   The size of the read buffer is independent of the rights buffer, which can be
1280   set by \l QUnixSocket::setRightsBufferSize().
1281 
1282   Attempting to reduce the buffer size while bytes are available for reading
1283   (ie. while the buffer is in use) will fail.
1284 
1285   \sa QUnixSocket::readBufferSize()
1286   */
setReadBufferSize(qint64 size)1287 void QUnixSocket::setReadBufferSize(qint64 size)
1288 {
1289     Q_ASSERT(size > 0);
1290     if(size == d->dataBufferCapacity || d->dataBufferLength) return;
1291     if(d->dataBuffer) delete [] d->dataBuffer;
1292     d->dataBuffer = new char[size];
1293     d->dataBufferCapacity = size;
1294 }
1295 
1296 /*!
1297   Returns the size of the rights buffer in rights entries.  The rights buffer
1298   size determines the number of rights transferences that can be received in
1299   any message.  Unlike byte stream data which can be fragmented into many
1300   smaller messages if the \link QUnixSocket::readBufferSize() read buffer
1301   \endlink is not large enough to contain all the available data, rights data
1302   is transmitted as unfragmentable datagrams.  If the rights buffer is not
1303   large enough to contain this unfragmentable datagram, the datagram will be
1304   truncated and rights data irretrievably lost.  If truncation occurs, the
1305   \l QUnixSocketMessage::rightsWereTruncated() flag will be set.  By default
1306   the rights buffer size is 0 entries - rights data cannot be received.
1307 
1308   The size of the rights buffer is independent of the read buffer, which can be
1309   queried by \l QUnixSocket::readBufferSize().
1310 
1311   \sa QUnixSocket::setRightsBufferSize()
1312   */
rightsBufferSize() const1313 qint64 QUnixSocket::rightsBufferSize() const
1314 {
1315     return d->ancillaryBufferCount;
1316 }
1317 
1318 /*!
1319   Sets the \a size of the socket's rights buffer in rights entries.
1320 
1321   The size of the rights buffer is independent of the read buffer, which can be
1322   set by \l QUnixSocket::setReadBufferSize().
1323 
1324   Attempting to reduce the buffer size while bytes are available for reading
1325   (ie. while the buffer is in use) will fail.
1326 
1327   \sa QUnixSocket::rightsBufferSize()
1328   */
setRightsBufferSize(qint64 size)1329 void QUnixSocket::setRightsBufferSize(qint64 size)
1330 {
1331     Q_ASSERT(size >= 0);
1332 
1333     if((size == d->ancillaryBufferCount || d->dataBufferLength) &&
1334             d->ancillaryBuffer)
1335         return;
1336 
1337     qint64 byteSize = CMSG_SPACE(sizeof(::ucred)) +
1338                       CMSG_SPACE(size * sizeof(int));
1339 
1340     if(d->ancillaryBuffer) delete [] d->ancillaryBuffer;
1341     d->ancillaryBuffer = new char[byteSize];
1342     d->ancillaryBufferCount = size;
1343 }
1344 
1345 /*!
1346   \overload
1347 
1348   Writes \a socketdata to the socket.  In addition to failing if the socket
1349   is not in the Connected state, writing will fail if \a socketdata is
1350   \l {QUnixSocketMessage::isValid()}{invalid. }
1351 
1352   Writes through the QUnixSocket class are asynchronous.  Rather than being
1353   written immediately, data is enqueued and written once the application
1354   reenters the Qt event loop and the socket becomes available for writing.
1355   Thus, this method will only fail if the socket is not in the Connected state
1356   - it is illegal to attempt a write on a Unconnected or Closing socket.
1357 
1358   Applications can monitor the progress of data writes through the
1359   \l QUnixSocket::bytesWritten() signal and \l QUnixSocket::bytesToWrite()
1360   method.
1361 
1362   \sa QUnixSocketMessage
1363   */
write(const QUnixSocketMessage & socketdata)1364 qint64 QUnixSocket::write(const QUnixSocketMessage & socketdata)
1365 {
1366     if(ConnectedState != state() || !socketdata.isValid()) return -1;
1367     if(socketdata.d->size() == 0) return 0;
1368 
1369     d->writeQueue.enqueue(socketdata);
1370     d->writeQueueBytes += socketdata.d->size();
1371     d->writeNotifier->setEnabled(true);
1372 
1373     return socketdata.d->size();
1374 }
1375 
1376 /*!
1377   Return the next available message, or an empty message if none is available.
1378 
1379   To avoid retrieving empty messages, applications should connect to the
1380   \l QUnixSocket::readyRead() signal to be notified when new messages are
1381   available or periodically poll the \l QUnixSocket::bytesAvailable() method.
1382 
1383   \sa QUnixSocket::readyRead() QUnixSocket::bytesAvailable()
1384   */
read()1385 QUnixSocketMessage QUnixSocket::read()
1386 {
1387     QUnixSocketMessage data;
1388     if(!d->dataBufferLength)
1389         return data;
1390 
1391     data.d->state = QUnixSocketMessagePrivate::Credential;
1392 
1393     // Bytes are easy
1394     data.setBytes(QByteArray(d->dataBuffer, d->dataBufferLength));
1395 
1396     // Extract ancillary data
1397     QList<QUnixSocketRights> a;
1398 
1399     ::cmsghdr * h = (::cmsghdr *)CMSG_FIRSTHDR(&(d->message));
1400     while(h) {
1401 
1402         if(SCM_CREDENTIALS == h->cmsg_type) {
1403             ::ucred * cred = (::ucred *)CMSG_DATA(h);
1404 #ifdef QUNIXSOCKET_DEBUG
1405             qDebug( "Credentials recd: pid %lu - gid %lu - uid %lu",
1406                     cred->pid, cred->gid, cred->uid );
1407 #endif
1408             data.d->pid = cred->pid;
1409             data.d->gid = cred->gid;
1410             data.d->uid = cred->uid;
1411 
1412         } else if(SCM_RIGHTS == h->cmsg_type) {
1413 
1414             int * fds = (int *)CMSG_DATA(h);
1415             int numFds = (h->cmsg_len - CMSG_LEN(0)) / sizeof(int);
1416 
1417             for(int ii = 0; ii < numFds; ++ii) {
1418                 QUnixSocketRights qusr(fds[ii], 0);
1419                 a.append(qusr);
1420             }
1421 
1422         } else {
1423 
1424 #ifdef QUNIXSOCKET_DEBUG
1425             qFatal("QUnixSocket: Unknown ancillary data type (%d) received.",
1426                    h->cmsg_type);
1427 #endif
1428 
1429         }
1430 
1431         h = (::cmsghdr *)CMSG_NXTHDR(&(d->message), h);
1432     }
1433 
1434     if(d->message.msg_flags & MSG_CTRUNC) {
1435         data.d->state = (QUnixSocketMessagePrivate::AncillaryDataState)(QUnixSocketMessagePrivate::Truncated |
1436                                QUnixSocketMessagePrivate::Credential );
1437     }
1438 
1439     if(!a.isEmpty())
1440         data.d->rights = a;
1441 
1442     d->dataBufferLength = 0;
1443     d->messageValid = false;
1444     d->readNotifier->setEnabled(true);
1445 
1446     return data;
1447 }
1448 
1449 /*! \internal */
isSequential() const1450 bool QUnixSocket::isSequential() const
1451 {
1452     return true;
1453 }
1454 
1455 /*! \internal */
waitForReadyRead(int msecs)1456 bool QUnixSocket::waitForReadyRead(int msecs)
1457 {
1458     if(UnconnectedState == d->state)
1459         return false;
1460 
1461     if(d->messageValid) {
1462         return true;
1463     }
1464 
1465     Q_ASSERT(-1 != d->fd);
1466 
1467     int     timeout = msecs;
1468     struct  timeval tv;
1469     struct  timeval *ptrTv = 0;
1470     QTime   stopWatch;
1471 
1472     stopWatch.start();
1473 
1474     do
1475     {
1476         fd_set readset;
1477 
1478         FD_ZERO(&readset);
1479         FD_SET(d->fd, &readset);
1480 
1481         if(-1 != msecs) {
1482             tv.tv_sec = timeout / 1000;
1483             tv.tv_usec = (timeout % 1000) * 1000;
1484             ptrTv = &tv;
1485         }
1486 
1487         int rv = ::select(d->fd + 1, &readset, 0, 0, ptrTv);
1488         switch(rv) {
1489             case 0:
1490                 // timeout
1491                 return false;
1492             case 1:
1493                 // ok
1494                 d->readActivated();
1495                 return true;
1496             default:
1497                 if (errno != EINTR)
1498                     abort();    // error
1499                 break;
1500         }
1501 
1502         timeout = msecs - stopWatch.elapsed();
1503     }
1504     while (timeout > 0);
1505 
1506     return false;
1507 }
1508 
waitForBytesWritten(int msecs)1509 bool QUnixSocket::waitForBytesWritten(int msecs)
1510 {
1511     if(UnconnectedState == d->state)
1512         return false;
1513 
1514     Q_ASSERT(-1 != d->fd);
1515 
1516     if ( d->writeQueue.isEmpty() )
1517         return true;
1518 
1519     QTime stopWatch;
1520     stopWatch.start();
1521 
1522     while ( true )
1523     {
1524         fd_set fdwrite;
1525         FD_ZERO(&fdwrite);
1526         FD_SET(d->fd, &fdwrite);
1527         int timeout = msecs < 0 ? 0 : msecs - stopWatch.elapsed();
1528         struct timeval tv;
1529         struct timeval *ptrTv = 0;
1530         if ( -1 != msecs )
1531         {
1532             tv.tv_sec = timeout / 1000;
1533             tv.tv_usec = (timeout % 1000) * 1000;
1534             ptrTv = &tv;
1535         }
1536 
1537         int rv = ::select(d->fd + 1, 0, &fdwrite, 0, ptrTv);
1538         switch ( rv )
1539         {
1540             case 0:
1541                 // timeout
1542                 return false;
1543             case 1:
1544             {
1545                 // ok to write
1546                 qint64 bytesWritten = d->writeActivated();
1547                 if (bytesWritten == 0) {
1548                     // We need to retry
1549                     int delay = 1;
1550                     do {
1551                         if (-1 != msecs) {
1552                             timeout = msecs - stopWatch.elapsed();
1553                             if (timeout <= 0) {
1554                                 // We have exceeded our allotted time
1555                                 return false;
1556                             } else {
1557                                 if (delay > timeout)
1558                                     delay = timeout;
1559                             }
1560                         }
1561 
1562                         // Pause before we make another attempt to send
1563                         ::usleep(delay * 1000);
1564                         if (delay < 1024)
1565                             delay *= 2;
1566 
1567                         bytesWritten = d->writeActivated();
1568                     } while (bytesWritten == 0);
1569                 }
1570                 return (bytesWritten != -1);
1571             }
1572             default:
1573                 // error - or an uncaught signal!!!!!!!!!
1574                 if ( rv == EINTR )
1575                     continue;
1576                 abort();
1577                 return false;
1578         }
1579     }
1580     return false; // fix warnings
1581 }
1582 
1583 /*! \internal */
canReadLine() const1584 bool QUnixSocket::canReadLine() const
1585 {
1586     for(unsigned int ii = 0; ii < d->dataBufferLength; ++ii)
1587         if(d->dataBuffer[ii] == '\n') return true;
1588     return false;
1589 }
1590 
1591 /*! \internal */
readData(char * data,qint64 maxSize)1592 qint64 QUnixSocket::readData(char * data, qint64 maxSize)
1593 {
1594     Q_ASSERT(data);
1595     if(0 >= maxSize) return 0;
1596     if(!d->dataBufferLength) return 0;
1597 
1598     // Read data
1599     unsigned int size = d->dataBufferLength>maxSize?maxSize:d->dataBufferLength;
1600     memcpy(data, d->dataBuffer, size);
1601     if(size == d->dataBufferLength) {
1602         d->dataBufferLength = 0;
1603     } else {
1604         memmove(d->dataBuffer, d->dataBuffer + size, d->dataBufferLength - size);
1605         d->dataBufferLength -= size;
1606     }
1607 
1608 
1609     // Flush ancillary
1610     d->flushAncillary();
1611 
1612     if(0 == d->dataBufferLength)
1613         d->readNotifier->setEnabled(true);
1614 
1615     return size;
1616 }
1617 
1618 /*! \internal */
writeData(const char * data,qint64 maxSize)1619 qint64 QUnixSocket::writeData (const char * data, qint64 maxSize)
1620 {
1621     return write(QUnixSocketMessage(QByteArray(data, maxSize)));
1622 }
1623 
writeActivated()1624 qint64 QUnixSocketPrivate::writeActivated()
1625 {
1626     writeNotifier->setEnabled(false);
1627 
1628     QUnixSocketMessage & m = writeQueue.head();
1629     const QList<QUnixSocketRights> & a = m.rights();
1630 
1631     //
1632     // Construct the message
1633     //
1634     ::iovec vec;
1635     if ( !m.d->vec ) // message does not already have an iovec
1636     {
1637         vec.iov_base = (void *)m.bytes().constData();
1638         vec.iov_len = m.bytes().size();
1639     }
1640 
1641     // Allocate the control buffer
1642     ::msghdr sendmessage;
1643     ::bzero(&sendmessage, sizeof(::msghdr));
1644     if ( m.d->vec )
1645     {
1646         sendmessage.msg_iov = m.d->vec;
1647         sendmessage.msg_iovlen = m.d->iovecLen;
1648     }
1649     else
1650     {
1651         sendmessage.msg_iov = &vec;
1652         sendmessage.msg_iovlen = 1;
1653     }
1654     unsigned int required = CMSG_SPACE(sizeof(::ucred)) +
1655                             a.size() * CMSG_SPACE(sizeof(int));
1656     sendmessage.msg_control = new char[required];
1657     ::bzero(sendmessage.msg_control, required);
1658     sendmessage.msg_controllen = required;
1659 
1660     // Create ancillary buffer
1661     ::cmsghdr * h = CMSG_FIRSTHDR(&sendmessage);
1662 
1663     if(m.d->state & QUnixSocketMessagePrivate::Credential) {
1664         h->cmsg_len = CMSG_LEN(sizeof(::ucred));
1665         h->cmsg_level = SOL_SOCKET;
1666         h->cmsg_type = SCM_CREDENTIALS;
1667         ((::ucred *)CMSG_DATA(h))->pid = m.d->pid;
1668         ((::ucred *)CMSG_DATA(h))->gid = m.d->gid;
1669         ((::ucred *)CMSG_DATA(h))->uid = m.d->uid;
1670         h = CMSG_NXTHDR(&sendmessage, h);
1671     } else {
1672         sendmessage.msg_controllen -= CMSG_SPACE(sizeof(::ucred));
1673     }
1674 
1675     for(int ii = 0; ii < a.count(); ++ii) {
1676         const QUnixSocketRights & r = a.at(ii);
1677 
1678         if(r.isValid()) {
1679             h->cmsg_len = CMSG_LEN(sizeof(int));
1680             h->cmsg_level = SOL_SOCKET;
1681             h->cmsg_type = SCM_RIGHTS;
1682             *((int *)CMSG_DATA(h)) = r.peekFd();
1683             h = CMSG_NXTHDR(&sendmessage, h);
1684         } else {
1685             sendmessage.msg_controllen -= CMSG_SPACE(sizeof(int));
1686         }
1687     }
1688 
1689 #ifdef QUNIXSOCKET_DEBUG
1690     qDebug() << "QUnixSocket: Transmitting message (length" << m.d->size() << ')';
1691 #endif
1692     ::ssize_t s = ::sendmsg(fd, &sendmessage, MSG_DONTWAIT | MSG_NOSIGNAL);
1693 #ifdef QUNIXSOCKET_DEBUG
1694     qDebug() << "QUnixSocket: Transmitted message (" << s << ')';
1695 #endif
1696 
1697     if(-1 == s) {
1698         if(EAGAIN == errno || EWOULDBLOCK == errno || EINTR == errno) {
1699             writeNotifier->setEnabled(true);
1700         } else if(EPIPE == errno) {
1701 #ifdef QUNIXSOCKET_DEBUG
1702             qDebug() << "QUnixSocket: Remote side disconnected during transmit "
1703                         "(" << ::strerror(errno) << ')';
1704 #endif
1705             me->abort();
1706         } else {
1707 #ifdef QUNIXSOCKET_DEBUG
1708             qDebug() << "QUnixSocket: Unable to transmit data ("
1709                      << ::strerror(errno) << ')';
1710 #endif
1711             error = (QUnixSocket::SocketError)(QUnixSocket::WriteFailure |
1712                     CausedAbort);
1713             me->abort();
1714         }
1715     } else if(s != m.d->size()) {
1716 
1717         // A partial transmission
1718         writeNotifier->setEnabled(true);
1719         delete [] (char *)sendmessage.msg_control;
1720         m.d->rights = QList<QUnixSocketRights>();
1721         m.d->removeBytes( s );
1722         writeQueueBytes -= s;
1723         emit bytesWritten(s);
1724         return s;
1725 
1726     } else {
1727 
1728         // Success!
1729         writeQueue.dequeue();
1730         Q_ASSERT(writeQueueBytes >= (unsigned)s);
1731         writeQueueBytes -= s;
1732         emit bytesWritten(s);
1733 
1734     }
1735 
1736     delete [] (char *)sendmessage.msg_control;
1737     if(-1 != s && !writeQueue.isEmpty())
1738         return writeActivated();
1739     else if(QUnixSocket::ClosingState == me->state() && writeQueue.isEmpty())
1740         me->abort();
1741 
1742     if((-1 == s) && (EAGAIN == errno || EWOULDBLOCK == errno || EINTR == errno))
1743         // Return zero bytes written to indicate retry may be required
1744         return 0;
1745     else
1746         return s;
1747 }
1748 
readActivated()1749 void QUnixSocketPrivate::readActivated()
1750 {
1751 #ifdef QUNIXSOCKET_DEBUG
1752     qDebug() << "QUnixSocket: readActivated";
1753 #endif
1754     readNotifier->setEnabled(false);
1755 
1756     ::iovec vec;
1757     vec.iov_base = dataBuffer;
1758     vec.iov_len = dataBufferCapacity;
1759 
1760     bzero(&message, sizeof(::msghdr));
1761     message.msg_iov = &vec;
1762     message.msg_iovlen = 1;
1763     message.msg_controllen = ancillaryBufferCapacity();
1764     message.msg_control = ancillaryBuffer;
1765 
1766     int flags = 0;
1767 #ifdef MSG_CMSG_CLOEXEC
1768     flags = MSG_CMSG_CLOEXEC;
1769 #endif
1770 
1771     int recvrv = ::recvmsg(fd, &message, flags);
1772 #ifdef QUNIXSOCKET_DEBUG
1773     qDebug() << "QUnixSocket: Received message (" << recvrv << ')';
1774 #endif
1775     if(-1 == recvrv) {
1776 #ifdef QUNIXSOCKET_DEBUG
1777         qDebug() << "QUnixSocket: Unable to receive data ("
1778                  << ::strerror(errno) << ')';
1779 #endif
1780         error = (QUnixSocket::SocketError)(QUnixSocket::ReadFailure |
1781                                            CausedAbort);
1782         me->abort();
1783     } else if(0 == recvrv) {
1784         me->abort();
1785     } else {
1786         Q_ASSERT(recvrv);
1787         Q_ASSERT((unsigned)recvrv <= dataBufferCapacity);
1788         dataBufferLength = recvrv;
1789         messageValid = true;
1790 
1791 #ifdef QUNIXSOCKET_DEBUG
1792         qDebug() << "QUnixSocket: readyRead() " << dataBufferLength;
1793 #endif
1794         emit readyRead();
1795     }
1796 }
1797 
1798 QT_END_NAMESPACE
1799 
1800 #include "qunixsocket.moc"
1801