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

KDECore

kdatagramsocket.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003,2004 Thiago Macieira <thiago.macieira@kdemail.net>
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 <config.h>
00026 
00027 #include <sys/types.h>
00028 #include <sys/socket.h>
00029 
00030 #include "ksocketaddress.h"
00031 #include "kresolver.h"
00032 #include "ksocketdevice.h"
00033 #include "kdatagramsocket.h"
00034 
00035 using namespace KNetwork;
00036 
00037 /*
00038  * TODO:
00039  *
00040  * don't use signals and slots to track state changes: use stateChanging
00041  *
00042  */
00043 
00044 KDatagramSocket::KDatagramSocket(QObject* parent, const char *name)
00045   : KClientSocketBase(parent, name), d(0L)
00046 {
00047   peerResolver().setFamily(KResolver::KnownFamily);
00048   localResolver().setFamily(KResolver::KnownFamily);
00049 
00050   peerResolver().setSocketType(SOCK_DGRAM);
00051   localResolver().setSocketType(SOCK_DGRAM);
00052 
00053   localResolver().setFlags(KResolver::Passive);
00054 
00055   //  QObject::connect(localResolver(), SIGNAL(finished(KResolverResults)),
00056   //           this, SLOT(lookupFinishedLocal()));
00057   QObject::connect(&peerResolver(), SIGNAL(finished(KResolverResults)),
00058            this, SLOT(lookupFinishedPeer()));
00059   QObject::connect(this, SIGNAL(hostFound()), this, SLOT(lookupFinishedLocal()));
00060 }
00061 
00062 KDatagramSocket::~KDatagramSocket()
00063 {
00064   // KClientSocketBase's destructor closes the socket
00065 
00066   //delete d;
00067 }
00068 
00069 bool KDatagramSocket::bind(const QString& node, const QString& service)
00070 {
00071   if (state() >= Bound)
00072     return false;
00073 
00074   if (localResolver().isRunning())
00075     localResolver().cancel(false);
00076 
00077   // no, we must do a host lookup
00078   localResolver().setAddress(node, service);
00079 
00080   if (!lookup())
00081     return false;
00082 
00083   // see if lookup has finished already
00084   // this also catches blocking mode, since lookup has to finish
00085   // its processing if we're in blocking mode
00086   if (state() > HostLookup)
00087     return doBind();
00088 
00089   return true;
00090 }
00091 
00092 bool KDatagramSocket::connect(const QString& node, const QString& service)
00093 {
00094   if (state() >= Connected)
00095     return true;        // already connected
00096 
00097   if (peerResolver().nodeName() != node ||
00098       peerResolver().serviceName() != service)
00099     peerResolver().setAddress(node, service); // this resets the resolver's state
00100 
00101   // KClientSocketBase::lookup only works if the state is Idle or HostLookup
00102   // therefore, we store the old state, call the lookup routine and then set
00103   // it back.
00104   SocketState s = state();
00105   setState(s == Connecting ? HostLookup : Idle);
00106   bool ok = lookup();
00107   if (!ok)
00108     {
00109       setState(s);      // go back
00110       return false;
00111     }
00112 
00113   // check if lookup is finished
00114   // if we're in blocking mode, then the lookup has to be finished
00115   if (state() == HostLookup)
00116     {
00117       // it hasn't finished
00118       setState(Connecting);
00119       emit stateChanged(Connecting);
00120       return true;
00121     }
00122 
00123   // it has to be finished here
00124   if (state() != Connected)
00125     {
00126       setState(Connecting);
00127       emit stateChanged(Connecting);
00128       lookupFinishedPeer();
00129     }
00130 
00131   return state() == Connected;
00132 }
00133 
00134 KDatagramPacket KDatagramSocket::receive()
00135 {
00136   Q_LONG size = bytesAvailable();
00137   if (size == 0)
00138     {
00139       // nothing available yet to read
00140       // wait for data if we're not blocking
00141       if (blocking())
00142     socketDevice()->waitForMore(-1); // wait forever
00143       else
00144     {
00145       // mimic error
00146       setError(IO_ReadError, WouldBlock);
00147       emit gotError(WouldBlock);
00148       return KDatagramPacket();
00149     }
00150 
00151       // try again
00152       size = bytesAvailable();
00153     }
00154 
00155   QByteArray data(size);
00156   KSocketAddress address;
00157   
00158   // now do the reading
00159   size = readBlock(data.data(), size, address);
00160   if (size < 0)
00161     // error has been set
00162     return KDatagramPacket();
00163 
00164   data.resize(size);        // just to be sure
00165   return KDatagramPacket(data, address);
00166 }
00167 
00168 Q_LONG KDatagramSocket::send(const KDatagramPacket& packet)
00169 {
00170   return writeBlock(packet.data(), packet.size(), packet.address());
00171 }
00172 
00173 Q_LONG KDatagramSocket::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to)
00174 {
00175   if (to.family() != AF_UNSPEC)
00176     {
00177       // make sure the socket is open at this point
00178       if (!socketDevice()->isOpen())
00179     // error handling will happen below
00180     socketDevice()->create(to.family(), SOCK_DGRAM, 0);
00181     }
00182   return KClientSocketBase::writeBlock(data, len, to);
00183 }
00184 
00185 void KDatagramSocket::lookupFinishedLocal()
00186 {
00187   // bind lookup has finished and succeeded
00188   // state() == HostFound
00189 
00190   if (!doBind())
00191     return;         // failed binding
00192 
00193   if (peerResults().count() > 0)
00194     {
00195       setState(Connecting);
00196       emit stateChanged(Connecting);
00197 
00198       lookupFinishedPeer();
00199     }
00200 }
00201 
00202 void KDatagramSocket::lookupFinishedPeer()
00203 {
00204   // this function is called by lookupFinishedLocal above
00205   // and is also connected to a signal
00206   // so it might be called twice.
00207 
00208   if (state() != Connecting)
00209     return;
00210 
00211   if (peerResults().count() == 0)
00212     {
00213       setState(Unconnected);
00214       emit stateChanged(Unconnected);
00215       return;
00216     }
00217 
00218   KResolverResults::ConstIterator it = peerResults().begin();
00219   for ( ; it != peerResults().end(); ++it)
00220     if (connect(*it))
00221       {
00222     // weee, we connected
00223 
00224     setState(Connected);    // this sets up signals
00225     //setupSignals();   // setState sets up the signals
00226 
00227     emit stateChanged(Connected);
00228     emit connected(*it);
00229     return;
00230       }
00231 
00232   // no connection
00233   copyError();
00234   setState(Unconnected);
00235   emit stateChanged(Unconnected);
00236   emit gotError(error());
00237 }
00238 
00239 bool KDatagramSocket::doBind()
00240 {
00241   if (localResults().count() == 0)
00242     return true;
00243   if (state() >= Bound)
00244     return true;        // already bound
00245 
00246   KResolverResults::ConstIterator it = localResults().begin();
00247   for ( ; it != localResults().end(); ++it)
00248     if (bind(*it))
00249       {
00250     // bound
00251     setupSignals();
00252     return true;
00253       }
00254 
00255   // not bound
00256   // no need to set state since it can only be HostFound already
00257   copyError();
00258   emit gotError(error());
00259   return false;
00260 }
00261 
00262 void KDatagramSocket::setupSignals()
00263 {
00264   QSocketNotifier *n = socketDevice()->readNotifier();
00265   if (n)
00266     {
00267       n->setEnabled(emitsReadyRead());
00268       QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotReadActivity()));
00269     }
00270   else
00271     return;
00272 
00273   n = socketDevice()->writeNotifier();
00274   if (n)
00275     {
00276       n->setEnabled(emitsReadyWrite());
00277       QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotWriteActivity()));
00278     }
00279   else
00280     return;
00281 }
00282 
00283 #include "kdatagramsocket.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