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

KDECore

k3datagramsocket.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003,2004 Thiago Macieira <thiago@kde.org>
00003  *
00004  *
00005  *  Permission is hereby granted, free of charge, to any person obtaining
00006  *  a copy of this software and associated documentation files (the
00007  *  "Software"), to deal in the Software without restriction, including
00008  *  without limitation the rights to use, copy, modify, merge, publish,
00009  *  distribute, sublicense, and/or sell copies of the Software, and to
00010  *  permit persons to whom the Software is furnished to do so, subject to
00011  *  the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be included
00014  *  in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #include "k3datagramsocket.h"
00026 
00027 #include <config.h>
00028 #include <config-network.h>
00029 
00030 #include <sys/types.h>
00031 #include <sys/socket.h>
00032 
00033 #include "k3socketaddress.h"
00034 #include "k3resolver.h"
00035 #include "k3socketdevice.h"
00036 
00037 using namespace KNetwork;
00038 
00039 /*
00040  * TODO:
00041  *
00042  * don't use signals and slots to track state changes: use stateChanging
00043  *
00044  */
00045 
00046 KDatagramSocket::KDatagramSocket(QObject* parent)
00047   : KClientSocketBase(parent), d(0L)
00048 {
00049   peerResolver().setFamily(KResolver::KnownFamily);
00050   localResolver().setFamily(KResolver::KnownFamily);
00051 
00052   peerResolver().setSocketType(SOCK_DGRAM);
00053   localResolver().setSocketType(SOCK_DGRAM);
00054 
00055   localResolver().setFlags(KResolver::Passive);
00056 
00057   //  QObject::connect(localResolver(), SIGNAL(finished(const KNetwork::KResolverResults&))
00058   //           this, SLOT(lookupFinishedLocal()));
00059   QObject::connect(&peerResolver(),
00060            SIGNAL(finished(const KNetwork::KResolverResults&)),
00061            this, SLOT(lookupFinishedPeer()));
00062   QObject::connect(this, SIGNAL(hostFound()), this, SLOT(lookupFinishedLocal()));
00063 }
00064 
00065 KDatagramSocket::~KDatagramSocket()
00066 {
00067   // KClientSocketBase's destructor closes the socket
00068 
00069   //delete d;
00070 }
00071 
00072 bool KDatagramSocket::bind(const QString& node, const QString& service)
00073 {
00074   if (state() >= Bound)
00075     return false;
00076 
00077   if (localResolver().isRunning())
00078     localResolver().cancel(false);
00079 
00080   // no, we must do a host lookup
00081   localResolver().setAddress(node, service);
00082 
00083   if (!lookup())
00084     return false;
00085 
00086   // see if lookup has finished already
00087   // this also catches blocking mode, since lookup has to finish
00088   // its processing if we're in blocking mode
00089   if (state() > HostLookup)
00090     return doBind();
00091 
00092   return true;
00093 }
00094 
00095 bool KDatagramSocket::bind(const KResolverEntry& entry)
00096 {
00097   return KClientSocketBase::bind(entry);
00098 }
00099 
00100 bool KDatagramSocket::connect(const QString& node, const QString& service,
00101                   OpenMode mode)
00102 {
00103   if (state() >= Connected)
00104     return true;        // already connected
00105 
00106   if (peerResolver().nodeName() != node ||
00107       peerResolver().serviceName() != service)
00108     peerResolver().setAddress(node, service); // this resets the resolver's state
00109 
00110   // KClientSocketBase::lookup only works if the state is Idle or HostLookup
00111   // therefore, we store the old state, call the lookup routine and then set
00112   // it back.
00113   SocketState s = state();
00114   setState(s == Connecting ? HostLookup : Idle);
00115   bool ok = lookup();
00116   if (!ok)
00117     {
00118       setState(s);      // go back
00119       return false;
00120     }
00121 
00122   // check if lookup is finished
00123   // if we're in blocking mode, then the lookup has to be finished
00124   if (state() == HostLookup)
00125     {
00126       // it hasn't finished
00127       setState(Connecting);
00128       emit stateChanged(Connecting);
00129       return true;
00130     }
00131 
00132   // it has to be finished here
00133   if (state() != Connected)
00134     {
00135       setState(Connecting);
00136       emit stateChanged(Connecting);
00137       lookupFinishedPeer();
00138     }
00139 
00140   KActiveSocketBase::open(mode | Unbuffered);
00141   return state() == Connected;
00142 }
00143 
00144 bool KDatagramSocket::connect(const KResolverEntry& entry, OpenMode mode)
00145 {
00146     return KClientSocketBase::connect(entry, mode);
00147 }
00148 
00149 KDatagramPacket KDatagramSocket::receive()
00150 {
00151   qint64 size = bytesAvailable();
00152   if (size == 0)
00153     {
00154       // nothing available yet to read
00155       // wait for data if we're not blocking
00156       if (blocking())
00157     socketDevice()->waitForMore(-1); // wait forever
00158       else
00159     {
00160       // mimic error
00161       setError(WouldBlock);
00162       emit gotError(WouldBlock);
00163       return KDatagramPacket();
00164     }
00165 
00166       // try again
00167       size = bytesAvailable();
00168     }
00169 
00170   QByteArray data;
00171   data.resize(size);
00172   KSocketAddress address;
00173 
00174   // now do the reading
00175   size = read(data.data(), size, address);
00176   if (size < 0)
00177     // error has been set
00178     return KDatagramPacket();
00179 
00180   data.resize(size);        // just to be sure
00181   return KDatagramPacket(data, address);
00182 }
00183 
00184 qint64 KDatagramSocket::send(const KDatagramPacket& packet)
00185 {
00186   return write(packet.data(), packet.size(), packet.address());
00187 }
00188 
00189 qint64 KDatagramSocket::writeData(const char *data, qint64 len,
00190                   const KSocketAddress* to)
00191 {
00192   if (to->family() != AF_UNSPEC)
00193     {
00194       // make sure the socket is open at this point
00195       if (!socketDevice()->isOpen())
00196     // error handling will happen below
00197     socketDevice()->create(to->family(), SOCK_DGRAM, 0);
00198     }
00199   return KClientSocketBase::writeData(data, len, to);
00200 }
00201 
00202 void KDatagramSocket::lookupFinishedLocal()
00203 {
00204   // bind lookup has finished and succeeded
00205   // state() == HostFound
00206 
00207   if (!doBind())
00208     return;         // failed binding
00209 
00210   if (peerResults().count() > 0)
00211     {
00212       setState(Connecting);
00213       emit stateChanged(Connecting);
00214 
00215       lookupFinishedPeer();
00216     }
00217 }
00218 
00219 void KDatagramSocket::lookupFinishedPeer()
00220 {
00221   // this function is called by lookupFinishedLocal above
00222   // and is also connected to a signal
00223   // so it might be called twice.
00224 
00225   if (state() != Connecting)
00226     return;
00227 
00228   if (peerResults().count() == 0)
00229     {
00230       setState(Unconnected);
00231       emit stateChanged(Unconnected);
00232       return;
00233     }
00234 
00235   KResolverResults::ConstIterator it = peerResults().begin();
00236   for ( ; it != peerResults().end(); ++it)
00237     if (connect(*it))
00238       {
00239     // weee, we connected
00240 
00241     setState(Connected);    // this sets up signals
00242     //setupSignals();   // setState sets up the signals
00243 
00244     emit stateChanged(Connected);
00245     emit connected(*it);
00246     return;
00247       }
00248 
00249   // no connection
00250   copyError();
00251   setState(Unconnected);
00252   emit stateChanged(Unconnected);
00253   emit gotError(error());
00254 }
00255 
00256 bool KDatagramSocket::doBind()
00257 {
00258   if (localResults().count() == 0)
00259     return true;
00260   if (state() >= Bound)
00261     return true;        // already bound
00262 
00263   KResolverResults::ConstIterator it = localResults().begin();
00264   for ( ; it != localResults().end(); ++it)
00265     if (bind(*it))
00266       {
00267     // bound
00268     setupSignals();
00269     KActiveSocketBase::open(ReadWrite | Unbuffered);
00270     return true;
00271       }
00272 
00273   // not bound
00274   // no need to set state since it can only be HostFound already
00275   copyError();
00276   emit gotError(error());
00277   return false;
00278 }
00279 
00280 void KDatagramSocket::setupSignals()
00281 {
00282   QSocketNotifier *n = socketDevice()->readNotifier();
00283   if (n)
00284     {
00285       n->setEnabled(emitsReadyRead());
00286       QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotReadActivity()));
00287     }
00288   else
00289     return;
00290 
00291   n = socketDevice()->writeNotifier();
00292   if (n)
00293     {
00294       n->setEnabled(emitsReadyWrite());
00295       QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotWriteActivity()));
00296     }
00297   else
00298     return;
00299 }
00300 
00301 #include "k3datagramsocket.moc"

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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