diff options
Diffstat (limited to 'kdecore/network/ksocketdevice.h')
-rw-r--r-- | kdecore/network/ksocketdevice.h | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/kdecore/network/ksocketdevice.h b/kdecore/network/ksocketdevice.h new file mode 100644 index 000000000..301bc2b07 --- /dev/null +++ b/kdecore/network/ksocketdevice.h @@ -0,0 +1,428 @@ +/* -*- C++ -*- + * Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net> + * + * + * 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 KSOCKETDEVICE_H +#define KSOCKETDEVICE_H + +#include <qsocketnotifier.h> +#include "ksocketbase.h" + +namespace KNetwork { + +class KSocketDevice; +class KSocketDeviceFactoryBase; + +class KSocketDevicePrivate; +/** @class KSocketDevice ksocketdevice.h ksocketdevice.h + * @brief Low-level socket functionality. + * + * This class provides low-level socket functionality. + * + * Most users will prefer "cooked" interfaces like those of @ref KStreamSocket or + * @ref KServerSocket. + * + * Descended classes from this one provide some other kinds of socket functionality, + * like proxying or specific socket types. + * + * @author Thiago Macieira <thiago.macieira@kdemail.net> + */ +class KDECORE_EXPORT KSocketDevice: public KActiveSocketBase, public KPassiveSocketBase +{ +public: + /** + * Capabilities for the socket implementation. + * + * KSocketDevice-derived classes can implement certain capabilities that are not + * available in the default class. These capabilities are described by these flags. + * The default KSocketDevice class has none of these capabilities. + * + * For the negative capabilities (inabilities, the CanNot* forms), when a capability + * is not present, the implementation will default to the original behaviour. + */ + enum Capabilities + { + /** Can connect to hostnames. + * If this flag is present, the string form of @ref connect can be used. */ + CanConnectString = 0x01, + + /** Can bind to hostnames. + * If this flag is present, the string form of @ref bind can be used */ + CanBindString = 0x02, + + /** Can not bind. + * If this flag is present, this implementation cannot bind */ + CanNotBind = 0x04, + + /** Can not listen. + * If this flag is present, this implementation cannot listen */ + CanNotListen = 0x08, + + /** + * Can send multicast as well as join/leave multicast groups. + */ + CanMulticast = 0x10, + + /** + * Can not use datagrams. + * Note that this implies multicast capability not being available either. + */ + CanNotUseDatagrams = 0x20 + }; +protected: + /// The socket file descriptor. It is used throughout the implementation + /// and subclasses. + int m_sockfd; + +public: + /** + * Default constructor. + * + * The parameter is used to specify which socket this object is used as + * a device for. + */ + explicit KSocketDevice(const KSocketBase* = 0L); + + /** + * Constructs a new object around an already-open socket. + * + * Note: you should write programs that create sockets through + * the classes whenever possible. + */ + explicit KSocketDevice(int fd); + + /** + * Destructor. This closes the socket if it's open. + */ + virtual ~KSocketDevice(); + + /** + * Returns the file descriptor for this socket. + */ + inline int socket() const + { return m_sockfd; } + + /** + * Returns the set of capabilities this socket class implements. + * The set of capabilities is defined as an OR-ed mask of + * @ref Capabilities bits. + * + * The default implementation is guaranteed to always return 0. That + * is, derived implementations always return bits where they differ + * from the system standard sockets. + */ + virtual int capabilities() const + { return 0; } + + /** + * This implementation sets the options on the socket. + */ + virtual bool setSocketOptions(int opts); + + /** + * Reimplementation from QIODevice. You should not call this function in sockets. + */ + virtual bool open(int mode); + + /** + * Closes the socket. Reimplemented from QIODevice. + * + * Use this function to close the socket this object is holding open. + */ + virtual void close(); + + /** + * This call is not supported on sockets. Reimplemented from QIODevice. + */ + virtual void flush() + { } + + /** + * Creates a socket but don't connect or bind anywhere. + * This function is the equivalent of the system call socket(2). + */ + virtual bool create(int family, int type, int protocol); + + /** + * @overload + * Creates a socket but don't connect or bind anywhere. + */ + bool create(const KResolverEntry& address); + + /** + * Binds this socket to the given address. + */ + virtual bool bind(const KResolverEntry& address); + + /** + * Puts this socket into listening mode. + */ + virtual bool listen(int backlog = 5); // 5 is arbitrary + + /** + * Connect to a remote host. + */ + virtual bool connect(const KResolverEntry& address); + + /** + * Accepts a new incoming connection. + * Note: this function returns a socket of type KSocketDevice. + */ + virtual KSocketDevice* accept(); + + /** + * Disconnects this socket. + */ + virtual bool disconnect(); + + /** + * Returns the number of bytes available for reading without blocking. + */ + virtual Q_LONG bytesAvailable() const; + + /** + * Waits up to @p msecs for more data to be available on this socket. + * + * This function is a wrapper against @ref poll. This function will wait + * for any read events. + */ + virtual Q_LONG waitForMore(int msecs, bool *timeout = 0L); + + /** + * Reads data from this socket. + */ + virtual Q_LONG readBlock(char *data, Q_ULONG maxlen); + + /** + * Reads data and the source address from this socket. + */ + virtual Q_LONG readBlock(char *data, Q_ULONG maxlen, KSocketAddress& from); + + /** + * Peeks data in the socket. + */ + virtual Q_LONG peekBlock(char *data, Q_ULONG maxlen); + + /** + * Peeks the data in the socket and the source address. + */ + virtual Q_LONG peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from); + + /** + * Writes data to the socket. + */ + virtual Q_LONG writeBlock(const char *data, Q_ULONG len); + + /** + * Writes the given data to the given destination address. + */ + virtual Q_LONG writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to); + + /** + * Returns this socket's local address. + */ + virtual KSocketAddress localAddress() const; + + /** + * Returns this socket's peer address. If this implementation does proxying + * of some sort, this is the real external address, not the proxy's address. + */ + virtual KSocketAddress peerAddress() const; + + /** + * Returns this socket's externally visible local address. + * + * If this socket has a local address visible externally different + * from the normal local address (as returned by @ref localAddress), then + * return it. + * + * Certain implementations will use proxies and thus have externally visible + * addresses different from the local socket values. The default implementation + * returns the same value as @ref localAddress. + * + * @note This function may return an empty KSocketAddress. In that case, the + * externally visible address could/can not be determined. + */ + virtual KSocketAddress externalAddress() const; + + /** + * Returns a socket notifier for input on this socket. + * The notifier is created only when requested. Whether + * it is enabled or not depends on the implementation. + * + * This function might return NULL. + */ + QSocketNotifier* readNotifier() const; + + /** + * Returns a socket notifier for output on this socket. + * The is created only when requested. + * + * This function might return NULL. + */ + QSocketNotifier* writeNotifier() const; + + /** + * Returns a socket notifier for exceptional events on this socket. + * The is created only when requested. + * + * This function might return NULL. + */ + QSocketNotifier* exceptionNotifier() const; + + /** + * Executes a poll in the socket, via select(2) or poll(2). + * The events polled are returned in the parameters pointers. + * Set any of them to NULL to disable polling of that event. + * + * On exit, @p input, @p output and @p exception will contain + * true if an event of that kind is waiting on the socket or false + * if not. If a timeout occurred, set @p timedout to true (all other + * parameters are necessarily set to false). + * + * @param input if set, turns on polling for input events + * @param output if set, turns on polling for output events + * @param exception if set, turns on polling for exceptional events + * @param timeout the time in milliseconds to wait for an event; + * 0 for no wait and any negative value to wait forever + * @param timedout on exit, will contain true if the polling timed out + * @return true if the poll call succeeded and false if an error occurred + */ + virtual bool poll(bool* input, bool* output, bool* exception = 0L, + int timeout = -1, bool* timedout = 0L); + + /** + * Shorter version to poll for any events in a socket. This call + * polls for input, output and exceptional events in a socket but + * does not return their states. This is useful if you need to wait for + * any event, but don't need to know which; or for timeouts. + * + * @param timeout the time in milliseconds to wait for an event; + * 0 for no wait and any negative value to wait forever + * @param timedout on exit, will contain true if the polling timed out + * @return true if the poll call succeeded and false if an error occurred + */ + bool poll(int timeout = -1, bool* timedout = 0L); + +protected: + /** + * Special constructor. This constructor will cause the internal + * socket device NOT to be set. Use this if your socket device class + * takes another underlying socket device. + * + * @param parent the parent, if any + */ + KSocketDevice(bool, const KSocketBase* parent = 0L); + + /** + * Creates a socket notifier of the given type. + * + * This function is called by @ref readNotifier, @ref writeNotifier and + * @ref exceptionNotifier when they need to create a socket notifier + * (i.e., the first call to those functions after the socket is open). + * After that call, those functions cache the socket notifier and will + * not need to call this function again. + * + * Reimplement this function in your derived class if your socket type + * requires a different kind of QSocketNotifier. The return value should + * be deleteable with delete. (@ref close deletes them). + * + * @param type the socket notifier type + */ + virtual QSocketNotifier* createNotifier(QSocketNotifier::Type type) const; + +public: + /** + * Creates a new default KSocketDevice object given + * the parent object. + * + * The capabilities flag indicates the desired capabilities the object being + * created should possess. Those capabilities are not guaranteed: if no factory + * can provide such an object, a default object will be created. + * + * @param parent the KSocketBase parent + */ + static KSocketDevice* createDefault(KSocketBase* parent); + + /** + * @overload + * + * This will create an object only if the requested capabilities match. + * + * @param parent the parent + * @param capabilities the requested capabilities + */ + static KSocketDevice* createDefault(KSocketBase* parent, int capabilities); + + /** + * Sets the default KSocketDevice implementation to use and + * return the old factory. + * + * @param factory the factory object for the implementation + */ + static KSocketDeviceFactoryBase* setDefaultImpl(KSocketDeviceFactoryBase* factory); + + /** + * Adds a factory of KSocketDevice objects to the list, along with its + * capabilities flag. + */ + static void addNewImpl(KSocketDeviceFactoryBase* factory, int capabilities); + +private: + KSocketDevice(const KSocketDevice&); + KSocketDevice& operator=(const KSocketDevice&); + + KSocketDevicePrivate *d; +}; + +/** @internal + * This class provides functionality for creating and registering + * socket implementations. + */ +class KSocketDeviceFactoryBase +{ +public: + KSocketDeviceFactoryBase() {} + virtual ~KSocketDeviceFactoryBase() {} + + virtual KSocketDevice* create(KSocketBase*) const = 0; +}; + +/** + * This class provides functionality for creating and registering + * socket implementations. + */ +template<class Impl> +class KSocketDeviceFactory: public KSocketDeviceFactoryBase +{ +public: + KSocketDeviceFactory() {} + virtual ~KSocketDeviceFactory() {} + + virtual KSocketDevice* create(KSocketBase* parent) const + { return new Impl(parent); } +}; + +} // namespaces + +#endif |