kclientsocketbase.cpp
00001 /* -*- C++ -*- 00002 * Copyright (C) 2003,2005 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 <tqsocketnotifier.h> 00028 #include <tqtimer.h> 00029 #include <tqmutex.h> 00030 00031 #include "tdesocketaddress.h" 00032 #include "kresolver.h" 00033 #include "tdesocketbase.h" 00034 #include "tdesocketdevice.h" 00035 #include "kclientsocketbase.h" 00036 00037 using namespace KNetwork; 00038 00039 class KNetwork::KClientSocketBasePrivate 00040 { 00041 public: 00042 int state; 00043 00044 KResolver localResolver, peerResolver; 00045 KResolverResults localResults, peerResults; 00046 00047 bool enableRead : 1, enableWrite : 1; 00048 }; 00049 00050 KClientSocketBase::KClientSocketBase(TQObject *parent, const char *name) : 00051 #ifdef USE_QT4 00052 #else // USE_QT4 00053 TQObject(parent, name), 00054 #endif // USE_QT4 00055 d(new KClientSocketBasePrivate) 00056 { 00057 #ifdef USE_QT4 00058 setParent(parent); 00059 setObjectName(name); 00060 #endif // USE_QT4 00061 d->state = Idle; 00062 d->enableRead = true; 00063 d->enableWrite = false; 00064 } 00065 00066 KClientSocketBase::~KClientSocketBase() 00067 { 00068 close(); 00069 delete d; 00070 } 00071 00072 KClientSocketBase::SocketState KClientSocketBase::state() const 00073 { 00074 return static_cast<SocketState>(d->state); 00075 } 00076 00077 void KClientSocketBase::setState(SocketState state) 00078 { 00079 d->state = state; 00080 stateChanging(state); 00081 } 00082 00083 bool KClientSocketBase::setSocketOptions(int opts) 00084 { 00085 TQMutexLocker locker(mutex()); 00086 TDESocketBase::setSocketOptions(opts); // call parent 00087 00088 // don't create the device unnecessarily 00089 if (hasDevice()) 00090 { 00091 bool result = socketDevice()->setSocketOptions(opts); // and set the implementation 00092 copyError(); 00093 return result; 00094 } 00095 00096 return true; 00097 } 00098 00099 KResolver& KClientSocketBase::peerResolver() const 00100 { 00101 return d->peerResolver; 00102 } 00103 00104 const KResolverResults& KClientSocketBase::peerResults() const 00105 { 00106 return d->peerResults; 00107 } 00108 00109 KResolver& KClientSocketBase::localResolver() const 00110 { 00111 return d->localResolver; 00112 } 00113 00114 const KResolverResults& KClientSocketBase::localResults() const 00115 { 00116 return d->localResults; 00117 } 00118 00119 void KClientSocketBase::setResolutionEnabled(bool enable) 00120 { 00121 if (enable) 00122 { 00123 d->localResolver.setFlags(d->localResolver.flags() & ~KResolver::NoResolve); 00124 d->peerResolver.setFlags(d->peerResolver.flags() & ~KResolver::NoResolve); 00125 } 00126 else 00127 { 00128 d->localResolver.setFlags(d->localResolver.flags() | KResolver::NoResolve); 00129 d->peerResolver.setFlags(d->peerResolver.flags() | KResolver::NoResolve); 00130 } 00131 } 00132 00133 void KClientSocketBase::setFamily(int families) 00134 { 00135 d->localResolver.setFamily(families); 00136 d->peerResolver.setFamily(families); 00137 } 00138 00139 bool KClientSocketBase::lookup() 00140 { 00141 if (state() == HostLookup && !blocking()) 00142 return true; // already doing lookup 00143 00144 if (state() > HostLookup) 00145 return true; // results are already available 00146 00147 if (state() < HostLookup) 00148 { 00149 if (d->localResolver.serviceName().isNull() && 00150 !d->localResolver.nodeName().isNull()) 00151 d->localResolver.setServiceName(TQString::fromLatin1("")); 00152 00153 // don't restart the lookups if they had succeeded and 00154 // the input values weren't changed 00155 TQObject::connect(&d->peerResolver, TQT_SIGNAL(finished(KResolverResults)), 00156 this, TQT_SLOT(lookupFinishedSlot())); 00157 TQObject::connect(&d->localResolver, TQT_SIGNAL(finished(KResolverResults)), 00158 this, TQT_SLOT(lookupFinishedSlot())); 00159 00160 if (d->localResolver.status() <= 0) 00161 d->localResolver.start(); 00162 if (d->peerResolver.status() <= 0) 00163 d->peerResolver.start(); 00164 00165 setState(HostLookup); 00166 emit stateChanged(HostLookup); 00167 00168 if (!d->localResolver.isRunning() && !d->peerResolver.isRunning()) 00169 { 00170 // if nothing is running, then the lookup results are still valid 00171 // pretend we had done lookup 00172 if (blocking()) 00173 lookupFinishedSlot(); 00174 else 00175 TQTimer::singleShot(0, this, TQT_SLOT(lookupFinishedSlot())); 00176 } 00177 else 00178 { 00179 d->localResults = d->peerResults = KResolverResults(); 00180 } 00181 } 00182 00183 if (blocking()) 00184 { 00185 // we're in blocking mode operation 00186 // wait for the results 00187 00188 localResolver().wait(); 00189 peerResolver().wait(); 00190 00191 // lookupFinishedSlot has been called 00192 } 00193 00194 return true; 00195 } 00196 00197 bool KClientSocketBase::bind(const KResolverEntry& address) 00198 { 00199 if (state() == HostLookup || state() > Connecting) 00200 return false; 00201 00202 if (socketDevice()->bind(address)) 00203 { 00204 resetError(); 00205 00206 // don't set the state or emit signals if we are in a higher state 00207 if (state() < Bound) 00208 { 00209 setState(Bound); 00210 emit stateChanged(Bound); 00211 emit bound(address); 00212 } 00213 return true; 00214 } 00215 return false; 00216 } 00217 00218 bool KClientSocketBase::connect(const KResolverEntry& address) 00219 { 00220 if (state() == Connected) 00221 return true; // to be compliant with the other classes 00222 if (state() == HostLookup || state() > Connecting) 00223 return false; 00224 00225 bool ok = socketDevice()->connect(address); 00226 copyError(); 00227 00228 if (ok) 00229 { 00230 SocketState newstate; 00231 if (error() == InProgress) 00232 newstate = Connecting; 00233 else 00234 newstate = Connected; 00235 00236 if (state() < newstate) 00237 { 00238 setState(newstate); 00239 emit stateChanged(newstate); 00240 if (error() == NoError) 00241 { 00242 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async); 00243 emit connected(address); 00244 } 00245 } 00246 00247 return true; 00248 } 00249 return false; 00250 } 00251 00252 bool KClientSocketBase::disconnect() 00253 { 00254 if (state() != Connected) 00255 return false; 00256 00257 bool ok = socketDevice()->disconnect(); 00258 copyError(); 00259 00260 if (ok) 00261 { 00262 setState(Unconnected); 00263 emit stateChanged(Unconnected); 00264 return true; 00265 } 00266 return false; 00267 } 00268 00269 void KClientSocketBase::close() 00270 { 00271 if (state() == Idle) 00272 return; // nothing to do 00273 00274 if (state() == HostLookup) 00275 { 00276 d->peerResolver.cancel(false); 00277 d->localResolver.cancel(false); 00278 } 00279 00280 d->localResults = d->peerResults = KResolverResults(); 00281 00282 socketDevice()->close(); 00283 setState(Idle); 00284 emit stateChanged(Idle); 00285 emit closed(); 00286 } 00287 00288 // This function is unlike all the others because it is const 00289 #ifdef USE_QT3 00290 TQ_LONG KClientSocketBase::bytesAvailable() const 00291 #endif 00292 #ifdef USE_QT4 00293 qint64 KClientSocketBase::bytesAvailable() const 00294 #endif 00295 { 00296 return socketDevice()->bytesAvailable(); 00297 } 00298 00299 // All the functions below look really alike 00300 // Should I use a macro to define them? 00301 00302 TQ_LONG KClientSocketBase::waitForMore(int msecs, bool *timeout) 00303 { 00304 resetError(); 00305 TQ_LONG retval = socketDevice()->waitForMore(msecs, timeout); 00306 if (retval == -1) 00307 { 00308 copyError(); 00309 emit gotError(error()); 00310 } 00311 return retval; 00312 } 00313 00314 TQT_TQIO_LONG KClientSocketBase::tqreadBlock(char *data, TQT_TQIO_ULONG maxlen) 00315 { 00316 resetError(); 00317 TQ_LONG retval = socketDevice()->tqreadBlock(data, maxlen); 00318 if (retval == -1) 00319 { 00320 copyError(); 00321 emit gotError(error()); 00322 } 00323 return retval; 00324 } 00325 00326 TQT_TQIO_LONG KClientSocketBase::tqreadBlock(char *data, TQT_TQIO_ULONG maxlen, TDESocketAddress& from) 00327 { 00328 resetError(); 00329 TQ_LONG retval = socketDevice()->tqreadBlock(data, maxlen, from); 00330 if (retval == -1) 00331 { 00332 copyError(); 00333 emit gotError(error()); 00334 } 00335 return retval; 00336 } 00337 00338 TQ_LONG KClientSocketBase::peekBlock(char *data, TQ_ULONG maxlen) 00339 { 00340 resetError(); 00341 TQ_LONG retval = socketDevice()->peekBlock(data, maxlen); 00342 if (retval == -1) 00343 { 00344 copyError(); 00345 emit gotError(error()); 00346 } 00347 return retval; 00348 } 00349 00350 TQ_LONG KClientSocketBase::peekBlock(char *data, TQ_ULONG maxlen, TDESocketAddress& from) 00351 { 00352 resetError(); 00353 TQ_LONG retval = socketDevice()->peekBlock(data, maxlen, from); 00354 if (retval == -1) 00355 { 00356 copyError(); 00357 emit gotError(error()); 00358 } 00359 return retval; 00360 } 00361 00362 TQT_TQIO_LONG KClientSocketBase::tqwriteBlock(const char *data, TQT_TQIO_ULONG len) 00363 { 00364 resetError(); 00365 TQ_LONG retval = socketDevice()->tqwriteBlock(data, len); 00366 if (retval == -1) 00367 { 00368 copyError(); 00369 emit gotError(error()); 00370 } 00371 return retval; 00372 } 00373 00374 TQT_TQIO_LONG KClientSocketBase::tqwriteBlock(const char *data, TQT_TQIO_ULONG len, const TDESocketAddress& to) 00375 { 00376 resetError(); 00377 TQ_LONG retval = socketDevice()->tqwriteBlock(data, len, to); 00378 if (retval == -1) 00379 { 00380 copyError(); 00381 emit gotError(error()); 00382 } 00383 return retval; 00384 } 00385 00386 TDESocketAddress KClientSocketBase::localAddress() const 00387 { 00388 return socketDevice()->localAddress(); 00389 } 00390 00391 TDESocketAddress KClientSocketBase::peerAddress() const 00392 { 00393 return socketDevice()->peerAddress(); 00394 } 00395 00396 bool KClientSocketBase::emitsReadyRead() const 00397 { 00398 return d->enableRead; 00399 } 00400 00401 void KClientSocketBase::enableRead(bool enable) 00402 { 00403 TQMutexLocker locker(mutex()); 00404 00405 d->enableRead = enable; 00406 TQSocketNotifier *n = socketDevice()->readNotifier(); 00407 if (n) 00408 n->setEnabled(enable); 00409 } 00410 00411 bool KClientSocketBase::emitsReadyWrite() const 00412 { 00413 return d->enableWrite; 00414 } 00415 00416 void KClientSocketBase::enableWrite(bool enable) 00417 { 00418 TQMutexLocker locker(mutex()); 00419 00420 d->enableWrite = enable; 00421 TQSocketNotifier *n = socketDevice()->writeNotifier(); 00422 if (n) 00423 n->setEnabled(enable); 00424 } 00425 00426 void KClientSocketBase::slotReadActivity() 00427 { 00428 if (d->enableRead) 00429 emit readyRead(); 00430 } 00431 00432 void KClientSocketBase::slotWriteActivity() 00433 { 00434 if (d->enableWrite) 00435 emit readyWrite(); 00436 } 00437 00438 void KClientSocketBase::lookupFinishedSlot() 00439 { 00440 if (d->peerResolver.isRunning() || d->localResolver.isRunning() || state() != HostLookup) 00441 return; 00442 00443 TQObject::disconnect(&d->peerResolver, 0L, this, TQT_SLOT(lookupFinishedSlot())); 00444 TQObject::disconnect(&d->localResolver, 0L, this, TQT_SLOT(lookupFinishedSlot())); 00445 if (d->peerResolver.status() < 0 || d->localResolver.status() < 0) 00446 { 00447 setState(Idle); // backtrack 00448 setError(IO_LookupError, LookupFailure); 00449 emit stateChanged(Idle); 00450 emit gotError(LookupFailure); 00451 return; 00452 } 00453 00454 d->localResults = d->localResolver.results(); 00455 d->peerResults = d->peerResolver.results(); 00456 setState(HostFound); 00457 emit stateChanged(HostFound); 00458 emit hostFound(); 00459 } 00460 00461 void KClientSocketBase::stateChanging(SocketState newState) 00462 { 00463 if (newState == Connected && socketDevice()) 00464 { 00465 TQSocketNotifier *n = socketDevice()->readNotifier(); 00466 if (n) 00467 { 00468 n->setEnabled(d->enableRead); 00469 TQObject::connect(n, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotReadActivity())); 00470 } 00471 else 00472 return; 00473 00474 n = socketDevice()->writeNotifier(); 00475 if (n) 00476 { 00477 n->setEnabled(d->enableWrite); 00478 TQObject::connect(n, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotWriteActivity())); 00479 } 00480 else 00481 return; 00482 } 00483 } 00484 00485 void KClientSocketBase::copyError() 00486 { 00487 setError(socketDevice()->status(), socketDevice()->error()); 00488 } 00489 00490 #include "kclientsocketbase.moc"