kdecore Library API Documentation

kdatagramsocket.cpp

00001 /* -*- C++ -*- 00002 * Copyright (C) 2003 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 KDatagramSocket::KDatagramSocket(QObject* parent, const char *name) 00038 : KClientSocketBase(parent, name), d(0L) 00039 { 00040 peerResolver().setFamily(KResolver::KnownFamily); 00041 localResolver().setFamily(KResolver::KnownFamily); 00042 00043 peerResolver().setSocketType(SOCK_DGRAM); 00044 localResolver().setSocketType(SOCK_DGRAM); 00045 00046 // QObject::connect(localResolver(), SIGNAL(finished(KResolverResults)), 00047 // this, SLOT(lookupFinishedLocal())); 00048 QObject::connect(&peerResolver(), SIGNAL(finished(KResolverResults)), 00049 this, SLOT(lookupFinishedPeer())); 00050 QObject::connect(this, SIGNAL(hostFound()), this, SLOT(lookupFinishedLocal())); 00051 } 00052 00053 KDatagramSocket::~KDatagramSocket() 00054 { 00055 // KClientSocketBase's destructor closes the socket 00056 00057 //delete d; 00058 } 00059 00060 bool KDatagramSocket::bind(const QString& node, const QString& service) 00061 { 00062 if (state() >= Bound) 00063 return false; 00064 00065 if (localResolver().isRunning()) 00066 localResolver().cancel(false); 00067 00068 // no, we must do a host lookup 00069 localResolver().setAddress(node, service); 00070 00071 if (!lookup()) 00072 return false; 00073 00074 // see if lookup has finished already 00075 // this also catches blocking mode, since lookup has to finish 00076 // its processing if we're in blocking mode 00077 if (state() > HostLookup) 00078 return doBind(); 00079 00080 return true; 00081 } 00082 00083 bool KDatagramSocket::connect(const QString& node, const QString& service) 00084 { 00085 if (state() >= Connected) 00086 return true; // already connected 00087 00088 if (peerResolver().nodeName() != node || 00089 peerResolver().serviceName() != service) 00090 peerResolver().setAddress(node, service); // this resets the resolver's state 00091 00092 // KClientSocketBase::lookup only works if the state is Idle or HostLookup 00093 // therefore, we store the old state, call the lookup routine and then set 00094 // it back. 00095 SocketState s = state(); 00096 setState(s == Connecting ? HostLookup : Idle); 00097 bool ok = lookup(); 00098 if (!ok) 00099 { 00100 setState(s); // go back 00101 return false; 00102 } 00103 00104 // check if lookup is finished 00105 // if we're in blocking mode, then the lookup has to be finished 00106 if (state() == HostLookup) 00107 { 00108 // it hasn't finished 00109 setState(Connecting); 00110 emit stateChanged(Connecting); 00111 return true; 00112 } 00113 00114 // it has to be finished here 00115 if (state() != Connected) 00116 { 00117 setState(Connecting); 00118 emit stateChanged(Connecting); 00119 lookupFinishedPeer(); 00120 } 00121 00122 return state() == Connected; 00123 } 00124 00125 KDatagramPacket KDatagramSocket::receive() 00126 { 00127 Q_LONG size = bytesAvailable(); 00128 if (size == 0) 00129 { 00130 // nothing available yet to read 00131 // wait for data if we're not blocking 00132 if (blocking()) 00133 socketDevice()->waitForMore(-1); // wait forever 00134 else 00135 { 00136 // mimic error 00137 setError(IO_ReadError, WouldBlock); 00138 emit gotError(WouldBlock); 00139 return KDatagramPacket(); 00140 } 00141 00142 // try again 00143 size = bytesAvailable(); 00144 } 00145 00146 QByteArray data(size); 00147 KSocketAddress address; 00148 00149 // now do the reading 00150 size = readBlock(data.data(), size, address); 00151 if (size < 0) 00152 // error has been set 00153 return KDatagramPacket(); 00154 00155 data.resize(size); // just to be sure 00156 return KDatagramPacket(data, address); 00157 } 00158 00159 Q_LONG KDatagramSocket::send(const KDatagramPacket& packet) 00160 { 00161 return writeBlock(packet.data(), packet.size(), packet.address()); 00162 } 00163 00164 void KDatagramSocket::lookupFinishedLocal() 00165 { 00166 // bind lookup has finished and succeeded 00167 // state() == HostFound 00168 00169 if (!doBind()) 00170 return; // failed binding 00171 00172 if (peerResults().count() > 0) 00173 { 00174 setState(Connecting); 00175 emit stateChanged(Connecting); 00176 00177 lookupFinishedPeer(); 00178 } 00179 } 00180 00181 void KDatagramSocket::lookupFinishedPeer() 00182 { 00183 // this function is called by lookupFinishedLocal above 00184 // and is also connected to a signal 00185 // so it might be called twice. 00186 00187 if (state() != Connecting) 00188 return; 00189 00190 if (peerResults().count() == 0) 00191 { 00192 setState(Unconnected); 00193 emit stateChanged(Unconnected); 00194 return; 00195 } 00196 00197 KResolverResults::ConstIterator it = peerResults().begin(); 00198 for ( ; it != peerResults().end(); ++it) 00199 if (connect(*it)) 00200 { 00201 // weee, we connected 00202 setState(Connected); 00203 emit stateChanged(Connected); 00204 emit connected(*it); 00205 return; 00206 } 00207 00208 // no connection 00209 copyError(); 00210 setState(Unconnected); 00211 emit stateChanged(Unconnected); 00212 emit gotError(error()); 00213 } 00214 00215 bool KDatagramSocket::doBind() 00216 { 00217 if (localResults().count() == 0) 00218 return true; 00219 if (state() >= Bound) 00220 return true; // already bound 00221 00222 KResolverResults::ConstIterator it = localResults().begin(); 00223 for ( ; it != localResults().end(); ++it) 00224 if (bind(*it)) 00225 { 00226 // bound 00227 return true; 00228 } 00229 00230 // not bound 00231 // no need to set state since it can only be HostFound already 00232 copyError(); 00233 emit gotError(error()); 00234 return false; 00235 } 00236 00237 #include "kdatagramsocket.moc"
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:43:09 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003