| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# ksock.cpp

    00001 /*
    00002  *  This file is part of the KDE libraries
    00003  *  Copyright (C) 1997 Torben Weis (weis@kde.org)
    00004  *
    00005  *  $Id: ksock.cpp 233990 2003-06-26 21:13:41Z tjansen $
    00006  *
    00007  *  This library is free software; you can redistribute it and/or
    00008  *  modify it under the terms of the GNU Library General Public
    00009  *  License as published by the Free Software Foundation; either
    00010  *  version 2 of the License, or (at your option) any later version.
    00011  *
    00012  *  This library is distributed in the hope that it will be useful,
    00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015  *  Library General Public License for more details.
    00016  *
    00017  *  You should have received a copy of the GNU Library General Public License
    00018  *  along with this library; see the file COPYING.LIB.  If not, write to
    00019  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00020  *  Boston, MA 02111-1307, USA.
    00021  **/
    00022
    00023 #include <config.h>
    00024
    00025 #include <sys/types.h>
    00026 #include <sys/stat.h>
    00027 // on Linux/libc5, this includes linux/socket.h where SOMAXCONN is defined
    00028 #include <sys/socket.h>
    00029 #include <sys/resource.h>
    00030 #include <sys/time.h>
    00031 #include <sys/un.h>
    00032 #ifdef HAVE_SYS_SELECT_H
    00033 #include <sys/select.h>
    00034 #endif
    00035 extern "C" {
    00036 #include <netinet/in.h>
    00037
    00038 #include <arpa/inet.h>
    00039 }
    00040
    00041 #define KSOCK_NO_BROKEN
    00042 #include "kdebug.h"
    00043 #include "ksock.h"
    00044 #include "kextsock.h"
    00045 #include "ksockaddr.h"
    00046
    00047 #include "ksocks.h"
    00048
    00049 extern "C" {
    00050 #include <errno.h>
    00051 #include <fcntl.h>
    00052
    00053 #ifdef HAVE_GETADDRINFO
    00054 #include <netdb.h>
    00055 #endif
    00056
    00057 // defines MAXDNAME under Solaris
    00058 #include <arpa/nameser.h>
    00059 #include <resolv.h>
    00060 }
    00061 #include <stdio.h>
    00062 #include <stdlib.h>
    00063 #include <string.h>
    00064 #include <signal.h>
    00065 #include <unistd.h>
    00066 #include <assert.h>
    00067
    00068 #ifdef HAVE_SYSENT_H
    00069 #include <sysent.h>
    00070 #endif
    00071
    00072 #if TIME_WITH_SYS_TIME
    00073 #include <time.h>
    00074 #endif
    00075
    00076
    00077 // Play it safe, use a reasonable default, if SOMAXCONN was nowhere defined.
    00078 #ifndef SOMAXCONN
    00079 #warning Your header files do not seem to support SOMAXCONN
    00080 #define SOMAXCONN 5
    00081 #endif
    00082
    00083 #include <qapplication.h>
    00084 #include <qsocketnotifier.h>
    00085
    00086 #include "netsupp.h"        // leave this last
    00087
    00088 class KSocketPrivate
    00089 {
    00090 public:
    00091   QSocketNotifier *readNotifier;
    00092   QSocketNotifier *writeNotifier;
    00093
    00094   KSocketPrivate() :
    00095     readNotifier(0), writeNotifier(0)
    00096   { }
    00097 };
    00098
    00099 // I moved this into here so we could accurately detect the domain, for
    00100 // posterity.  Really.
    00101 KSocket::KSocket( int _sock)
    00102   : sock(_sock), d(new KSocketPrivate)
    00103 {
    00104   struct sockaddr_in sin;
    00105   ksocklen_t len = sizeof(sin);
    00106
    00107   memset(&sin, 0, len);
    00108
    00109   // getsockname will fill in all the appropriate details, and
    00110   // since sockaddr_in will exist everywhere and is somewhat compatible
    00111   // with sockaddr_in6, we can use it to avoid needless ifdefs.
    00112   KSocks::self()->getsockname(_sock, (struct sockaddr *)&sin, &len);
    00113 }
    00114
    00115 KSocket::KSocket( const char *_host, unsigned short int _port, int _timeout ) :
    00116   sock( -1 ), d(new KSocketPrivate)
    00117 {
    00118     connect( _host, _port, _timeout );
    00119 }
    00120
    00121 KSocket::KSocket( const char *_path ) :
    00122   sock( -1 ), d(new KSocketPrivate)
    00123 {
    00124   connect( _path );
    00125 }
    00126
    00127 void KSocket::enableRead( bool _state )
    00128 {
    00129   if ( _state )
    00130     {
    00131       if ( !d->readNotifier  )
    00132         {
    00133           d->readNotifier = new QSocketNotifier( sock, QSocketNotifier::Read );
    00134           QObject::connect( d->readNotifier, SIGNAL( activated(int) ), this, SLOT( slotRead(int) ) );
    00135         }
    00136       else
    00137         d->readNotifier->setEnabled( true );
    00138     }
    00139   else if ( d->readNotifier )
    00140     d->readNotifier->setEnabled( false );
    00141 }
    00142
    00143 void KSocket::enableWrite( bool _state )
    00144 {
    00145   if ( _state )
    00146     {
    00147       if ( !d->writeNotifier )
    00148         {
    00149           d->writeNotifier = new QSocketNotifier( sock, QSocketNotifier::Write );
    00150           QObject::connect( d->writeNotifier, SIGNAL( activated(int) ), this,
    00151                             SLOT( slotWrite(int) ) );
    00152         }
    00153       else
    00154         d->writeNotifier->setEnabled( true );
    00155     }
    00156   else if ( d->writeNotifier )
    00157     d->writeNotifier->setEnabled( false );
    00158 }
    00159
    00160 void KSocket::slotRead( int )
    00161 {
    00162   char buffer[2];
    00163
    00164   int n = recv( sock, buffer, 1, MSG_PEEK );
    00165   if ( n <= 0 )
    00166     emit closeEvent( this );
    00167   else
    00168     emit readEvent( this );
    00169 }
    00170
    00171 void KSocket::slotWrite( int )
    00172 {
    00173   emit writeEvent( this );
    00174 }
    00175
    00176 /*
    00177  * Connects the PF_UNIX domain socket to _path.
    00178  */
    00179 bool KSocket::connect( const char *_path )
    00180 {
    00181   KExtendedSocket ks(QString::null, _path, KExtendedSocket::unixSocket);
    00182
    00183   ks.connect();
    00184   sock = ks.fd();
    00185   ks.release();
    00186
    00187   return sock >= 0;
    00188 }
    00189
    00190 /*
    00191  * Connects the socket to _host, _port.
    00192  */
    00193 bool KSocket::connect( const QString& _host, unsigned short int _port, int _timeout )
    00194 {
    00195   KExtendedSocket ks(_host, _port, KExtendedSocket::inetSocket);
    00196   ks.setTimeout(_timeout, 0);
    00197
    00198   ks.connect();
    00199   sock = ks.fd();
    00200   ks.release();
    00201
    00202   return sock >= 0;
    00203 }
    00204
    00205 // only for doxygen - the define is always true as defined above
    00206 #ifdef KSOCK_NO_BROKEN
    00207 unsigned long KSocket::ipv4_addr()
    00208 {
    00209   unsigned long retval = 0;
    00210   KSocketAddress *sa = KExtendedSocket::peerAddress(sock);
    00211   if (sa == NULL)
    00212     return 0;
    00213
    00214   if (sa->address() != NULL && (sa->address()->sa_family == PF_INET
    00215 #ifdef PF_INET6
    00216                 || sa->address()->sa_family == PF_INET6
    00217 #endif
    00218       ))
    00219     {
    00220       KInetSocketAddress *ksin = (KInetSocketAddress*)sa;
    00221       const sockaddr_in *sin = ksin->addressV4();
    00222       if (sin != NULL)
    00223     retval = *(unsigned long*)&sin->sin_addr; // I told you this was dumb
    00224     }
    00225   delete sa;
    00226   return retval;
    00227 }
    00228
    00229 bool KSocket::initSockaddr (ksockaddr_in *server_name, const char *hostname, unsigned short int port, int domain)
    00230 {
    00231   // This function is now IPv4 only
    00232   // if you want something better, you should use KExtendedSocket::lookup yourself
    00233
    00234   kdWarning(170) << "deprecated KSocket::initSockaddr called" << endl;
    00235
    00236   if (domain != PF_INET)
    00237     return false;
    00238
    00239   QPtrList<KAddressInfo> list = KExtendedSocket::lookup(hostname, QString::number(port),
    00240                                                         KExtendedSocket::ipv4Socket);
    00241   list.setAutoDelete(true);
    00242
    00243   if (list.isEmpty())
    00244     return false;
    00245
    00246   memset(server_name, 0, sizeof(*server_name));
    00247
    00248   // We are sure that only KInetSocketAddress objects are in the list
    00249   KInetSocketAddress *sin = (KInetSocketAddress*)list.getFirst()->address();
    00250   if (sin == NULL)
    00251     return false;
    00252
    00253   memcpy(server_name, sin->addressV4(), sizeof(*server_name));
    00254   kdDebug(170) << "KSocket::initSockaddr: returning " << sin->pretty() << endl;
    00255   return true;
    00256 }
    00257
    00258 #endif
    00259
    00260 KSocket::~KSocket()
    00261 {
    00262   // Coolo says delete 0 is ok :) -thiago
    00263   delete d->readNotifier;
    00264   delete d->writeNotifier;
    00265
    00266   delete d;
    00267
    00268   if (sock != -1) {
    00269     ::close( sock );
    00270   }
    00271 }
    00272
    00273 class KServerSocketPrivate
    00274 {
    00275 public:
    00276    bool bind;
    00277    QCString path;
    00278    unsigned short int port;
    00279    KExtendedSocket *ks;
    00280 };
    00281
    00282
    00283 KServerSocket::KServerSocket( const char *_path, bool _bind ) :
    00284   sock( -1 )
    00285 {
    00286   d = new KServerSocketPrivate();
    00287   d->bind = _bind;
    00288
    00289   init ( _path );
    00290 }
    00291
    00292 KServerSocket::KServerSocket( unsigned short int _port, bool _bind ) :
    00293   sock( -1 )
    00294 {
    00295   d = new KServerSocketPrivate();
    00296   d->bind = _bind;
    00297
    00298   init ( _port );
    00299 }
    00300
    00301 bool KServerSocket::init( const char *_path )
    00302 {
    00303   unlink(_path );
    00304   d->path = _path;
    00305
    00306   KExtendedSocket *ks = new KExtendedSocket(QString::null, _path, KExtendedSocket::passiveSocket |
    00307                         KExtendedSocket::unixSocket);
    00308   d->ks = ks;
    00309
    00310   if (d->bind)
    00311     return bindAndListen();
    00312   return true;
    00313 }
    00314
    00315
    00316 bool KServerSocket::init( unsigned short int _port )
    00317 {
    00318   d->port = _port;
    00319   KExtendedSocket *ks;
    00320   ks = new KExtendedSocket(QString::null, _port, KExtendedSocket::passiveSocket |
    00321                KExtendedSocket::inetSocket);
    00322   d->ks = ks;
    00323
    00324   if (d->bind)
    00325     return bindAndListen();
    00326   return true;
    00327 }
    00328
    00329 bool KServerSocket::bindAndListen()
    00330 {
    00331   if (d == NULL || d->ks == NULL)
    00332     return false;
    00333
    00334
    00335   int ret = d->ks->listen( SOMAXCONN );
    00336   if (ret < 0)
    00337     {
    00338         kdWarning(170) << "Error listening on socket: " << ret << "\n";
    00339     delete d->ks;
    00340     d->ks = NULL;
    00341     sock = -1;
    00342     return false;
    00343     }
    00344
    00345
    00346   sock = d->ks->fd();
    00347
    00348   connect( d->ks->readNotifier(), SIGNAL( activated(int) ), this, SLOT( slotAccept(int) ) );
    00349   return true;
    00350 }
    00351
    00352
    00353 unsigned short int KServerSocket::port()
    00354 {
    00355   if (d == NULL || d->ks == NULL || sock == -1)
    00356     return 0;
    00357   const KSocketAddress *sa = d->ks->localAddress();
    00358   if (sa == NULL)
    00359     return 0;
    00360
    00361   // we can use sockaddr_in here even if it isn't IPv4
    00362   sockaddr_in *sin = (sockaddr_in*)sa->address();
    00363
    00364   if (sin->sin_family == PF_INET)
    00365     // correct family
    00366     return sin->sin_port;
    00367 #ifdef PF_INET6
    00368   else if (sin->sin_family == PF_INET6)
    00369     {
    00370       kde_sockaddr_in6 *sin6 = (kde_sockaddr_in6*)sin;
    00371       return sin6->sin6_port;
    00372     }
    00373 #endif
    00374   return 0;         // not a port we know
    00375 }
    00376
    00377 unsigned long KServerSocket::ipv4_addr()
    00378 {
    00379   if (d == NULL || d->ks == NULL || sock == -1)
    00380     return 0;
    00381   const KSocketAddress *sa = d->ks->localAddress();
    00382
    00383   const sockaddr_in *sin = (sockaddr_in*)sa->address();
    00384
    00385   if (sin->sin_family == PF_INET)
    00386     // correct family
    00387     return ntohl(*(unsigned long*)&sin->sin_addr);
    00388 #ifdef PF_INET6
    00389   else if (sin->sin_family == PF_INET6)
    00390     {
    00391       KInetSocketAddress *ksin = (KInetSocketAddress*)sa;
    00392       sin = ksin->addressV4();
    00393       if (sin != NULL)
    00394     return *(unsigned long*)&sin->sin_addr;
    00395     }
    00396 #endif
    00397   return 0;         // this is dumb, isn't it?
    00398 }
    00399
    00400 void KServerSocket::slotAccept( int )
    00401 {
    00402   if (d == NULL || d->ks == NULL || sock == -1)
    00403     return;         // nothing!
    00404
    00405   KExtendedSocket *s;
    00406   if (d->ks->accept(s) < 0)
    00407     {
    00408         kdWarning(170) << "Error accepting\n";
    00409         return;
    00410     }
    00411
    00412   int new_sock = s->fd();
    00413   s->release();         // we're getting rid of the KExtendedSocket
    00414   delete s;
    00415
    00416   emit accepted( new KSocket( new_sock ) );
    00417 }
    00418
    00419 KServerSocket::~KServerSocket()
    00420 {
    00421   if (d != NULL)
    00422     {
    00423       if (d->ks != NULL)
    00424     delete d->ks;
    00425       delete d;
    00426     }
    00427   // deleting d->ks closes the socket
    00428   //  ::close( sock );
    00429 }
    00430
    00431 #include "ksock.moc"

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:10 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003