kserversocket.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 <tqsocketnotifier.h> 00028 #include <tqmutex.h> 00029 00030 #include "ksocketaddress.h" 00031 #include "kresolver.h" 00032 #include "ksocketbase.h" 00033 #include "ksocketdevice.h" 00034 #include "kstreamsocket.h" 00035 #include "kbufferedsocket.h" 00036 #include "kserversocket.h" 00037 00038 using namespace KNetwork; 00039 00040 class KNetwork::KServerSocketPrivate 00041 { 00042 public: 00043 KResolver resolver; 00044 KResolverResults resolverResults; 00045 00046 enum { None, LookupDone, Bound, Listening } state; 00047 int backlog; 00048 int timeout; 00049 00050 bool bindWhenFound : 1, listenWhenBound : 1, useKBufferedSocket : 1; 00051 00052 KServerSocketPrivate() 00053 : state(None), timeout(0), bindWhenFound(false), listenWhenBound(false), 00054 useKBufferedSocket(true) 00055 { 00056 resolver.setFlags(KResolver::Passive); 00057 resolver.setFamily(KResolver::KnownFamily); 00058 } 00059 }; 00060 00061 KServerSocket::KServerSocket(TQObject* parent, const char *name) 00062 : TQObject(parent, name), d(new KServerSocketPrivate) 00063 { 00064 TQObject::connect(&d->resolver, TQT_SIGNAL(finished(KResolverResults)), 00065 this, TQT_SLOT(lookupFinishedSlot())); 00066 } 00067 00068 KServerSocket::KServerSocket(const TQString& service, TQObject* parent, const char *name) 00069 : TQObject(parent, name), d(new KServerSocketPrivate) 00070 { 00071 TQObject::connect(&d->resolver, TQT_SIGNAL(finished(KResolverResults)), 00072 this, TQT_SLOT(lookupFinishedSlot())); 00073 d->resolver.setServiceName(service); 00074 } 00075 00076 KServerSocket::KServerSocket(const TQString& node, const TQString& service, 00077 TQObject* parent, const char* name) 00078 : TQObject(parent, name), d(new KServerSocketPrivate) 00079 { 00080 TQObject::connect(&d->resolver, TQT_SIGNAL(finished(KResolverResults)), 00081 this, TQT_SLOT(lookupFinishedSlot())); 00082 setAddress(node, service); 00083 } 00084 00085 KServerSocket::~KServerSocket() 00086 { 00087 close(); 00088 delete d; 00089 } 00090 00091 bool KServerSocket::setSocketOptions(int opts) 00092 { 00093 TQMutexLocker locker(mutex()); 00094 KSocketBase::setSocketOptions(opts); // call parent 00095 bool result = socketDevice()->setSocketOptions(opts); // and set the implementation 00096 copyError(); 00097 return result; 00098 } 00099 00100 KResolver& KServerSocket::resolver() const 00101 { 00102 return d->resolver; 00103 } 00104 00105 const KResolverResults& KServerSocket::resolverResults() const 00106 { 00107 return d->resolverResults; 00108 } 00109 00110 void KServerSocket::setResolutionEnabled(bool enable) 00111 { 00112 if (enable) 00113 d->resolver.setFlags(d->resolver.flags() & ~KResolver::NoResolve); 00114 else 00115 d->resolver.setFlags(d->resolver.flags() | KResolver::NoResolve); 00116 } 00117 00118 void KServerSocket::setFamily(int families) 00119 { 00120 d->resolver.setFamily(families); 00121 } 00122 00123 void KServerSocket::setAddress(const TQString& service) 00124 { 00125 d->resolver.setNodeName(TQString::null); 00126 d->resolver.setServiceName(service); 00127 d->resolverResults.empty(); 00128 if (d->state <= KServerSocketPrivate::LookupDone) 00129 d->state = KServerSocketPrivate::None; 00130 } 00131 00132 void KServerSocket::setAddress(const TQString& node, const TQString& service) 00133 { 00134 d->resolver.setNodeName(node); 00135 d->resolver.setServiceName(service); 00136 d->resolverResults.empty(); 00137 if (d->state <= KServerSocketPrivate::LookupDone) 00138 d->state = KServerSocketPrivate::None; 00139 } 00140 00141 void KServerSocket::setTimeout(int msec) 00142 { 00143 d->timeout = msec; 00144 } 00145 00146 bool KServerSocket::lookup() 00147 { 00148 setError(NoError); 00149 if (d->resolver.isRunning() && !blocking()) 00150 return true; // already doing lookup 00151 00152 if (d->state >= KServerSocketPrivate::LookupDone) 00153 return true; // results are already available 00154 00155 // make sure we have at least one parameter for lookup 00156 if (d->resolver.serviceName().isNull() && 00157 !d->resolver.nodeName().isNull()) 00158 d->resolver.setServiceName(TQString::fromLatin1("")); 00159 00160 // don't restart the lookups if they had succeeded and 00161 // the input values weren't changed 00162 00163 // reset results 00164 d->resolverResults = KResolverResults(); 00165 00166 if (d->resolver.status() <= 0) 00167 // if it's already running, there's no harm in calling again 00168 d->resolver.start(); // signal may emit 00169 00170 if (blocking()) 00171 { 00172 // we're in blocking mode operation 00173 // wait for the results 00174 00175 d->resolver.wait(); // signal may be emitted again 00176 // lookupFinishedSlot has been called 00177 } 00178 00179 return true; 00180 } 00181 00182 bool KServerSocket::bind(const KResolverEntry& address) 00183 { 00184 if (socketDevice()->bind(address)) 00185 { 00186 setError(NoError); 00187 00188 d->state = KServerSocketPrivate::Bound; 00189 emit bound(address); 00190 return true; 00191 } 00192 copyError(); 00193 return false; 00194 } 00195 00196 bool KServerSocket::bind(const TQString& node, const TQString& service) 00197 { 00198 setAddress(node, service); 00199 return bind(); 00200 } 00201 00202 bool KServerSocket::bind(const TQString& service) 00203 { 00204 setAddress(service); 00205 return bind(); 00206 } 00207 00208 bool KServerSocket::bind() 00209 { 00210 if (d->state >= KServerSocketPrivate::Bound) 00211 return true; 00212 00213 if (d->state < KServerSocketPrivate::LookupDone) 00214 { 00215 if (!blocking()) 00216 { 00217 d->bindWhenFound = true; 00218 bool ok = lookup(); // will call doBind 00219 if (d->state >= KServerSocketPrivate::Bound) 00220 d->bindWhenFound = false; 00221 return ok; 00222 } 00223 00224 // not blocking 00225 if (!lookup()) 00226 return false; 00227 } 00228 00229 return doBind(); 00230 } 00231 00232 bool KServerSocket::listen(int backlog) 00233 { 00234 // WARNING 00235 // this function has to be reentrant 00236 // due to the mechanisms used for binding, this function might 00237 // end up calling itself 00238 00239 if (d->state == KServerSocketPrivate::Listening) 00240 return true; // already listening 00241 00242 d->backlog = backlog; 00243 00244 if (d->state < KServerSocketPrivate::Bound) 00245 { 00246 // we must bind 00247 // note that we can end up calling ourselves here 00248 d->listenWhenBound = true; 00249 if (!bind()) 00250 { 00251 d->listenWhenBound = false; 00252 return false; 00253 } 00254 00255 if (d->state < KServerSocketPrivate::Bound) 00256 // asynchronous lookup in progress... 00257 // we can't be blocking here anyways 00258 return true; 00259 00260 d->listenWhenBound = false; 00261 } 00262 00263 if (d->state < KServerSocketPrivate::Listening) 00264 return doListen(); 00265 00266 return true; 00267 } 00268 00269 void KServerSocket::close() 00270 { 00271 socketDevice()->close(); 00272 if (d->resolver.isRunning()) 00273 d->resolver.cancel(false); 00274 d->state = KServerSocketPrivate::None; 00275 emit closed(); 00276 } 00277 00278 void KServerSocket::setAcceptBuffered(bool enable) 00279 { 00280 d->useKBufferedSocket = enable; 00281 } 00282 00283 KActiveSocketBase* KServerSocket::accept() 00284 { 00285 if (d->state < KServerSocketPrivate::Listening) 00286 { 00287 if (!blocking()) 00288 { 00289 listen(); 00290 setError(WouldBlock); 00291 return NULL; 00292 } 00293 else if (!listen()) 00294 // error happened during listen 00295 return 0L; 00296 } 00297 00298 // check to see if we're doing a timeout 00299 if (blocking() && d->timeout > 0) 00300 { 00301 bool timedout; 00302 if (!socketDevice()->poll(d->timeout, &timedout)) 00303 { 00304 copyError(); 00305 return NULL; 00306 } 00307 00308 if (timedout) 00309 return 0L; 00310 } 00311 00312 // we're listening here 00313 KSocketDevice* accepted = socketDevice()->accept(); 00314 if (!accepted) 00315 { 00316 // error happened during accept 00317 copyError(); 00318 return NULL; 00319 } 00320 00321 KStreamSocket* streamsocket; 00322 if (d->useKBufferedSocket) 00323 streamsocket = new KBufferedSocket(); 00324 else 00325 streamsocket = new KStreamSocket(); 00326 streamsocket->setSocketDevice(accepted); 00327 00328 // FIXME! 00329 // when KStreamSocket can find out the state of the socket passed through 00330 // setSocketDevice, this will probably be unnecessary: 00331 streamsocket->setState(KStreamSocket::Connected); 00332 streamsocket->setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async); 00333 00334 return streamsocket; 00335 } 00336 00337 KSocketAddress KServerSocket::localAddress() const 00338 { 00339 return socketDevice()->localAddress(); 00340 } 00341 00342 KSocketAddress KServerSocket::externalAddress() const 00343 { 00344 return socketDevice()->externalAddress(); 00345 } 00346 00347 void KServerSocket::lookupFinishedSlot() 00348 { 00349 if (d->resolver.isRunning() || d->state > KServerSocketPrivate::LookupDone) 00350 return; 00351 00352 if (d->resolver.status() < 0) 00353 { 00354 setError(LookupFailure); 00355 emit gotError(LookupFailure); 00356 d->bindWhenFound = d->listenWhenBound = false; 00357 d->state = KServerSocketPrivate::None; 00358 return; 00359 } 00360 00361 // lookup succeeded 00362 d->resolverResults = d->resolver.results(); 00363 d->state = KServerSocketPrivate::LookupDone; 00364 emit hostFound(); 00365 00366 if (d->bindWhenFound) 00367 doBind(); 00368 } 00369 00370 void KServerSocket::copyError() 00371 { 00372 setError(socketDevice()->error()); 00373 } 00374 00375 bool KServerSocket::doBind() 00376 { 00377 d->bindWhenFound = false; 00378 // loop through the results and bind to the first that works 00379 00380 KResolverResults::ConstIterator it = d->resolverResults.begin(); 00381 for ( ; it != d->resolverResults.end(); ++it) 00382 if (bind(*it)) 00383 { 00384 if (d->listenWhenBound) 00385 return doListen(); 00386 return true; 00387 } 00388 else 00389 socketDevice()->close(); // didn't work, try again 00390 00391 // failed to bind 00392 emit gotError(error()); 00393 return false; 00394 } 00395 00396 bool KServerSocket::doListen() 00397 { 00398 if (!socketDevice()->listen(d->backlog)) 00399 { 00400 copyError(); 00401 emit gotError(error()); 00402 return false; // failed to listen 00403 } 00404 00405 // set up ready accept signal 00406 TQObject::connect(socketDevice()->readNotifier(), TQT_SIGNAL(activated(int)), 00407 this, TQT_SIGNAL(readyAccept())); 00408 d->state = KServerSocketPrivate::Listening; 00409 return true; 00410 } 00411 00412 00413 #include "kserversocket.moc"