KDECore
k3sockssocketdevice.cpp
Go to the documentation of this file.
00001 /* -*- C++ -*- 00002 * Copyright (C) 2004 Thiago Macieira <thiago@kde.org> 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public License 00015 * along with this library; see the file COPYING.LIB. If not, write to 00016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 * Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "k3sockssocketdevice.h" 00021 00022 #include <config.h> 00023 #include <config-network.h> 00024 00025 #include <errno.h> 00026 #include <sys/types.h> 00027 #include <sys/socket.h> 00028 00029 #if defined(HAVE_UNISTD_H) 00030 #include <unistd.h> 00031 #endif 00032 00033 00034 #include <QCoreApplication> 00035 #ifndef KDE_USE_FINAL 00036 #define I_KNOW_KSOCKS_ISNT_PUBLIC 00037 #include "k3socks.h" 00038 #undef I_KNOW_KSOCKS_ISNT_PUBLIC 00039 #endif 00040 #include "k3socketaddress.h" 00041 #include "k3resolver.h" 00042 00043 using namespace KNetwork; 00044 00045 // constructor 00046 // nothing to do 00047 KSocksSocketDevice::KSocksSocketDevice(const KSocketBase* obj) 00048 : KSocketDevice(obj), d(0) 00049 { 00050 } 00051 00052 // constructor with argument 00053 // nothing to do 00054 KSocksSocketDevice::KSocksSocketDevice(int fd) 00055 : KSocketDevice(fd), d(0) 00056 { 00057 } 00058 00059 // destructor 00060 // also nothing to do 00061 KSocksSocketDevice::~KSocksSocketDevice() 00062 { 00063 } 00064 00065 // returns the capabilities 00066 int KSocksSocketDevice::capabilities() const 00067 { 00068 return 0; // can do everything! 00069 } 00070 00071 // From here on, the code is almost exactly a copy of KSocketDevice 00072 // the differences are the use of KSocks where appropriate 00073 00074 bool KSocksSocketDevice::bind(const KResolverEntry& address) 00075 { 00076 resetError(); 00077 00078 if (m_sockfd == -1 && !create(address)) 00079 return false; // failed creating 00080 00081 // we have a socket, so try and bind 00082 if (KSocks::self()->bind(m_sockfd, address.address(), address.length()) == -1) 00083 { 00084 if (errno == EADDRINUSE) 00085 setError(AddressInUse); 00086 else if (errno == EINVAL) 00087 setError(AlreadyBound); 00088 else 00089 // assume the address is the cause 00090 setError(NotSupported); 00091 return false; 00092 } 00093 00094 return true; 00095 } 00096 00097 00098 bool KSocksSocketDevice::listen(int backlog) 00099 { 00100 if (m_sockfd != -1) 00101 { 00102 if (KSocks::self()->listen(m_sockfd, backlog) == -1) 00103 { 00104 setError(NotSupported); 00105 return false; 00106 } 00107 00108 resetError(); 00109 setOpenMode(ReadWrite | Unbuffered); 00110 return true; 00111 } 00112 00113 // we don't have a socket 00114 // can't listen 00115 setError(NotCreated); 00116 return false; 00117 } 00118 00119 bool KSocksSocketDevice::connect(const KResolverEntry& address) 00120 { 00121 resetError(); 00122 00123 if (m_sockfd == -1 && !create(address)) 00124 return false; // failed creating! 00125 00126 int retval; 00127 if (KSocks::self()->hasWorkingAsyncConnect()) 00128 retval = KSocks::self()->connect(m_sockfd, address.address(), 00129 address.length()); 00130 else 00131 { 00132 // work around some SOCKS implementation bugs 00133 // we will do a *synchronous* connection here! 00134 // FIXME: KDE4, write a proper SOCKS implementation 00135 bool isBlocking = blocking(); 00136 setBlocking(true); 00137 retval = KSocks::self()->connect(m_sockfd, address.address(), 00138 address.length()); 00139 setBlocking(isBlocking); 00140 } 00141 00142 if (retval == -1) 00143 { 00144 if (errno == EISCONN) 00145 return true; // we're already connected 00146 else if (errno == EALREADY || errno == EINPROGRESS) 00147 { 00148 setError(InProgress); 00149 return true; 00150 } 00151 else if (errno == ECONNREFUSED) 00152 setError(ConnectionRefused); 00153 else if (errno == ENETDOWN || errno == ENETUNREACH || 00154 errno == ENETRESET || errno == ECONNABORTED || 00155 errno == ECONNRESET || errno == EHOSTDOWN || 00156 errno == EHOSTUNREACH) 00157 setError(NetFailure); 00158 else 00159 setError(NotSupported); 00160 00161 return false; 00162 } 00163 00164 setOpenMode(ReadWrite | Unbuffered); 00165 return true; // all is well 00166 } 00167 00168 KSocksSocketDevice* KSocksSocketDevice::accept() 00169 { 00170 if (m_sockfd == -1) 00171 { 00172 // can't accept without a socket 00173 setError(NotCreated); 00174 return 0L; 00175 } 00176 00177 struct sockaddr sa; 00178 kde_socklen_t len = sizeof(sa); 00179 int newfd = KSocks::self()->accept(m_sockfd, &sa, &len); 00180 if (newfd == -1) 00181 { 00182 if (errno == EAGAIN || errno == EWOULDBLOCK) 00183 setError(WouldBlock); 00184 else 00185 setError(UnknownError); 00186 return NULL; 00187 } 00188 00189 return new KSocksSocketDevice(newfd); 00190 } 00191 00192 static int socks_read_common(int sockfd, char *data, quint64 maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false) 00193 { 00194 kde_socklen_t len; 00195 if (from) 00196 { 00197 from->setLength(len = 128); // arbitrary length 00198 retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len); 00199 } 00200 else 00201 retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL); 00202 00203 if (retval == -1) 00204 { 00205 if (errno == EAGAIN || errno == EWOULDBLOCK) 00206 return KSocketDevice::WouldBlock; 00207 else 00208 return KSocketDevice::UnknownError; 00209 } 00210 00211 if (from) 00212 from->setLength(len); 00213 return 0; 00214 } 00215 00216 qint64 KSocksSocketDevice::readBlock(char *data, quint64 maxlen) 00217 { 00218 resetError(); 00219 if (m_sockfd == -1) 00220 return -1; 00221 00222 if (maxlen == 0 || data == 0L) 00223 return 0; // can't read 00224 00225 ssize_t retval; 00226 int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval); 00227 00228 if (err) 00229 { 00230 setError(static_cast<SocketError>(err)); 00231 return -1; 00232 } 00233 00234 return retval; 00235 } 00236 00237 qint64 KSocksSocketDevice::readBlock(char *data, quint64 maxlen, KSocketAddress &from) 00238 { 00239 resetError(); 00240 if (m_sockfd == -1) 00241 return -1; // nothing to do here 00242 00243 if (data == 0L || maxlen == 0) 00244 return 0; // user doesn't want to read 00245 00246 ssize_t retval; 00247 int err = socks_read_common(m_sockfd, data, maxlen, &from, retval); 00248 00249 if (err) 00250 { 00251 setError(static_cast<SocketError>(err)); 00252 return -1; 00253 } 00254 00255 return retval; 00256 } 00257 00258 qint64 KSocksSocketDevice::peekBlock(char *data, quint64 maxlen) 00259 { 00260 resetError(); 00261 if (m_sockfd == -1) 00262 return -1; 00263 00264 if (maxlen == 0 || data == 0L) 00265 return 0; // can't read 00266 00267 ssize_t retval; 00268 int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval, true); 00269 00270 if (err) 00271 { 00272 setError(static_cast<SocketError>(err)); 00273 return -1; 00274 } 00275 00276 return retval; 00277 } 00278 00279 qint64 KSocksSocketDevice::peekBlock(char *data, quint64 maxlen, KSocketAddress& from) 00280 { 00281 resetError(); 00282 if (m_sockfd == -1) 00283 return -1; // nothing to do here 00284 00285 if (data == 0L || maxlen == 0) 00286 return 0; // user doesn't want to read 00287 00288 ssize_t retval; 00289 int err = socks_read_common(m_sockfd, data, maxlen, &from, retval, true); 00290 00291 if (err) 00292 { 00293 setError(static_cast<SocketError>(err)); 00294 return -1; 00295 } 00296 00297 return retval; 00298 } 00299 00300 qint64 KSocksSocketDevice::writeBlock(const char *data, quint64 len) 00301 { 00302 return writeBlock(data, len, KSocketAddress()); 00303 } 00304 00305 qint64 KSocksSocketDevice::writeBlock(const char *data, quint64 len, const KSocketAddress& to) 00306 { 00307 resetError(); 00308 if (m_sockfd == -1) 00309 return -1; // can't write to unopen socket 00310 00311 if (data == 0L || len == 0) 00312 return 0; // nothing to be written 00313 00314 ssize_t retval = KSocks::self()->sendto(m_sockfd, data, len, 0, to.address(), to.length()); 00315 if (retval == -1) 00316 { 00317 if (errno == EAGAIN || errno == EWOULDBLOCK) 00318 setError(WouldBlock); 00319 else 00320 setError(UnknownError); 00321 return -1; // nothing written 00322 } 00323 00324 return retval; 00325 } 00326 00327 KSocketAddress KSocksSocketDevice::localAddress() const 00328 { 00329 if (m_sockfd == -1) 00330 return KSocketAddress(); // not open, empty value 00331 00332 kde_socklen_t len; 00333 KSocketAddress localAddress; 00334 localAddress.setLength(len = 32); // arbitrary value 00335 if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1) 00336 // error! 00337 return KSocketAddress(); 00338 00339 if (len <= localAddress.length()) 00340 { 00341 // it has fit already 00342 localAddress.setLength(len); 00343 return localAddress; 00344 } 00345 00346 // no, the socket address is actually larger than we had anticipated 00347 // call again 00348 localAddress.setLength(len); 00349 if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1) 00350 // error! 00351 return KSocketAddress(); 00352 00353 return localAddress; 00354 } 00355 00356 KSocketAddress KSocksSocketDevice::peerAddress() const 00357 { 00358 if (m_sockfd == -1) 00359 return KSocketAddress(); // not open, empty value 00360 00361 kde_socklen_t len; 00362 KSocketAddress peerAddress; 00363 peerAddress.setLength(len = 32); // arbitrary value 00364 if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00365 // error! 00366 return KSocketAddress(); 00367 00368 if (len <= peerAddress.length()) 00369 { 00370 // it has fit already 00371 peerAddress.setLength(len); 00372 return peerAddress; 00373 } 00374 00375 // no, the socket address is actually larger than we had anticipated 00376 // call again 00377 peerAddress.setLength(len); 00378 if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00379 // error! 00380 return KSocketAddress(); 00381 00382 return peerAddress; 00383 } 00384 00385 KSocketAddress KSocksSocketDevice::externalAddress() const 00386 { 00387 // return empty, indicating unknown external address 00388 return KSocketAddress(); 00389 } 00390 00391 bool KSocksSocketDevice::poll(bool *input, bool *output, bool *exception, 00392 int timeout, bool *timedout) 00393 { 00394 if (m_sockfd == -1) 00395 { 00396 setError(NotCreated); 00397 return false; 00398 } 00399 00400 resetError(); 00401 fd_set readfds, writefds, exceptfds; 00402 fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L; 00403 00404 if (input) 00405 { 00406 preadfds = &readfds; 00407 FD_ZERO(preadfds); 00408 FD_SET(m_sockfd, preadfds); 00409 *input = false; 00410 } 00411 if (output) 00412 { 00413 pwritefds = &writefds; 00414 FD_ZERO(pwritefds); 00415 FD_SET(m_sockfd, pwritefds); 00416 *output = false; 00417 } 00418 if (exception) 00419 { 00420 pexceptfds = &exceptfds; 00421 FD_ZERO(pexceptfds); 00422 FD_SET(m_sockfd, pexceptfds); 00423 *exception = false; 00424 } 00425 00426 int retval; 00427 if (timeout < 0) 00428 retval = KSocks::self()->select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L); 00429 else 00430 { 00431 // convert the milliseconds to timeval 00432 struct timeval tv; 00433 tv.tv_sec = timeout / 1000; 00434 tv.tv_usec = timeout % 1000 * 1000; 00435 00436 retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv); 00437 } 00438 00439 if (retval == -1) 00440 { 00441 setError(UnknownError); 00442 return false; 00443 } 00444 if (retval == 0) 00445 { 00446 // timeout 00447 if (timedout) 00448 *timedout = true; 00449 return true; 00450 } 00451 00452 if (input && FD_ISSET(m_sockfd, preadfds)) 00453 *input = true; 00454 if (output && FD_ISSET(m_sockfd, pwritefds)) 00455 *output = true; 00456 if (exception && FD_ISSET(m_sockfd, pexceptfds)) 00457 *exception = true; 00458 00459 return true; 00460 } 00461 00462 void KSocksSocketDevice::initSocks() 00463 { 00464 static bool init = false; 00465 00466 if (init) 00467 return; 00468 00469 if (QCoreApplication::instance() == 0L) 00470 return; // no KApplication, so don't initialize 00471 // this should, however, test for KComponentData 00472 00473 init = true; 00474 00475 if (KSocks::self()->hasSocks()) 00476 delete KSocketDevice::setDefaultImpl(new KSocketDeviceFactory<KSocksSocketDevice>); 00477 } 00478 00479 #if 0 00480 static bool register() 00481 { 00482 KSocketDevice::addNewImpl(new KSocketDeviceFactory<KSocksSocketDevice>, 0); 00483 } 00484 00485 static bool register = registered(); 00486 #endif
KDE 4.6 API Reference