/*
* This file is part of the KDE libraries
* Copyright (C) 1997 Torben Weis (weis@kde.org)
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef KSOCK_H
#define KSOCK_H
#include <qobject.h>
#include <sys/types.h>
// we define STRICT_ANSI to get rid of some warnings in glibc
#ifndef __STRICT_ANSI__
#define __STRICT_ANSI__
#define _WE_DEFINED_IT_
#endif
#include <sys/socket.h>
#ifdef _WE_DEFINED_IT_
#undef __STRICT_ANSI__
#undef _WE_DEFINED_IT_
#endif
#include <sys/un.h>
#include <netinet/in.h>
class QSocketNotifier;
#ifdef INET6
typedef sockaddr_in6 ksockaddr_in;
#define KSOCK_DEFAULT_DOMAIN PF_INET6
#else
typedef sockaddr_in ksockaddr_in;
#define KSOCK_DEFAULT_DOMAIN PF_INET
#endif
class KSocketPrivate;
class KServerSocketPrivate;
/**
* A TCP/IP client socket.
*
* You can connect this socket to any Internet address.
*
* The socket gives you three signals: When ready for reading,
* ready for writing or if the connection is broken.
* Using @ref socket() you get a file descriptor
* which you can use with the usual UNIX function like @ref write(..) or
* @ref read(...).
* If you have already such a socket identifier you can construct a KSocket
* on this identifier.
*
* If @ref socket() delivers a value of -1 or less, the connection
* was not successful.
*
* @author Torben Weis <weis@uni-frankfurt.de>
* @version $Id: ksock.h,v 1.41 2000/09/09 23:34:44 rikkus Exp $
* @short a TCP/IP client socket.
*/
class KSocket : public QObject
{
Q_OBJECT
public:
/**
* Create a KSocket with the provided file descriptor.
* @param _sock The file descriptor to use.
*/
KSocket( int _sock );
/**
* Create a socket and connect to a host.
* @param _host The remote host to which to connect.
* @param _port The port on the remote host.
* @param timeOut The number of seconds waiting for connect (default 30).
*/
KSocket( const char *_host, unsigned short int _port, int timeOut = 30);
/**
* Connects to a UNIX domain socket.
* @param _path The filename of the socket.
*/
KSocket( const char * _path );
/**
* Destructor. Closes the socket if it is still open.
*/
virtual ~KSocket();
/**
* A small wrapper around @ref gethostbyname() and such.
*/
static bool initSockaddr(ksockaddr_in *server_name, const char *hostname, unsigned short int port, int domain = PF_INET);
/**
* Returns a file descriptor for this socket.
*/
int socket() const { return sock; }
/**
* Enable the socket for reading.
*
* If you enable read mode, the socket will emit the signal
* @ref readEvent() whenever there is something to read out of this
* socket.
*/
void enableRead( bool );
/**
* Enable the socket for writing.
*
* If you enable write mode, the socket will emit the signal
* @ref writeEvent() whenever the socket is ready for writing.
*
* Warning: If you forget to call enableWrite(false) when you are
* not ready to send data, you will get lots of writeEvent() signals,
* in the order of thousands a second !
*/
void enableWrite( bool );
/**
* Return address.
*/
unsigned long ipv4_addr();
signals:
/**
* Data has arrived for reading.
*
* This signal will only be raised if @ref enableRead( @p true ) was called
* first.
*/
void readEvent( KSocket * );
/**
* Socket is ready for writing.
*
* This signal will only be raised if @ref enableWrite( @p true ) was
* called first.
*
* Warning: If you forget to call enableWrite(false) when you are
* not ready to send data, you will get lots of writeEvent() signals,
* in the order of thousands a second !
*/
void writeEvent( KSocket * );
/**
* Raised when the connection is broken.
*/
void closeEvent( KSocket * );
public slots:
/**
* Connected to the writeNotifier.
*
* Called when
* the socket is ready for writing.
*/
void slotWrite( int );
/**
* Connected to the readNotifier.
*
* Called when
* the socket is ready for reading.
*/
void slotRead( int );
protected:
bool connect( const QString& _host, unsigned short int _port );
bool connect( const char *_path );
bool init_sockaddr( const QString& hostname, unsigned short int port );
ksockaddr_in server_name;
struct sockaddr_un unix_addr;
/******************************************************
* The file descriptor for this socket. sock may be -1.
* This indicates that it is not connected.
*/
int sock;
int domain;
QSocketNotifier *readNotifier;
QSocketNotifier *writeNotifier;
private:
int timeOut;
KSocket(const KSocket&);
KSocket& operator=(const KSocket&);
KSocketPrivate *d;
static char *cachedHostname;
static ksockaddr_in *cachedServerName;
};
/**
* Monitor a port for incoming TCP/IP connections.
*
* You can use a KServerSocket to listen on a port for incoming
* connections. When a connection arrived in the port, a KSocket
* is created and the signal accepted is raised. Make sure you
* always connect to this signal. If you dont the ServerSocket will
* create new KSocket's and no one will delete them!
*
* If socket() is -1 or less the socket was not created properly.
*
* @author Torben Weis <weis@stud.uni-frankfurt.de>
* @version $Id: ksock.h,v 1.41 2000/09/09 23:34:44 rikkus Exp $
* @short Monitor a port for incoming TCP/IP connections.
*/
class KServerSocket : public QObject
{
Q_OBJECT
public:
/**
* Constructor.
* @param _port the port number to monitor for incoming connections.
*/
KServerSocket( unsigned short int _port );
/**
* Creates a UNIX domain server socket.
*/
KServerSocket( const char *_path );
/**
* Destructor. Closes the socket if it was not already closed.
*/
virtual ~KServerSocket();
/**
* Get the file descriptor assoziated with the socket.
*/
int socket() const { return sock; }
/**
* Returns the port number which is being monitored.
*/
unsigned short int port();
/**
* The address.
*/
unsigned long ipv4_addr();
public slots:
/**
* Called when someone connected to our port.
*/
virtual void slotAccept( int );
signals:
/**
* A connection has been accepted.
* It is your task to delete the KSocket if it is no longer needed.
*/
void accepted( KSocket* );
protected:
bool init( short unsigned int );
bool init( const char *_path );
/**
* Notifies us when there is something to read on the port.
*/
QSocketNotifier *notifier;
/**
* The file descriptor for this socket. sock may be -1.
* This indicates that it is not connected.
*/
int sock;
int domain;
private:
KServerSocket(const KServerSocket&);
KServerSocket& operator=(const KServerSocket&);
KServerSocketPrivate *d;
};
// Here are a whole bunch of hackish macros that allow one to
// get at the correct member of ksockaddr_in
#ifdef INET6
#define get_sin_addr(x) x.sin6_addr
#define get_sin_port(x) x.sin6_port
#define get_sin_family(x) x.sin6_family
#define get_sin_paddr(x) x->sin6_addr
#define get_sin_pport(x) x->sin6_port
#define get_sin_pfamily(x) x->sin6_family
#else
#define get_sin_addr(x) x.sin_addr
#define get_sin_port(x) x.sin_port
#define get_sin_family(x) x.sin_family
#define get_sin_paddr(x) x->sin_addr
#define get_sin_pport(x) x->sin_port
#define get_sin_pfamily(x) x->sin_family
#endif
#endif