/* * Copyright (C) 2003 Thiago Macieira * * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef KCLIENTSOCKETBASE_H #define KCLIENTSOCKETBASE_H #include #include #include "tdesocketbase.h" #include "kresolver.h" #include #ifdef Q_MOC_RUN #define USE_QT4 #endif // Q_MOC_RUN namespace KNetwork { class KClientSocketBasePrivate; /** @class KClientSocketBase kclientsocketbase.h kclientsocketbase.h * @brief Abstract client socket class. * * This class provides the base functionality for client sockets, * such as, and especially, name resolution and signals. * * @note This class is abstract. If you're looking for a normal, * client socket class, see @ref KStreamSocket and TDEBufferedSocket * * @author Thiago Macieira */ class TDECORE_EXPORT KClientSocketBase : #ifdef USE_QT4 #else // USE_QT4 public TQObject, #endif // USE_QT4 public KActiveSocketBase { Q_OBJECT public: /** * Socket states. * * These are the possible states for a KClientSocketBase: * - Idle: socket is not connected * - HostLookup: socket is doing host lookup prior to connecting * - HostFound: name lookup is complete * - Bound: the socket is locally bound * - Connecting: socket is attempting connection * - Open: socket is open * - Connected (=Open): socket is connected * - Connection (=Open): yet another name for a connected socket * - Closing: socket is shutting down * * Whenever the socket state changes, the @ref stateChanged(int) signal * will be emitted. */ enum SocketState { Idle, HostLookup, HostFound, Bound, Connecting, Open, Closing, Unconnected = Bound, Connected = Open, Connection = Open }; public: /** * Default constructor. * * @param parent the parent TQObject object * @param name the name of this object */ KClientSocketBase(TQObject* parent, const char *name); /** * Destructor. */ virtual ~KClientSocketBase(); /** * Returns the current state for this socket. * @see SocketState */ SocketState state() const; protected: /** * Sets the socket options. Reimplemented from TDESocketBase. */ virtual bool setSocketOptions(int opts); public: /** * Returns the internal KResolver object used for * looking up the peer host name and service. * * This can be used to set extra options to the * lookup process other than the default values, as well * as obtaining the error codes in case of lookup failure. */ KResolver& peerResolver() const; /** * Returns the internal list of resolved results for the peer address. */ const KResolverResults& peerResults() const; /** * Returns the internal KResolver object used for * looking up the local host name and service. * * This can be used to set extra options to the * lookup process other than the default values, as well * as obtaining the error codes in case of lookup failure. */ KResolver& localResolver() const; /** * Returns the internal list of resolved results for the local address. */ const KResolverResults& localResults() const; /** * Enables or disables name resolution. If this flag is set to true, * @ref bind and @ref connect operations will trigger name lookup * operations (i.e., converting a hostname into its binary form). * If the flag is set to false, those operations will instead * try to convert a string representation of an address without * attempting name resolution. * * This is useful, for instance, when IP addresses are in * their string representation (such as "1.2.3.4") or come * from other sources like @ref TDESocketAddress. * * @param enable whether to enable */ void setResolutionEnabled(bool enable); /** * Sets the allowed families for the resolutions. * * @param families the families that we want/accept * @see KResolver::SocketFamilies for possible values */ void setFamily(int families); /** * Starts the lookup for peer and local hostnames as * well as their services. * * If the blocking mode for this object is on, this function will * wait for the lookup results to be available (by calling the * @ref KResolver::wait method on the resolver objects). * * When the lookup is done, the signal @ref hostFound will be * emitted (only once, even if we're doing a double lookup). * If the lookup failed (for any of the two lookups) the * @ref gotError signal will be emitted with the appropriate * error condition (see @ref TDESocketBase::SocketError). * * This function returns true on success and false on error. Note that * this is not the lookup result! */ virtual bool lookup(); /** * Binds this socket to the given nodename and service, * or use the default ones if none are given. * * Upon successful binding, the @ref bound signal will be * emitted. If an error is found, the @ref gotError * signal will be emitted. * * @note Due to the internals of the name lookup and binding * mechanism, some (if not most) implementations of this function * do not actually bind the socket until the connection * is requested (see @ref connect). They only set the values * for future reference. * * This function returns true on success. * * @param node the nodename * @param service the service */ virtual bool bind(const TQString& node = TQString::null, const TQString& service = TQString::null) = 0; /** * Reimplemented from TDESocketBase. Connect this socket to this * specific address. * * Unlike @ref bind(const TQString&, const TQString&) above, this function * really does bind the socket. No lookup is performed. The @ref bound * signal will be emitted. */ virtual bool bind(const KResolverEntry& address); /** * Attempts to connect to the these hostname and service, * or use the default ones if none are given. If a connection attempt * is already in progress, check on its state and set the error status * (NoError or InProgress). * * If the blocking mode for this object is on, this function will only * return when all the resolved peer addresses have been tried or when * a connection is established. * * Upon successfully connecting, the @ref connected signal * will be emitted. If an error is found, the @ref gotError * signal will be emitted. * * @par Note for derived classes: * Derived classes must implement this function. The implementation * will set the parameters for the lookup (using the peer KResolver * object) and call @ref lookup to start it. * * @par * The implementation should use the @ref hostFound * signal to be notified of the completion of the lookup process and * then proceed to start the connection itself. Care should be taken * regarding the value of @ref blocking flag. * * @param node the nodename * @param service the service */ virtual bool connect(const TQString& node = TQString::null, const TQString& service = TQString::null) = 0; /** * @overload * Reimplemented from TDESocketBase. */ virtual bool connect(const KResolverEntry& address); /** * @deprecated * This is a convenience function provided to ease migrating from * Qt 3.x's TQSocket class. */ inline void connectToHost(const TQString& host, TQ_UINT16 port) { connect(host, TQString::number(port)); } /** * Disconnects the socket. * Note that not all socket types can disconnect. */ virtual bool disconnect(); /** * Opens the socket. Reimplemented from TQIODevice. * * You should not call this function; instead, use @ref connect */ virtual inline bool open(TQ_OpenMode) { return connect(); } /** * Closes the socket. Reimplemented from TQIODevice. * * The closing of the socket causes the emission of the * signal @ref closed. */ virtual void close(); /** * This call is not supported on sockets. Reimplemented from TQIODevice. */ virtual void flush() { } /** * Returns the number of bytes available on this socket. * Reimplemented from TDESocketBase. */ #ifdef USE_QT3 virtual TQ_LONG bytesAvailable() const; #endif #ifdef USE_QT4 virtual qint64 bytesAvailable() const; #endif /** * Waits for more data. Reimplemented from TDESocketBase. */ virtual TQ_LONG waitForMore(int msecs, bool *timeout = 0L); /** * Reads data from a socket. Reimplemented from TDESocketBase. */ virtual TQT_TQIO_LONG tqreadBlock(char *data, TQT_TQIO_ULONG maxlen); /** * @overload * Reads data from a socket. Reimplemented from TDESocketBase. */ virtual TQT_TQIO_LONG tqreadBlock(char *data, TQT_TQIO_ULONG maxlen, TDESocketAddress& from); /** * Peeks data from the socket. Reimplemented from TDESocketBase. */ virtual TQ_LONG peekBlock(char *data, TQ_ULONG maxlen); /** * @overload * Peeks data from the socket. Reimplemented from TDESocketBase. */ virtual TQ_LONG peekBlock(char *data, TQ_ULONG maxlen, TDESocketAddress &from); /** * Writes data to the socket. Reimplemented from TDESocketBase. */ virtual TQT_TQIO_LONG tqwriteBlock(const char *data, TQT_TQIO_ULONG len); /** * @overload * Writes data to the socket. Reimplemented from TDESocketBase. */ virtual TQT_TQIO_LONG tqwriteBlock(const char *data, TQT_TQIO_ULONG len, const TDESocketAddress& to); /** * Returns the local socket address. Reimplemented from TDESocketBase. */ virtual TDESocketAddress localAddress() const; /** * Returns the peer socket address. Reimplemented from TDESocketBase. */ virtual TDESocketAddress peerAddress() const; /** * Returns true if the readyRead signal is set to be emitted. */ bool emitsReadyRead() const; /** * Enables the emission of the readyRead signal. * By default, this signal is enabled. * * @param enable whether to enable the signal */ virtual void enableRead(bool enable); /** * Returns true if the readyWrite signal is set to be emitted. */ bool emitsReadyWrite() const; /** * Enables the emission of the readyWrite signal. * By default, this signal is disabled. * * @param enable whether to enable the signal */ virtual void enableWrite(bool enable); protected slots: // protected slots /** * This slot is connected to the read notifier's signal meaning * the socket can read more data. * * The default implementation only emits the readyRead signal. * * Override if your class requires processing of incoming * data. */ virtual void slotReadActivity(); /** * This slot is connected to the write notifier's signal * meaning the socket can write more data. * * The default implementation only emits the readyWrite signal. * * Override if your class writes data from another source * (like a buffer). */ virtual void slotWriteActivity(); private slots: void lookupFinishedSlot(); signals: /** * This signal is emitted whenever the socket state changes. * * Note: do not delete this object inside the slot called by this * signal. * * @param newstate the new state of the socket object */ void stateChanged(int newstate); /** * This signal is emitted when this object finds an error. * The @p code parameter contains the error code that can * also be found by calling @ref error. */ void gotError(int code); /** * This signal is emitted when the lookup is successfully completed. */ void hostFound(); /** * This signal is emitted when the socket successfully binds * to an address. * * @param local the local address we bound to */ void bound(const KResolverEntry& local); /** * This signal is emitted when the socket is about to connect * to an address (but before doing so). * * The @p skip parameter can be used to make the loop skip this address. * Its value is initially false: change it to true if you want to * skip the current address (as given by @p remote). * * This function is also useful if one wants to reset the timeout. * * @param remote the address we're about to connect to * @param skip set to true if you want to skip this address * @note if the connection is successful, the @ref connected signal will be * emitted. */ void aboutToConnect(const KResolverEntry& remote, bool& skip); /** * This socket is emitted when the socket successfully connects * to a remote address. * * @param remote the remote address we did connect to */ void connected(const KResolverEntry& remote); /** * This signal is emitted when the socket completes the * closing/shut down process. */ void closed(); /** * This signal is emitted whenever the socket is ready for * reading -- i.e., there is data to be read in the buffers. * The subsequent read operation is guaranteed to be non-blocking. * * You can toggle the emission of this signal with the @ref enableRead * function. This signal is by default enabled. */ void readyRead(); /** * This signal is emitted whenever the socket is ready for * writing -- i.e., whenever there's space available in the buffers * to receive more data. The subsequent write operation is * guaranteed to be non-blocking. * * You can toggle the emission of this signal with the @ref enableWrite * function. This signal is by default disabled. You will * want to disable this signal after the first reception, since * it'll probably fire at every event loop. */ void readyWrite(); protected: /** * Sets the socket state to @p state. This function does not * emit the @ref stateChanged signal. */ void setState(SocketState state); /** * This function is called by @ref setState whenever the state * changes. You should override it if you need to specify any * actions to be done when the state changes. * * The default implementation acts for these states only: * - Connected: it sets up the socket notifiers to fire readyRead and * readyWrite signals. */ virtual void stateChanging(SocketState newState); /** * Convenience function to set this object's error code to match * that of the socket device. */ void copyError(); private: KClientSocketBase(const KClientSocketBase&); KClientSocketBase& operator=(const KClientSocketBase&); KClientSocketBasePrivate *d; }; } // namespace KNetwork #endif