diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch) | |
tree | 5ac38a06f3dde268dc7927dc155896926aaf7012 /kdecore/kextsock.h | |
download | tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdecore/kextsock.h')
-rw-r--r-- | kdecore/kextsock.h | 1110 |
1 files changed, 1110 insertions, 0 deletions
diff --git a/kdecore/kextsock.h b/kdecore/kextsock.h new file mode 100644 index 000000000..f3d1f5923 --- /dev/null +++ b/kdecore/kextsock.h @@ -0,0 +1,1110 @@ +/* + * This file is part of the KDE libraries + * Copyright (C) 2000-2004 Thiago Macieira <thiago.macieira@kdemail.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef KEXTSOCK_H +#define KEXTSOCK_H + +#include "kdelibs_export.h" + +#ifdef Q_OS_UNIX + +#include <sys/time.h> + +#include <qstring.h> +#include <qptrlist.h> +#include <qiodevice.h> + +#include "kbufferedio.h" +#include "ksockaddr.h" + +/* External reference to netdb.h */ +struct addrinfo; +struct kde_addrinfo; +class KAddressInfo; /* our abstraction of it */ +class QSocketNotifier; + +/* + * This is extending QIODevice's error codes + * + * According to qiodevice.h, the last error is IO_UnspecifiedError + * These errors will never occur in functions declared in QIODevice + * (except open, but you shouldn't call open) + */ +#define IO_ListenError (IO_UnspecifiedError+1) +#define IO_AcceptError (IO_UnspecifiedError+2) +#define IO_LookupError (IO_UnspecifiedError+3) + +class KExtendedSocketPrivate; +/** + * The extended socket class. + * + * This class should be used instead of KSocket whenever the user needs + * fine-grained control over the socket being created. Unlike KSocket, which + * does everything at once, without much intervention, KExtendedSocket allows + * intervention at every step of the process and the setting of parameters. + * + * This class allows for the creation of both server and client sockets. The + * only difference is that the passiveSocket flag must be passed either to + * the constructor or to setSocketFlags(). If passiveSocket is used, the class will + * enable functions listen() and accept() and related signals, and will + * also disable readBlock() and writeBlock(). + * + * To create a Unix socket, one would pass flag unixSocket to the constructor + * or setSocketFlags(). The hostname and service/port can be set to whatever is + * necessary. If no hostname is given, but a service/port is, the socket created + * will be implementation dependant (usually in /tmp). In any other case, the + * fields will be concatenated. + * + * To create an Internet socket, inetSocket flag can be used. If, on the other + * hand a specific IP protocol is desired, ipv4Socket and/or ipv6Socket can be + * used. + * + * Note that the socket type selection flags are cumulative. One could select + * Unix and Internet sockets by using unixSocket | inetSocket. Or, for instance, + * to make sure only IPv4 and IPv6 sockets are selected, even if future implementations + * support newer IP protocols, ipv4Socket | ipv6Socket is your guy. + * + * @deprecated + * This class is now deprecated. Please use the classes in KNetwork for + * new programs. In particular, this class is replaced by KNetwork::KStreamSocket + * and @ref KNetwork::KServerSocket. + * + * @author Thiago Macieira <thiago.macieira@kdemail.net> + * @short an extended socket + */ +class KDECORE_EXPORT KExtendedSocket: public KBufferedIO // public QObject, public QIODevice +{ + Q_OBJECT + +public: + /** + * flags that can be passed down to the member functions + */ + enum Flags + { + /* socket address families */ + /* + * NOTE: if you change this, you have to change function valid_socket() as well + * These values are hard coded! + */ + anySocket = 0x00, + knownSocket = 0x01, + unixSocket = knownSocket | 0x02, + inetSocket = knownSocket | 0x04, + ipv4Socket = inetSocket | 0x100, + ipv6Socket = inetSocket | 0x200, + + passiveSocket = 0x1000, /* passive socket (i.e., one that accepts connections) */ + canonName = 0x2000, /* request that the canon name be found */ + noResolve = 0x4000, /* do not attempt to resolve, treat as numeric host */ + + streamSocket = 0x8000, /* request a streaming socket (e.g., TCP) */ + datagramSocket = 0x10000, /* request a datagram socket (e.g., UDP) */ + rawSocket = 0x20000, /* request a raw socket. This probably requires privileges */ + + inputBufferedSocket = 0x200000, /* buffer input in this socket */ + outputBufferedSocket = 0x400000, /* buffer output in this socket */ + bufferedSocket = 0x600000 /* make this a fully buffered socket */ + }; + + /** + * status of the class + * The status are sequential. If a change to one status is requested, + * all the prior status will be passed and their actions, performed + */ + enum SockStatus + { + // the numbers are scattered so that we leave room for future expansion + error = -1, // invalid status! + + nothing = 0, // no status, the class has just been created + + lookupInProgress = 50, // lookup is in progress. Signals will be sent + lookupDone = 70, // lookup has been done. Flags cannot be changed + // from this point on + + created = 100, // ::socket() has been called, a socket exists + bound = 140, // socket has been bound + + connecting = 200, // socket is connecting (not passiveSocket) + connected = 220, // socket has connected (not passiveSocket) + + listening = 200, // socket is listening (passiveSocket) + accepting = 220, // socket is accepting (passiveSocket) + + closing = 350, // socket is closing (delayed close) + + done = 400 // socket has been closed + }; + +public: + /** + * Creates an empty KExtendedSocket. + */ + KExtendedSocket(); + + /** + * Creates a socket with the given hostname and port. + * + * If this is a connecting (active) socket, the hostname and port specify + * the remote address to which we will connect. + * + * If this is a listening (passive) socket, the hostname and port specify + * the address to listen on. In order to listen on every interface + * available on this node, set @p host to QString::null. To let the operating + * system select a port, set it to 0. + * + * @sa setAddress + * @param host the hostname + * @param port the port number + * @param flags flags + */ + KExtendedSocket(const QString& host, int port, int flags = 0); + + /** + * Creates a socket with the given hostname and service. + * + * If this is a connecting (active) socket, the hostname and service specify + * the remote address to which we will connect. + * + * If this is a listening (passive) socket, the hostname and service specify + * the address to listen on. In order to listen on every interface + * available on this node, set @p host to QString::null. To let the operating + * system select a port, set the service to "0". + * + * @sa setAddress + * @param host the hostname + * @param service the service + * @param flags flags + */ + KExtendedSocket(const QString& host, const QString& service, int flags = 0); + + /** + * Destroys the socket, disconnecting if still connected and + * freeing any related resources still being kept. + */ + virtual ~KExtendedSocket(); + + /** + * Resets the socket, disconnecting if still connected and + * freeing any related resources still being kept. + * @since 3.1 + */ + void reset(); + + /* + * --- status, flags and internal variables --- * + */ + + /** + * Returns the class status. + * @return the class status + * @see ::SockStatus + */ + int socketStatus() const; + + /** + * Returns the related system error code + * Except for IO_LookupError errors, these are codes found in + * errno + * @return the system error code + */ + int systemError() const; + + /** + * Sets the given flags. + * @param flags the flags to be set + * @return the new flags status, or -1 if flags can no longer be set + */ + int setSocketFlags(int flags); + + /** + * Returns the current flags + * @return the current flags + * @see ::Flags + */ + int socketFlags() const; + + /** + * Sets the hostname to the given value. + * + * If this is a listening (passive) socket, the hostname is the host to which the socket + * will bind in order to listen. If you want to listen in every interface, set it + * to "*" or QString::null. + * + * If this is a connecting (active) socket, the hostname is the host to which we will try + * to connect. + * + * @param host the hostname + * @return true on success, false on error + */ + bool setHost(const QString& host); + + /** + * Returns the hostname. + * @return the hostname or QString::null if no host has been set + */ + QString host() const; + + /** + * Sets the port/service. + * @param port the port + */ + bool setPort(int port); + + /** + * Sets the port/service. + * + * In the case of Unix-domain sockets, the port is the filename for the socket. + * If the name is not an absolute path, "/tmp/" will be prepended. + * + * @param port the port + * @return true if successful, false on error (e.g. connection already established) + */ + bool setPort(const QString& port); + + /** + * Returns the port/service. If it is a port, the string contains a number. + * @return the port or QString::null if it has not been set. + */ + QString port() const; + + /** + * Sets the address where we will connect to. + * + * See @ref setHost and @ref setPort for information on the parameters. + * + * @param host the hostname + * @param port port number + * @return true if successful, false on error (e.g. connection already established) + */ + bool setAddress(const QString& host, int port); + + /** + * Sets the address where we will connect to. + * + * See @ref setHost and @ref setPort for information on the parameters. + * + * @param host the hostname + * @param serv the service + * @return true if successful, false on error (e.g. connection already established) + */ + bool setAddress(const QString& host, const QString& serv); + + /** + * Sets the hostname to which we will bind locally before connecting. + * @param host the hostname + * @return false if this is a passiveSocket, otherwise true. + */ + bool setBindHost(const QString& host); + + /** + * Unsets the bind hostname. That is, don't request a binding host. + * @return true if successful, false on error (e.g. connection already established) + */ + bool unsetBindHost(); + + /** + * Returns the hostname to which the socket will be/is bound. + * @return the host or QString::null if it has not been set. + */ + QString bindHost() const; + + /** + * Sets the port/service to which we will bind before connecting + * @param port the port number + * @return true if successful, false on error (e.g. connection already established) + */ + bool setBindPort(int port); + + /** + * Sets the port/service to which we will bind before connecting. + * @param service the port number or service name + * @return true if successful, false on error (e.g. connection already established) + */ + bool setBindPort(const QString& service); + + /** + * Unsets the bind port/service. + * @return true if successful, false on error (e.g. connection already established) + */ + bool unsetBindPort(); + + /** + * Returns the service to which the socket will be/is bound. + * @return the host or QString::null if it has not been set. + */ + QString bindPort() const; + + /** + * Sets both host and port to which we will bind the socket. Will return + * false if this is a passiveSocket. + * @param host the hostname + * @param port the port number + * @return true if successful, false on error (e.g. connection already established) + */ + bool setBindAddress(const QString& host, int port); + + /** + * Sets both host and service to which we will bind the socket. Will return + * false if this is a passiveSocket. + * @param host the hostname + * @param service the service + * @return true if successful, false on error (e.g. connection already established) + */ + bool setBindAddress(const QString& host, const QString& service); + + /** + * Unsets the bind address for the socket. That means that we won't + * attempt to bind to an address before connecting. + * @return true if successful, false on error (e.g. connection already established) + */ + bool unsetBindAddress(); + + /** + * Sets the timeout value for the connection (if this is not passiveSocket) or + * acception (if it is). In the event the given function + * (connect or accept) returns due to time out, it's possible to call it again. + * + * Setting the timeout to 0 disables the timeout feature. + * + * @param secs the timeout length, in seconds + * @param usecs the timeout complement, in microseconds + * @return false if setting timeout makes no sense in the context. + */ + bool setTimeout(int secs, int usecs = 0); + + /** + * Returns the timeout value for the connection. + * @return the timeout value. 0 if there is no timeout. + */ + timeval timeout() const; + + /** + * Sets/unsets blocking mode for the socket. When non-blocking mode is enabled, + * I/O operations might return error and set errno to EWOULDBLOCK. Also, + * it's not recommended to use this when using the class signals. + * + * @param enable if true, set blocking mode. False, non-blocking mode. + * @return false on error. + */ + bool setBlockingMode(bool enable); + + /** + * Returns the current blocking mode for this socket. + * @return true if in blocking mode + */ + bool blockingMode(); + + /** + * Sets/unsets address reusing flag for this socket. + * + * This function returns true if the value was set correctly. That is NOT + * the result of the set. + * @param enable if true, set address reusable + * @return true on success, false on failure. If the socket was not yet created, + * the value is only remembered. In this case the return value is always true. + */ + bool setAddressReusable(bool enable); + + /** + * Returns whether this socket's address can be reused + * @return true if the address can be reused + */ + bool addressReusable(); + + /** + * Sets/unsets the v6-only flag for IPv6 sockets. + * + * When an IPv6 socket is in use, communication with IPv4 sockets is + * guaranteed by translating those IPv4 addresses into IPv6 ones + * (specifically, the v4-mapped addresses). This flag allows that + * behavior to be turned on and off. + * + * Note that this does not have any effect on sockets that are not + * IPv6 and the function will always return false in those cases. + * Also note that this flag defaults to off in order to accommodate + * existing applications. + * + * @param enable if true, no IPv4 translation will be performed; + * this socket will be restricted to IPv6 communication + * @returns true on success, false on failure. + * @see localAddress to find out if this is an IPv6 socket + */ + bool setIPv6Only(bool enable); + + /** + * Returns the status of the v6-only flag for IPv6 sockets. + * @returns true if the flag is set to on; false if it is not. If this + * socket is not an IPv6 one, the return value is false. + * @see setIPv6Only + */ + bool isIPv6Only(); + + /** + * Sets the buffer sizes for this socket. + * + * This implementation allows any size for both parameters. The value given + * will be interpreted as the maximum size allowed for the buffers, after + * which the I/O functions will stop buffering. The value of -1 will be + * interpreted as "unlimited" size. The value of -2 means "no change". + * + * Note: changing the buffer size to 0 for any buffer will cause the given + * buffer's to be discarded. Likewise, setting the size to a value less than + * the current size will cause the buffer to be shrunk to the wanted value, + * as if the data had been read. + * @param rsize read buffer size + * @param wsize write buffer size + * @return true on success, false if this is not possible in this state (e.g. connection + * not established yet) + */ + virtual bool setBufferSize(int rsize, int wsize = -2); + + /** + * Returns the local socket address + * @return the local socket address, can be 0 if the connection has not been established + * yet + */ + const ::KSocketAddress *localAddress(); + + /** + * Returns the peer socket address. Use KExtendedSocket::resolve() to + * resolve this to a human-readable hostname/service or port. + * @return the peer address, can be 0 if the connection has not been established yet + * or the socket is passive + */ + const ::KSocketAddress *peerAddress(); + + /** + * Returns the file descriptor + * @return the file descriptor. -1 if there is no fd yet. + */ + inline int fd() const + { return sockfd; } + + /* + * -- socket creation -- * + */ + + /** + * Performs lookup on the addresses we were given before. + * + * This will perform lookups on the bind addresses if they were given. + * @return 0 or an error. Do not rely on the values returned by lookup + * as of now. They are not specified. + */ + virtual int lookup(); + + /** + * Starts an asynchronous lookup for the addresses given. + * + * When the lookup is done, the lookupReady signal will be emitted. + * + * Note that, depending on the parameters for the lookup, this function might + * know the results without the need for blocking or queuing an + * asynchronous lookup. That means that the lookupReady signal might be + * emitted by this function, so your code should be prepared for that. + * + * One such case is when noResolve flag is set. + * If this function is able to determine the results without queuing + * and the lookup failed, this function will return -1. + * + * @return 0 on success or -1 on error. Note that + * returning 0 means that either we are in the process of doing + * lookup or that it has finished already. + */ + virtual int startAsyncLookup(); + + /** + * Cancels any on-going asynchronous lookups + */ + virtual void cancelAsyncLookup(); + + /** + * Place the socket in listen mode. The parameters are the same as for + * the system listen() call. + * @param N the queue length for pending connections + * @return 0 on success, -1 on system error (errno + * available) and -2 if this is not a passiveSocket. + */ + virtual int listen(int N = 5); // 5 is arbitrary + + /** + * Accepts an incoming connection from the socket. If this socket is in + * blocking mode, this function will block until a connection is received. + * Otherwise, it might return with error. The sock parameter will be + * initialised with the newly created socket. + * + * Upon successful acception (i.e., this function returns 0), the newly + * created socket will be already connected. The socket will be unbuffered + * and readyRead() and readyWrite() signals will be disabled. + * + * @param sock a pointer to an KExtendedSocket variable + * @return 0 on success, -1 on system error (errno set) and -2 if this is + * not a passiveSocket and -3 if this took too long (time out) + */ + virtual int accept(KExtendedSocket *&sock); + + /** + * Attempts to connect to the remote host. + * After successful connection (return value 0), the socket will be ready + * for I/O operations. Note, however, that not all signals may be enabled + * for emission by this socket: + * @li readyRead and readyWrite signals will be enabled only if + * enableRead or enableWrite were called. You can still enable + * them by calling those functions, of course. + * @li #closed() will only be sent if we are indeed reading from the input + * stream. That is, if this socket is buffering the input. See setBufferSize + * + * Note that, in general, functions inherited/overridden from KBufferedIO will only + * work on buffered sockets, like bytesAvailable and bytesToWrite. + * @return The return values are: + * @li 0: success + * @li -1: system error, errno was set accordingly + * @li -2: this socket cannot connect(); this is a passiveSocket. It can also + * mean that the function was unable to make a connection with the given + * bind address or that an asynchronous connection attempt is already + * in progress. + * @li -3: connection timed out + * + */ + virtual int connect(); + + /** + * Starts an asynchronous connect. This works exactly the same as #connect, + * except that the connection result won't be returned. + * + * Note that those signals might be emitted before this function returns, so your + * code should be prepared for that condition. + * + * You must call cancelAsyncConnect() before you delete the socket if you + * call this. Otherwise you will have crashes. + * + * @return 0 on successful queuing of the connect or -1 on error. + * If this function returns 0, then the connectionSuccess() or the + * connectionFailed() signals will be emitted. + */ + virtual int startAsyncConnect(); + + /** + * Cancels any on-going asynchronous connection attempt. + */ + virtual void cancelAsyncConnect(); + + /** + * Implementation of QIODevice::open() pure virtual function. + * This depends on the target host address already being there. + * If this is a passiveSocket, this is identical to call listen(); else, if + * this is not a passiveSocket and no connection attempt is in progress, this + * is like connect(). If one is in progress, this function will fail. + * @param mode the open mode. Must be IO_Raw | IO_ReadWrite + * @return true if successful, false when an error occurred or the most was + * not correct + */ + virtual bool open(int mode = IO_Raw | IO_ReadWrite); + + /** + * Closes the socket. If we have data still in the write buffer yet to be + * sent, the socket won't be closed right now. It'll be closed after we managed + * to send everything out. + * If you want to close the socket now, you may want to call flush() first, + * and then closeNow(). + */ + virtual void close(); + + /** + * Closes the socket now, discarding the contents of the write buffer, if any. + * The read buffer's contents are kept until they are emptied by read operations + * or the class is destroyed. + */ + virtual void closeNow(); + + /** + * Releases the socket and anything we have holding on it. The class cannot + * be used anymore. In other words, this is just like closeNow(), but it does + * not actually close the socket. + * + * This is useful if you just want to connect and don't need the rest of the + * class. + * + * Note that the buffers' contents will be discarded. + * + * Use of this method is discouraged, because the socket created might be such that + * normal library routines can't handle (read, write, close, etc.) + */ + virtual void release(); + + /* + * -- I/O -- + */ + + /** + * Flushes the socket buffer. You need not call this method during normal + * operation as we will try and send everything as soon as possible. + * However, if you want to make sure that data in the buffer is being sent + * at this moment, you can call this function. It will try to send as much + * data as possible, but it will stop as soon as the kernel cannot receive + * any more data, and would possibly block. + * + * By repeatedly calling this function, the behavior will be like that of + * a blocking socket. Indeed, if this function is called with the kernel not + * ready to receive data, it will block, unless this is a non-blocking socket. + * + * This function does not touch the read buffer. You can empty it by calling + * readBlock() with a null destination buffer. + */ + virtual void flush(); + + /** + * Returns length of this socket. This call is not supported on sockets. + * @return the length of this socket, or 0 if unsupported + */ + virtual inline Q_ULONG size() const + { return 0; } + + /** + * Returns relative position from start. This call is not supported on sockets. + * @return the relative position from the start, or 0 if unsupported + */ + virtual inline Q_ULONG at() const + { return 0; } + + /** + * Returns true if we are at position. This is not supported on sockets. + * @param i the position to check + * @return true if we art at the given position, or always true if unsupported. + */ + virtual inline bool at(int i) + { Q_UNUSED(i);return true; } + + /** + * Returns true if we are at the end. This is not supported on sockets, but + * we always are at the end in a socket... + * @return true if we are at the end. Always false if unsupported. + */ + virtual inline bool atEnd() const + { return false; } + + /** + * Reads a block of data from the socket. + * + * If the socket is not buffered, this function will simply call the underlying + * read method. This function will block if the socket is not on non-blocking mode + * (see setBlockingMode) and there is not enough data to be read in the + * Operating System yet. If we are in non-blocking operation, the call will + * fail in this case. + * + * However, if we are buffering, this function will instead read from the + * buffer while there is available data. This function will never block + * in buffering mode, which means that if you try to read while the buffers + * are empty, this function will always return -1 and set the system error to + * EWOULDBLOCK (aka EAGAIN), so as to mimic non-blocking operation. + * + * @param data where we will write the read data to + * @param maxlen maximum length of data to be read + * @return the number of bytes effectively read, or a negative number in case + * or an error. If the @p data param is not null, then this is also the number + * of bytes copied into that buffer. If the return value is different than + * @p maxlen, then this function encountered a situation in which no more + * bytes were available. Subsequent calls might cause this function to one + * of these behaviours: + * @li return an error, with EWOULDBLOCK system error, if we buffering + * or we are in non-blocking mode + * @li otherwise, it'll block + * This function returns 0, if the function detected end-of-file condition + * (socket was closed) + */ + virtual Q_LONG readBlock(char *data, Q_ULONG maxlen); + + /** + * Writes a block of data to the socket. + * + * If the socket is not buffered, this function will simply call the underlying + * write method. This means that the function might block if that method blocks + * as well. That situation is possible if we are not in non-blocking mode and + * the operating system buffers are full for this socket. If we are in + * non-blocking mode and the operating system buffers are full, this function + * will return -1 and the system error will be set to EWOULDBLOCK. + * + * If we are buffering, this function will simply transfer the data into the + * write buffer. This function will then always succeed, as long as there is + * enough room in the buffer. If the buffer size was limited and that limit + * is reached, this function will copy no more bytes than that limit. Trying + * to write with a full buffer will return -1 and set system error to + * EWOULDBLOCK. + * + * @param data the data to write + * @param len the length of data to write + * @return the number of bytes written from @p data buffer. + * The return value might be less than @p len if the output buffers cannot + * accommodate that many bytes and -1 in the case of an errro. + */ + virtual Q_LONG writeBlock(const char *data, Q_ULONG len); + + /** + * Peeks at a block of data from the socket. + * + * This is exactly like read, except that the data won't be flushed from the + * read buffer. + * + * If this socket is not buffered, this function will always return with + * 0 bytes copied. + * + * @param data where to store the data + * @param maxlen how many bytes to copy, at most + * @return the number of bytes copied. 0 does not mean end-of-file + * condition. + */ + virtual int peekBlock(char *data, uint maxlen); + + /** + * Reimplementation of unreadBlock() method. This is so because unreading in + * sockets doesn't make sense, so this function will always return -1 (error) + * and set the system error to ENOSYS. + * @return always -1 (error) + */ + virtual int unreadBlock(const char *data, uint len); + + /** + * Returns the number of available bytes yet to be read via readBlock + * and family of functions. + * + * Note: as of now, this only works on input-buffered sockets. This will + * change in the future + * @return The number of available bytes, or -1 on error or -2 if this call is invalid + * in the current state. + */ + virtual int bytesAvailable() const; + + /** + * Waits @p msec milliseconds for more data to be available (use 0 to + * wait forever). The return value is the amount of data available for + * read in the read buffer. + * + * @param msec milliseconds to wait + * @return -1 in case of system error and -2 in case of invalid socket + * state + */ + virtual int waitForMore(int msec); + + /** + * Gets a single character (unsigned char) from the stream. + * @return the value of the character. Negative if there was an error. + */ + virtual int getch(); + + /** + * Writes a single character (unsigned char) to the stream. All other bits + * will be ignored. + * @param ch character to write, converted to char + */ + virtual int putch(int ch); + + /** + * Unreads one character from the stream. This is not possible on sockets. + * @return always returns -1 on sockets. + */ + virtual int ungetch(int) + { return -1; } + + /** + * Toggles the emission of the readyRead signal. + * + * Note that this signal is emitted every time more data is available to be + * read, so you might get flooded with it being emitted every time, when in + * non-buffered mode. However, in buffered mode, this signal will be + * emitted only when there is data coming in from the wire. + * By default, this flag is set to false, i.e., signal not being emitted. + * @param enable if true, the signal will be emitted + */ + virtual void enableRead(bool enable); + + /** + * Toggles the emission of the readyWrite signal. + * + * Note that this signal is emitted only when the OS is ready to receive more + * data, which means that the write buffer is empty. And when that is reached, + * this signal will possibly be emitted on every loop, so you might + * want to disable it. By default, this flag is set to false. + * @param enable if true, the signal will be emitted + */ + virtual void enableWrite(bool enable); + +signals: + /** + * This signal is emitted whenever an asynchronous lookup process is done. + * The parameter @p count tells + * @param count the number of results + */ + void lookupFinished(int count); + + /** + * This signal is emitted whenever we connected asynchronously to a host. + */ + void connectionSuccess(); + + /** + * This signal is emitted whenever our asynchronous connection attempt + * failed to all hosts listed. + * @param error the errno code of the last connection attempt + */ + void connectionFailed(int error); + + /** + * This signal is emitted whenever this socket is ready to accept another + * socket. + * @see accept() + */ + void readyAccept(); + +protected: + int sockfd; // file descriptor of the socket + +protected slots: + + void socketActivityRead(); + void socketActivityWrite(); + void dnsResultsReady(); + void startAsyncConnectSlot(); + void connectionEvent(); + +protected: + + QSocketNotifier *readNotifier(); + QSocketNotifier *writeNotifier(); + +private: + + // protection against accidental use + KExtendedSocket(KExtendedSocket&); + KExtendedSocket& operator=(KExtendedSocket&); + + /** + * This is actually a wrapper around getaddrinfo(). + * @internal + */ + static int doLookup(const QString& host, const QString& serv, addrinfo& hint, + kde_addrinfo** result); + +protected: + /** + * Sets the error code + */ + void setError(int errorkind, int error); + + inline void cleanError() + { setError(IO_Ok, 0); } + + /** + * Sets the socket status. For derived classes only. + */ + void setSocketStatus(int status); + +public: + /** + * Performs resolution on the given socket address. + * + * That is, tries to resolve the raw form of the socket address into a textual + * representation. + * + * @param sock the socket address + * @param len the length of the socket address + * @param host where the hostname will be written + * @param port where the service-port will be written + * @param flags the same flags as getnameinfo() + * @returns 0 on success, nonzero otherwise. + */ + static int resolve(sockaddr* sock, ksocklen_t len, QString& host, QString& port, int flags = 0) KDE_DEPRECATED; + + /** + * Performs resolution on the given socket address. + * + * That is, tries to resolve the raw form of the socket address into a textual + * representation. + * + * @param sock the socket address + * @param host where the hostname will be written + * @param port where the service-port will be written + * @param flags the same flags as getnameinfo() + * @returns 0 on success, nonzero otherwise. + */ + static int resolve(::KSocketAddress* sock, QString& host, QString& port, int flags = 0) KDE_DEPRECATED; + + /** @deprecated + * This function is now deprecated. Please use @ref KNetwork::KResolver::resolve. + * + * Performs lookup on the given hostname/port combination and returns a list + * of matching addresses. + * The error code can be transformed into string by KExtendedSocket::strError() + * with code of IO_LookupError. + * + * IMPORTANT: the result values of the QPtrList must be deleted after use. So, + * if you don't copy the KAddressInfo objects, the best way to assure that + * is to call setAutoDelete(true) on the list right after this function + * returns. If you do copy the results out, you must assure that the objects + * get deleted when they are not needed any more. + * + * @param host the hostname to look up + * @param port the port/service to look up + * @param flags flags to be used when looking up, Flags + * @param error pointer to a variable holding the error code + * @return a list of KAddressInfos + */ + static QPtrList<KAddressInfo> lookup(const QString& host, const QString& port, int flags = 0, int *error = 0) KDE_DEPRECATED; + + /** + * Returns the local socket address + * Remember to delete the returned object when it is no longer needed. + * @param fd the file descriptor + * @return the local socket address or 0 if an error occurred. Delete after use. + */ + static ::KSocketAddress *localAddress(int fd) KDE_DEPRECATED; + + /** + * Returns the peer socket address. Use KExtendedSocket::resolve() to + * resolve this to a human-readable hostname/service or port. + * Remember to delete the returned object when it is no longer needed. + * @param fd the file descriptor + * @return the peer socket address or 0 if an error occurred. Delete after use. + */ + static ::KSocketAddress *peerAddress(int fd) KDE_DEPRECATED; + + /** + * Returns the representing text of this error code + * @param code the error code, as seen in status() + * @param syserr the system error, as from systemError() + * @return the text for the given error code + */ + static QString strError(int code, int syserr); + + /** + * Sets/unsets address reusing flag for this socket. + * + * This function returns true if the value was set correctly. That is NOT + * the result of the set. + * @param fd the file descriptor + * @param enable if true, set address reusable + * @return true on success, false on failure. + */ + static bool setAddressReusable(int fd, bool enable) KDE_DEPRECATED; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KExtendedSocketPrivate *d; + + friend class KSocket; + friend class KServerSocket; +}; + +/** @deprecated + * This class is now deprecated. Please see @ref KNetwork::KResolver for the new API. + * + * Contains information about an internet address. It wraps addrinfo, + * see getaddrinfo(3) for more information. + */ +class KDECORE_EXPORT KAddressInfo +{ +private: + addrinfo *ai; + ::KSocketAddress *addr; + + inline KAddressInfo() : ai(0), addr(0) + { } + + // KAddressInfo(addrinfo *ai); + KAddressInfo(KAddressInfo&) { } + KAddressInfo& operator=(KAddressInfo&) { return *this; } + +public: + ~KAddressInfo(); + + /** + * Returns the KAddressInfo's KSocketAddress. + * Only valid as long as the KAddressInfo exists. + */ + inline KDE_DEPRECATED operator const ::KSocketAddress*() const + { return addr; } + + /** + * Returns the KAddressInfo's addrinfo. + */ + inline KDE_DEPRECATED operator const addrinfo&() const + { return *ai; } + + /** + * Returns a pointer to KAddressInfo's addrinfo. + * Only valid as long as the KAddressInfo exists. + */ + inline KDE_DEPRECATED operator const addrinfo*() const + { return ai; } + + /** + * Returns the KAddressInfo's KSocketAddress. + * Only valid as long as the KAddressInfo exists. + * @return the KAddressInfo's KSocketAddress. + */ + inline KDE_DEPRECATED const ::KSocketAddress* address() const + { return addr; } + + /** + * Returns the flags of the address info (see getaddrinfo(3)). + * @return the flags of the addres info. + */ + int flags() const KDE_DEPRECATED; + + /** + * Returns the family of the address info (see getaddrinfo(3)). + * @return the family of the addres info. + */ + int family() const KDE_DEPRECATED; + + /** + * Returns the socket type of the address info (see getaddrinfo(3)). + * @return the socket type of the addres info. + */ + int socktype() const KDE_DEPRECATED; + + /** + * Returns the protocol of the address info (see getaddrinfo(3)). + * @return the protocol of the addres info. + */ + int protocol() const KDE_DEPRECATED; + + + /** + * Returns the official name of the host (see getaddrinfo(3)). + * Only valid as long as the KAddressInfo exists. + * @return the official name of the host + */ + const char* canonname() const KDE_DEPRECATED; + + /** + * Returns the length of the KSocketAddress. + * @return the KSocketAddress's length + */ + inline int length() const + { if (addr) return addr->size(); return 0; } + + friend class KExtendedSocket; +}; + +#endif //Q_OS_UNIX + +#endif // KEXTSOCK_H |