kdecore Library API Documentation

ksocketdevice.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 <qmap.h> 00028 00029 #ifdef USE_SOLARIS 00030 # include <sys/filio.h> 00031 #endif 00032 #include <sys/types.h> 00033 #include <sys/socket.h> 00034 #include <sys/time.h> 00035 #include <sys/ioctl.h> 00036 #include <errno.h> 00037 #include <fcntl.h> 00038 #include <netinet/in.h> 00039 #include <unistd.h> 00040 00041 #ifdef HAVE_POLL 00042 # include <sys/poll.h> 00043 #else 00044 # ifdef HAVE_SYS_SELECT 00045 # include <sys/select.h> 00046 # endif 00047 #endif 00048 00049 // Include syssocket before our local includes 00050 #include "syssocket.h" 00051 00052 #include <qmutex.h> 00053 #include <qsocketnotifier.h> 00054 00055 #include "kresolver.h" 00056 #include "ksocketaddress.h" 00057 #include "ksocketbase.h" 00058 #include "ksocketdevice.h" 00059 #include "ksockssocketdevice.h" 00060 00061 using namespace KNetwork; 00062 00063 class KNetwork::KSocketDevicePrivate 00064 { 00065 public: 00066 mutable QSocketNotifier *input, *output, *exception; 00067 int af; 00068 00069 inline KSocketDevicePrivate() 00070 { 00071 input = output = exception = 0L; 00072 } 00073 }; 00074 00075 00076 KSocketDevice::KSocketDevice(const KSocketBase* parent) 00077 : m_sockfd(-1), d(new KSocketDevicePrivate) 00078 { 00079 setSocketDevice(this); 00080 if (parent) 00081 setSocketOptions(parent->socketOptions()); 00082 } 00083 00084 KSocketDevice::KSocketDevice(int fd) 00085 : m_sockfd(fd), d(new KSocketDevicePrivate) 00086 { 00087 setState(IO_Open); 00088 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite); 00089 setSocketDevice(this); 00090 } 00091 00092 KSocketDevice::KSocketDevice(bool, const KSocketBase* parent) 00093 : m_sockfd(-1), d(new KSocketDevicePrivate) 00094 { 00095 // do not set parent 00096 if (parent) 00097 setSocketOptions(parent->socketOptions()); 00098 } 00099 00100 KSocketDevice::~KSocketDevice() 00101 { 00102 close(); // deletes the notifiers 00103 unsetSocketDevice(); // prevent double deletion 00104 delete d; 00105 } 00106 00107 bool KSocketDevice::setSocketOptions(int opts) 00108 { 00109 // must call parent 00110 QMutexLocker locker(mutex()); 00111 KSocketBase::setSocketOptions(opts); 00112 00113 if (m_sockfd == -1) 00114 return true; // flags are stored 00115 00116 { 00117 int fdflags = fcntl(m_sockfd, F_GETFL, 0); 00118 if (fdflags == -1) 00119 { 00120 setError(IO_UnspecifiedError, UnknownError); 00121 return false; // error 00122 } 00123 00124 if (opts & Blocking) 00125 fdflags &= ~O_NONBLOCK; 00126 else 00127 fdflags |= O_NONBLOCK; 00128 00129 if (fcntl(m_sockfd, F_SETFL, fdflags) == -1) 00130 { 00131 setError(IO_UnspecifiedError, UnknownError); 00132 return false; // error 00133 } 00134 } 00135 00136 { 00137 int on = opts & AddressReuseable ? 1 : 0; 00138 if (setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1) 00139 { 00140 setError(IO_UnspecifiedError, UnknownError); 00141 return false; // error 00142 } 00143 } 00144 00145 #if defined(IPV6_V6ONLY) && defined(AF_INET6) 00146 if (d->af == AF_INET6) 00147 { 00148 // don't try this on non-IPv6 sockets, or we'll get an error 00149 00150 int on = opts & IPv6Only ? 1 : 0; 00151 if (setsockopt(m_sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&on, sizeof(on)) == -1) 00152 { 00153 setError(IO_UnspecifiedError, UnknownError); 00154 return false; // error 00155 } 00156 } 00157 #endif 00158 00159 { 00160 int on = opts & Broadcast ? 1 : 0; 00161 if (setsockopt(m_sockfd, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on)) == -1) 00162 { 00163 setError(IO_UnspecifiedError, UnknownError); 00164 return false; // error 00165 } 00166 } 00167 00168 return true; // all went well 00169 } 00170 00171 bool KSocketDevice::open(int) 00172 { 00173 resetError(); 00174 return false; 00175 } 00176 00177 void KSocketDevice::close() 00178 { 00179 resetError(); 00180 if (m_sockfd != -1) 00181 { 00182 delete d->input; 00183 delete d->output; 00184 delete d->exception; 00185 00186 d->input = d->output = d->exception = 0L; 00187 00188 ::close(m_sockfd); 00189 } 00190 setState(0); 00191 00192 m_sockfd = -1; 00193 } 00194 00195 bool KSocketDevice::create(int family, int type, int protocol) 00196 { 00197 resetError(); 00198 00199 if (m_sockfd != -1) 00200 { 00201 // it's already created! 00202 setError(IO_SocketCreateError, AlreadyCreated); 00203 return false; 00204 } 00205 00206 // no socket yet; we have to create it 00207 m_sockfd = kde_socket(family, type, protocol); 00208 00209 if (m_sockfd == -1) 00210 { 00211 setError(IO_SocketCreateError, NotSupported); 00212 return false; 00213 } 00214 00215 d->af = family; 00216 setSocketOptions(socketOptions()); 00217 return true; // successfully created 00218 } 00219 00220 bool KSocketDevice::create(const KResolverEntry& address) 00221 { 00222 return create(address.family(), address.socketType(), address.protocol()); 00223 } 00224 00225 bool KSocketDevice::bind(const KResolverEntry& address) 00226 { 00227 resetError(); 00228 00229 if (m_sockfd == -1 && !create(address)) 00230 return false; // failed creating 00231 00232 // we have a socket, so try and bind 00233 if (kde_bind(m_sockfd, address.address(), address.length()) == -1) 00234 { 00235 if (errno == EADDRINUSE) 00236 setError(IO_BindError, AddressInUse); 00237 else if (errno == EINVAL) 00238 setError(IO_BindError, AlreadyBound); 00239 else 00240 // assume the address is the cause 00241 setError(IO_BindError, NotSupported); 00242 return false; 00243 } 00244 00245 return true; 00246 } 00247 00248 bool KSocketDevice::listen(int backlog) 00249 { 00250 if (m_sockfd != -1) 00251 { 00252 if (kde_listen(m_sockfd, backlog) == -1) 00253 { 00254 setError(IO_ListenError, NotSupported); 00255 return false; 00256 } 00257 00258 resetError(); 00259 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite); 00260 setState(IO_Open); 00261 return true; 00262 } 00263 00264 // we don't have a socket 00265 // can't listen 00266 setError(IO_ListenError, NotCreated); 00267 return false; 00268 } 00269 00270 bool KSocketDevice::connect(const KResolverEntry& address) 00271 { 00272 resetError(); 00273 00274 if (m_sockfd == -1 && !create(address)) 00275 return false; // failed creating! 00276 00277 if (kde_connect(m_sockfd, address.address(), address.length()) == -1) 00278 { 00279 if (errno == EISCONN) 00280 return true; // we're already connected 00281 else if (errno == EALREADY || errno == EINPROGRESS) 00282 { 00283 setError(IO_ConnectError, InProgress); 00284 return true; 00285 } 00286 else if (errno == ECONNREFUSED) 00287 setError(IO_ConnectError, ConnectionRefused); 00288 else if (errno == ENETDOWN || errno == ENETUNREACH || 00289 errno == ENETRESET || errno == ECONNABORTED || 00290 errno == ECONNRESET || errno == EHOSTDOWN || 00291 errno == EHOSTUNREACH) 00292 setError(IO_ConnectError, NetFailure); 00293 else 00294 setError(IO_ConnectError, NotSupported); 00295 00296 return false; 00297 } 00298 00299 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite); 00300 setState(IO_Open); 00301 return true; // all is well 00302 } 00303 00304 KSocketDevice* KSocketDevice::accept() 00305 { 00306 if (m_sockfd == -1) 00307 { 00308 // can't accept without a socket 00309 setError(IO_AcceptError, NotCreated); 00310 return 0L; 00311 } 00312 00313 struct sockaddr sa; 00314 socklen_t len = sizeof(sa); 00315 int newfd = kde_accept(m_sockfd, &sa, &len); 00316 if (newfd == -1) 00317 { 00318 if (errno == EAGAIN || errno == EWOULDBLOCK) 00319 setError(IO_AcceptError, WouldBlock); 00320 else 00321 setError(IO_AcceptError, UnknownError); 00322 return NULL; 00323 } 00324 00325 return new KSocketDevice(newfd); 00326 } 00327 00328 bool KSocketDevice::disconnect() 00329 { 00330 resetError(); 00331 00332 if (m_sockfd == -1) 00333 return false; // can't create 00334 00335 KSocketAddress address; 00336 address.setFamily(AF_UNSPEC); 00337 if (kde_connect(m_sockfd, address.address(), address.length()) == -1) 00338 { 00339 if (errno == EALREADY || errno == EINPROGRESS) 00340 { 00341 setError(IO_ConnectError, InProgress); 00342 return false; 00343 } 00344 else if (errno == ECONNREFUSED) 00345 setError(IO_ConnectError, ConnectionRefused); 00346 else if (errno == ENETDOWN || errno == ENETUNREACH || 00347 errno == ENETRESET || errno == ECONNABORTED || 00348 errno == ECONNRESET || errno == EHOSTDOWN || 00349 errno == EHOSTUNREACH) 00350 setError(IO_ConnectError, NetFailure); 00351 else 00352 setError(IO_ConnectError, NotSupported); 00353 00354 return false; 00355 } 00356 00357 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite); 00358 setState(IO_Open); 00359 return true; // all is well 00360 } 00361 00362 Q_LONG KSocketDevice::bytesAvailable() const 00363 { 00364 if (m_sockfd == -1) 00365 return -1; // there's nothing to read in a closed socket 00366 00367 int nchars; 00368 if (ioctl(m_sockfd, FIONREAD, &nchars) == -1) 00369 return -1; // error! 00370 00371 return nchars; 00372 } 00373 00374 Q_LONG KSocketDevice::waitForMore(int msecs, bool *timeout) 00375 { 00376 if (m_sockfd == -1) 00377 return -1; // there won't ever be anything to read... 00378 00379 bool input; 00380 if (!poll(&input, 0, 0, msecs, timeout)) 00381 return -1; // failed polling 00382 00383 return bytesAvailable(); 00384 } 00385 00386 static int do_read_common(int sockfd, char *data, Q_ULONG maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false) 00387 { 00388 socklen_t len; 00389 if (from) 00390 { 00391 from->setLength(len = 128); // arbitrary length 00392 retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len); 00393 } 00394 else 00395 retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL); 00396 00397 if (retval == -1) 00398 { 00399 if (errno == EAGAIN || errno == EWOULDBLOCK) 00400 return KSocketDevice::WouldBlock; 00401 else 00402 return KSocketDevice::UnknownError; 00403 } 00404 00405 if (from) 00406 from->setLength(len); 00407 return 0; 00408 } 00409 00410 Q_LONG KSocketDevice::readBlock(char *data, Q_ULONG maxlen) 00411 { 00412 resetError(); 00413 if (m_sockfd == -1) 00414 return -1; 00415 00416 if (maxlen == 0 || data == 0L) 00417 return 0; // can't read 00418 00419 ssize_t retval; 00420 int err = do_read_common(m_sockfd, data, maxlen, 0L, retval); 00421 00422 if (err) 00423 { 00424 setError(IO_ReadError, static_cast<SocketError>(err)); 00425 return -1; 00426 } 00427 00428 return retval; 00429 } 00430 00431 Q_LONG KSocketDevice::readBlock(char *data, Q_ULONG maxlen, KSocketAddress &from) 00432 { 00433 resetError(); 00434 if (m_sockfd == -1) 00435 return -1; // nothing to do here 00436 00437 if (data == 0L || maxlen == 0) 00438 return 0; // user doesn't want to read 00439 00440 ssize_t retval; 00441 int err = do_read_common(m_sockfd, data, maxlen, &from, retval); 00442 00443 if (err) 00444 { 00445 setError(IO_ReadError, static_cast<SocketError>(err)); 00446 return -1; 00447 } 00448 00449 return retval; 00450 } 00451 00452 Q_LONG KSocketDevice::peekBlock(char *data, Q_ULONG maxlen) 00453 { 00454 resetError(); 00455 if (m_sockfd == -1) 00456 return -1; 00457 00458 if (maxlen == 0 || data == 0L) 00459 return 0; // can't read 00460 00461 ssize_t retval; 00462 int err = do_read_common(m_sockfd, data, maxlen, 0L, retval, true); 00463 00464 if (err) 00465 { 00466 setError(IO_ReadError, static_cast<SocketError>(err)); 00467 return -1; 00468 } 00469 00470 return retval; 00471 } 00472 00473 Q_LONG KSocketDevice::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from) 00474 { 00475 resetError(); 00476 if (m_sockfd == -1) 00477 return -1; // nothing to do here 00478 00479 if (data == 0L || maxlen == 0) 00480 return 0; // user doesn't want to read 00481 00482 ssize_t retval; 00483 int err = do_read_common(m_sockfd, data, maxlen, &from, retval, true); 00484 00485 if (err) 00486 { 00487 setError(IO_ReadError, static_cast<SocketError>(err)); 00488 return -1; 00489 } 00490 00491 return retval; 00492 } 00493 00494 Q_LONG KSocketDevice::writeBlock(const char *data, Q_ULONG len) 00495 { 00496 return writeBlock(data, len, KSocketAddress()); 00497 } 00498 00499 Q_LONG KSocketDevice::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to) 00500 { 00501 resetError(); 00502 if (m_sockfd == -1) 00503 return -1; // can't write to unopen socket 00504 00505 if (data == 0L || len == 0) 00506 return 0; // nothing to be written 00507 00508 ssize_t retval = ::sendto(m_sockfd, data, len, 0, to.address(), to.length()); 00509 if (retval == -1) 00510 { 00511 if (errno == EAGAIN || errno == EWOULDBLOCK) 00512 setError(IO_WriteError, WouldBlock); 00513 else 00514 setError(IO_WriteError, UnknownError); 00515 return -1; // nothing written 00516 } 00517 00518 return retval; 00519 } 00520 00521 KSocketAddress KSocketDevice::localAddress() const 00522 { 00523 if (m_sockfd == -1) 00524 return KSocketAddress(); // not open, empty value 00525 00526 socklen_t len; 00527 KSocketAddress localAddress; 00528 localAddress.setLength(len = 32); // arbitrary value 00529 if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1) 00530 // error! 00531 return KSocketAddress(); 00532 00533 if (len <= localAddress.length()) 00534 { 00535 // it has fit already 00536 localAddress.setLength(len); 00537 return localAddress; 00538 } 00539 00540 // no, the socket address is actually larger than we had anticipated 00541 // call again 00542 localAddress.setLength(len); 00543 if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1) 00544 // error! 00545 return KSocketAddress(); 00546 00547 return localAddress; 00548 } 00549 00550 KSocketAddress KSocketDevice::peerAddress() const 00551 { 00552 if (m_sockfd == -1) 00553 return KSocketAddress(); // not open, empty value 00554 00555 socklen_t len; 00556 KSocketAddress peerAddress; 00557 peerAddress.setLength(len = 32); // arbitrary value 00558 if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00559 // error! 00560 return KSocketAddress(); 00561 00562 if (len <= peerAddress.length()) 00563 { 00564 // it has fit already 00565 peerAddress.setLength(len); 00566 return peerAddress; 00567 } 00568 00569 // no, the socket address is actually larger than we had anticipated 00570 // call again 00571 peerAddress.setLength(len); 00572 if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00573 // error! 00574 return KSocketAddress(); 00575 00576 return peerAddress; 00577 } 00578 00579 KSocketAddress KSocketDevice::externalAddress() const 00580 { 00581 // for normal sockets, the externally visible address is the same 00582 // as the local address 00583 return localAddress(); 00584 } 00585 00586 QSocketNotifier* KSocketDevice::readNotifier() const 00587 { 00588 if (d->input) 00589 return d->input; 00590 00591 QMutexLocker locker(mutex()); 00592 if (d->input) 00593 return d->input; 00594 00595 if (m_sockfd == -1) 00596 { 00597 // socket doesn't exist; can't create notifier 00598 return 0L; 00599 } 00600 00601 return d->input = createNotifier(QSocketNotifier::Read); 00602 } 00603 00604 QSocketNotifier* KSocketDevice::writeNotifier() const 00605 { 00606 if (d->output) 00607 return d->output; 00608 00609 QMutexLocker locker(mutex()); 00610 if (d->output) 00611 return d->output; 00612 00613 if (m_sockfd == -1) 00614 { 00615 // socket doesn't exist; can't create notifier 00616 return 0L; 00617 } 00618 00619 return d->output = createNotifier(QSocketNotifier::Write); 00620 } 00621 00622 QSocketNotifier* KSocketDevice::exceptionNotifier() const 00623 { 00624 if (d->exception) 00625 return d->exception; 00626 00627 QMutexLocker locker(mutex()); 00628 if (d->exception) 00629 return d->exception; 00630 00631 if (m_sockfd == -1) 00632 { 00633 // socket doesn't exist; can't create notifier 00634 return 0L; 00635 } 00636 00637 return d->exception = createNotifier(QSocketNotifier::Exception); 00638 } 00639 00640 bool KSocketDevice::poll(bool *input, bool *output, bool *exception, 00641 int timeout, bool* timedout) 00642 { 00643 if (m_sockfd == -1) 00644 { 00645 setError(IO_UnspecifiedError, NotCreated); 00646 return false; 00647 } 00648 00649 resetError(); 00650 #ifdef HAVE_POLL 00651 struct pollfd fds; 00652 fds.fd = m_sockfd; 00653 fds.events = 0; 00654 00655 if (input) 00656 { 00657 fds.events |= POLLIN; 00658 *input = false; 00659 } 00660 if (output) 00661 { 00662 fds.events |= POLLOUT; 00663 *output = false; 00664 } 00665 if (exception) 00666 { 00667 fds.events |= POLLPRI; 00668 *exception = false; 00669 } 00670 00671 int retval = ::poll(&fds, 1, timeout); 00672 if (retval == -1) 00673 { 00674 setError(IO_UnspecifiedError, UnknownError); 00675 return false; 00676 } 00677 if (retval == 0) 00678 { 00679 // timeout 00680 if (timedout) 00681 *timedout = true; 00682 return true; 00683 } 00684 00685 if (input && fds.revents & POLLIN) 00686 *input = true; 00687 if (output && fds.revents & POLLOUT) 00688 *output = true; 00689 if (exception && fds.revents & POLLPRI) 00690 *exception = true; 00691 00692 return true; 00693 #else 00694 /* 00695 * We don't have poll(2). We'll have to make do with select(2). 00696 */ 00697 00698 fd_set readfds, writefds, exceptfds; 00699 fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L; 00700 00701 if (input) 00702 { 00703 preadfds = &readfds; 00704 FD_ZERO(preadfds); 00705 FD_SET(m_sockfd, preadfds); 00706 *input = false; 00707 } 00708 if (output) 00709 { 00710 pwritefds = &writefds; 00711 FD_ZERO(pwritefds); 00712 FD_SET(m_sockfd, pwritefds); 00713 *output = false; 00714 } 00715 if (exception) 00716 { 00717 pexceptfds = &exceptfds; 00718 FD_ZERO(pexceptfds); 00719 FD_SET(m_sockfd, pexceptfds); 00720 *exception = false; 00721 } 00722 00723 int retval; 00724 if (timeout < 0) 00725 retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L); 00726 else 00727 { 00728 // convert the milliseconds to timeval 00729 struct timeval tv; 00730 tv.tv_sec = timeout / 1000; 00731 tv.tv_usec = timeout % 1000 * 1000; 00732 00733 retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv); 00734 } 00735 00736 if (retval == -1) 00737 { 00738 setError(IO_UnspecifiedError, UnknownError); 00739 return false; 00740 } 00741 if (retval == 0) 00742 { 00743 // timeout 00744 if (timedout) 00745 *timedout = true; 00746 return true; 00747 } 00748 00749 if (input && FD_ISSET(m_sockfd, preadfds)) 00750 *input = true; 00751 if (output && FD_ISSET(m_sockfd, pwritefds)) 00752 *output = true; 00753 if (exception && FD_ISSET(m_sockfd, pexceptfds)) 00754 *exception = true; 00755 00756 return true; 00757 #endif 00758 } 00759 00760 bool KSocketDevice::poll(int timeout, bool *timedout) 00761 { 00762 bool input, output, exception; 00763 return poll(&input, &output, &exception, timeout, timedout); 00764 } 00765 00766 QSocketNotifier* KSocketDevice::createNotifier(QSocketNotifier::Type type) const 00767 { 00768 if (m_sockfd == -1) 00769 return 0L; 00770 00771 return new QSocketNotifier(m_sockfd, type); 00772 } 00773 00774 namespace 00775 { 00776 // simple class to avoid pointer stuff 00777 template<class T> class ptr 00778 { 00779 typedef T type; 00780 type* obj; 00781 public: 00782 ptr() : obj(0) 00783 { } 00784 00785 ptr(const ptr<T>& other) : obj(other.obj) 00786 { } 00787 00788 ptr(type* _obj) : obj(_obj) 00789 { } 00790 00791 ~ptr() 00792 { } 00793 00794 ptr<T>& operator=(const ptr<T>& other) 00795 { obj = other.obj; return *this; } 00796 00797 ptr<T>& operator=(T* _obj) 00798 { obj = _obj; return *this; } 00799 00800 type* operator->() const { return obj; } 00801 00802 operator T*() const { return obj; } 00803 00804 bool isNull() const 00805 { return obj == 0; } 00806 }; 00807 00808 static KSocketDeviceFactoryBase* defaultImplFactory; 00809 static QMutex defaultImplFactoryMutex; 00810 typedef QMap<int, KSocketDeviceFactoryBase* > factoryMap; 00811 static factoryMap factories; 00812 00813 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent) 00814 { 00815 KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent); 00816 if (device != 0L) 00817 return device; 00818 00819 KSocksSocketDevice::initSocks(); 00820 00821 if (defaultImplFactory) 00822 return defaultImplFactory->create(parent); 00823 00824 // the really default 00825 return new KSocketDevice(parent); 00826 } 00827 00828 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent, int capabilities) 00829 { 00830 KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent); 00831 if (device != 0L) 00832 return device; 00833 00834 QMutexLocker locker(&defaultImplFactoryMutex); 00835 factoryMap::ConstIterator it = factories.constBegin(); 00836 for ( ; it != factories.constEnd(); ++it) 00837 if ((it.key() & capabilities) == capabilities) 00838 // found a match 00839 return it.data()->create(parent); 00840 00841 return 0L; // no default 00842 } 00843 00844 KSocketDeviceFactoryBase* 00845 KSocketDevice::setDefaultImpl(KSocketDeviceFactoryBase* factory) 00846 { 00847 QMutexLocker locker(&defaultImplFactoryMutex); 00848 KSocketDeviceFactoryBase* old = defaultImplFactory; 00849 defaultImplFactory = factory; 00850 return old; 00851 } 00852 00853 void KSocketDevice::addNewImpl(KSocketDeviceFactoryBase* factory, int capabilities) 00854 { 00855 QMutexLocker locker(&defaultImplFactoryMutex); 00856 if (factories.contains(capabilities)) 00857 delete factories[capabilities]; 00858 factories.insert(capabilities, factory); 00859 } 00860 00861 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:26:09 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003