• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

ksock.cpp

Go to the documentation of this file.
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (C) 1997 Torben Weis (weis@kde.org)
00004  *
00005  *  $Id: ksock.cpp 482738 2005-11-24 00:21:15Z mueller $
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., 51 Franklin Street, Fifth Floor,
00020  *  Boston, MA 02110-1301, 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 #ifdef __CYGWIN__
00089 #include "qwindowdefs.h"
00090 #endif 
00091 
00092 class KSocketPrivate
00093 {
00094 public:
00095   QSocketNotifier *readNotifier;
00096   QSocketNotifier *writeNotifier;
00097 
00098   KSocketPrivate() :
00099     readNotifier(0), writeNotifier(0)
00100   { }
00101 };
00102 
00103 // I moved this into here so we could accurately detect the domain, for
00104 // posterity.  Really.
00105 KSocket::KSocket( int _sock)
00106   : sock(_sock), d(new KSocketPrivate)
00107 {
00108   struct sockaddr_in sin;
00109   ksocklen_t len = sizeof(sin);
00110 
00111   memset(&sin, 0, len);
00112 
00113   // getsockname will fill in all the appropriate details, and
00114   // since sockaddr_in will exist everywhere and is somewhat compatible
00115   // with sockaddr_in6, we can use it to avoid needless ifdefs.
00116   KSocks::self()->getsockname(_sock, (struct sockaddr *)&sin, &len);
00117 }
00118 
00119 KSocket::KSocket( const char *_host, unsigned short int _port, int _timeout ) :
00120   sock( -1 ), d(new KSocketPrivate)
00121 {
00122     connect( _host, _port, _timeout );
00123 }
00124 
00125 KSocket::KSocket( const char *_path ) :
00126   sock( -1 ), d(new KSocketPrivate)
00127 {
00128   connect( _path );
00129 }
00130 
00131 void KSocket::enableRead( bool _state )
00132 {
00133   if ( _state )
00134     {
00135       if ( !d->readNotifier  )
00136         {
00137           d->readNotifier = new QSocketNotifier( sock, QSocketNotifier::Read );
00138           QObject::connect( d->readNotifier, SIGNAL( activated(int) ), this, SLOT( slotRead(int) ) );
00139         }
00140       else
00141         d->readNotifier->setEnabled( true );
00142     }
00143   else if ( d->readNotifier )
00144     d->readNotifier->setEnabled( false );
00145 }
00146 
00147 void KSocket::enableWrite( bool _state )
00148 {
00149   if ( _state )
00150     {
00151       if ( !d->writeNotifier )
00152         {
00153           d->writeNotifier = new QSocketNotifier( sock, QSocketNotifier::Write );
00154           QObject::connect( d->writeNotifier, SIGNAL( activated(int) ), this,
00155                             SLOT( slotWrite(int) ) );
00156         }
00157       else
00158         d->writeNotifier->setEnabled( true );
00159     }
00160   else if ( d->writeNotifier )
00161     d->writeNotifier->setEnabled( false );
00162 }
00163 
00164 void KSocket::slotRead( int )
00165 {
00166   char buffer[2];
00167 
00168   int n = recv( sock, buffer, 1, MSG_PEEK );
00169   if ( n <= 0 )
00170     emit closeEvent( this );
00171   else
00172     emit readEvent( this );
00173 }
00174 
00175 void KSocket::slotWrite( int )
00176 {
00177   emit writeEvent( this );
00178 }
00179 
00180 /*
00181  * Connects the PF_UNIX domain socket to _path.
00182  */
00183 bool KSocket::connect( const char *_path )
00184 {
00185   KExtendedSocket ks(QString::null, _path, KExtendedSocket::unixSocket);
00186 
00187   ks.connect();
00188   sock = ks.fd();
00189   ks.release();
00190 
00191   return sock >= 0;
00192 }
00193 
00194 /*
00195  * Connects the socket to _host, _port.
00196  */
00197 bool KSocket::connect( const QString& _host, unsigned short int _port, int _timeout )
00198 {
00199   KExtendedSocket ks(_host, _port, KExtendedSocket::inetSocket);
00200   ks.setTimeout(_timeout, 0);
00201 
00202   ks.connect();
00203   sock = ks.fd();
00204   ks.release();
00205 
00206   return sock >= 0;
00207 }
00208 
00209 // only for doxygen - the define is always true as defined above
00210 #ifdef KSOCK_NO_BROKEN
00211 unsigned long KSocket::ipv4_addr()
00212 {
00213   unsigned long retval = 0;
00214   KSocketAddress *sa = KExtendedSocket::peerAddress(sock);
00215   if (sa == NULL)
00216     return 0;
00217 
00218   if (sa->address() != NULL && (sa->address()->sa_family == PF_INET
00219 #ifdef PF_INET6
00220                 || sa->address()->sa_family == PF_INET6
00221 #endif
00222       ))
00223     {
00224       KInetSocketAddress *ksin = (KInetSocketAddress*)sa;
00225       const sockaddr_in *sin = ksin->addressV4();
00226       if (sin != NULL)
00227     retval = sin->sin_addr.s_addr;
00228     }
00229   delete sa;
00230   return retval;
00231 }
00232 
00233 bool KSocket::initSockaddr (ksockaddr_in *server_name, const char *hostname, unsigned short int port, int domain)
00234 {
00235   // This function is now IPv4 only
00236   // if you want something better, you should use KExtendedSocket::lookup yourself
00237 
00238   kdWarning(170) << "deprecated KSocket::initSockaddr called" << endl;
00239 
00240   if (domain != PF_INET)
00241     return false;
00242 
00243   QPtrList<KAddressInfo> list = KExtendedSocket::lookup(hostname, QString::number(port),
00244                                                         KExtendedSocket::ipv4Socket);
00245   list.setAutoDelete(true);
00246 
00247   if (list.isEmpty())
00248     return false;
00249 
00250   memset(server_name, 0, sizeof(*server_name));
00251 
00252   // We are sure that only KInetSocketAddress objects are in the list
00253   KInetSocketAddress *sin = (KInetSocketAddress*)list.getFirst()->address();
00254   if (sin == NULL)
00255     return false;
00256 
00257   memcpy(server_name, sin->addressV4(), sizeof(*server_name));
00258   kdDebug(170) << "KSocket::initSockaddr: returning " << sin->pretty() << endl;
00259   return true;
00260 }
00261 
00262 #endif
00263 
00264 KSocket::~KSocket()
00265 {
00266   // Coolo says delete 0 is ok :) -thiago
00267   delete d->readNotifier;
00268   delete d->writeNotifier;
00269 
00270   delete d;
00271 
00272   if (sock != -1) {
00273     ::close( sock );
00274   }
00275 }
00276 
00277 class KServerSocketPrivate
00278 {
00279 public:
00280    bool bind;
00281    QCString path;
00282    unsigned short int port;
00283    KExtendedSocket *ks;
00284 };
00285 
00286 
00287 KServerSocket::KServerSocket( const char *_path, bool _bind ) :
00288   sock( -1 )
00289 {
00290   d = new KServerSocketPrivate();
00291   d->bind = _bind;
00292 
00293   init ( _path );
00294 }
00295 
00296 KServerSocket::KServerSocket( unsigned short int _port, bool _bind ) :
00297   sock( -1 )
00298 {
00299   d = new KServerSocketPrivate();
00300   d->bind = _bind;
00301 
00302   init ( _port );
00303 }
00304 
00305 bool KServerSocket::init( const char *_path )
00306 {
00307   unlink(_path );
00308   d->path = _path;
00309 
00310   KExtendedSocket *ks = new KExtendedSocket(QString::null, _path, KExtendedSocket::passiveSocket |
00311                         KExtendedSocket::unixSocket);
00312   d->ks = ks;
00313 
00314   if (d->bind)
00315     return bindAndListen();
00316   return true;
00317 }
00318 
00319 
00320 bool KServerSocket::init( unsigned short int _port )
00321 {
00322   d->port = _port;
00323   KExtendedSocket *ks;
00324   ks = new KExtendedSocket(QString::null, _port, KExtendedSocket::passiveSocket |
00325                KExtendedSocket::inetSocket);
00326   d->ks = ks;
00327 
00328   if (d->bind)
00329     return bindAndListen();
00330   return true;
00331 }
00332 
00333 bool KServerSocket::bindAndListen()
00334 {
00335   if (d == NULL || d->ks == NULL)
00336     return false;
00337 
00338 
00339   int ret = d->ks->listen( SOMAXCONN );
00340   if (ret < 0)
00341     {
00342         kdWarning(170) << "Error listening on socket: " << ret << "\n";
00343     delete d->ks;
00344     d->ks = NULL;
00345     sock = -1;
00346     return false;
00347     }
00348 
00349 
00350   sock = d->ks->fd();
00351 
00352   connect( d->ks->readNotifier(), SIGNAL( activated(int) ), this, SLOT( slotAccept(int) ) );
00353   return true;
00354 }
00355 
00356 
00357 unsigned short int KServerSocket::port()
00358 {
00359   if (d == NULL || d->ks == NULL || sock == -1)
00360     return 0;
00361   const KSocketAddress *sa = d->ks->localAddress();
00362   if (sa == NULL)
00363     return 0;
00364 
00365   // we can use sockaddr_in here even if it isn't IPv4
00366   sockaddr_in *sin = (sockaddr_in*)sa->address();
00367 
00368   if (sin->sin_family == PF_INET)
00369     // correct family
00370     return sin->sin_port;
00371 #ifdef PF_INET6
00372   else if (sin->sin_family == PF_INET6)
00373     {
00374       kde_sockaddr_in6 *sin6 = (kde_sockaddr_in6*)sin;
00375       return sin6->sin6_port;
00376     }
00377 #endif
00378   return 0;         // not a port we know
00379 }
00380 
00381 unsigned long KServerSocket::ipv4_addr()
00382 {
00383   if (d == NULL || d->ks == NULL || sock == -1)
00384     return 0;
00385   const KSocketAddress *sa = d->ks->localAddress();
00386 
00387   const sockaddr_in *sin = (sockaddr_in*)sa->address();
00388 
00389   if (sin->sin_family == PF_INET)
00390     // correct family
00391     return ntohl(sin->sin_addr.s_addr);
00392 #ifdef PF_INET6
00393   else if (sin->sin_family == PF_INET6)
00394     {
00395       KInetSocketAddress *ksin = (KInetSocketAddress*)sa;
00396       sin = ksin->addressV4();
00397       if (sin != NULL)
00398     return sin->sin_addr.s_addr;
00399     }
00400 #endif
00401   return 0;         // this is dumb, isn't it?
00402 }
00403 
00404 void KServerSocket::slotAccept( int )
00405 {
00406   if (d == NULL || d->ks == NULL || sock == -1)
00407     return;         // nothing!
00408 
00409   KExtendedSocket *s;
00410   if (d->ks->accept(s) < 0)
00411     {
00412         kdWarning(170) << "Error accepting\n";
00413         return;
00414     }
00415 
00416   int new_sock = s->fd();
00417   s->release();         // we're getting rid of the KExtendedSocket
00418   delete s;
00419 
00420   emit accepted( new KSocket( new_sock ) );
00421 }
00422 
00423 KServerSocket::~KServerSocket()
00424 {
00425   if (d != NULL)
00426     {
00427       if (d->ks != NULL)
00428     delete d->ks;
00429       delete d;
00430     }
00431   // deleting d->ks closes the socket
00432   //  ::close( sock );
00433 }
00434 
00435 #include "ksock.moc"

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal