KDECore
k3datagramsocket.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00041
00042
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
00058
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
00068
00069
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
00081 localResolver().setAddress(node, service);
00082
00083 if (!lookup())
00084 return false;
00085
00086
00087
00088
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;
00105
00106 if (peerResolver().nodeName() != node ||
00107 peerResolver().serviceName() != service)
00108 peerResolver().setAddress(node, service);
00109
00110
00111
00112
00113 SocketState s = state();
00114 setState(s == Connecting ? HostLookup : Idle);
00115 bool ok = lookup();
00116 if (!ok)
00117 {
00118 setState(s);
00119 return false;
00120 }
00121
00122
00123
00124 if (state() == HostLookup)
00125 {
00126
00127 setState(Connecting);
00128 emit stateChanged(Connecting);
00129 return true;
00130 }
00131
00132
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
00155
00156 if (blocking())
00157 socketDevice()->waitForMore(-1);
00158 else
00159 {
00160
00161 setError(WouldBlock);
00162 emit gotError(WouldBlock);
00163 return KDatagramPacket();
00164 }
00165
00166
00167 size = bytesAvailable();
00168 }
00169
00170 QByteArray data;
00171 data.resize(size);
00172 KSocketAddress address;
00173
00174
00175 size = read(data.data(), size, address);
00176 if (size < 0)
00177
00178 return KDatagramPacket();
00179
00180 data.resize(size);
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
00195 if (!socketDevice()->isOpen())
00196
00197 socketDevice()->create(to->family(), SOCK_DGRAM, 0);
00198 }
00199 return KClientSocketBase::writeData(data, len, to);
00200 }
00201
00202 void KDatagramSocket::lookupFinishedLocal()
00203 {
00204
00205
00206
00207 if (!doBind())
00208 return;
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
00222
00223
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
00240
00241 setState(Connected);
00242
00243
00244 emit stateChanged(Connected);
00245 emit connected(*it);
00246 return;
00247 }
00248
00249
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;
00262
00263 KResolverResults::ConstIterator it = localResults().begin();
00264 for ( ; it != localResults().end(); ++it)
00265 if (bind(*it))
00266 {
00267
00268 setupSignals();
00269 KActiveSocketBase::open(ReadWrite | Unbuffered);
00270 return true;
00271 }
00272
00273
00274
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"