1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2007 Thiago Macieira <thiago@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#ifndef KLOCALSOCKET_H
22#define KLOCALSOCKET_H
23
24#include <kdecore_export.h>
25#include <QtCore/QString>
26#include <QtNetwork/QTcpSocket>
27#include <QtNetwork/QTcpServer>
28
29class KLocalSocketPrivate;
30/**
31 * @class KLocalSocket
32 * @brief KLocalSocket allows one to create and use local (Unix) sockets
33 *
34 * On some platforms, local sockets are a kind of streaming socket
35 * that can be used to transmit and receive data just like Internet
36 * (TCP) streaming sockets. The difference is that they remain local
37 * to the host running them and cannot be accessed externally. They
38 * are also very fast and (in theory) consume less resources than
39 * standard TCP sockets.
40 *
41 * KLocalSocket supports two kinds of local socket types (see
42 * KLocalSocket::LocalSocketType):
43 * - Unix sockets (UnixSocket): standard Unix sockets whose names are
44 * file paths and obey filesystem restrictions
45 * - Abstract Unix sockets (AbstractUnixSocket): similar to Unix
46 * sockets, but they don't exist as entries in the filesystem and,
47 * thus, aren't restricted by its permissions
48 *
49 * @author Thiago Macieira <thiago@kde.org>
50 */
51class KDECORE_EXPORT KLocalSocket : public QTcpSocket
52{
53 Q_OBJECT
54public:
55 /**
56 * Defines the local socket type. See KLocalSocket for more
57 * information
58 */
59 enum LocalSocketType {
60 UnixSocket, ///< Unix sockets
61 AbstractUnixSocket, ///< Abstract Unix sockets
62 UnknownLocalSocketType = -1
63 };
64
65 /**
66 * Creates a KLocalSocket object with @p parent as the parent
67 * object.
68 *
69 * @param parent the parent object
70 */
71 explicit KLocalSocket(QObject *parent = 0);
72 /**
73 * Destroys the KLocalSocket object and frees up any resources
74 * associated. If the socket is open, it will be closed.
75 */
76 virtual ~KLocalSocket();
77
78 /**
79 * Opens a connection to a listening Unix socket at @p path. Use
80 * waitForConnection() to find out if the connection succeeded or
81 * not.
82 *
83 * @param path the Unix socket to connect to
84 * @param mode the mode to use when opening (see QIODevice::OpenMode)
85 */
86 void connectToPath(const QString &path, OpenMode mode = ReadWrite);
87 /**
88 * @overload
89 * Opens a connection to a listening local socket at address @p
90 * path. Use waitForConnection() to find out if the connection
91 * succeeded or not.
92 *
93 * @param path the local socket address to connect to
94 * @param type the local socket type to use
95 * @param mode the mode to use when opening (see QIODevice::OpenMode)
96 */
97 void connectToPath(const QString &path, LocalSocketType type, OpenMode mode = ReadWrite);
98 /**
99 * Disconnects the socket from its server.
100 */
101 void disconnectFromPath();
102
103 /**
104 * Returns the socket type for this socket, when
105 * connected. Returns UnknownLocalSocketType if not
106 * connected.
107 */
108 LocalSocketType localSocketType() const;
109
110 /**
111 * Returns the local address of this socket, when
112 * connected. Returns QString() if not connected.
113 *
114 * Most of the time, the socket has no local address.
115 */
116 QString localPath() const;
117 /**
118 * Returns the peer address of this socket. That is, the address
119 * that this socket connected to (see connectToPath). Returns
120 * QString() if not connected.
121 */
122 QString peerPath() const;
123
124private:
125 using QAbstractSocket::connectToHost;
126 using QAbstractSocket::disconnectFromHost;
127
128protected Q_SLOTS:
129 /// @internal
130 void connectToHostImplementation(const QString &hostName, quint16 port, OpenMode mode);
131 void disconnectFromHostImplementation();
132
133private:
134 Q_DISABLE_COPY(KLocalSocket)
135 friend class KLocalSocketPrivate;
136 KLocalSocketPrivate * const d;
137};
138
139class KLocalSocketServerPrivate;
140/**
141 * @class KLocalSocketServer
142 * @brief KLocalSocketServer allows one to create a listening local
143 * socket and accept incoming connections
144 *
145 * On some platforms, local sockets are a kind of streaming socket
146 * that can be used to transmit and receive data just like Internet
147 * (TCP) streaming sockets. The difference is that they remain local
148 * to the host running them and cannot be accessed externally. They
149 * are also very fast and (in theory) consume less resources than
150 * standard TCP sockets.
151 *
152 * KLocalSocketServer allows you to create the listening (i.e.,
153 * passive) end of this local socket and accept incoming connections
154 * from users of KLocalSocket. It supports the same kind of socket
155 * types that KLocalSocket does (see KLocalSocket::LocalSocketType).
156 *
157 * @author Thiago Macieira <thiago@kde.org>
158 */
159class KDECORE_EXPORT KLocalSocketServer : public QObject
160{
161 Q_OBJECT
162public:
163 /**
164 * Creates a KLocalSocketServer object with @p parent as the
165 * parent object. The object is created without binding to any
166 * address.
167 *
168 * @param parent the parent object
169 */
170 explicit KLocalSocketServer(QObject *parent = 0);
171 /**
172 * Destroys the KLocalSocketServer object and frees up any
173 * resource associated. If the socket is still listening, it's
174 * closed (see close()).
175 *
176 * The sockets that were accepted using this KLocalSocketServer
177 * object are not affected and will remain open. However, note
178 * that nextPendingConnection() returns objects that have this
179 * KLocalSocketServer as parents, so the QObject destruction will
180 * delete any objects that were not reparented.
181 */
182 virtual ~KLocalSocketServer();
183
184 /**
185 * Binds this socket to the address @p path and starts listening
186 * there.
187 *
188 * If @p type is KLocalSocket::UnixSocket, @p path is
189 * treated as a Unix filesystem path and the calling user must
190 * have permission to create the named directory entry (that is,
191 * the user must have write permission to the parent directory,
192 * etc.)
193 *
194 * If @p type is KLocalSocket::AbstractUnixSocket, @p path is
195 * just a name that can be anything. It'll be converted to an
196 * 8-bit identifier just as if it were a file path, but
197 * filesystem restrictions do not apply.
198 *
199 * This function returns true if it succeeded in binding the
200 * socket to @p path and placing it in listen mode. It returns
201 * false otherwise.
202 *
203 * @param path the path to listen on
204 * @param type the local socket type
205 * @returns true on success, false otherwise
206 */
207 bool listen(const QString &path, KLocalSocket::LocalSocketType type = KLocalSocket::UnixSocket);
208
209 /**
210 * Closes the socket. No further connections will be accepted,
211 * but connections that were already pending can still be
212 * retrieved with nextPendingConnection().
213 *
214 * Connections that were accepted and are already open will not
215 * be affected.
216 */
217 void close();
218
219 /**
220 * Returns true if the socket is listening, false otherwise.
221 */
222 bool isListening() const;
223
224 /**
225 * Sets the maximum number of connections that KLocalSocketServer
226 * will accept on your behalf and keep queued, ready to be
227 * retrieved with nextPendingConnection(). If you set @p
228 * numConnections to 0, hasPendingConnections() will always
229 * return false. You can still use waitForNewConnection(),
230 * though.
231 *
232 * @param numConnections the number of connections to accept
233 * and keep queued.
234 */
235 void setMaxPendingConnections(int numConnections);
236 /**
237 * Returns the value set with setMaxPendingConnections().
238 */
239 int maxPendingConnections() const;
240
241 /**
242 * Returns the socket type that this socket is listening on. If it
243 * is not listening, returns QAbstractSocket::UnknownLocalSocketType.
244 */
245 KLocalSocket::LocalSocketType localSocketType() const;
246 /**
247 * Returns the address of this socket if it is listening on, or
248 * QString() if it is not listening.
249 */
250 QString localPath() const;
251
252 /**
253 * Suspends the execution of the calling thread for at most @p
254 * msec milliseconds and wait for a new socket connection to be
255 * accepted (whichever comes first). If no new socket connection
256 * is received within @p msec milliseconds, consider this a
257 * time-out and set the boolean pointed by @p timedOut to false
258 * (if it's not 0).
259 *
260 * If @p msec is 0, this call will not block, but will simply poll
261 * the system to check if a new connection has been received in
262 * the background.
263 *
264 * Use @p msec value of -1 to block indefinitely.
265 *
266 * @param msec the time in milliseconds to block at most (-1
267 * to block forever)
268 * @param timedOut points to a boolean that will be set to true
269 * if a timeout did occur
270 * @returns true if a new connection has been accepted or false if
271 * an error occurred or if the operation timed out.
272 */
273 bool waitForNewConnection(int msec = 0, bool *timedOut = 0);
274
275 /**
276 * Returns true if a new socket can be received with
277 * nextPendingConnection().
278 */
279 virtual bool hasPendingConnections() const;
280 /**
281 * Returns a new socket if one is available or 0 if none is.
282 *
283 * Note that the objects returned by this function will have the
284 * current KLocalSocketServer object as its parent. You may want
285 * to reparent the accepted objects if you intend them to outlive
286 * the current object.
287 */
288 virtual KLocalSocket *nextPendingConnection();
289
290 /**
291 * If an error occurred, return the error code.
292 */
293 QAbstractSocket::SocketError serverError() const;
294 /**
295 * If an error occurred, return the error message.
296 */
297 QString errorString() const;
298
299protected:
300 /// @internal
301 virtual void incomingConnection(int handle);
302
303Q_SIGNALS:
304 /**
305 * The newConnection() signal is emitted whenever a new connection
306 * is ready and has been accepted. Whenever it is emitted, calling
307 * nextPendingConnection() will return a valid object at least
308 * once.
309 */
310 void newConnection();
311
312private:
313 Q_PRIVATE_SLOT(d, void _k_newConnectionActivity())
314 Q_DISABLE_COPY(KLocalSocketServer)
315 friend class KLocalSocketServerPrivate;
316 KLocalSocketServerPrivate * const d;
317};
318
319#endif
320