kdecore Library API Documentation

ksocketdevice.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 <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 if (retval == 0) 00405 return KSocketDevice::RemotelyDisconnected; 00406 00407 if (from) 00408 from->setLength(len); 00409 return 0; 00410 } 00411 00412 Q_LONG KSocketDevice::readBlock(char *data, Q_ULONG maxlen) 00413 { 00414 resetError(); 00415 if (m_sockfd == -1) 00416 return -1; 00417 00418 if (maxlen == 0 || data == 0L) 00419 return 0; // can't read 00420 00421 ssize_t retval; 00422 int err = do_read_common(m_sockfd, data, maxlen, 0L, retval); 00423 00424 if (err) 00425 { 00426 setError(IO_ReadError, static_cast<SocketError>(err)); 00427 return -1; 00428 } 00429 00430 return retval; 00431 } 00432 00433 Q_LONG KSocketDevice::readBlock(char *data, Q_ULONG maxlen, KSocketAddress &from) 00434 { 00435 resetError(); 00436 if (m_sockfd == -1) 00437 return -1; // nothing to do here 00438 00439 if (data == 0L || maxlen == 0) 00440 return 0; // user doesn't want to read 00441 00442 ssize_t retval; 00443 int err = do_read_common(m_sockfd, data, maxlen, &from, retval); 00444 00445 if (err) 00446 { 00447 setError(IO_ReadError, static_cast<SocketError>(err)); 00448 return -1; 00449 } 00450 00451 return retval; 00452 } 00453 00454 Q_LONG KSocketDevice::peekBlock(char *data, Q_ULONG maxlen) 00455 { 00456 resetError(); 00457 if (m_sockfd == -1) 00458 return -1; 00459 00460 if (maxlen == 0 || data == 0L) 00461 return 0; // can't read 00462 00463 ssize_t retval; 00464 int err = do_read_common(m_sockfd, data, maxlen, 0L, retval, true); 00465 00466 if (err) 00467 { 00468 setError(IO_ReadError, static_cast<SocketError>(err)); 00469 return -1; 00470 } 00471 00472 return retval; 00473 } 00474 00475 Q_LONG KSocketDevice::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from) 00476 { 00477 resetError(); 00478 if (m_sockfd == -1) 00479 return -1; // nothing to do here 00480 00481 if (data == 0L || maxlen == 0) 00482 return 0; // user doesn't want to read 00483 00484 ssize_t retval; 00485 int err = do_read_common(m_sockfd, data, maxlen, &from, retval, true); 00486 00487 if (err) 00488 { 00489 setError(IO_ReadError, static_cast<SocketError>(err)); 00490 return -1; 00491 } 00492 00493 return retval; 00494 } 00495 00496 Q_LONG KSocketDevice::writeBlock(const char *data, Q_ULONG len) 00497 { 00498 return writeBlock(data, len, KSocketAddress()); 00499 } 00500 00501 Q_LONG KSocketDevice::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to) 00502 { 00503 resetError(); 00504 if (m_sockfd == -1) 00505 return -1; // can't write to unopen socket 00506 00507 if (data == 0L || len == 0) 00508 return 0; // nothing to be written 00509 00510 ssize_t retval = ::sendto(m_sockfd, data, len, 0, to.address(), to.length()); 00511 if (retval == -1) 00512 { 00513 if (errno == EAGAIN || errno == EWOULDBLOCK) 00514 setError(IO_WriteError, WouldBlock); 00515 else 00516 setError(IO_WriteError, UnknownError); 00517 return -1; // nothing written 00518 } 00519 else if (retval == 0) 00520 setError(IO_WriteError, RemotelyDisconnected); 00521 00522 return retval; 00523 } 00524 00525 KSocketAddress KSocketDevice::localAddress() const 00526 { 00527 if (m_sockfd == -1) 00528 return KSocketAddress(); // not open, empty value 00529 00530 socklen_t len; 00531 KSocketAddress localAddress; 00532 localAddress.setLength(len = 32); // arbitrary value 00533 if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1) 00534 // error! 00535 return KSocketAddress(); 00536 00537 if (len <= localAddress.length()) 00538 { 00539 // it has fit already 00540 localAddress.setLength(len); 00541 return localAddress; 00542 } 00543 00544 // no, the socket address is actually larger than we had anticipated 00545 // call again 00546 localAddress.setLength(len); 00547 if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1) 00548 // error! 00549 return KSocketAddress(); 00550 00551 return localAddress; 00552 } 00553 00554 KSocketAddress KSocketDevice::peerAddress() const 00555 { 00556 if (m_sockfd == -1) 00557 return KSocketAddress(); // not open, empty value 00558 00559 socklen_t len; 00560 KSocketAddress peerAddress; 00561 peerAddress.setLength(len = 32); // arbitrary value 00562 if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00563 // error! 00564 return KSocketAddress(); 00565 00566 if (len <= peerAddress.length()) 00567 { 00568 // it has fit already 00569 peerAddress.setLength(len); 00570 return peerAddress; 00571 } 00572 00573 // no, the socket address is actually larger than we had anticipated 00574 // call again 00575 peerAddress.setLength(len); 00576 if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00577 // error! 00578 return KSocketAddress(); 00579 00580 return peerAddress; 00581 } 00582 00583 KSocketAddress KSocketDevice::externalAddress() const 00584 { 00585 // for normal sockets, the externally visible address is the same 00586 // as the local address 00587 return localAddress(); 00588 } 00589 00590 QSocketNotifier* KSocketDevice::readNotifier() const 00591 { 00592 if (d->input) 00593 return d->input; 00594 00595 QMutexLocker locker(mutex()); 00596 if (d->input) 00597 return d->input; 00598 00599 if (m_sockfd == -1) 00600 { 00601 // socket doesn't exist; can't create notifier 00602 return 0L; 00603 } 00604 00605 return d->input = createNotifier(QSocketNotifier::Read); 00606 } 00607 00608 QSocketNotifier* KSocketDevice::writeNotifier() const 00609 { 00610 if (d->output) 00611 return d->output; 00612 00613 QMutexLocker locker(mutex()); 00614 if (d->output) 00615 return d->output; 00616 00617 if (m_sockfd == -1) 00618 { 00619 // socket doesn't exist; can't create notifier 00620 return 0L; 00621 } 00622 00623 return d->output = createNotifier(QSocketNotifier::Write); 00624 } 00625 00626 QSocketNotifier* KSocketDevice::exceptionNotifier() const 00627 { 00628 if (d->exception) 00629 return d->exception; 00630 00631 QMutexLocker locker(mutex()); 00632 if (d->exception) 00633 return d->exception; 00634 00635 if (m_sockfd == -1) 00636 { 00637 // socket doesn't exist; can't create notifier 00638 return 0L; 00639 } 00640 00641 return d->exception = createNotifier(QSocketNotifier::Exception); 00642 } 00643 00644 bool KSocketDevice::poll(bool *input, bool *output, bool *exception, 00645 int timeout, bool* timedout) 00646 { 00647 if (m_sockfd == -1) 00648 { 00649 setError(IO_UnspecifiedError, NotCreated); 00650 return false; 00651 } 00652 00653 resetError(); 00654 #ifdef HAVE_POLL 00655 struct pollfd fds; 00656 fds.fd = m_sockfd; 00657 fds.events = 0; 00658 00659 if (input) 00660 { 00661 fds.events |= POLLIN; 00662 *input = false; 00663 } 00664 if (output) 00665 { 00666 fds.events |= POLLOUT; 00667 *output = false; 00668 } 00669 if (exception) 00670 { 00671 fds.events |= POLLPRI; 00672 *exception = false; 00673 } 00674 00675 int retval = ::poll(&fds, 1, timeout); 00676 if (retval == -1) 00677 { 00678 setError(IO_UnspecifiedError, UnknownError); 00679 return false; 00680 } 00681 if (retval == 0) 00682 { 00683 // timeout 00684 if (timedout) 00685 *timedout = true; 00686 return true; 00687 } 00688 00689 if (input && fds.revents & POLLIN) 00690 *input = true; 00691 if (output && fds.revents & POLLOUT) 00692 *output = true; 00693 if (exception && fds.revents & POLLPRI) 00694 *exception = true; 00695 00696 return true; 00697 #else 00698 /* 00699 * We don't have poll(2). We'll have to make do with select(2). 00700 */ 00701 00702 fd_set readfds, writefds, exceptfds; 00703 fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L; 00704 00705 if (input) 00706 { 00707 preadfds = &readfds; 00708 FD_ZERO(preadfds); 00709 FD_SET(m_sockfd, preadfds); 00710 *input = false; 00711 } 00712 if (output) 00713 { 00714 pwritefds = &writefds; 00715 FD_ZERO(pwritefds); 00716 FD_SET(m_sockfd, pwritefds); 00717 *output = false; 00718 } 00719 if (exception) 00720 { 00721 pexceptfds = &exceptfds; 00722 FD_ZERO(pexceptfds); 00723 FD_SET(m_sockfd, pexceptfds); 00724 *exception = false; 00725 } 00726 00727 int retval; 00728 if (timeout < 0) 00729 retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L); 00730 else 00731 { 00732 // convert the milliseconds to timeval 00733 struct timeval tv; 00734 tv.tv_sec = timeout / 1000; 00735 tv.tv_usec = timeout % 1000 * 1000; 00736 00737 retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv); 00738 } 00739 00740 if (retval == -1) 00741 { 00742 setError(IO_UnspecifiedError, UnknownError); 00743 return false; 00744 } 00745 if (retval == 0) 00746 { 00747 // timeout 00748 if (timedout) 00749 *timedout = true; 00750 return true; 00751 } 00752 00753 if (input && FD_ISSET(m_sockfd, preadfds)) 00754 *input = true; 00755 if (output && FD_ISSET(m_sockfd, pwritefds)) 00756 *output = true; 00757 if (exception && FD_ISSET(m_sockfd, pexceptfds)) 00758 *exception = true; 00759 00760 return true; 00761 #endif 00762 } 00763 00764 bool KSocketDevice::poll(int timeout, bool *timedout) 00765 { 00766 bool input, output, exception; 00767 return poll(&input, &output, &exception, timeout, timedout); 00768 } 00769 00770 QSocketNotifier* KSocketDevice::createNotifier(QSocketNotifier::Type type) const 00771 { 00772 if (m_sockfd == -1) 00773 return 0L; 00774 00775 return new QSocketNotifier(m_sockfd, type); 00776 } 00777 00778 namespace 00779 { 00780 // simple class to avoid pointer stuff 00781 template<class T> class ptr 00782 { 00783 typedef T type; 00784 type* obj; 00785 public: 00786 ptr() : obj(0) 00787 { } 00788 00789 ptr(const ptr<T>& other) : obj(other.obj) 00790 { } 00791 00792 ptr(type* _obj) : obj(_obj) 00793 { } 00794 00795 ~ptr() 00796 { } 00797 00798 ptr<T>& operator=(const ptr<T>& other) 00799 { obj = other.obj; return *this; } 00800 00801 ptr<T>& operator=(T* _obj) 00802 { obj = _obj; return *this; } 00803 00804 type* operator->() const { return obj; } 00805 00806 operator T*() const { return obj; } 00807 00808 bool isNull() const 00809 { return obj == 0; } 00810 }; 00811 } 00812 00813 static KSocketDeviceFactoryBase* defaultImplFactory; 00814 static QMutex defaultImplFactoryMutex; 00815 typedef QMap<int, KSocketDeviceFactoryBase* > factoryMap; 00816 static factoryMap factories; 00817 00818 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent) 00819 { 00820 KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent); 00821 if (device != 0L) 00822 return device; 00823 00824 KSocksSocketDevice::initSocks(); 00825 00826 if (defaultImplFactory) 00827 return defaultImplFactory->create(parent); 00828 00829 // the really default 00830 return new KSocketDevice(parent); 00831 } 00832 00833 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent, int capabilities) 00834 { 00835 KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent); 00836 if (device != 0L) 00837 return device; 00838 00839 QMutexLocker locker(&defaultImplFactoryMutex); 00840 factoryMap::ConstIterator it = factories.constBegin(); 00841 for ( ; it != factories.constEnd(); ++it) 00842 if ((it.key() & capabilities) == capabilities) 00843 // found a match 00844 return it.data()->create(parent); 00845 00846 return 0L; // no default 00847 } 00848 00849 KSocketDeviceFactoryBase* 00850 KSocketDevice::setDefaultImpl(KSocketDeviceFactoryBase* factory) 00851 { 00852 QMutexLocker locker(&defaultImplFactoryMutex); 00853 KSocketDeviceFactoryBase* old = defaultImplFactory; 00854 defaultImplFactory = factory; 00855 return old; 00856 } 00857 00858 void KSocketDevice::addNewImpl(KSocketDeviceFactoryBase* factory, int capabilities) 00859 { 00860 QMutexLocker locker(&defaultImplFactoryMutex); 00861 if (factories.contains(capabilities)) 00862 delete factories[capabilities]; 00863 factories.insert(capabilities, factory); 00864 } 00865
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 22:47:40 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003