kdecore Library API Documentation

ksockssocketdevice.cpp

00001 /* -*- C++ -*- 00002 * Copyright (C) 2004 Thiago Macieira <thiago.macieira@kdemail.net> 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., 59 Temple Place - Suite 330, 00017 * Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include <config.h> 00021 00022 #include <errno.h> 00023 #include <sys/types.h> 00024 #include <sys/socket.h> 00025 00026 #if defined(HAVE_UNISTD_H) 00027 #include <unistd.h> 00028 #endif 00029 00030 #include "ksocks.h" 00031 #include "ksocketaddress.h" 00032 #include "kresolver.h" 00033 #include "ksockssocketdevice.h" 00034 00035 using namespace KNetwork; 00036 00037 // constructor 00038 // nothing to do 00039 KSocksSocketDevice::KSocksSocketDevice(const KSocketBase* obj) 00040 : KSocketDevice(obj) 00041 { 00042 } 00043 00044 // constructor with argument 00045 // nothing to do 00046 KSocksSocketDevice::KSocksSocketDevice(int fd) 00047 : KSocketDevice(fd) 00048 { 00049 } 00050 00051 // destructor 00052 // also nothing to do 00053 KSocksSocketDevice::~KSocksSocketDevice() 00054 { 00055 } 00056 00057 // returns the capabilities 00058 int KSocksSocketDevice::capabilities() const 00059 { 00060 return 0; // can do everything! 00061 } 00062 00063 // From here on, the code is almost exactly a copy of KSocketDevice 00064 // the differences are the use of KSocks where appropriate 00065 00066 bool KSocksSocketDevice::bind(const KResolverEntry& address) 00067 { 00068 resetError(); 00069 00070 if (m_sockfd == -1 && !create(address)) 00071 return false; // failed creating 00072 00073 // we have a socket, so try and bind 00074 if (KSocks::self()->bind(m_sockfd, address.address(), address.length()) == -1) 00075 { 00076 if (errno == EADDRINUSE) 00077 setError(IO_BindError, AddressInUse); 00078 else if (errno == EINVAL) 00079 setError(IO_BindError, AlreadyBound); 00080 else 00081 // assume the address is the cause 00082 setError(IO_BindError, NotSupported); 00083 return false; 00084 } 00085 00086 return true; 00087 } 00088 00089 00090 bool KSocksSocketDevice::listen(int backlog) 00091 { 00092 if (m_sockfd != -1) 00093 { 00094 if (KSocks::self()->listen(m_sockfd, backlog) == -1) 00095 { 00096 setError(IO_ListenError, NotSupported); 00097 return false; 00098 } 00099 00100 resetError(); 00101 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite); 00102 setState(IO_Open); 00103 return true; 00104 } 00105 00106 // we don't have a socket 00107 // can't listen 00108 setError(IO_ListenError, NotCreated); 00109 return false; 00110 } 00111 00112 bool KSocksSocketDevice::connect(const KResolverEntry& address) 00113 { 00114 resetError(); 00115 00116 if (m_sockfd == -1 && !create(address)) 00117 return false; // failed creating! 00118 00119 if (KSocks::self()->connect(m_sockfd, address.address(), address.length()) == -1) 00120 { 00121 if (errno == EISCONN) 00122 return true; // we're already connected 00123 else if (errno == EALREADY || errno == EINPROGRESS) 00124 { 00125 setError(IO_ConnectError, InProgress); 00126 return true; 00127 } 00128 else if (errno == ECONNREFUSED) 00129 setError(IO_ConnectError, ConnectionRefused); 00130 else if (errno == ENETDOWN || errno == ENETUNREACH || 00131 errno == ENETRESET || errno == ECONNABORTED || 00132 errno == ECONNRESET || errno == EHOSTDOWN || 00133 errno == EHOSTUNREACH) 00134 setError(IO_ConnectError, NetFailure); 00135 else 00136 setError(IO_ConnectError, NotSupported); 00137 00138 return false; 00139 } 00140 00141 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite); 00142 setState(IO_Open); 00143 return true; // all is well 00144 } 00145 00146 KSocksSocketDevice* KSocksSocketDevice::accept() 00147 { 00148 if (m_sockfd == -1) 00149 { 00150 // can't accept without a socket 00151 setError(IO_AcceptError, NotCreated); 00152 return 0L; 00153 } 00154 00155 struct sockaddr sa; 00156 socklen_t len = sizeof(sa); 00157 int newfd = KSocks::self()->accept(m_sockfd, &sa, &len); 00158 if (newfd == -1) 00159 { 00160 if (errno == EAGAIN || errno == EWOULDBLOCK) 00161 setError(IO_AcceptError, WouldBlock); 00162 else 00163 setError(IO_AcceptError, UnknownError); 00164 return NULL; 00165 } 00166 00167 return new KSocksSocketDevice(newfd); 00168 } 00169 00170 static int socks_read_common(int sockfd, char *data, Q_ULONG maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false) 00171 { 00172 socklen_t len; 00173 if (from) 00174 { 00175 from->setLength(len = 128); // arbitrary length 00176 retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len); 00177 } 00178 else 00179 retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL); 00180 00181 if (retval == -1) 00182 { 00183 if (errno == EAGAIN || errno == EWOULDBLOCK) 00184 return KSocketDevice::WouldBlock; 00185 else 00186 return KSocketDevice::UnknownError; 00187 } 00188 00189 if (from) 00190 from->setLength(len); 00191 return 0; 00192 } 00193 00194 Q_LONG KSocksSocketDevice::readBlock(char *data, Q_ULONG maxlen) 00195 { 00196 resetError(); 00197 if (m_sockfd == -1) 00198 return -1; 00199 00200 if (maxlen == 0 || data == 0L) 00201 return 0; // can't read 00202 00203 ssize_t retval; 00204 int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval); 00205 00206 if (err) 00207 { 00208 setError(IO_ReadError, static_cast<SocketError>(err)); 00209 return -1; 00210 } 00211 00212 return retval; 00213 } 00214 00215 Q_LONG KSocksSocketDevice::readBlock(char *data, Q_ULONG maxlen, KSocketAddress &from) 00216 { 00217 resetError(); 00218 if (m_sockfd == -1) 00219 return -1; // nothing to do here 00220 00221 if (data == 0L || maxlen == 0) 00222 return 0; // user doesn't want to read 00223 00224 ssize_t retval; 00225 int err = socks_read_common(m_sockfd, data, maxlen, &from, retval); 00226 00227 if (err) 00228 { 00229 setError(IO_ReadError, static_cast<SocketError>(err)); 00230 return -1; 00231 } 00232 00233 return retval; 00234 } 00235 00236 Q_LONG KSocksSocketDevice::peekBlock(char *data, Q_ULONG maxlen) 00237 { 00238 resetError(); 00239 if (m_sockfd == -1) 00240 return -1; 00241 00242 if (maxlen == 0 || data == 0L) 00243 return 0; // can't read 00244 00245 ssize_t retval; 00246 int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval, true); 00247 00248 if (err) 00249 { 00250 setError(IO_ReadError, static_cast<SocketError>(err)); 00251 return -1; 00252 } 00253 00254 return retval; 00255 } 00256 00257 Q_LONG KSocksSocketDevice::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from) 00258 { 00259 resetError(); 00260 if (m_sockfd == -1) 00261 return -1; // nothing to do here 00262 00263 if (data == 0L || maxlen == 0) 00264 return 0; // user doesn't want to read 00265 00266 ssize_t retval; 00267 int err = socks_read_common(m_sockfd, data, maxlen, &from, retval, true); 00268 00269 if (err) 00270 { 00271 setError(IO_ReadError, static_cast<SocketError>(err)); 00272 return -1; 00273 } 00274 00275 return retval; 00276 } 00277 00278 Q_LONG KSocksSocketDevice::writeBlock(const char *data, Q_ULONG len) 00279 { 00280 return writeBlock(data, len, KSocketAddress()); 00281 } 00282 00283 Q_LONG KSocksSocketDevice::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to) 00284 { 00285 resetError(); 00286 if (m_sockfd == -1) 00287 return -1; // can't write to unopen socket 00288 00289 if (data == 0L || len == 0) 00290 return 0; // nothing to be written 00291 00292 ssize_t retval = KSocks::self()->sendto(m_sockfd, data, len, 0, to.address(), to.length()); 00293 if (retval == -1) 00294 { 00295 if (errno == EAGAIN || errno == EWOULDBLOCK) 00296 setError(IO_WriteError, WouldBlock); 00297 else 00298 setError(IO_WriteError, UnknownError); 00299 return -1; // nothing written 00300 } 00301 00302 return retval; 00303 } 00304 00305 KSocketAddress KSocksSocketDevice::localAddress() const 00306 { 00307 if (m_sockfd == -1) 00308 return KSocketAddress(); // not open, empty value 00309 00310 socklen_t len; 00311 KSocketAddress localAddress; 00312 localAddress.setLength(len = 32); // arbitrary value 00313 if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1) 00314 // error! 00315 return KSocketAddress(); 00316 00317 if (len <= localAddress.length()) 00318 { 00319 // it has fit already 00320 localAddress.setLength(len); 00321 return localAddress; 00322 } 00323 00324 // no, the socket address is actually larger than we had anticipated 00325 // call again 00326 localAddress.setLength(len); 00327 if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1) 00328 // error! 00329 return KSocketAddress(); 00330 00331 return localAddress; 00332 } 00333 00334 KSocketAddress KSocksSocketDevice::peerAddress() const 00335 { 00336 if (m_sockfd == -1) 00337 return KSocketAddress(); // not open, empty value 00338 00339 socklen_t len; 00340 KSocketAddress peerAddress; 00341 peerAddress.setLength(len = 32); // arbitrary value 00342 if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00343 // error! 00344 return KSocketAddress(); 00345 00346 if (len <= peerAddress.length()) 00347 { 00348 // it has fit already 00349 peerAddress.setLength(len); 00350 return peerAddress; 00351 } 00352 00353 // no, the socket address is actually larger than we had anticipated 00354 // call again 00355 peerAddress.setLength(len); 00356 if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1) 00357 // error! 00358 return KSocketAddress(); 00359 00360 return peerAddress; 00361 } 00362 00363 KSocketAddress KSocksSocketDevice::externalAddress() const 00364 { 00365 // return empty, indicating unknown external address 00366 return KSocketAddress(); 00367 } 00368 00369 bool KSocksSocketDevice::poll(bool *input, bool *output, bool *exception, 00370 int timeout, bool *timedout) 00371 { 00372 if (m_sockfd == -1) 00373 { 00374 setError(IO_UnspecifiedError, NotCreated); 00375 return false; 00376 } 00377 00378 resetError(); 00379 fd_set readfds, writefds, exceptfds; 00380 fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L; 00381 00382 if (input) 00383 { 00384 preadfds = &readfds; 00385 FD_ZERO(preadfds); 00386 FD_SET(m_sockfd, preadfds); 00387 *input = false; 00388 } 00389 if (output) 00390 { 00391 pwritefds = &writefds; 00392 FD_ZERO(pwritefds); 00393 FD_SET(m_sockfd, pwritefds); 00394 *output = false; 00395 } 00396 if (exception) 00397 { 00398 pexceptfds = &exceptfds; 00399 FD_ZERO(pexceptfds); 00400 FD_SET(m_sockfd, pexceptfds); 00401 *exception = false; 00402 } 00403 00404 int retval; 00405 if (timeout < 0) 00406 retval = KSocks::self()->select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L); 00407 else 00408 { 00409 // convert the milliseconds to timeval 00410 struct timeval tv; 00411 tv.tv_sec = timeout / 1000; 00412 tv.tv_usec = timeout % 1000 * 1000; 00413 00414 retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv); 00415 } 00416 00417 if (retval == -1) 00418 { 00419 setError(IO_UnspecifiedError, UnknownError); 00420 return false; 00421 } 00422 if (retval == 0) 00423 { 00424 // timeout 00425 if (timedout) 00426 *timedout = true; 00427 return true; 00428 } 00429 00430 if (input && FD_ISSET(m_sockfd, preadfds)) 00431 *input = true; 00432 if (output && FD_ISSET(m_sockfd, pwritefds)) 00433 *output = true; 00434 if (exception && FD_ISSET(m_sockfd, pexceptfds)) 00435 *exception = true; 00436 00437 return true; 00438 }
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:43:11 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003