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