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